From 6a92348cf5a80dfdbc8d080c15d6edbdfe465ec9 Mon Sep 17 00:00:00 2001 From: Dobie Wollert Date: Sun, 14 Sep 2014 07:04:16 -0400 Subject: [PATCH] Added node-modules --- node_modules/.bin/express | 1 + node_modules/.bin/jade | 1 + node_modules/.bin/lessc | 1 + node_modules/.bin/node-supervisor | 1 + node_modules/.bin/supervisor | 1 + node_modules/async/LICENSE | 19 + node_modules/async/README.md | 1414 + node_modules/async/component.json | 11 + node_modules/async/lib/async.js | 955 + node_modules/async/package.json | 46 + node_modules/emailjs/LICENSE | 19 + node_modules/emailjs/Readme.md | 183 + node_modules/emailjs/email.js | 3 + .../node_modules/bufferjs/add-chunk.js | 29 + .../emailjs/node_modules/bufferjs/concat.js | 31 + .../emailjs/node_modules/bufferjs/index.js | 7 + .../emailjs/node_modules/bufferjs/indexOf.js | 30 + .../node_modules/bufferjs/package.json | 38 + .../emailjs/node_modules/mimelib/.npmignore | 2 + .../emailjs/node_modules/mimelib/LICENSE | 16 + .../emailjs/node_modules/mimelib/README.md | 212 + .../emailjs/node_modules/mimelib/index.js | 4 + .../mimelib/lib/content-types-reversed.js | 40 + .../node_modules/mimelib/lib/content-types.js | 60 + .../node_modules/mimelib/lib/mimelib.js | 576 + .../node_modules/addressparser/.npmignore | 1 + .../node_modules/addressparser/README.md | 51 + .../node_modules/addressparser/index.js | 288 + .../node_modules/addressparser/package.json | 28 + .../node_modules/addressparser/test.js | 87 + .../mimelib/node_modules/encoding/.npmignore | 1 + .../mimelib/node_modules/encoding/README.md | 49 + .../node_modules/encoding/lib/encoding.js | 118 + .../node_modules/iconv-lite/.npmignore | 5 + .../node_modules/iconv-lite/.travis.yml | 5 + .../node_modules/iconv-lite/Changelog.md | 29 + .../encoding/node_modules/iconv-lite/LICENSE | 21 + .../node_modules/iconv-lite/README.md | 137 + .../node_modules/iconv-lite/README.md~ | 54 + .../iconv-lite/encodings/dbcs-codec.js | 564 + .../iconv-lite/encodings/dbcs-data.js | 168 + .../iconv-lite/encodings/index.js | 20 + .../iconv-lite/encodings/internal.js | 81 + .../iconv-lite/encodings/sbcs-codec.js | 76 + .../encodings/sbcs-data-generated.js | 450 + .../iconv-lite/encodings/sbcs-data.js | 168 + .../encodings/tables/big5-added.json | 122 + .../iconv-lite/encodings/tables/cp936.json | 264 + .../iconv-lite/encodings/tables/cp949.json | 273 + .../iconv-lite/encodings/tables/cp950.json | 177 + .../iconv-lite/encodings/tables/eucjp.json | 182 + .../encodings/tables/gb18030-ranges.json | 1 + .../encodings/tables/gbk-added.json | 55 + .../iconv-lite/encodings/tables/shiftjis.json | 125 + .../iconv-lite/encodings/utf16.js | 202 + .../node_modules/iconv-lite/encodings/utf7.js | 284 + .../iconv-lite/lib/extend-node.js | 210 + .../node_modules/iconv-lite/lib/index.js | 122 + .../node_modules/iconv-lite/lib/streams.js | 118 + .../node_modules/iconv-lite/package.json | 95 + .../node_modules/encoding/package.json | 31 + .../node_modules/encoding/test/test.js | 48 + .../emailjs/node_modules/mimelib/package.json | 55 + .../emailjs/node_modules/moment/.jshintrc | 26 + .../emailjs/node_modules/moment/.npmignore | 2 + .../emailjs/node_modules/moment/.travis.yml | 5 + .../emailjs/node_modules/moment/LICENSE | 22 + .../emailjs/node_modules/moment/Makefile | 71 + .../emailjs/node_modules/moment/ender.js | 1 + .../emailjs/node_modules/moment/lang/bg.js | 66 + .../emailjs/node_modules/moment/lang/ca.js | 64 + .../emailjs/node_modules/moment/lang/cv.js | 54 + .../emailjs/node_modules/moment/lang/da.js | 54 + .../emailjs/node_modules/moment/lang/de.js | 54 + .../emailjs/node_modules/moment/lang/en-ca.js | 58 + .../emailjs/node_modules/moment/lang/en-gb.js | 58 + .../emailjs/node_modules/moment/lang/es.js | 64 + .../emailjs/node_modules/moment/lang/eu.js | 54 + .../emailjs/node_modules/moment/lang/fi.js | 98 + .../emailjs/node_modules/moment/lang/fr-ca.js | 54 + .../emailjs/node_modules/moment/lang/fr.js | 54 + .../emailjs/node_modules/moment/lang/gl.js | 64 + .../emailjs/node_modules/moment/lang/hu.js | 108 + .../emailjs/node_modules/moment/lang/is.js | 132 + .../emailjs/node_modules/moment/lang/it.js | 54 + .../emailjs/node_modules/moment/lang/ja.js | 61 + .../emailjs/node_modules/moment/lang/jp.js | 64 + .../emailjs/node_modules/moment/lang/ko.js | 58 + .../emailjs/node_modules/moment/lang/kr.js | 61 + .../emailjs/node_modules/moment/lang/nb.js | 54 + .../emailjs/node_modules/moment/lang/nl.js | 62 + .../emailjs/node_modules/moment/lang/pl.js | 76 + .../emailjs/node_modules/moment/lang/pt-br.js | 58 + .../emailjs/node_modules/moment/lang/pt.js | 58 + .../emailjs/node_modules/moment/lang/ru.js | 133 + .../emailjs/node_modules/moment/lang/sv.js | 58 + .../emailjs/node_modules/moment/lang/tr.js | 88 + .../emailjs/node_modules/moment/lang/zh-cn.js | 67 + .../emailjs/node_modules/moment/lang/zh-tw.js | 67 + .../node_modules/moment/min/lang-all.min.js | 5 + .../node_modules/moment/min/lang/bg.js | 4 + .../node_modules/moment/min/lang/ca.js | 4 + .../node_modules/moment/min/lang/cv.js | 4 + .../node_modules/moment/min/lang/da.js | 4 + .../node_modules/moment/min/lang/de.js | 4 + .../node_modules/moment/min/lang/en-ca.js | 4 + .../node_modules/moment/min/lang/en-gb.js | 4 + .../node_modules/moment/min/lang/es.js | 4 + .../node_modules/moment/min/lang/eu.js | 4 + .../node_modules/moment/min/lang/fi.js | 4 + .../node_modules/moment/min/lang/fr-ca.js | 4 + .../node_modules/moment/min/lang/fr.js | 4 + .../node_modules/moment/min/lang/gl.js | 4 + .../node_modules/moment/min/lang/hu.js | 4 + .../node_modules/moment/min/lang/is.js | 4 + .../node_modules/moment/min/lang/it.js | 4 + .../node_modules/moment/min/lang/ja.js | 4 + .../node_modules/moment/min/lang/jp.js | 6 + .../node_modules/moment/min/lang/ko.js | 4 + .../node_modules/moment/min/lang/kr.js | 6 + .../node_modules/moment/min/lang/nb.js | 4 + .../node_modules/moment/min/lang/nl.js | 4 + .../node_modules/moment/min/lang/pl.js | 4 + .../node_modules/moment/min/lang/pt-br.js | 4 + .../node_modules/moment/min/lang/pt.js | 4 + .../node_modules/moment/min/lang/ru.js | 4 + .../node_modules/moment/min/lang/sv.js | 4 + .../node_modules/moment/min/lang/tr.js | 5 + .../node_modules/moment/min/lang/zh-cn.js | 4 + .../node_modules/moment/min/lang/zh-tw.js | 4 + .../node_modules/moment/min/moment.min.js | 6 + .../moment/min/moment.min.pretty.js | 440 + .../emailjs/node_modules/moment/moment.js | 1106 + .../emailjs/node_modules/moment/package.json | 61 + .../emailjs/node_modules/moment/readme.md | 228 + .../node_modules/moment/test/filesize-diff.js | 55 + .../moment/test/filesize-history.js | 108 + .../node_modules/moment/test/lang/bg.js | 265 + .../node_modules/moment/test/lang/ca.js | 221 + .../node_modules/moment/test/lang/cv.js | 246 + .../node_modules/moment/test/lang/da.js | 183 + .../node_modules/moment/test/lang/de.js | 241 + .../node_modules/moment/test/lang/en-ca.js | 248 + .../node_modules/moment/test/lang/en-gb.js | 248 + .../node_modules/moment/test/lang/en.js | 248 + .../node_modules/moment/test/lang/es.js | 218 + .../node_modules/moment/test/lang/eu.js | 248 + .../node_modules/moment/test/lang/fi.js | 248 + .../node_modules/moment/test/lang/fr-ca.js | 241 + .../node_modules/moment/test/lang/fr.js | 241 + .../node_modules/moment/test/lang/gl.js | 232 + .../node_modules/moment/test/lang/hu.js | 250 + .../node_modules/moment/test/lang/is.js | 254 + .../node_modules/moment/test/lang/it.js | 241 + .../node_modules/moment/test/lang/ja.js | 208 + .../node_modules/moment/test/lang/jp.js | 208 + .../node_modules/moment/test/lang/ko.js | 247 + .../node_modules/moment/test/lang/kr.js | 247 + .../node_modules/moment/test/lang/nb.js | 248 + .../node_modules/moment/test/lang/nl.js | 258 + .../node_modules/moment/test/lang/pl.js | 249 + .../node_modules/moment/test/lang/pt-br.js | 241 + .../node_modules/moment/test/lang/pt.js | 241 + .../node_modules/moment/test/lang/ru.js | 280 + .../node_modules/moment/test/lang/sv.js | 248 + .../node_modules/moment/test/lang/tr.js | 259 + .../node_modules/moment/test/lang/zh-cn.js | 227 + .../node_modules/moment/test/lang/zh-tw.js | 227 + .../moment/test/moment/add_subtract.js | 128 + .../node_modules/moment/test/moment/create.js | 319 + .../moment/test/moment/days_in_month.js | 28 + .../node_modules/moment/test/moment/diff.js | 94 + .../moment/test/moment/duration.js | 212 + .../node_modules/moment/test/moment/format.js | 111 + .../moment/test/moment/getters_setters.js | 103 + .../moment/test/moment/humanize_duration.js | 52 + .../moment/test/moment/is_moment.js | 27 + .../moment/test/moment/is_valid.js | 118 + .../node_modules/moment/test/moment/lang.js | 197 + .../moment/test/moment/leapyear.js | 13 + .../moment/test/moment/mutable.js | 56 + .../moment/test/moment/sod_eod.js | 232 + .../node_modules/moment/test/moment/utc.js | 63 + .../emailjs/node_modules/moment/test/zone.js | 181 + node_modules/emailjs/package.json | 56 + node_modules/emailjs/smtp/address.js | 416 + node_modules/emailjs/smtp/client.js | 209 + node_modules/emailjs/smtp/error.js | 21 + node_modules/emailjs/smtp/message.js | 622 + node_modules/emailjs/smtp/response.js | 75 + node_modules/emailjs/smtp/smtp.js | 537 + node_modules/emailjs/smtp/tls.js | 64 + node_modules/express/.npmignore | 9 + node_modules/express/.travis.yml | 4 + node_modules/express/History.md | 1183 + node_modules/express/LICENSE | 22 + node_modules/express/Makefile | 33 + node_modules/express/Readme.md | 179 + node_modules/express/bin/express | 422 + node_modules/express/index.js | 4 + node_modules/express/lib/application.js | 535 + node_modules/express/lib/express.js | 86 + node_modules/express/lib/middleware.js | 32 + node_modules/express/lib/request.js | 526 + node_modules/express/lib/response.js | 757 + node_modules/express/lib/router/index.js | 273 + node_modules/express/lib/router/route.js | 72 + node_modules/express/lib/utils.js | 313 + node_modules/express/lib/view.js | 77 + .../node_modules/buffer-crc32/.npmignore | 1 + .../node_modules/buffer-crc32/.travis.yml | 8 + .../node_modules/buffer-crc32/README.md | 47 + .../node_modules/buffer-crc32/index.js | 88 + .../node_modules/buffer-crc32/package.json | 40 + .../buffer-crc32/tests/crc.test.js | 89 + .../express/node_modules/commander/History.md | 158 + .../express/node_modules/commander/Readme.md | 276 + .../express/node_modules/commander/index.js | 1152 + .../commander/node_modules/keypress/README.md | 101 + .../commander/node_modules/keypress/index.js | 346 + .../node_modules/keypress/package.json | 32 + .../commander/node_modules/keypress/test.js | 28 + .../node_modules/commander/package.json | 41 + .../express/node_modules/connect/.npmignore | 12 + .../express/node_modules/connect/.travis.yml | 4 + .../express/node_modules/connect/LICENSE | 24 + .../express/node_modules/connect/Readme.md | 133 + .../express/node_modules/connect/index.js | 4 + .../express/node_modules/connect/lib/cache.js | 81 + .../node_modules/connect/lib/connect.js | 92 + .../express/node_modules/connect/lib/index.js | 50 + .../connect/lib/middleware/basicAuth.js | 103 + .../connect/lib/middleware/bodyParser.js | 61 + .../connect/lib/middleware/compress.js | 189 + .../connect/lib/middleware/cookieParser.js | 62 + .../connect/lib/middleware/cookieSession.js | 115 + .../connect/lib/middleware/csrf.js | 75 + .../connect/lib/middleware/directory.js | 229 + .../connect/lib/middleware/errorHandler.js | 86 + .../connect/lib/middleware/favicon.js | 80 + .../connect/lib/middleware/json.js | 89 + .../connect/lib/middleware/limit.js | 78 + .../connect/lib/middleware/logger.js | 339 + .../connect/lib/middleware/methodOverride.js | 59 + .../connect/lib/middleware/multipart.js | 133 + .../connect/lib/middleware/query.js | 46 + .../connect/lib/middleware/responseTime.js | 32 + .../connect/lib/middleware/session.js | 355 + .../connect/lib/middleware/session/cookie.js | 140 + .../connect/lib/middleware/session/memory.js | 129 + .../connect/lib/middleware/session/session.js | 116 + .../connect/lib/middleware/session/store.js | 84 + .../connect/lib/middleware/static.js | 95 + .../connect/lib/middleware/staticCache.js | 231 + .../connect/lib/middleware/timeout.js | 55 + .../connect/lib/middleware/urlencoded.js | 78 + .../connect/lib/middleware/vhost.js | 40 + .../express/node_modules/connect/lib/patch.js | 79 + .../express/node_modules/connect/lib/proto.js | 230 + .../connect/lib/public/directory.html | 81 + .../connect/lib/public/error.html | 14 + .../connect/lib/public/favicon.ico | Bin 0 -> 1406 bytes .../connect/lib/public/icons/page.png | Bin 0 -> 635 bytes .../connect/lib/public/icons/page_add.png | Bin 0 -> 739 bytes .../connect/lib/public/icons/page_attach.png | Bin 0 -> 794 bytes .../connect/lib/public/icons/page_code.png | Bin 0 -> 818 bytes .../connect/lib/public/icons/page_copy.png | Bin 0 -> 663 bytes .../connect/lib/public/icons/page_delete.png | Bin 0 -> 740 bytes .../connect/lib/public/icons/page_edit.png | Bin 0 -> 807 bytes .../connect/lib/public/icons/page_error.png | Bin 0 -> 793 bytes .../connect/lib/public/icons/page_excel.png | Bin 0 -> 817 bytes .../connect/lib/public/icons/page_find.png | Bin 0 -> 879 bytes .../connect/lib/public/icons/page_gear.png | Bin 0 -> 833 bytes .../connect/lib/public/icons/page_go.png | Bin 0 -> 779 bytes .../connect/lib/public/icons/page_green.png | Bin 0 -> 621 bytes .../connect/lib/public/icons/page_key.png | Bin 0 -> 801 bytes .../lib/public/icons/page_lightning.png | Bin 0 -> 839 bytes .../connect/lib/public/icons/page_link.png | Bin 0 -> 830 bytes .../lib/public/icons/page_paintbrush.png | Bin 0 -> 813 bytes .../connect/lib/public/icons/page_paste.png | Bin 0 -> 703 bytes .../connect/lib/public/icons/page_red.png | Bin 0 -> 641 bytes .../connect/lib/public/icons/page_refresh.png | Bin 0 -> 858 bytes .../connect/lib/public/icons/page_save.png | Bin 0 -> 774 bytes .../connect/lib/public/icons/page_white.png | Bin 0 -> 294 bytes .../lib/public/icons/page_white_acrobat.png | Bin 0 -> 591 bytes .../public/icons/page_white_actionscript.png | Bin 0 -> 664 bytes .../lib/public/icons/page_white_add.png | Bin 0 -> 512 bytes .../connect/lib/public/icons/page_white_c.png | Bin 0 -> 587 bytes .../lib/public/icons/page_white_camera.png | Bin 0 -> 656 bytes .../lib/public/icons/page_white_cd.png | Bin 0 -> 666 bytes .../lib/public/icons/page_white_code.png | Bin 0 -> 603 bytes .../lib/public/icons/page_white_code_red.png | Bin 0 -> 587 bytes .../public/icons/page_white_coldfusion.png | Bin 0 -> 592 bytes .../public/icons/page_white_compressed.png | Bin 0 -> 724 bytes .../lib/public/icons/page_white_copy.png | Bin 0 -> 309 bytes .../lib/public/icons/page_white_cplusplus.png | Bin 0 -> 621 bytes .../lib/public/icons/page_white_csharp.png | Bin 0 -> 700 bytes .../lib/public/icons/page_white_cup.png | Bin 0 -> 639 bytes .../lib/public/icons/page_white_database.png | Bin 0 -> 579 bytes .../lib/public/icons/page_white_delete.png | Bin 0 -> 536 bytes .../lib/public/icons/page_white_dvd.png | Bin 0 -> 638 bytes .../lib/public/icons/page_white_edit.png | Bin 0 -> 618 bytes .../lib/public/icons/page_white_error.png | Bin 0 -> 623 bytes .../lib/public/icons/page_white_excel.png | Bin 0 -> 663 bytes .../lib/public/icons/page_white_find.png | Bin 0 -> 676 bytes .../lib/public/icons/page_white_flash.png | Bin 0 -> 582 bytes .../lib/public/icons/page_white_freehand.png | Bin 0 -> 639 bytes .../lib/public/icons/page_white_gear.png | Bin 0 -> 402 bytes .../lib/public/icons/page_white_get.png | Bin 0 -> 516 bytes .../lib/public/icons/page_white_go.png | Bin 0 -> 612 bytes .../connect/lib/public/icons/page_white_h.png | Bin 0 -> 603 bytes .../public/icons/page_white_horizontal.png | Bin 0 -> 296 bytes .../lib/public/icons/page_white_key.png | Bin 0 -> 616 bytes .../lib/public/icons/page_white_lightning.png | Bin 0 -> 669 bytes .../lib/public/icons/page_white_link.png | Bin 0 -> 614 bytes .../lib/public/icons/page_white_magnify.png | Bin 0 -> 554 bytes .../lib/public/icons/page_white_medal.png | Bin 0 -> 706 bytes .../lib/public/icons/page_white_office.png | Bin 0 -> 779 bytes .../lib/public/icons/page_white_paint.png | Bin 0 -> 688 bytes .../public/icons/page_white_paintbrush.png | Bin 0 -> 618 bytes .../lib/public/icons/page_white_paste.png | Bin 0 -> 620 bytes .../lib/public/icons/page_white_php.png | Bin 0 -> 538 bytes .../lib/public/icons/page_white_picture.png | Bin 0 -> 650 bytes .../public/icons/page_white_powerpoint.png | Bin 0 -> 588 bytes .../lib/public/icons/page_white_put.png | Bin 0 -> 523 bytes .../lib/public/icons/page_white_ruby.png | Bin 0 -> 626 bytes .../lib/public/icons/page_white_stack.png | Bin 0 -> 317 bytes .../lib/public/icons/page_white_star.png | Bin 0 -> 565 bytes .../lib/public/icons/page_white_swoosh.png | Bin 0 -> 634 bytes .../lib/public/icons/page_white_text.png | Bin 0 -> 342 bytes .../public/icons/page_white_text_width.png | Bin 0 -> 315 bytes .../lib/public/icons/page_white_tux.png | Bin 0 -> 668 bytes .../lib/public/icons/page_white_vector.png | Bin 0 -> 644 bytes .../public/icons/page_white_visualstudio.png | Bin 0 -> 702 bytes .../lib/public/icons/page_white_width.png | Bin 0 -> 309 bytes .../lib/public/icons/page_white_word.png | Bin 0 -> 651 bytes .../lib/public/icons/page_white_world.png | Bin 0 -> 734 bytes .../lib/public/icons/page_white_wrench.png | Bin 0 -> 613 bytes .../lib/public/icons/page_white_zip.png | Bin 0 -> 386 bytes .../connect/lib/public/icons/page_word.png | Bin 0 -> 777 bytes .../connect/lib/public/icons/page_world.png | Bin 0 -> 903 bytes .../node_modules/connect/lib/public/style.css | 141 + .../express/node_modules/connect/lib/utils.js | 386 + .../connect/node_modules/bytes/.npmignore | 1 + .../connect/node_modules/bytes/History.md | 10 + .../connect/node_modules/bytes/Makefile | 7 + .../connect/node_modules/bytes/Readme.md | 51 + .../connect/node_modules/bytes/component.json | 7 + .../connect/node_modules/bytes/index.js | 39 + .../connect/node_modules/bytes/package.json | 24 + .../node_modules/formidable/.npmignore | 4 + .../node_modules/formidable/.travis.yml | 5 + .../connect/node_modules/formidable/LICENSE | 7 + .../connect/node_modules/formidable/Readme.md | 419 + .../benchmark/bench-multipart-parser.js | 71 + .../node_modules/formidable/example/json.js | 67 + .../node_modules/formidable/example/post.js | 43 + .../node_modules/formidable/example/upload.js | 48 + .../connect/node_modules/formidable/index.js | 1 + .../node_modules/formidable/lib/file.js | 72 + .../formidable/lib/incoming_form.js | 535 + .../node_modules/formidable/lib/index.js | 3 + .../formidable/lib/json_parser.js | 35 + .../formidable/lib/multipart_parser.js | 324 + .../formidable/lib/octet_parser.js | 20 + .../formidable/lib/querystring_parser.js | 27 + .../node_modules/formidable/package.json | 42 + .../node_modules/formidable/test/common.js | 18 + .../test/fixture/file/beta-sticker-1.png | Bin 0 -> 1660 bytes .../test/fixture/file/binaryfile.tar.gz | Bin 0 -> 301 bytes .../formidable/test/fixture/file/blank.gif | Bin 0 -> 49 bytes .../test/fixture/file/funkyfilename.txt | 1 + .../test/fixture/file/menu_separator.png | Bin 0 -> 931 bytes .../formidable/test/fixture/file/plain.txt | 1 + .../http/special-chars-in-filename/info.md | 3 + .../formidable/test/fixture/js/encoding.js | 24 + .../formidable/test/fixture/js/misc.js | 6 + .../formidable/test/fixture/js/no-filename.js | 9 + .../formidable/test/fixture/js/preamble.js | 9 + .../fixture/js/special-chars-in-filename.js | 21 + .../formidable/test/fixture/js/workarounds.js | 8 + .../formidable/test/fixture/multipart.js | 72 + .../test/integration/test-fixtures.js | 96 + .../formidable/test/integration/test-json.js | 38 + .../test/integration/test-octet-stream.js | 45 + .../formidable/test/legacy/common.js | 24 + .../integration/test-multipart-parser.js | 80 + .../test/legacy/simple/test-file.js | 104 + .../test/legacy/simple/test-incoming-form.js | 756 + .../legacy/simple/test-multipart-parser.js | 50 + .../legacy/simple/test-querystring-parser.js | 45 + .../legacy/system/test-multi-video-upload.js | 71 + .../node_modules/formidable/test/run.js | 1 + .../standalone/test-connection-aborted.js | 27 + .../test-content-transfer-encoding.js | 48 + .../test/standalone/test-issue-46.js | 49 + .../formidable/test/tools/base64.html | 67 + .../formidable/test/unit/test-file.js | 33 + .../test/unit/test-incoming-form.js | 63 + .../node_modules/formidable/tool/record.js | 47 + .../connect/node_modules/pause/.npmignore | 4 + .../connect/node_modules/pause/History.md | 5 + .../connect/node_modules/pause/Makefile | 7 + .../connect/node_modules/pause/Readme.md | 29 + .../connect/node_modules/pause/index.js | 29 + .../connect/node_modules/pause/package.json | 25 + .../connect/node_modules/qs/.gitmodules | 6 + .../connect/node_modules/qs/.npmignore | 7 + .../connect/node_modules/qs/Readme.md | 58 + .../connect/node_modules/qs/index.js | 387 + .../connect/node_modules/qs/package.json | 38 + .../connect/node_modules/uid2/index.js | 49 + .../connect/node_modules/uid2/package.json | 16 + .../express/node_modules/connect/package.json | 56 + .../express/node_modules/connect/test.js | 8 + .../node_modules/cookie-signature/.npmignore | 4 + .../node_modules/cookie-signature/History.md | 11 + .../node_modules/cookie-signature/Makefile | 7 + .../node_modules/cookie-signature/Readme.md | 42 + .../node_modules/cookie-signature/index.js | 42 + .../cookie-signature/package.json | 28 + .../express/node_modules/cookie/.npmignore | 1 + .../express/node_modules/cookie/.travis.yml | 5 + .../express/node_modules/cookie/LICENSE | 9 + .../express/node_modules/cookie/README.md | 44 + .../express/node_modules/cookie/index.js | 70 + .../express/node_modules/cookie/package.json | 37 + .../node_modules/cookie/test/mocha.opts | 1 + .../express/node_modules/cookie/test/parse.js | 44 + .../node_modules/cookie/test/serialize.js | 64 + .../express/node_modules/debug/.npmignore | 4 + .../express/node_modules/debug/History.md | 62 + .../express/node_modules/debug/Readme.md | 115 + .../express/node_modules/debug/component.json | 9 + .../express/node_modules/debug/debug.js | 124 + .../express/node_modules/debug/example/app.js | 19 + .../node_modules/debug/example/browser.html | 24 + .../node_modules/debug/example/wildcards.js | 10 + .../node_modules/debug/example/worker.js | 22 + .../express/node_modules/debug/index.js | 5 + .../express/node_modules/debug/lib/debug.js | 134 + .../express/node_modules/debug/package.json | 41 + .../express/node_modules/fresh/.npmignore | 1 + .../express/node_modules/fresh/Makefile | 7 + .../express/node_modules/fresh/Readme.md | 32 + .../express/node_modules/fresh/index.js | 49 + .../express/node_modules/fresh/package.json | 24 + .../express/node_modules/methods/index.js | 26 + .../express/node_modules/methods/package.json | 24 + .../express/node_modules/mkdirp/.npmignore | 2 + .../express/node_modules/mkdirp/.travis.yml | 5 + .../express/node_modules/mkdirp/LICENSE | 21 + .../node_modules/mkdirp/examples/pow.js | 6 + .../express/node_modules/mkdirp/index.js | 82 + .../express/node_modules/mkdirp/package.json | 34 + .../node_modules/mkdirp/readme.markdown | 63 + .../express/node_modules/mkdirp/test/chmod.js | 38 + .../node_modules/mkdirp/test/clobber.js | 37 + .../node_modules/mkdirp/test/mkdirp.js | 28 + .../express/node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 39 + .../express/node_modules/mkdirp/test/race.js | 41 + .../express/node_modules/mkdirp/test/rel.js | 32 + .../node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../express/node_modules/mkdirp/test/root.js | 18 + .../express/node_modules/mkdirp/test/sync.js | 32 + .../express/node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + .../node_modules/range-parser/.npmignore | 1 + .../node_modules/range-parser/History.md | 15 + .../node_modules/range-parser/Makefile | 7 + .../node_modules/range-parser/Readme.md | 28 + .../node_modules/range-parser/index.js | 49 + .../node_modules/range-parser/package.json | 24 + .../express/node_modules/send/.npmignore | 4 + .../express/node_modules/send/History.md | 35 + .../express/node_modules/send/Makefile | 8 + .../express/node_modules/send/Readme.md | 128 + .../express/node_modules/send/index.js | 2 + .../express/node_modules/send/lib/send.js | 474 + .../express/node_modules/send/lib/utils.js | 47 + .../send/node_modules/mime/LICENSE | 19 + .../send/node_modules/mime/README.md | 63 + .../send/node_modules/mime/mime.js | 113 + .../send/node_modules/mime/package.json | 36 + .../send/node_modules/mime/test.js | 55 + .../send/node_modules/mime/types/mime.types | 1588 + .../send/node_modules/mime/types/node.types | 60 + .../express/node_modules/send/package.json | 42 + node_modules/express/package.json | 85 + node_modules/express/test.js | 17 + .../googleapis/.cache/admindirectory_v1 | 1 + node_modules/googleapis/.cache/calendarv3 | 1 + node_modules/googleapis/.npmignore | 4 + node_modules/googleapis/.travis.yml | 3 + node_modules/googleapis/COPYING | 202 + node_modules/googleapis/README.md | 247 + .../googleapis/lib/auth/authclient.js | 41 + .../googleapis/lib/auth/computeclient.js | 79 + .../googleapis/lib/auth/oauth2client.js | 199 + node_modules/googleapis/lib/cache.js | 112 + node_modules/googleapis/lib/client.js | 140 + node_modules/googleapis/lib/googleapis.js | 268 + node_modules/googleapis/lib/requests.js | 286 + node_modules/googleapis/lib/transporters.js | 90 + .../googleapis/node_modules/async/LICENSE | 19 + .../googleapis/node_modules/async/README.md | 1365 + .../node_modules/async/lib/async.js | 982 + .../node_modules/async/package.json | 46 + .../googleapis/node_modules/request/LICENSE | 55 + .../googleapis/node_modules/request/README.md | 331 + .../googleapis/node_modules/request/aws.js | 191 + .../node_modules/request/forever.js | 103 + .../googleapis/node_modules/request/main.js | 1245 + .../request/node_modules/form-data/.npmignore | 5 + .../request/node_modules/form-data/License | 19 + .../request/node_modules/form-data/Makefile | 7 + .../request/node_modules/form-data/Readme.md | 118 + .../node_modules/form-data/lib/form_data.js | 291 + .../form-data/node_modules/async/.gitmodules | 9 + .../form-data/node_modules/async/.npmignore | 4 + .../form-data/node_modules/async/LICENSE | 19 + .../form-data/node_modules/async/Makefile | 25 + .../form-data/node_modules/async/README.md | 1021 + .../form-data/node_modules/async/index.js | 3 + .../form-data/node_modules/async/lib/async.js | 692 + .../form-data/node_modules/async/package.json | 42 + .../node_modules/combined-stream/.npmignore | 3 + .../node_modules/combined-stream/License | 19 + .../node_modules/combined-stream/Makefile | 7 + .../node_modules/combined-stream/Readme.md | 132 + .../combined-stream/lib/combined_stream.js | 185 + .../node_modules/delayed-stream/.npmignore | 2 + .../node_modules/delayed-stream/License | 19 + .../node_modules/delayed-stream/Makefile | 7 + .../node_modules/delayed-stream/Readme.md | 154 + .../delayed-stream/lib/delayed_stream.js | 99 + .../node_modules/delayed-stream/package.json | 38 + .../delayed-stream/test/common.js | 6 + .../integration/test-delayed-http-upload.js | 38 + .../test-delayed-stream-auto-pause.js | 21 + .../integration/test-delayed-stream-pause.js | 14 + .../test/integration/test-delayed-stream.js | 48 + .../integration/test-handle-source-errors.js | 15 + .../test/integration/test-max-data-size.js | 18 + .../test/integration/test-pipe-resumes.js | 13 + .../test/integration/test-proxy-readable.js | 13 + .../node_modules/delayed-stream/test/run.js | 7 + .../node_modules/combined-stream/package.json | 39 + .../combined-stream/test/common.js | 23 + .../combined-stream/test/fixture/file1.txt | 256 + .../combined-stream/test/fixture/file2.txt | 256 + .../test/integration/test-callback-streams.js | 27 + .../test/integration/test-data-size.js | 34 + ...delayed-streams-and-buffers-and-strings.js | 38 + .../test/integration/test-delayed-streams.js | 35 + .../test/integration/test-empty-string.js | 39 + .../test/integration/test-is-stream-like.js | 17 + .../test/integration/test-max-data-size.js | 24 + .../test/integration/test-unpaused-streams.js | 30 + .../node_modules/combined-stream/test/run.js | 7 + .../node_modules/form-data/package.json | 43 + .../node_modules/form-data/test/common.js | 14 + .../form-data/test/fixture/bacon.txt | 1 + .../form-data/test/fixture/unicycle.jpg | Bin 0 -> 19806 bytes .../test/integration/test-custom-headers.js | 75 + .../test/integration/test-form-get-length.js | 93 + .../test/integration/test-get-boundary.js | 18 + .../test/integration/test-http-response.js | 121 + .../form-data/test/integration/test-pipe.js | 120 + .../test/integration/test-submit-custom.js | 121 + .../form-data/test/integration/test-submit.js | 117 + .../node_modules/form-data/test/run.js | 7 + .../request/node_modules/mime/LICENSE | 19 + .../request/node_modules/mime/README.md | 63 + .../request/node_modules/mime/mime.js | 113 + .../request/node_modules/mime/package.json | 42 + .../request/node_modules/mime/test.js | 55 + .../node_modules/mime/types/mime.types | 1588 + .../node_modules/mime/types/node.types | 60 + .../googleapis/node_modules/request/oauth.js | 43 + .../node_modules/request/package.json | 45 + .../request/tests/googledoodle.png | Bin 0 -> 38510 bytes .../node_modules/request/tests/run.js | 59 + .../node_modules/request/tests/server.js | 90 + .../node_modules/request/tests/squid.conf | 77 + .../node_modules/request/tests/ssl/ca/ca.cnf | 20 + .../node_modules/request/tests/ssl/ca/ca.crl | 0 .../node_modules/request/tests/ssl/ca/ca.crt | 17 + .../node_modules/request/tests/ssl/ca/ca.csr | 13 + .../node_modules/request/tests/ssl/ca/ca.key | 18 + .../node_modules/request/tests/ssl/ca/ca.srl | 1 + .../request/tests/ssl/ca/server.cnf | 19 + .../request/tests/ssl/ca/server.crt | 16 + .../request/tests/ssl/ca/server.csr | 11 + .../request/tests/ssl/ca/server.js | 28 + .../request/tests/ssl/ca/server.key | 9 + .../node_modules/request/tests/ssl/npm-ca.crt | 16 + .../node_modules/request/tests/ssl/test.crt | 15 + .../node_modules/request/tests/ssl/test.key | 15 + .../request/tests/test-basic-auth.js | 66 + .../node_modules/request/tests/test-body.js | 117 + .../node_modules/request/tests/test-cookie.js | 29 + .../request/tests/test-cookiejar.js | 90 + .../request/tests/test-defaults.js | 114 + .../request/tests/test-digest-auth.js | 69 + .../node_modules/request/tests/test-errors.js | 37 + .../request/tests/test-follow-all-303.js | 30 + .../request/tests/test-follow-all.js | 35 + .../node_modules/request/tests/test-form.js | 79 + .../request/tests/test-headers.js | 52 + .../request/tests/test-httpModule.js | 94 + .../request/tests/test-https-strict.js | 97 + .../node_modules/request/tests/test-https.js | 87 + .../node_modules/request/tests/test-oauth.js | 117 + .../node_modules/request/tests/test-params.js | 92 + .../request/tests/test-piped-redirect.js | 52 + .../node_modules/request/tests/test-pipes.js | 216 + .../node_modules/request/tests/test-pool.js | 16 + .../tests/test-protocol-changing-redirect.js | 61 + .../node_modules/request/tests/test-proxy.js | 39 + .../node_modules/request/tests/test-qs.js | 28 + .../request/tests/test-redirect.js | 154 + .../node_modules/request/tests/test-s3.js | 13 + .../request/tests/test-timeout.js | 87 + .../node_modules/request/tests/test-toJSON.js | 14 + .../node_modules/request/tests/test-tunnel.js | 63 + .../node_modules/request/tests/unicycle.jpg | Bin 0 -> 19806 bytes .../googleapis/node_modules/request/tunnel.js | 227 + .../googleapis/node_modules/request/uuid.js | 19 + .../request/vendor/cookie/index.js | 65 + .../node_modules/request/vendor/cookie/jar.js | 72 + node_modules/googleapis/package.json | 50 + node_modules/jade/.npmignore | 14 + node_modules/jade/LICENSE | 22 + node_modules/jade/Readme.md | 1310 + node_modules/jade/Readme_zh-cn.md | 1278 + node_modules/jade/bin/jade | 178 + node_modules/jade/component.json | 16 + node_modules/jade/index.js | 4 + node_modules/jade/jade.js | 6709 + node_modules/jade/jade.md | 510 + node_modules/jade/lib/compiler.js | 644 + node_modules/jade/lib/doctypes.js | 18 + node_modules/jade/lib/filters-client.js | 18 + node_modules/jade/lib/filters.js | 29 + node_modules/jade/lib/index.js | 1 + node_modules/jade/lib/inline-tags.js | 28 + node_modules/jade/lib/jade.js | 238 + node_modules/jade/lib/lexer.js | 782 + node_modules/jade/lib/nodes/attrs.js | 77 + node_modules/jade/lib/nodes/block-comment.js | 33 + node_modules/jade/lib/nodes/block.js | 122 + node_modules/jade/lib/nodes/case.js | 43 + node_modules/jade/lib/nodes/code.js | 35 + node_modules/jade/lib/nodes/comment.js | 32 + node_modules/jade/lib/nodes/doctype.js | 29 + node_modules/jade/lib/nodes/each.js | 35 + node_modules/jade/lib/nodes/filter.js | 34 + node_modules/jade/lib/nodes/index.js | 20 + node_modules/jade/lib/nodes/literal.js | 29 + node_modules/jade/lib/nodes/mixin.js | 36 + node_modules/jade/lib/nodes/node.js | 25 + node_modules/jade/lib/nodes/tag.js | 95 + node_modules/jade/lib/nodes/text.js | 36 + node_modules/jade/lib/parser.js | 732 + node_modules/jade/lib/runtime.js | 199 + node_modules/jade/lib/self-closing.js | 19 + node_modules/jade/lib/utils.js | 21 + .../node_modules/character-parser/.npmignore | 16 + .../node_modules/character-parser/.travis.yml | 4 + .../node_modules/character-parser/README.md | 123 + .../node_modules/character-parser/index.js | 205 + .../character-parser/package.json | 39 + .../character-parser/test/index.js | 50 + .../jade/node_modules/commander/History.md | 158 + .../jade/node_modules/commander/Readme.md | 276 + .../jade/node_modules/commander/index.js | 1152 + .../commander/node_modules/keypress/README.md | 101 + .../commander/node_modules/keypress/index.js | 346 + .../node_modules/keypress/package.json | 32 + .../commander/node_modules/keypress/test.js | 28 + .../jade/node_modules/commander/package.json | 41 + .../constantinople/.gitattributes | 22 + .../node_modules/constantinople/.npmignore | 13 + .../node_modules/constantinople/.travis.yml | 4 + .../jade/node_modules/constantinople/LICENSE | 19 + .../node_modules/constantinople/README.md | 35 + .../jade/node_modules/constantinople/index.js | 35 + .../constantinople/node_modules/.bin/uglifyjs | 1 + .../node_modules/uglify-js/.npmignore | 2 + .../node_modules/uglify-js/.travis.yml | 7 + .../node_modules/uglify-js/LICENSE | 29 + .../node_modules/uglify-js/README.md | 588 + .../node_modules/uglify-js/bin/uglifyjs | 402 + .../node_modules/uglify-js/lib/ast.js | 985 + .../node_modules/uglify-js/lib/compress.js | 2028 + .../node_modules/uglify-js/lib/mozilla-ast.js | 267 + .../node_modules/uglify-js/lib/output.js | 1229 + .../node_modules/uglify-js/lib/parse.js | 1410 + .../node_modules/uglify-js/lib/scope.js | 581 + .../node_modules/uglify-js/lib/sourcemap.js | 81 + .../node_modules/uglify-js/lib/transform.js | 217 + .../node_modules/uglify-js/lib/utils.js | 295 + .../node_modules/optimist/.travis.yml | 4 + .../uglify-js/node_modules/optimist/LICENSE | 21 + .../node_modules/optimist/example/bool.js | 10 + .../optimist/example/boolean_double.js | 7 + .../optimist/example/boolean_single.js | 7 + .../optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + .../node_modules/optimist/example/divide.js | 8 + .../optimist/example/line_count.js | 20 + .../optimist/example/line_count_options.js | 29 + .../optimist/example/line_count_wrap.js | 29 + .../node_modules/optimist/example/nonopt.js | 4 + .../node_modules/optimist/example/reflect.js | 2 + .../node_modules/optimist/example/short.js | 3 + .../node_modules/optimist/example/string.js | 11 + .../optimist/example/usage-options.js | 19 + .../node_modules/optimist/example/xup.js | 10 + .../uglify-js/node_modules/optimist/index.js | 478 + .../optimist/node_modules/wordwrap/.npmignore | 1 + .../node_modules/wordwrap/README.markdown | 70 + .../node_modules/wordwrap/example/center.js | 10 + .../node_modules/wordwrap/example/meat.js | 3 + .../optimist/node_modules/wordwrap/index.js | 76 + .../node_modules/wordwrap/package.json | 45 + .../node_modules/wordwrap/test/break.js | 30 + .../node_modules/wordwrap/test/idleness.txt | 63 + .../node_modules/wordwrap/test/wrap.js | 31 + .../node_modules/optimist/package.json | 46 + .../node_modules/optimist/readme.markdown | 487 + .../uglify-js/node_modules/optimist/test/_.js | 71 + .../node_modules/optimist/test/_/argv.js | 2 + .../node_modules/optimist/test/_/bin.js | 3 + .../node_modules/optimist/test/parse.js | 446 + .../node_modules/optimist/test/usage.js | 292 + .../node_modules/source-map/.npmignore | 2 + .../node_modules/source-map/.travis.yml | 4 + .../node_modules/source-map/CHANGELOG.md | 75 + .../uglify-js/node_modules/source-map/LICENSE | 28 + .../source-map/Makefile.dryice.js | 166 + .../node_modules/source-map/README.md | 347 + .../source-map/build/assert-shim.js | 56 + .../source-map/build/mini-require.js | 152 + .../source-map/build/prefix-source-map.jsm | 20 + .../source-map/build/prefix-utils.jsm | 18 + .../source-map/build/suffix-browser.js | 8 + .../source-map/build/suffix-source-map.jsm | 6 + .../source-map/build/suffix-utils.jsm | 21 + .../source-map/build/test-prefix.js | 8 + .../source-map/build/test-suffix.js | 3 + .../node_modules/source-map/lib/source-map.js | 8 + .../source-map/lib/source-map/array-set.js | 96 + .../source-map/lib/source-map/base64-vlq.js | 144 + .../source-map/lib/source-map/base64.js | 42 + .../lib/source-map/binary-search.js | 81 + .../lib/source-map/source-map-consumer.js | 441 + .../lib/source-map/source-map-generator.js | 381 + .../source-map/lib/source-map/source-node.js | 353 + .../source-map/lib/source-map/util.js | 117 + .../source-map/node_modules/amdefine/LICENSE | 58 + .../node_modules/amdefine/README.md | 119 + .../node_modules/amdefine/amdefine.js | 299 + .../node_modules/amdefine/package.json | 37 + .../node_modules/source-map/package.json | 98 + .../node_modules/source-map/test/run-tests.js | 73 + .../source-map/test/source-map/test-api.js | 26 + .../test/source-map/test-array-set.js | 71 + .../test/source-map/test-base64-vlq.js | 24 + .../source-map/test/source-map/test-base64.js | 35 + .../test/source-map/test-binary-search.js | 54 + .../test/source-map/test-dog-fooding.js | 72 + .../source-map/test-source-map-consumer.js | 321 + .../source-map/test-source-map-generator.js | 391 + .../test/source-map/test-source-node.js | 301 + .../source-map/test/source-map/util.js | 160 + .../node_modules/uglify-js/package.json | 40 + .../uglify-js/test/compress/arrays.js | 12 + .../uglify-js/test/compress/blocks.js | 49 + .../uglify-js/test/compress/conditionals.js | 143 + .../uglify-js/test/compress/dead-code.js | 89 + .../uglify-js/test/compress/debugger.js | 24 + .../uglify-js/test/compress/drop-unused.js | 97 + .../uglify-js/test/compress/issue-105.js | 25 + .../uglify-js/test/compress/issue-12.js | 11 + .../uglify-js/test/compress/issue-143.js | 48 + .../uglify-js/test/compress/issue-22.js | 17 + .../uglify-js/test/compress/issue-44.js | 31 + .../uglify-js/test/compress/issue-59.js | 30 + .../uglify-js/test/compress/labels.js | 163 + .../uglify-js/test/compress/loops.js | 123 + .../uglify-js/test/compress/properties.js | 54 + .../uglify-js/test/compress/sequences.js | 161 + .../uglify-js/test/compress/switch.js | 260 + .../uglify-js/test/compress/typeof.js | 25 + .../node_modules/uglify-js/test/run-tests.js | 170 + .../node_modules/uglify-js/tools/node.js | 165 + .../node_modules/constantinople/package.json | 31 + .../node_modules/constantinople/test/index.js | 51 + .../jade/node_modules/mkdirp/.npmignore | 2 + .../jade/node_modules/mkdirp/.travis.yml | 5 + node_modules/jade/node_modules/mkdirp/LICENSE | 21 + .../jade/node_modules/mkdirp/examples/pow.js | 6 + .../jade/node_modules/mkdirp/index.js | 82 + .../jade/node_modules/mkdirp/package.json | 34 + .../jade/node_modules/mkdirp/readme.markdown | 63 + .../jade/node_modules/mkdirp/test/chmod.js | 38 + .../jade/node_modules/mkdirp/test/clobber.js | 37 + .../jade/node_modules/mkdirp/test/mkdirp.js | 28 + .../jade/node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 39 + .../jade/node_modules/mkdirp/test/race.js | 41 + .../jade/node_modules/mkdirp/test/rel.js | 32 + .../jade/node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../jade/node_modules/mkdirp/test/root.js | 18 + .../jade/node_modules/mkdirp/test/sync.js | 32 + .../jade/node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + .../jade/node_modules/monocle/.npmignore | 2 + .../jade/node_modules/monocle/.travis.yml | 5 + .../jade/node_modules/monocle/LICENSE | 23 + .../jade/node_modules/monocle/README.md | 67 + .../jade/node_modules/monocle/logo.png | Bin 0 -> 25575 bytes .../jade/node_modules/monocle/monocle.js | 142 + .../monocle/node_modules/readdirp/.npmignore | 15 + .../monocle/node_modules/readdirp/.travis.yml | 5 + .../monocle/node_modules/readdirp/LICENSE | 18 + .../monocle/node_modules/readdirp/README.md | 227 + .../node_modules/readdirp/examples/Readme.md | 37 + .../readdirp/examples/callback-api.js | 10 + .../node_modules/readdirp/examples/grep.js | 73 + .../node_modules/event-stream/.npmignore | 3 + .../node_modules/event-stream/.travis.yml | 4 + .../node_modules/event-stream/LICENCE | 22 + .../event-stream/examples/pretty.js | 25 + .../node_modules/event-stream/index.js | 341 + .../node_modules/duplexer/.npmignore | 3 + .../node_modules/duplexer/.travis.yml | 3 + .../node_modules/duplexer/LICENCE | 19 + .../node_modules/duplexer/Makefile | 4 + .../node_modules/duplexer/README.md | 36 + .../node_modules/duplexer/index.js | 87 + .../node_modules/duplexer/package.json | 41 + .../node_modules/duplexer/test.js | 27 + .../node_modules/from/LICENSE.APACHE2 | 15 + .../node_modules/from/LICENSE.MIT | 24 + .../event-stream/node_modules/from/index.js | 62 + .../node_modules/from/package.json | 33 + .../node_modules/from/readme.markdown | 6 + .../node_modules/from/test/index.js | 141 + .../node_modules/map-stream/.npmignore | 3 + .../node_modules/map-stream/.travis.yml | 4 + .../node_modules/map-stream/LICENCE | 22 + .../map-stream/examples/pretty.js | 25 + .../node_modules/map-stream/index.js | 105 + .../node_modules/map-stream/package.json | 30 + .../node_modules/map-stream/readme.markdown | 35 + .../map-stream/test/simple-map.asynct.js | 295 + .../node_modules/optimist/.npmignore | 4 + .../node_modules/optimist/LICENSE | 21 + .../node_modules/optimist/README.markdown | 474 + .../node_modules/optimist/examples/bool.js | 10 + .../optimist/examples/boolean_double.js | 7 + .../optimist/examples/boolean_single.js | 7 + .../optimist/examples/default_hash.js | 8 + .../optimist/examples/default_singles.js | 7 + .../node_modules/optimist/examples/divide.js | 8 + .../optimist/examples/line_count.js | 20 + .../optimist/examples/line_count_options.js | 29 + .../optimist/examples/line_count_wrap.js | 29 + .../node_modules/optimist/examples/nonopt.js | 4 + .../node_modules/optimist/examples/reflect.js | 2 + .../node_modules/optimist/examples/short.js | 3 + .../node_modules/optimist/examples/string.js | 11 + .../optimist/examples/usage-options.js | 19 + .../node_modules/optimist/examples/xup.js | 10 + .../node_modules/optimist/index.js | 457 + .../optimist/node_modules/wordwrap/.npmignore | 1 + .../node_modules/wordwrap/README.markdown | 70 + .../node_modules/wordwrap/example/center.js | 10 + .../node_modules/wordwrap/example/meat.js | 3 + .../optimist/node_modules/wordwrap/index.js | 76 + .../node_modules/wordwrap/package.json | 40 + .../node_modules/wordwrap/test/break.js | 30 + .../node_modules/wordwrap/test/idleness.txt | 63 + .../node_modules/wordwrap/test/wrap.js | 31 + .../node_modules/optimist/package.json | 46 + .../node_modules/optimist/test/_.js | 66 + .../node_modules/optimist/test/_/argv.js | 2 + .../node_modules/optimist/test/_/bin.js | 3 + .../node_modules/optimist/test/parse.js | 304 + .../node_modules/optimist/test/usage.js | 256 + .../node_modules/pause-stream/.npmignore | 3 + .../node_modules/pause-stream/index.js | 76 + .../node_modules/pause-stream/package.json | 38 + .../node_modules/pause-stream/readme.markdown | 24 + .../node_modules/pause-stream/test/index.js | 17 + .../pause-stream/test/pause-end.js | 33 + .../node_modules/split/.npmignore | 3 + .../node_modules/split/.travis.yml | 4 + .../event-stream/node_modules/split/LICENCE | 22 + .../node_modules/split/examples/pretty.js | 25 + .../event-stream/node_modules/split/index.js | 35 + .../split/node_modules/through/.travis.yml | 4 + .../node_modules/through/LICENSE.APACHE2 | 15 + .../split/node_modules/through/LICENSE.MIT | 24 + .../split/node_modules/through/index.js | 65 + .../split/node_modules/through/package.json | 29 + .../node_modules/through/readme.markdown | 26 + .../split/node_modules/through/test/index.js | 113 + .../node_modules/split/package.json | 35 + .../node_modules/split/readme.markdown | 20 + .../node_modules/split/test/split.asynct.js | 47 + .../node_modules/through/.travis.yml | 4 + .../node_modules/through/LICENSE.APACHE2 | 15 + .../node_modules/through/LICENSE.MIT | 24 + .../node_modules/through/index.js | 100 + .../node_modules/through/package.json | 34 + .../node_modules/through/readme.markdown | 44 + .../node_modules/through/test/buffering.js | 37 + .../node_modules/through/test/end.js | 27 + .../node_modules/through/test/index.js | 113 + .../node_modules/event-stream/package.json | 40 + .../node_modules/event-stream/readme.markdown | 286 + .../event-stream/test/connect.asynct.js | 82 + .../event-stream/test/merge.asynct.js | 20 + .../event-stream/test/pause.asynct.js | 38 + .../event-stream/test/pipeline.asynct.js | 51 + .../event-stream/test/readArray.asynct.js | 88 + .../event-stream/test/readable.asynct.js | 167 + .../event-stream/test/replace.asynct.js | 50 + .../event-stream/test/simple-map.asynct.js | 342 + .../event-stream/test/spec.asynct.js | 85 + .../event-stream/test/split.asynct.js | 46 + .../event-stream/test/stringify.js | 14 + .../event-stream/test/writeArray.asynct.js | 30 + .../node_modules/tap-stream/.npmignore | 1 + .../node_modules/tap-stream/.travis.yml | 5 + .../node_modules/tap-stream/README.md | 98 + .../tap-stream/examples/tap-nested-objects.js | 38 + .../examples/node_modules/tap-stream/index.js | 56 + .../node_modules/through/.travis.yml | 4 + .../node_modules/through/LICENSE.APACHE2 | 15 + .../node_modules/through/LICENSE.MIT | 24 + .../tap-stream/node_modules/through/index.js | 100 + .../node_modules/through/package.json | 34 + .../node_modules/through/readme.markdown | 44 + .../node_modules/through/test/buffering.js | 37 + .../node_modules/through/test/end.js | 27 + .../node_modules/through/test/index.js | 113 + .../node_modules/tap-stream/package.json | 38 + .../tap-stream/test/tap-stream.js | 104 + .../readdirp/examples/package.json | 9 + .../readdirp/examples/stream-api-pipe.js | 13 + .../readdirp/examples/stream-api.js | 15 + .../readdirp/node_modules/minimatch/LICENSE | 23 + .../readdirp/node_modules/minimatch/README.md | 218 + .../node_modules/minimatch/minimatch.js | 1079 + .../node_modules/lru-cache/.npmignore | 1 + .../minimatch/node_modules/lru-cache/AUTHORS | 8 + .../minimatch/node_modules/lru-cache/LICENSE | 23 + .../node_modules/lru-cache/README.md | 97 + .../node_modules/lru-cache/lib/lru-cache.js | 257 + .../node_modules/lru-cache/package.json | 63 + .../minimatch/node_modules/lru-cache/s.js | 25 + .../node_modules/lru-cache/test/basic.js | 329 + .../node_modules/lru-cache/test/foreach.js | 52 + .../lru-cache/test/memory-leak.js | 50 + .../minimatch/node_modules/sigmund/LICENSE | 27 + .../minimatch/node_modules/sigmund/README.md | 53 + .../minimatch/node_modules/sigmund/bench.js | 283 + .../node_modules/sigmund/package.json | 42 + .../minimatch/node_modules/sigmund/sigmund.js | 39 + .../node_modules/sigmund/test/basic.js | 24 + .../node_modules/minimatch/package.json | 40 + .../node_modules/minimatch/test/basic.js | 399 + .../minimatch/test/brace-expand.js | 33 + .../node_modules/minimatch/test/caching.js | 14 + .../node_modules/minimatch/test/defaults.js | 274 + .../node_modules/readdirp/package.json | 50 + .../monocle/node_modules/readdirp/readdirp.js | 276 + .../node_modules/readdirp/stream-api.js | 86 + .../test/bed/root_dir1/root_dir1_file1.ext1 | 0 .../test/bed/root_dir1/root_dir1_file2.ext2 | 0 .../test/bed/root_dir1/root_dir1_file3.ext3 | 0 .../root1_dir1_subdir1_file1.ext1 | 0 .../test/bed/root_dir2/root_dir2_file1.ext1 | 0 .../test/bed/root_dir2/root_dir2_file2.ext2 | 0 .../readdirp/test/bed/root_file1.ext1 | 0 .../readdirp/test/bed/root_file2.ext2 | 0 .../readdirp/test/bed/root_file3.ext3 | 0 .../readdirp/test/readdirp-stream.js | 215 + .../node_modules/readdirp/test/readdirp.js | 252 + .../jade/node_modules/monocle/package.json | 43 + .../monocle/test/sample_files/creation3.txt | 1 + .../monocle/test/sample_files/creation4.txt | 1 + .../monocle/test/sample_files/creation5.txt | 1 + .../monocle/test/sample_files/foo.txt | 1 + .../monocle/test/sample_files/longbow.js | 1 + .../test/sample_files/nestedDir/servent.txt | 1 + .../monocle/test/sample_files/zap.bat | 31 + .../jade/node_modules/monocle/test/tester.js | 180 + .../jade/node_modules/transformers/.npmignore | 15 + .../node_modules/transformers/.travis.yml | 3 + .../jade/node_modules/transformers/README.md | 138 + .../jade/node_modules/transformers/history.md | 69 + .../node_modules/transformers/lib/shared.js | 162 + .../transformers/lib/transformers.js | 575 + .../transformers/node_modules/.bin/uglifyjs | 1 + .../transformers/node_modules/css/.npmignore | 4 + .../transformers/node_modules/css/History.md | 20 + .../transformers/node_modules/css/Makefile | 8 + .../transformers/node_modules/css/Readme.md | 77 + .../node_modules/css/benchmark.js | 36 + .../node_modules/css/component.json | 13 + .../transformers/node_modules/css/index.js | 3 + .../css/node_modules/css-parse/.npmignore | 6 + .../css/node_modules/css-parse/History.md | 30 + .../css/node_modules/css-parse/Makefile | 7 + .../css/node_modules/css-parse/Readme.md | 62 + .../css/node_modules/css-parse/component.json | 8 + .../css/node_modules/css-parse/index.js | 265 + .../css/node_modules/css-parse/package.json | 27 + .../css/node_modules/css-stringify/.npmignore | 6 + .../css/node_modules/css-stringify/History.md | 30 + .../css/node_modules/css-stringify/Makefile | 7 + .../css/node_modules/css-stringify/Readme.md | 33 + .../node_modules/css-stringify/component.json | 8 + .../css/node_modules/css-stringify/index.js | 182 + .../node_modules/css-stringify/package.json | 28 + .../node_modules/css/package.json | 27 + .../transformers/node_modules/css/test.js | 6 + .../node_modules/promise/.npmignore | 6 + .../node_modules/promise/Readme.md | 85 + .../node_modules/promise/index.js | 164 + .../node_modules/is-promise/.npmignore | 6 + .../promise/node_modules/is-promise/index.js | 5 + .../node_modules/is-promise/package.json | 29 + .../promise/node_modules/is-promise/readme.md | 29 + .../node_modules/promise/package.json | 33 + .../node_modules/uglify-js/.npmignore | 2 + .../node_modules/uglify-js/README.md | 544 + .../node_modules/uglify-js/bin/uglifyjs | 370 + .../node_modules/uglify-js/lib/ast.js | 964 + .../node_modules/uglify-js/lib/compress.js | 1968 + .../node_modules/uglify-js/lib/mozilla-ast.js | 265 + .../node_modules/uglify-js/lib/output.js | 1220 + .../node_modules/uglify-js/lib/parse.js | 1407 + .../node_modules/uglify-js/lib/scope.js | 580 + .../node_modules/uglify-js/lib/sourcemap.js | 81 + .../node_modules/uglify-js/lib/transform.js | 218 + .../node_modules/uglify-js/lib/utils.js | 288 + .../node_modules/optimist/.travis.yml | 4 + .../uglify-js/node_modules/optimist/LICENSE | 21 + .../node_modules/optimist/example/bool.js | 10 + .../optimist/example/boolean_double.js | 7 + .../optimist/example/boolean_single.js | 7 + .../optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + .../node_modules/optimist/example/divide.js | 8 + .../optimist/example/line_count.js | 20 + .../optimist/example/line_count_options.js | 29 + .../optimist/example/line_count_wrap.js | 29 + .../node_modules/optimist/example/nonopt.js | 4 + .../node_modules/optimist/example/reflect.js | 2 + .../node_modules/optimist/example/short.js | 3 + .../node_modules/optimist/example/string.js | 11 + .../optimist/example/usage-options.js | 19 + .../node_modules/optimist/example/xup.js | 10 + .../uglify-js/node_modules/optimist/index.js | 478 + .../optimist/node_modules/wordwrap/.npmignore | 1 + .../node_modules/wordwrap/README.markdown | 70 + .../node_modules/wordwrap/example/center.js | 10 + .../node_modules/wordwrap/example/meat.js | 3 + .../optimist/node_modules/wordwrap/index.js | 76 + .../node_modules/wordwrap/package.json | 45 + .../node_modules/wordwrap/test/break.js | 30 + .../node_modules/wordwrap/test/idleness.txt | 63 + .../node_modules/wordwrap/test/wrap.js | 31 + .../node_modules/optimist/package.json | 46 + .../node_modules/optimist/readme.markdown | 487 + .../uglify-js/node_modules/optimist/test/_.js | 71 + .../node_modules/optimist/test/_/argv.js | 2 + .../node_modules/optimist/test/_/bin.js | 3 + .../node_modules/optimist/test/parse.js | 446 + .../node_modules/optimist/test/usage.js | 292 + .../node_modules/source-map/.npmignore | 2 + .../node_modules/source-map/.travis.yml | 4 + .../node_modules/source-map/CHANGELOG.md | 75 + .../uglify-js/node_modules/source-map/LICENSE | 28 + .../source-map/Makefile.dryice.js | 166 + .../node_modules/source-map/README.md | 347 + .../source-map/build/assert-shim.js | 56 + .../source-map/build/mini-require.js | 152 + .../source-map/build/prefix-source-map.jsm | 20 + .../source-map/build/prefix-utils.jsm | 18 + .../source-map/build/suffix-browser.js | 8 + .../source-map/build/suffix-source-map.jsm | 6 + .../source-map/build/suffix-utils.jsm | 21 + .../source-map/build/test-prefix.js | 8 + .../source-map/build/test-suffix.js | 3 + .../node_modules/source-map/lib/source-map.js | 8 + .../source-map/lib/source-map/array-set.js | 96 + .../source-map/lib/source-map/base64-vlq.js | 144 + .../source-map/lib/source-map/base64.js | 42 + .../lib/source-map/binary-search.js | 81 + .../lib/source-map/source-map-consumer.js | 441 + .../lib/source-map/source-map-generator.js | 381 + .../source-map/lib/source-map/source-node.js | 353 + .../source-map/lib/source-map/util.js | 117 + .../source-map/node_modules/amdefine/LICENSE | 58 + .../node_modules/amdefine/README.md | 119 + .../node_modules/amdefine/amdefine.js | 299 + .../node_modules/amdefine/package.json | 37 + .../node_modules/source-map/package.json | 98 + .../node_modules/source-map/test/run-tests.js | 73 + .../source-map/test/source-map/test-api.js | 26 + .../test/source-map/test-array-set.js | 71 + .../test/source-map/test-base64-vlq.js | 24 + .../source-map/test/source-map/test-base64.js | 35 + .../test/source-map/test-binary-search.js | 54 + .../test/source-map/test-dog-fooding.js | 72 + .../source-map/test-source-map-consumer.js | 321 + .../source-map/test-source-map-generator.js | 391 + .../test/source-map/test-source-node.js | 301 + .../source-map/test/source-map/util.js | 160 + .../node_modules/uglify-js/package.json | 41 + .../uglify-js/test/compress/arrays.js | 12 + .../uglify-js/test/compress/blocks.js | 49 + .../uglify-js/test/compress/conditionals.js | 143 + .../uglify-js/test/compress/dead-code.js | 89 + .../uglify-js/test/compress/debugger.js | 24 + .../uglify-js/test/compress/drop-unused.js | 97 + .../uglify-js/test/compress/issue-105.js | 17 + .../uglify-js/test/compress/issue-12.js | 11 + .../uglify-js/test/compress/issue-22.js | 17 + .../uglify-js/test/compress/issue-44.js | 31 + .../uglify-js/test/compress/issue-59.js | 30 + .../uglify-js/test/compress/labels.js | 163 + .../uglify-js/test/compress/loops.js | 123 + .../uglify-js/test/compress/properties.js | 25 + .../uglify-js/test/compress/sequences.js | 161 + .../uglify-js/test/compress/switch.js | 210 + .../node_modules/uglify-js/test/run-tests.js | 170 + .../node_modules/uglify-js/tools/node.js | 164 + .../node_modules/transformers/package.json | 77 + .../test/fixtures/component/build/build.css | 6 + .../test/fixtures/component/build/build.js | 1235 + .../test/fixtures/component/component.json | 8 + .../component-classes/component.json | 19 + .../components/component-classes/index.js | 164 + .../component-delegate/component.json | 19 + .../components/component-delegate/index.js | 42 + .../components/component-dom/component.json | 27 + .../components/component-dom/index.js | 579 + .../component-domify/component.json | 20 + .../components/component-domify/index.js | 79 + .../components/component-event/component.json | 13 + .../components/component-event/index.js | 40 + .../component-indexof/component.json | 15 + .../components/component-indexof/index.js | 10 + .../component-matches-selector/component.json | 17 + .../component-matches-selector/index.js | 40 + .../components/component-type/component.json | 15 + .../components/component-type/index.js | 31 + .../test/fixtures/component/index.css | 3 + .../test/fixtures/component/index.js | 1 + .../test/fixtures/component/second.css | 3 + .../test/fixtures/uglify-js/script.js | 6 + .../test/simple/atpl/sample-a.txt | 1 + .../test/simple/atpl/sample-b.txt | 1 + .../test/simple/cdata/sample-a-expected.txt | 3 + .../test/simple/cdata/sample-a.txt | 1 + .../test/simple/cdata/sample-b-expected.txt | 3 + .../test/simple/cdata/sample-b.txt | 1 + .../coffee-script/sample-a-expected.txt | 6 + .../test/simple/coffee-script/sample-a.txt | 1 + .../coffee-script/sample-b-expected.txt | 6 + .../test/simple/coffee-script/sample-b.txt | 1 + .../simple/coffeecup/sample-a-expected.txt | 1 + .../test/simple/coffeecup/sample-a.txt | 3 + .../simple/coffeecup/sample-b-expected.txt | 1 + .../test/simple/coffeecup/sample-b.txt | 3 + .../test/simple/cson/sample-a-expected.txt | 1 + .../test/simple/cson/sample-a.txt | 9 + .../test/simple/cson/sample-b-expected.txt | 1 + .../test/simple/cson/sample-b.txt | 9 + .../transformers/test/simple/dot/sample-a.txt | 1 + .../transformers/test/simple/dot/sample-b.txt | 1 + .../test/simple/dust/sample-a.txt | 1 + .../test/simple/dust/sample-b.txt | 1 + .../transformers/test/simple/eco/sample-a.txt | 1 + .../transformers/test/simple/eco/sample-b.txt | 1 + .../transformers/test/simple/ect/sample-a.txt | 1 + .../transformers/test/simple/ect/sample-b.txt | 1 + .../transformers/test/simple/ejs/sample-a.txt | 1 + .../transformers/test/simple/ejs/sample-b.txt | 1 + .../test/simple/haml-coffee/sample-a.txt | 1 + .../test/simple/haml-coffee/sample-b.txt | 1 + .../test/simple/haml/sample-a-expected.txt | 2 + .../test/simple/haml/sample-a.txt | 1 + .../test/simple/haml/sample-b-expected.txt | 2 + .../test/simple/haml/sample-b.txt | 1 + .../test/simple/handlebars/sample-a.txt | 1 + .../test/simple/handlebars/sample-b.txt | 1 + .../test/simple/hogan/sample-a.txt | 1 + .../test/simple/hogan/sample-b.txt | 1 + .../simple/html2jade/sample-a-expected.txt | 7 + .../test/simple/html2jade/sample-a.txt | 10 + .../simple/html2jade/sample-b-expected.txt | 7 + .../test/simple/html2jade/sample-b.txt | 10 + .../test/simple/jade/sample-a.txt | 1 + .../test/simple/jade/sample-b.txt | 1 + .../test/simple/jazz/sample-a.txt | 1 + .../test/simple/jazz/sample-b.txt | 1 + .../test/simple/jqtpl/sample-a.txt | 1 + .../test/simple/jqtpl/sample-b.txt | 1 + .../test/simple/just/sample-a.txt | 1 + .../test/simple/just/sample-b.txt | 1 + .../test/simple/less/sample-a-expected.txt | 27 + .../test/simple/less/sample-a.txt | 54 + .../test/simple/less/sample-b-expected.txt | 27 + .../test/simple/less/sample-b.txt | 54 + .../test/simple/liquor/sample-a.txt | 1 + .../test/simple/liquor/sample-b.txt | 1 + .../simple/markdown/sample-a-expected.txt | 6 + .../test/simple/markdown/sample-a.txt | 6 + .../simple/markdown/sample-b-expected.txt | 6 + .../test/simple/markdown/sample-b.txt | 6 + .../test/simple/mote/sample-a.txt | 1 + .../test/simple/mote/sample-b.txt | 1 + .../test/simple/mustache/sample-a.txt | 1 + .../test/simple/mustache/sample-b.txt | 1 + .../test/simple/plates/sample-a-expected.txt | 1 + .../test/simple/plates/sample-a.txt | 1 + .../test/simple/plates/sample-b-expected.txt | 1 + .../test/simple/plates/sample-b.txt | 1 + .../test/simple/qejs/sample-a.txt | 1 + .../test/simple/qejs/sample-b.txt | 1 + .../test/simple/sass/sample-a-expected.txt | 8 + .../test/simple/sass/sample-a.txt | 11 + .../test/simple/sass/sample-b-expected.txt | 8 + .../test/simple/sass/sample-b.txt | 11 + .../test/simple/stylus/sample-a-expected.txt | 8 + .../test/simple/stylus/sample-a.txt | 10 + .../test/simple/stylus/sample-b-expected.txt | 8 + .../test/simple/stylus/sample-b.txt | 10 + .../test/simple/swig/sample-a.txt | 1 + .../test/simple/swig/sample-b.txt | 1 + .../test/simple/templayed/sample-a.txt | 1 + .../test/simple/templayed/sample-b.txt | 1 + .../test/simple/toffee/sample-a.txt | 1 + .../test/simple/toffee/sample-b.txt | 1 + .../simple/uglify-css/sample-a-expected.txt | 1 + .../test/simple/uglify-css/sample-a.txt | 3 + .../simple/uglify-css/sample-b-expected.txt | 1 + .../test/simple/uglify-css/sample-b.txt | 3 + .../simple/uglify-json/sample-a-expected.txt | 1 + .../test/simple/uglify-json/sample-a.txt | 3 + .../simple/uglify-json/sample-b-expected.txt | 1 + .../test/simple/uglify-json/sample-b.txt | 5 + .../test/simple/underscore/sample-a.txt | 1 + .../test/simple/underscore/sample-b.txt | 1 + .../test/simple/walrus/sample-a.txt | 1 + .../test/simple/walrus/sample-b.txt | 1 + .../test/simple/whiskers/sample-a.txt | 1 + .../test/simple/whiskers/sample-b.txt | 1 + .../node_modules/transformers/test/test.js | 123 + .../transformers/test/update-package.js | 13 + .../jade/node_modules/with/.npmignore | 16 + .../jade/node_modules/with/.travis.yml | 4 + node_modules/jade/node_modules/with/README.md | 55 + node_modules/jade/node_modules/with/index.js | 40 + .../with/node_modules/.bin/uglifyjs | 1 + .../with/node_modules/uglify-js/.npmignore | 2 + .../with/node_modules/uglify-js/.travis.yml | 7 + .../with/node_modules/uglify-js/LICENSE | 29 + .../with/node_modules/uglify-js/README.md | 588 + .../with/node_modules/uglify-js/bin/uglifyjs | 402 + .../with/node_modules/uglify-js/lib/ast.js | 985 + .../node_modules/uglify-js/lib/compress.js | 2028 + .../node_modules/uglify-js/lib/mozilla-ast.js | 267 + .../with/node_modules/uglify-js/lib/output.js | 1229 + .../with/node_modules/uglify-js/lib/parse.js | 1410 + .../with/node_modules/uglify-js/lib/scope.js | 581 + .../node_modules/uglify-js/lib/sourcemap.js | 81 + .../node_modules/uglify-js/lib/transform.js | 217 + .../with/node_modules/uglify-js/lib/utils.js | 295 + .../node_modules/optimist/.travis.yml | 4 + .../uglify-js/node_modules/optimist/LICENSE | 21 + .../node_modules/optimist/example/bool.js | 10 + .../optimist/example/boolean_double.js | 7 + .../optimist/example/boolean_single.js | 7 + .../optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + .../node_modules/optimist/example/divide.js | 8 + .../optimist/example/line_count.js | 20 + .../optimist/example/line_count_options.js | 29 + .../optimist/example/line_count_wrap.js | 29 + .../node_modules/optimist/example/nonopt.js | 4 + .../node_modules/optimist/example/reflect.js | 2 + .../node_modules/optimist/example/short.js | 3 + .../node_modules/optimist/example/string.js | 11 + .../optimist/example/usage-options.js | 19 + .../node_modules/optimist/example/xup.js | 10 + .../uglify-js/node_modules/optimist/index.js | 478 + .../optimist/node_modules/wordwrap/.npmignore | 1 + .../node_modules/wordwrap/README.markdown | 70 + .../node_modules/wordwrap/example/center.js | 10 + .../node_modules/wordwrap/example/meat.js | 3 + .../optimist/node_modules/wordwrap/index.js | 76 + .../node_modules/wordwrap/package.json | 45 + .../node_modules/wordwrap/test/break.js | 30 + .../node_modules/wordwrap/test/idleness.txt | 63 + .../node_modules/wordwrap/test/wrap.js | 31 + .../node_modules/optimist/package.json | 46 + .../node_modules/optimist/readme.markdown | 487 + .../uglify-js/node_modules/optimist/test/_.js | 71 + .../node_modules/optimist/test/_/argv.js | 2 + .../node_modules/optimist/test/_/bin.js | 3 + .../node_modules/optimist/test/parse.js | 446 + .../node_modules/optimist/test/usage.js | 292 + .../node_modules/source-map/.npmignore | 2 + .../node_modules/source-map/.travis.yml | 4 + .../node_modules/source-map/CHANGELOG.md | 75 + .../uglify-js/node_modules/source-map/LICENSE | 28 + .../source-map/Makefile.dryice.js | 166 + .../node_modules/source-map/README.md | 347 + .../source-map/build/assert-shim.js | 56 + .../source-map/build/mini-require.js | 152 + .../source-map/build/prefix-source-map.jsm | 20 + .../source-map/build/prefix-utils.jsm | 18 + .../source-map/build/suffix-browser.js | 8 + .../source-map/build/suffix-source-map.jsm | 6 + .../source-map/build/suffix-utils.jsm | 21 + .../source-map/build/test-prefix.js | 8 + .../source-map/build/test-suffix.js | 3 + .../node_modules/source-map/lib/source-map.js | 8 + .../source-map/lib/source-map/array-set.js | 96 + .../source-map/lib/source-map/base64-vlq.js | 144 + .../source-map/lib/source-map/base64.js | 42 + .../lib/source-map/binary-search.js | 81 + .../lib/source-map/source-map-consumer.js | 441 + .../lib/source-map/source-map-generator.js | 381 + .../source-map/lib/source-map/source-node.js | 353 + .../source-map/lib/source-map/util.js | 117 + .../source-map/node_modules/amdefine/LICENSE | 58 + .../node_modules/amdefine/README.md | 119 + .../node_modules/amdefine/amdefine.js | 299 + .../node_modules/amdefine/package.json | 37 + .../node_modules/source-map/package.json | 98 + .../node_modules/source-map/test/run-tests.js | 73 + .../source-map/test/source-map/test-api.js | 26 + .../test/source-map/test-array-set.js | 71 + .../test/source-map/test-base64-vlq.js | 24 + .../source-map/test/source-map/test-base64.js | 35 + .../test/source-map/test-binary-search.js | 54 + .../test/source-map/test-dog-fooding.js | 72 + .../source-map/test-source-map-consumer.js | 321 + .../source-map/test-source-map-generator.js | 391 + .../test/source-map/test-source-node.js | 301 + .../source-map/test/source-map/util.js | 160 + .../with/node_modules/uglify-js/package.json | 40 + .../uglify-js/test/compress/arrays.js | 12 + .../uglify-js/test/compress/blocks.js | 49 + .../uglify-js/test/compress/conditionals.js | 143 + .../uglify-js/test/compress/dead-code.js | 89 + .../uglify-js/test/compress/debugger.js | 24 + .../uglify-js/test/compress/drop-unused.js | 97 + .../uglify-js/test/compress/issue-105.js | 25 + .../uglify-js/test/compress/issue-12.js | 11 + .../uglify-js/test/compress/issue-143.js | 48 + .../uglify-js/test/compress/issue-22.js | 17 + .../uglify-js/test/compress/issue-44.js | 31 + .../uglify-js/test/compress/issue-59.js | 30 + .../uglify-js/test/compress/labels.js | 163 + .../uglify-js/test/compress/loops.js | 123 + .../uglify-js/test/compress/properties.js | 54 + .../uglify-js/test/compress/sequences.js | 161 + .../uglify-js/test/compress/switch.js | 260 + .../uglify-js/test/compress/typeof.js | 25 + .../node_modules/uglify-js/test/run-tests.js | 170 + .../with/node_modules/uglify-js/tools/node.js | 165 + .../jade/node_modules/with/package.json | 31 + .../jade/node_modules/with/test/index.js | 107 + node_modules/jade/package.json | 65 + node_modules/jade/runtime.js | 208 + node_modules/less/.gitattributes | 9 + node_modules/less/.npmignore | 0 node_modules/less/CHANGELOG.md | 177 + node_modules/less/CONTRIBUTING.md | 49 + node_modules/less/LICENSE | 179 + node_modules/less/Makefile | 102 + node_modules/less/README.md | 20 + node_modules/less/benchmark/benchmark.less | 3979 + node_modules/less/benchmark/less-benchmark.js | 47 + node_modules/less/bin/lessc | 267 + node_modules/less/build/amd.js | 6 + node_modules/less/build/header.js | 9 + node_modules/less/build/require-rhino.js | 7 + node_modules/less/build/require.js | 7 + node_modules/less/dist/less-1.1.0.js | 2695 + node_modules/less/dist/less-1.1.0.min.js | 16 + node_modules/less/dist/less-1.1.1.js | 2710 + node_modules/less/dist/less-1.1.1.min.js | 16 + node_modules/less/dist/less-1.1.2.js | 2712 + node_modules/less/dist/less-1.1.2.min.js | 16 + node_modules/less/dist/less-1.1.3.js | 2721 + node_modules/less/dist/less-1.1.3.min.js | 16 + node_modules/less/dist/less-1.1.4.js | 2769 + node_modules/less/dist/less-1.1.4.min.js | 16 + node_modules/less/dist/less-1.1.5.js | 2805 + node_modules/less/dist/less-1.1.5.min.js | 9 + node_modules/less/dist/less-1.1.6.js | 3004 + node_modules/less/dist/less-1.1.6.min.js | 9 + node_modules/less/dist/less-1.2.0.js | 3293 + node_modules/less/dist/less-1.2.0.min.js | 9 + node_modules/less/dist/less-1.2.1.js | 3318 + node_modules/less/dist/less-1.2.1.min.js | 9 + node_modules/less/dist/less-1.2.2.js | 3337 + node_modules/less/dist/less-1.2.2.min.js | 9 + node_modules/less/dist/less-1.3.0.js | 3478 + node_modules/less/dist/less-1.3.0.min.js | 9 + node_modules/less/dist/less-1.3.1.js | 4011 + node_modules/less/dist/less-1.3.1.min.js | 9 + node_modules/less/dist/less-1.3.2.js | 4401 + node_modules/less/dist/less-1.3.2.min.js | 9 + node_modules/less/dist/less-1.3.3.js | 4413 + node_modules/less/dist/less-1.3.3.min.js | 9 + node_modules/less/dist/less-1.4.0-beta.js | 5830 + node_modules/less/dist/less-1.4.0-beta.min.js | 11 + node_modules/less/dist/less-1.4.0.js | 5830 + node_modules/less/dist/less-1.4.0.min.js | 11 + node_modules/less/dist/less-1.4.1.js | 5837 + node_modules/less/dist/less-1.4.1.min.js | 11 + node_modules/less/dist/less-rhino-1.1.3.js | 2460 + node_modules/less/dist/less-rhino-1.1.5.js | 2481 + node_modules/less/dist/less-rhino-1.3.1.js | 3725 + node_modules/less/dist/less-rhino-1.3.2.js | 3990 + node_modules/less/dist/less-rhino-1.3.3.js | 4002 + node_modules/less/dist/less-rhino-1.4.0.js | 4273 + node_modules/less/lib/less/browser.js | 549 + node_modules/less/lib/less/colors.js | 152 + node_modules/less/lib/less/env.js | 105 + node_modules/less/lib/less/extend-visitor.js | 391 + node_modules/less/lib/less/functions.js | 532 + node_modules/less/lib/less/import-visitor.js | 107 + node_modules/less/lib/less/index.js | 223 + .../less/lib/less/join-selector-visitor.js | 37 + node_modules/less/lib/less/lessc_helper.js | 71 + node_modules/less/lib/less/parser.js | 1611 + node_modules/less/lib/less/rhino.js | 126 + node_modules/less/lib/less/tree.js | 45 + node_modules/less/lib/less/tree/alpha.js | 21 + node_modules/less/lib/less/tree/anonymous.js | 28 + node_modules/less/lib/less/tree/assignment.js | 23 + node_modules/less/lib/less/tree/call.js | 60 + node_modules/less/lib/less/tree/color.js | 156 + node_modules/less/lib/less/tree/comment.js | 15 + node_modules/less/lib/less/tree/condition.js | 49 + node_modules/less/lib/less/tree/dimension.js | 305 + node_modules/less/lib/less/tree/directive.js | 44 + node_modules/less/lib/less/tree/element.js | 85 + node_modules/less/lib/less/tree/expression.js | 48 + node_modules/less/lib/less/tree/extend.js | 43 + node_modules/less/lib/less/tree/import.js | 103 + node_modules/less/lib/less/tree/javascript.js | 52 + node_modules/less/lib/less/tree/keyword.js | 20 + node_modules/less/lib/less/tree/media.js | 137 + node_modules/less/lib/less/tree/mixin.js | 232 + node_modules/less/lib/less/tree/negative.js | 22 + node_modules/less/lib/less/tree/operation.js | 52 + node_modules/less/lib/less/tree/paren.js | 20 + node_modules/less/lib/less/tree/quoted.js | 45 + node_modules/less/lib/less/tree/rule.js | 62 + node_modules/less/lib/less/tree/ruleset.js | 441 + node_modules/less/lib/less/tree/selector.js | 62 + .../less/lib/less/tree/unicode-descriptor.js | 14 + node_modules/less/lib/less/tree/url.js | 31 + node_modules/less/lib/less/tree/value.js | 27 + node_modules/less/lib/less/tree/variable.js | 39 + node_modules/less/lib/less/visitor.js | 54 + node_modules/less/node_modules/.bin/ycssmin | 1 + node_modules/less/node_modules/mime/LICENSE | 19 + node_modules/less/node_modules/mime/README.md | 63 + node_modules/less/node_modules/mime/mime.js | 113 + .../less/node_modules/mime/package.json | 37 + node_modules/less/node_modules/mime/test.js | 55 + .../less/node_modules/mime/types/mime.types | 1588 + .../less/node_modules/mime/types/node.types | 60 + .../less/node_modules/mkdirp/.npmignore | 2 + .../less/node_modules/mkdirp/.travis.yml | 5 + node_modules/less/node_modules/mkdirp/LICENSE | 21 + .../less/node_modules/mkdirp/examples/pow.js | 6 + .../less/node_modules/mkdirp/index.js | 82 + .../less/node_modules/mkdirp/package.json | 34 + .../less/node_modules/mkdirp/readme.markdown | 63 + .../less/node_modules/mkdirp/test/chmod.js | 38 + .../less/node_modules/mkdirp/test/clobber.js | 37 + .../less/node_modules/mkdirp/test/mkdirp.js | 28 + .../less/node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 39 + .../less/node_modules/mkdirp/test/race.js | 41 + .../less/node_modules/mkdirp/test/rel.js | 32 + .../less/node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../less/node_modules/mkdirp/test/root.js | 18 + .../less/node_modules/mkdirp/test/sync.js | 32 + .../less/node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + .../less/node_modules/request/LICENSE | 55 + .../less/node_modules/request/README.md | 344 + .../less/node_modules/request/index.js | 1377 + .../request/node_modules/aws-sign/LICENSE | 55 + .../request/node_modules/aws-sign/README.md | 4 + .../request/node_modules/aws-sign/index.js | 202 + .../node_modules/aws-sign/package.json | 28 + .../request/node_modules/cookie-jar/LICENSE | 55 + .../request/node_modules/cookie-jar/README.md | 4 + .../request/node_modules/cookie-jar/index.js | 67 + .../request/node_modules/cookie-jar/jar.js | 72 + .../node_modules/cookie-jar/package.json | 31 + .../node_modules/cookie-jar/tests/run.js | 40 + .../cookie-jar/tests/test-cookie.js | 29 + .../cookie-jar/tests/test-cookiejar.js | 90 + .../node_modules/forever-agent/LICENSE | 55 + .../node_modules/forever-agent/README.md | 4 + .../node_modules/forever-agent/index.js | 119 + .../node_modules/forever-agent/package.json | 28 + .../request/node_modules/form-data/.npmignore | 5 + .../node_modules/form-data/.travis.yml | 4 + .../request/node_modules/form-data/License | 19 + .../request/node_modules/form-data/Makefile | 7 + .../request/node_modules/form-data/Readme.md | 146 + .../node_modules/form-data/lib/form_data.js | 292 + .../form-data/node-form-data.sublime-project | 8 + .../node-form-data.sublime-workspace | 673 + .../node_modules/combined-stream/.npmignore | 3 + .../node_modules/combined-stream/License | 19 + .../node_modules/combined-stream/Makefile | 7 + .../node_modules/combined-stream/Readme.md | 132 + .../combined-stream/lib/combined_stream.js | 185 + .../node_modules/delayed-stream/.npmignore | 2 + .../node_modules/delayed-stream/License | 19 + .../node_modules/delayed-stream/Makefile | 7 + .../node_modules/delayed-stream/Readme.md | 154 + .../delayed-stream/lib/delayed_stream.js | 99 + .../node_modules/delayed-stream/package.json | 32 + .../delayed-stream/test/common.js | 6 + .../integration/test-delayed-http-upload.js | 38 + .../test-delayed-stream-auto-pause.js | 21 + .../integration/test-delayed-stream-pause.js | 14 + .../test/integration/test-delayed-stream.js | 48 + .../integration/test-handle-source-errors.js | 15 + .../test/integration/test-max-data-size.js | 18 + .../test/integration/test-pipe-resumes.js | 13 + .../test/integration/test-proxy-readable.js | 13 + .../node_modules/delayed-stream/test/run.js | 7 + .../node_modules/combined-stream/package.json | 33 + .../combined-stream/test/common.js | 23 + .../combined-stream/test/fixture/file1.txt | 256 + .../combined-stream/test/fixture/file2.txt | 256 + .../test/integration/test-callback-streams.js | 27 + .../test/integration/test-data-size.js | 34 + ...delayed-streams-and-buffers-and-strings.js | 38 + .../test/integration/test-delayed-streams.js | 35 + .../test/integration/test-empty-string.js | 39 + .../test/integration/test-is-stream-like.js | 17 + .../test/integration/test-max-data-size.js | 24 + .../test/integration/test-unpaused-streams.js | 30 + .../node_modules/combined-stream/test/run.js | 7 + .../node_modules/form-data/package.json | 40 + .../node_modules/form-data/sftp-config.json | 43 + .../node_modules/form-data/test/common.js | 14 + .../form-data/test/fixture/bacon.txt | 1 + .../form-data/test/fixture/unicycle.jpg | Bin 0 -> 19806 bytes .../test/integration/test-custom-filename.js | 52 + .../test/integration/test-custom-headers.js | 75 + .../test/integration/test-form-get-length.js | 93 + .../test/integration/test-get-boundary.js | 18 + .../test/integration/test-http-response.js | 83 + .../form-data/test/integration/test-pipe.js | 73 + .../test/integration/test-submit-custom.js | 77 + .../form-data/test/integration/test-submit.js | 73 + .../node_modules/form-data/test/run.js | 7 + .../request/node_modules/hawk/.npmignore | 18 + .../request/node_modules/hawk/.travis.yml | 5 + .../request/node_modules/hawk/LICENSE | 24 + .../request/node_modules/hawk/Makefile | 11 + .../request/node_modules/hawk/README.md | 620 + .../node_modules/hawk/example/usage.js | 78 + .../request/node_modules/hawk/images/hawk.png | Bin 0 -> 6945 bytes .../request/node_modules/hawk/images/logo.png | Bin 0 -> 71732 bytes .../request/node_modules/hawk/index.js | 1 + .../request/node_modules/hawk/lib/browser.js | 430 + .../request/node_modules/hawk/lib/client.js | 285 + .../request/node_modules/hawk/lib/crypto.js | 111 + .../request/node_modules/hawk/lib/index.js | 15 + .../request/node_modules/hawk/lib/server.js | 424 + .../request/node_modules/hawk/lib/utils.js | 174 + .../hawk/node_modules/boom/.npmignore | 18 + .../hawk/node_modules/boom/.travis.yml | 5 + .../hawk/node_modules/boom/LICENSE | 24 + .../hawk/node_modules/boom/Makefile | 11 + .../hawk/node_modules/boom/README.md | 6 + .../hawk/node_modules/boom/images/boom.png | Bin 0 -> 29479 bytes .../hawk/node_modules/boom/index.js | 1 + .../hawk/node_modules/boom/lib/index.js | 207 + .../boom/node_modules/hoek/.npmignore | 18 + .../boom/node_modules/hoek/.travis.yml | 5 + .../boom/node_modules/hoek/LICENSE | 33 + .../boom/node_modules/hoek/Makefile | 10 + .../boom/node_modules/hoek/README.md | 436 + .../boom/node_modules/hoek/images/hoek.png | Bin 0 -> 37939 bytes .../boom/node_modules/hoek/index.js | 1 + .../boom/node_modules/hoek/lib/escape.js | 132 + .../boom/node_modules/hoek/lib/index.js | 585 + .../boom/node_modules/hoek/package.json | 49 + .../boom/node_modules/hoek/test/escaper.js | 86 + .../boom/node_modules/hoek/test/index.js | 1078 + .../node_modules/hoek/test/modules/test1.js | 1 + .../node_modules/hoek/test/modules/test2.js | 1 + .../node_modules/hoek/test/modules/test3.js | 1 + .../hawk/node_modules/boom/package.json | 47 + .../hawk/node_modules/boom/test/index.js | 245 + .../hawk/node_modules/cryptiles/.npmignore | 18 + .../hawk/node_modules/cryptiles/.travis.yml | 5 + .../hawk/node_modules/cryptiles/LICENSE | 24 + .../hawk/node_modules/cryptiles/Makefile | 11 + .../hawk/node_modules/cryptiles/README.md | 6 + .../hawk/node_modules/cryptiles/index.js | 1 + .../hawk/node_modules/cryptiles/lib/index.js | 68 + .../hawk/node_modules/cryptiles/package.json | 48 + .../hawk/node_modules/cryptiles/test/index.js | 101 + .../hawk/node_modules/hoek/.npmignore | 18 + .../hawk/node_modules/hoek/.travis.yml | 5 + .../hawk/node_modules/hoek/LICENSE | 33 + .../hawk/node_modules/hoek/Makefile | 10 + .../hawk/node_modules/hoek/README.md | 436 + .../hawk/node_modules/hoek/images/hoek.png | Bin 0 -> 37939 bytes .../hawk/node_modules/hoek/index.js | 1 + .../hawk/node_modules/hoek/lib/escape.js | 132 + .../hawk/node_modules/hoek/lib/index.js | 580 + .../hawk/node_modules/hoek/package.json | 49 + .../hawk/node_modules/hoek/test/escaper.js | 86 + .../hawk/node_modules/hoek/test/index.js | 1069 + .../node_modules/hoek/test/modules/test1.js | 1 + .../node_modules/hoek/test/modules/test2.js | 1 + .../node_modules/hoek/test/modules/test3.js | 1 + .../hawk/node_modules/sntp/.npmignore | 18 + .../hawk/node_modules/sntp/.travis.yml | 5 + .../hawk/node_modules/sntp/LICENSE | 24 + .../hawk/node_modules/sntp/Makefile | 11 + .../hawk/node_modules/sntp/README.md | 68 + .../hawk/node_modules/sntp/examples/offset.js | 16 + .../hawk/node_modules/sntp/examples/time.js | 25 + .../hawk/node_modules/sntp/index.js | 1 + .../hawk/node_modules/sntp/lib/index.js | 409 + .../sntp/node_modules/hoek/.npmignore | 18 + .../sntp/node_modules/hoek/.travis.yml | 5 + .../sntp/node_modules/hoek/LICENSE | 33 + .../sntp/node_modules/hoek/Makefile | 10 + .../sntp/node_modules/hoek/README.md | 436 + .../sntp/node_modules/hoek/images/hoek.png | Bin 0 -> 37939 bytes .../sntp/node_modules/hoek/index.js | 1 + .../sntp/node_modules/hoek/lib/escape.js | 132 + .../sntp/node_modules/hoek/lib/index.js | 585 + .../sntp/node_modules/hoek/package.json | 49 + .../sntp/node_modules/hoek/test/escaper.js | 86 + .../sntp/node_modules/hoek/test/index.js | 1078 + .../node_modules/hoek/test/modules/test1.js | 1 + .../node_modules/hoek/test/modules/test2.js | 1 + .../node_modules/hoek/test/modules/test3.js | 1 + .../hawk/node_modules/sntp/package.json | 48 + .../hawk/node_modules/sntp/test/index.js | 359 + .../request/node_modules/hawk/package.json | 53 + .../request/node_modules/hawk/test/browser.js | 723 + .../request/node_modules/hawk/test/client.js | 206 + .../request/node_modules/hawk/test/crypto.js | 86 + .../request/node_modules/hawk/test/index.js | 316 + .../request/node_modules/hawk/test/readme.js | 98 + .../request/node_modules/hawk/test/server.js | 648 + .../request/node_modules/hawk/test/uri.js | 456 + .../request/node_modules/hawk/test/utils.js | 82 + .../http-signature/.dir-locals.el | 6 + .../node_modules/http-signature/.npmignore | 7 + .../node_modules/http-signature/LICENSE | 18 + .../node_modules/http-signature/README.md | 75 + .../http-signature/http_signing.md | 296 + .../node_modules/http-signature/lib/index.js | 25 + .../node_modules/http-signature/lib/parser.js | 304 + .../node_modules/http-signature/lib/signer.js | 179 + .../node_modules/http-signature/lib/util.js | 249 + .../node_modules/http-signature/lib/verify.js | 42 + .../node_modules/asn1/.npmignore | 2 + .../http-signature/node_modules/asn1/LICENSE | 19 + .../node_modules/asn1/README.md | 50 + .../node_modules/asn1/lib/ber/errors.js | 13 + .../node_modules/asn1/lib/ber/index.js | 27 + .../node_modules/asn1/lib/ber/reader.js | 267 + .../node_modules/asn1/lib/ber/types.js | 36 + .../node_modules/asn1/lib/ber/writer.js | 317 + .../node_modules/asn1/lib/index.js | 20 + .../node_modules/asn1/package.json | 43 + .../node_modules/asn1/tst/ber/reader.test.js | 172 + .../node_modules/asn1/tst/ber/writer.test.js | 296 + .../node_modules/assert-plus/README.md | 126 + .../node_modules/assert-plus/assert.js | 196 + .../node_modules/assert-plus/package.json | 24 + .../node_modules/ctype/CHANGELOG | 71 + .../http-signature/node_modules/ctype/LICENSE | 24 + .../http-signature/node_modules/ctype/README | 82 + .../http-signature/node_modules/ctype/ctf.js | 245 + .../http-signature/node_modules/ctype/ctio.js | 1485 + .../node_modules/ctype/ctype.js | 944 + .../ctype/man/man3ctype/ctio.3ctype | 241 + .../node_modules/ctype/package.json | 22 + .../node_modules/ctype/tools/jsl.conf | 129 + .../node_modules/ctype/tools/jsstyle | 839 + .../node_modules/ctype/tst/ctf/float.json | 13 + .../node_modules/ctype/tst/ctf/int.json | 13 + .../node_modules/ctype/tst/ctf/psinfo.json | 104 + .../node_modules/ctype/tst/ctf/struct.json | 19 + .../node_modules/ctype/tst/ctf/tst.fail.js | 39 + .../node_modules/ctype/tst/ctf/tst.float.js | 14 + .../node_modules/ctype/tst/ctf/tst.int.js | 14 + .../node_modules/ctype/tst/ctf/tst.psinfo.js | 17 + .../node_modules/ctype/tst/ctf/tst.struct.js | 18 + .../node_modules/ctype/tst/ctf/tst.typedef.js | 15 + .../node_modules/ctype/tst/ctf/typedef.json | 14 + .../ctype/tst/ctio/float/tst.rfloat.js | 767 + .../ctype/tst/ctio/float/tst.wfloat.js | 753 + .../node_modules/ctype/tst/ctio/int/tst.64.js | 638 + .../ctype/tst/ctio/int/tst.rint.js | 101 + .../ctype/tst/ctio/int/tst.wbounds.js | 53 + .../ctype/tst/ctio/int/tst.wint.js | 92 + .../ctype/tst/ctio/uint/tst.64.js | 451 + .../ctype/tst/ctio/uint/tst.roundtrip.js | 81 + .../ctype/tst/ctio/uint/tst.ruint.js | 95 + .../ctype/tst/ctio/uint/tst.wuint.js | 156 + .../ctype/tst/ctype/tst.basicr.js | 50 + .../ctype/tst/ctype/tst.basicw.js | 44 + .../node_modules/ctype/tst/ctype/tst.char.js | 42 + .../ctype/tst/ctype/tst.endian.js | 45 + .../ctype/tst/ctype/tst.oldwrite.js | 28 + .../ctype/tst/ctype/tst.readSize.js | 128 + .../ctype/tst/ctype/tst.structw.js | 28 + .../ctype/tst/ctype/tst.writeStruct.js | 31 + .../node_modules/http-signature/package.json | 36 + .../node_modules/json-stringify-safe/LICENSE | 27 + .../json-stringify-safe/README.md | 27 + .../json-stringify-safe/package.json | 33 + .../json-stringify-safe/stringify.js | 25 + .../node_modules/json-stringify-safe/test.js | 96 + .../request/node_modules/node-uuid/.npmignore | 2 + .../request/node_modules/node-uuid/LICENSE.md | 3 + .../request/node_modules/node-uuid/README.md | 203 + .../node-uuid/benchmark/README.md | 53 + .../node-uuid/benchmark/bench.gnu | 174 + .../node_modules/node-uuid/benchmark/bench.sh | 34 + .../node-uuid/benchmark/benchmark-native.c | 34 + .../node-uuid/benchmark/benchmark.js | 84 + .../node_modules/node-uuid/package.json | 35 + .../node_modules/node-uuid/test/compare_v1.js | 63 + .../node_modules/node-uuid/test/test.html | 17 + .../node_modules/node-uuid/test/test.js | 228 + .../request/node_modules/node-uuid/uuid.js | 245 + .../request/node_modules/oauth-sign/LICENSE | 55 + .../request/node_modules/oauth-sign/README.md | 4 + .../request/node_modules/oauth-sign/index.js | 43 + .../node_modules/oauth-sign/package.json | 31 + .../request/node_modules/oauth-sign/test.js | 49 + .../request/node_modules/qs/.gitmodules | 6 + .../request/node_modules/qs/.npmignore | 7 + .../request/node_modules/qs/Readme.md | 58 + .../request/node_modules/qs/index.js | 387 + .../request/node_modules/qs/package.json | 38 + .../request/node_modules/tunnel-agent/LICENSE | 55 + .../node_modules/tunnel-agent/README.md | 4 + .../node_modules/tunnel-agent/index.js | 227 + .../node_modules/tunnel-agent/package.json | 28 + .../less/node_modules/request/package.json | 51 + .../request/tests/googledoodle.jpg | Bin 0 -> 38510 bytes .../less/node_modules/request/tests/run.js | 40 + .../less/node_modules/request/tests/server.js | 90 + .../node_modules/request/tests/squid.conf | 77 + .../node_modules/request/tests/ssl/ca/ca.cnf | 20 + .../node_modules/request/tests/ssl/ca/ca.crl | 0 .../node_modules/request/tests/ssl/ca/ca.crt | 17 + .../node_modules/request/tests/ssl/ca/ca.csr | 13 + .../node_modules/request/tests/ssl/ca/ca.key | 18 + .../node_modules/request/tests/ssl/ca/ca.srl | 1 + .../request/tests/ssl/ca/server.cnf | 19 + .../request/tests/ssl/ca/server.crt | 16 + .../request/tests/ssl/ca/server.csr | 11 + .../request/tests/ssl/ca/server.js | 28 + .../request/tests/ssl/ca/server.key | 9 + .../node_modules/request/tests/ssl/npm-ca.crt | 16 + .../node_modules/request/tests/ssl/test.crt | 15 + .../node_modules/request/tests/ssl/test.key | 15 + .../request/tests/test-agentOptions.js | 23 + .../request/tests/test-basic-auth.js | 143 + .../node_modules/request/tests/test-body.js | 122 + .../request/tests/test-defaults.js | 129 + .../request/tests/test-digest-auth.js | 69 + .../request/tests/test-emptyBody.js | 20 + .../node_modules/request/tests/test-errors.js | 37 + .../request/tests/test-follow-all-303.js | 30 + .../request/tests/test-follow-all.js | 35 + .../node_modules/request/tests/test-form.js | 79 + .../node_modules/request/tests/test-hawk.js | 33 + .../request/tests/test-headers.js | 52 + .../request/tests/test-http-signature.js | 106 + .../request/tests/test-httpModule.js | 94 + .../request/tests/test-https-strict.js | 97 + .../node_modules/request/tests/test-https.js | 87 + .../request/tests/test-localAddress.js | 15 + .../node_modules/request/tests/test-oauth.js | 117 + .../request/tests/test-onelineproxy.js | 46 + .../node_modules/request/tests/test-params.js | 93 + .../request/tests/test-piped-redirect.js | 42 + .../node_modules/request/tests/test-pipes.js | 216 + .../node_modules/request/tests/test-pool.js | 16 + .../tests/test-protocol-changing-redirect.js | 61 + .../node_modules/request/tests/test-proxy.js | 39 + .../node_modules/request/tests/test-qs.js | 42 + .../request/tests/test-redirect.js | 155 + .../node_modules/request/tests/test-s3.js | 13 + .../request/tests/test-timeout.js | 87 + .../node_modules/request/tests/test-toJSON.js | 14 + .../node_modules/request/tests/test-tunnel.js | 75 + .../node_modules/request/tests/unicycle.jpg | Bin 0 -> 19806 bytes .../less/node_modules/ycssmin/.npmignore | 11 + .../less/node_modules/ycssmin/.travis.yml | 8 + .../less/node_modules/ycssmin/LICENSE | 25 + .../less/node_modules/ycssmin/Makefile | 14 + .../less/node_modules/ycssmin/README.md | 97 + .../less/node_modules/ycssmin/bin/cssmin | 27 + .../less/node_modules/ycssmin/cssmin.js | 361 + .../less/node_modules/ycssmin/package.json | 66 + .../tests/files/background-position.css | 2 + .../tests/files/background-position.css.min | 1 + .../ycssmin/tests/files/border-none.css | 5 + .../ycssmin/tests/files/border-none.css.min | 1 + .../ycssmin/tests/files/box-model-hack.css | 9 + .../tests/files/box-model-hack.css.min | 1 + .../ycssmin/tests/files/bug2527974.css | 10 + .../ycssmin/tests/files/bug2527974.css.min | 1 + .../ycssmin/tests/files/bug2527991.css | 19 + .../ycssmin/tests/files/bug2527991.css.min | 1 + .../ycssmin/tests/files/bug2527998.css | 4 + .../ycssmin/tests/files/bug2527998.css.min | 1 + .../ycssmin/tests/files/bug2528034.css | 5 + .../ycssmin/tests/files/bug2528034.css.min | 1 + .../ycssmin/tests/files/charset-media.css | 9 + .../ycssmin/tests/files/charset-media.css.min | 1 + .../ycssmin/tests/files/color-simple.css | 8 + .../ycssmin/tests/files/color-simple.css.min | 1 + .../ycssmin/tests/files/color.css | 46 + .../ycssmin/tests/files/color.css.min | 1 + .../ycssmin/tests/files/comment.css | 3 + .../ycssmin/tests/files/comment.css.min | 1 + .../ycssmin/tests/files/concat-charset.css | 15 + .../tests/files/concat-charset.css.min | 1 + .../files/dataurl-base64-doublequotes.css | 23 + .../files/dataurl-base64-doublequotes.css.min | 1 + .../tests/files/dataurl-base64-eof.css | 10 + .../tests/files/dataurl-base64-eof.css.min | 1 + .../files/dataurl-base64-linebreakindata.css | 34 + .../dataurl-base64-linebreakindata.css.min | 1 + .../tests/files/dataurl-base64-noquotes.css | 26 + .../files/dataurl-base64-noquotes.css.min | 1 + .../files/dataurl-base64-singlequotes.css | 23 + .../files/dataurl-base64-singlequotes.css.min | 1 + .../tests/files/dataurl-base64-twourls.css | 27 + .../files/dataurl-base64-twourls.css.min | 1 + .../tests/files/dataurl-dbquote-font.css | 30 + .../tests/files/dataurl-dbquote-font.css.min | 5 + .../files/dataurl-nonbase64-doublequotes.css | 13 + .../dataurl-nonbase64-doublequotes.css.min | 1 + .../files/dataurl-nonbase64-noquotes.css | 11 + .../files/dataurl-nonbase64-noquotes.css.min | 1 + .../files/dataurl-nonbase64-singlequotes.css | 15 + .../dataurl-nonbase64-singlequotes.css.min | 2 + .../files/dataurl-noquote-multiline-font.css | 31 + .../dataurl-noquote-multiline-font.css.min | 3 + .../files/dataurl-realdata-doublequotes.css | 90 + .../dataurl-realdata-doublequotes.css.min | 1 + .../tests/files/dataurl-realdata-noquotes.css | 90 + .../files/dataurl-realdata-noquotes.css.min | 1 + .../files/dataurl-realdata-singlequotes.css | 90 + .../dataurl-realdata-singlequotes.css.min | 1 + .../tests/files/dataurl-realdata-yuiapp.css | 106 + .../files/dataurl-realdata-yuiapp.css.min | 1 + .../tests/files/dataurl-singlequote-font.css | 30 + .../files/dataurl-singlequote-font.css.min | 3 + .../ycssmin/tests/files/decimals.css | 3 + .../ycssmin/tests/files/decimals.css.min | 1 + .../ycssmin/tests/files/dollar-header.css | 7 + .../ycssmin/tests/files/dollar-header.css.min | 3 + .../ycssmin/tests/files/font-face.css | 6 + .../ycssmin/tests/files/font-face.css.min | 1 + .../ycssmin/tests/files/ie5mac.css | 5 + .../ycssmin/tests/files/ie5mac.css.min | 1 + .../ycssmin/tests/files/media-empty-class.css | 16 + .../tests/files/media-empty-class.css.min | 1 + .../ycssmin/tests/files/media-multi.css | 3 + .../ycssmin/tests/files/media-multi.css.min | 1 + .../ycssmin/tests/files/media-test.css | 3 + .../ycssmin/tests/files/media-test.css.min | 1 + .../ycssmin/tests/files/opacity-filter.css | 14 + .../tests/files/opacity-filter.css.min | 1 + .../ycssmin/tests/files/preserve-case.css | 15 + .../ycssmin/tests/files/preserve-case.css.min | 1 + .../ycssmin/tests/files/preserve-new-line.css | 6 + .../tests/files/preserve-new-line.css.min | 3 + .../ycssmin/tests/files/preserve-strings.css | 7 + .../tests/files/preserve-strings.css.min | 1 + .../ycssmin/tests/files/pseudo-first.css | 16 + .../ycssmin/tests/files/pseudo-first.css.min | 1 + .../ycssmin/tests/files/pseudo.css | 5 + .../ycssmin/tests/files/pseudo.css.min | 1 + .../ycssmin/tests/files/special-comments.css | 13 + .../tests/files/special-comments.css.min | 9 + .../tests/files/special/linebreakpos.css | 118 + .../tests/files/special/linebreakpos.css.min | 6 + .../tests/files/star-underscore-hacks.css | 5 + .../tests/files/star-underscore-hacks.css.min | 1 + .../ycssmin/tests/files/string-in-comment.css | 8 + .../tests/files/string-in-comment.css.min | 1 + .../ycssmin/tests/files/webkit-transform.css | 2 + .../tests/files/webkit-transform.css.min | 1 + .../ycssmin/tests/files/zeros.css | 6 + .../ycssmin/tests/files/zeros.css.min | 1 + .../less/node_modules/ycssmin/tests/tests.js | 49 + node_modules/less/package.json | 92 + .../less/test/browser-test-prepare.js | 46 + node_modules/less/test/browser/common.js | 126 + .../test/browser/css/relative-urls/urls.css | 36 + .../browser/css/rootpath-relative/urls.css | 36 + .../less/test/browser/css/rootpath/urls.css | 36 + node_modules/less/test/browser/css/urls.css | 49 + .../less/test/browser/jasmine-html.js | 681 + node_modules/less/test/browser/jasmine.css | 82 + node_modules/less/test/browser/jasmine.js | 2600 + .../less/test/browser/less/imports/urls.less | 4 + .../less/test/browser/less/imports/urls2.less | 4 + .../test/browser/less/relative-urls/urls.less | 33 + .../browser/less/rootpath-relative/urls.less | 33 + .../less/test/browser/less/rootpath/urls.less | 33 + node_modules/less/test/browser/less/urls.less | 49 + .../less/test/browser/phantom-runner.js | 141 + .../less/test/browser/runner-browser.js | 7 + .../less/test/browser/runner-errors.js | 5 + .../less/test/browser/runner-legacy.js | 6 + node_modules/less/test/browser/runner-main.js | 15 + .../less/test/browser/runner-production.js | 7 + .../less/test/browser/runner-relative-urls.js | 4 + .../test/browser/runner-rootpath-relative.js | 5 + .../less/test/browser/runner-rootpath.js | 4 + node_modules/less/test/browser/template.htm | 10 + node_modules/less/test/css/charsets.css | 1 + node_modules/less/test/css/colors.css | 80 + node_modules/less/test/css/comments.css | 64 + .../less/test/css/compression/compression.css | 2 + node_modules/less/test/css/css-3.css | 114 + node_modules/less/test/css/css-escapes.css | 24 + node_modules/less/test/css/css.css | 95 + .../less/test/css/debug/linenumbers-all.css | 43 + .../test/css/debug/linenumbers-comments.css | 35 + .../test/css/debug/linenumbers-mediaquery.css | 35 + .../less/test/css/extend-chaining.css | 72 + .../less/test/css/extend-clearfix.css | 19 + node_modules/less/test/css/extend-exact.css | 37 + node_modules/less/test/css/extend-media.css | 24 + node_modules/less/test/css/extend-nest.css | 57 + .../less/test/css/extend-selector.css | 72 + node_modules/less/test/css/extend.css | 76 + node_modules/less/test/css/functions.css | 128 + node_modules/less/test/css/ie-filters.css | 9 + .../less/test/css/import-interpolation.css | 6 + node_modules/less/test/css/import-once.css | 3 + node_modules/less/test/css/import.css | 38 + node_modules/less/test/css/javascript.css | 23 + node_modules/less/test/css/lazy-eval.css | 3 + node_modules/less/test/css/legacy/legacy.css | 7 + node_modules/less/test/css/media.css | 203 + node_modules/less/test/css/mixins-args.css | 113 + node_modules/less/test/css/mixins-closure.css | 9 + node_modules/less/test/css/mixins-guards.css | 76 + .../less/test/css/mixins-important.css | 38 + .../less/test/css/mixins-named-args.css | 27 + node_modules/less/test/css/mixins-nested.css | 14 + node_modules/less/test/css/mixins-pattern.css | 47 + node_modules/less/test/css/mixins.css | 121 + node_modules/less/test/css/operations.css | 49 + node_modules/less/test/css/parens.css | 33 + node_modules/less/test/css/rulesets.css | 33 + node_modules/less/test/css/scope.css | 35 + node_modules/less/test/css/selectors.css | 141 + .../less/test/css/static-urls/urls.css | 42 + node_modules/less/test/css/strings.css | 40 + node_modules/less/test/css/urls.css | 59 + node_modules/less/test/css/variables.css | 45 + node_modules/less/test/css/whitespace.css | 42 + node_modules/less/test/data/data-uri-fail.png | Bin 0 -> 52420 bytes node_modules/less/test/data/image.jpg | 1 + node_modules/less/test/data/page.html | 1 + node_modules/less/test/less-test.js | 214 + node_modules/less/test/less/charsets.less | 3 + node_modules/less/test/less/colors.less | 92 + node_modules/less/test/less/comments.less | 77 + .../test/less/compression/compression.less | 16 + node_modules/less/test/less/css-3.less | 114 + node_modules/less/test/less/css-escapes.less | 33 + node_modules/less/test/less/css.less | 108 + .../less/test/less/debug/import/test.less | 25 + .../less/test/less/debug/linenumbers.less | 23 + .../test/less/errors/add-mixed-units.less | 3 + .../less/test/less/errors/add-mixed-units.txt | 2 + .../test/less/errors/add-mixed-units2.less | 3 + .../test/less/errors/add-mixed-units2.txt | 2 + .../errors/bad-variable-declaration1.less | 1 + .../less/errors/bad-variable-declaration1.txt | 2 + .../less/errors/color-operation-error.less | 3 + .../less/errors/color-operation-error.txt | 2 + .../test/less/errors/comment-in-selector.less | 1 + .../test/less/errors/comment-in-selector.txt | 2 + .../test/less/errors/divide-mixed-units.less | 3 + .../test/less/errors/divide-mixed-units.txt | 4 + .../test/less/errors/extend-no-selector.less | 3 + .../test/less/errors/extend-no-selector.txt | 3 + .../test/less/errors/extend-not-at-end.less | 3 + .../test/less/errors/extend-not-at-end.txt | 3 + .../less/test/less/errors/import-missing.less | 6 + .../less/test/less/errors/import-missing.txt | 3 + .../less/test/less/errors/import-no-semi.less | 1 + .../less/test/less/errors/import-no-semi.txt | 2 + .../test/less/errors/import-subfolder1.less | 1 + .../test/less/errors/import-subfolder1.txt | 3 + .../test/less/errors/import-subfolder2.less | 1 + .../test/less/errors/import-subfolder2.txt | 2 + .../errors/imports/import-subfolder1.less | 1 + .../errors/imports/import-subfolder2.less | 1 + .../test/less/errors/imports/import-test.less | 4 + .../imports/subfolder/mixin-not-defined.less | 1 + .../subfolder/parse-error-curly-bracket.less | 1 + .../test/less/errors/javascript-error.less | 3 + .../test/less/errors/javascript-error.txt | 4 + .../errors/mixed-mixin-definition-args-1.less | 6 + .../errors/mixed-mixin-definition-args-1.txt | 4 + .../errors/mixed-mixin-definition-args-2.less | 6 + .../errors/mixed-mixin-definition-args-2.txt | 4 + .../test/less/errors/mixin-not-defined.less | 11 + .../test/less/errors/mixin-not-defined.txt | 3 + .../test/less/errors/mixin-not-matched.less | 6 + .../test/less/errors/mixin-not-matched.txt | 3 + .../test/less/errors/mixin-not-matched2.less | 6 + .../test/less/errors/mixin-not-matched2.txt | 3 + .../less/errors/multiply-mixed-units.less | 7 + .../test/less/errors/multiply-mixed-units.txt | 4 + .../less/test/less/errors/parens-error-1.less | 3 + .../less/test/less/errors/parens-error-1.txt | 4 + .../less/test/less/errors/parens-error-2.less | 3 + .../less/test/less/errors/parens-error-2.txt | 4 + .../less/test/less/errors/parens-error-3.less | 3 + .../less/test/less/errors/parens-error-3.txt | 4 + .../errors/parse-error-curly-bracket.less | 1 + .../less/errors/parse-error-curly-bracket.txt | 2 + .../errors/parse-error-missing-bracket.less | 2 + .../errors/parse-error-missing-bracket.txt | 3 + .../less/errors/parse-error-with-import.less | 13 + .../less/errors/parse-error-with-import.txt | 4 + .../test/less/errors/property-ie5-hack.less | 3 + .../test/less/errors/property-ie5-hack.txt | 4 + .../test/less/errors/property-in-root.less | 4 + .../test/less/errors/property-in-root.txt | 4 + .../test/less/errors/property-in-root2.less | 1 + .../test/less/errors/property-in-root2.txt | 4 + .../test/less/errors/property-in-root3.less | 4 + .../test/less/errors/property-in-root3.txt | 3 + .../test/less/errors/recursive-variable.less | 1 + .../test/less/errors/recursive-variable.txt | 2 + .../less/test/less/extend-chaining.less | 79 + .../less/test/less/extend-clearfix.less | 19 + node_modules/less/test/less/extend-exact.less | 46 + node_modules/less/test/less/extend-media.less | 24 + node_modules/less/test/less/extend-nest.less | 65 + .../less/test/less/extend-selector.less | 84 + node_modules/less/test/less/extend.less | 81 + node_modules/less/test/less/functions.less | 142 + node_modules/less/test/less/ie-filters.less | 15 + .../less/test/less/import-interpolation.less | 8 + node_modules/less/test/less/import-once.less | 4 + node_modules/less/test/less/import.less | 21 + .../import/deeper/import-once-test-a.less | 1 + .../import-and-relative-paths-test.less | 6 + .../test/less/import/import-charset-test.less | 1 + .../less/import/import-interpolation.less | 1 + .../less/import/import-interpolation2.less | 5 + .../test/less/import/import-once-test-c.less | 6 + .../less/test/less/import/import-test-a.less | 3 + .../less/test/less/import/import-test-b.less | 8 + .../less/test/less/import/import-test-c.less | 6 + .../less/test/less/import/import-test-d.css | 1 + .../less/test/less/import/import-test-e.less | 2 + .../less/test/less/import/imports/font.less | 8 + .../less/test/less/import/imports/logo.less | 5 + node_modules/less/test/less/import/urls.less | 1 + node_modules/less/test/less/javascript.less | 29 + node_modules/less/test/less/lazy-eval.less | 6 + .../less/test/less/legacy/legacy.less | 7 + node_modules/less/test/less/media.less | 210 + node_modules/less/test/less/mixins-args.less | 205 + .../less/test/less/mixins-closure.less | 26 + .../less/test/less/mixins-guards.less | 137 + .../less/test/less/mixins-important.less | 22 + .../less/test/less/mixins-named-args.less | 36 + .../less/test/less/mixins-nested.less | 22 + .../less/test/less/mixins-pattern.less | 99 + node_modules/less/test/less/mixins.less | 114 + node_modules/less/test/less/operations.less | 62 + node_modules/less/test/less/parens.less | 41 + node_modules/less/test/less/rulesets.less | 30 + node_modules/less/test/less/scope.less | 79 + node_modules/less/test/less/selectors.less | 143 + .../less/test/less/static-urls/urls.less | 33 + node_modules/less/test/less/strings.less | 51 + node_modules/less/test/less/urls.less | 57 + node_modules/less/test/less/variables.less | 83 + node_modules/less/test/less/whitespace.less | 44 + node_modules/log4node/.npmignore | 4 + node_modules/log4node/CHANGELOG | 6 + node_modules/log4node/Readme.markdown | 132 + node_modules/log4node/lib/log4node.js | 175 + node_modules/log4node/license.txt | 13 + node_modules/log4node/package.json | 45 + node_modules/log4node/test-runner.sh | 15 + .../test/cluster-logger-after-fork/output1 | 4 + .../test/cluster-logger-after-fork/test1.js | 16 + .../test/cluster-logrotate/logrotate.conf | 7 + .../log4node/test/cluster-logrotate/output1 | 5 + .../log4node/test/cluster-logrotate/output2 | 4 + .../log4node/test/cluster-logrotate/test1.js | 22 + .../log4node/test/cluster-stdout-sig/output1 | 9 + .../log4node/test/cluster-stdout-sig/test1.js | 22 + .../logrotate.conf | 7 + .../test/cluster-sub-logger-logrotate/output1 | 5 + .../test/cluster-sub-logger-logrotate/output2 | 4 + .../cluster-sub-logger-logrotate/test1.js | 24 + .../log4node/test/cluster-sub-logger/output1 | 9 + .../log4node/test/cluster-sub-logger/test1.js | 25 + node_modules/log4node/test/cluster/output1 | 9 + node_modules/log4node/test/cluster/test1.js | 23 + node_modules/log4node/test/helper.js | 123 + .../test/multiple-appender/logrotate.conf | 7 + .../log4node/test/multiple-appender/output1 | 2 + .../log4node/test/multiple-appender/output2 | 2 + .../log4node/test/multiple-appender/test1.js | 10 + .../log4node/test/no-cluster-append/output1 | 1 + .../log4node/test/no-cluster-append/output2 | 2 + .../log4node/test/no-cluster-append/test1.js | 7 + .../test/no-cluster-logrotate/logrotate.conf | 7 + .../test/no-cluster-logrotate/output1 | 1 + .../test/no-cluster-logrotate/output2 | 1 + .../test/no-cluster-logrotate/test1.js | 12 + .../log4node/test/no-cluster-sig/output1 | 1 + .../log4node/test/no-cluster-sig/output2 | 2 + .../log4node/test/no-cluster-sig/test1.js | 12 + .../test/no-cluster-stdout-sig/output1 | 2 + .../test/no-cluster-stdout-sig/test1.js | 11 + node_modules/log4node/test/no-cluster/output1 | 2 + node_modules/log4node/test/no-cluster/output2 | 3 + .../log4node/test/no-cluster/test1.js | 13 + .../log4node/test/sub-logger-default/output1 | 2 + .../log4node/test/sub-logger-default/output2 | 3 + .../log4node/test/sub-logger-default/test1.js | 15 + node_modules/log4node/test/sub-logger/output1 | 2 + node_modules/log4node/test/sub-logger/output2 | 3 + .../log4node/test/sub-logger/test1.js | 16 + .../test/test-cluster-logger-after-fork.js | 3 + .../log4node/test/test-cluster-logrotate.js | 12 + .../log4node/test/test-cluster-stdout-sig.js | 14 + .../test/test-cluster-sub-logger-logrotate.js | 12 + .../log4node/test/test-cluster-sub-logger.js | 3 + node_modules/log4node/test/test-cluster.js | 15 + .../log4node/test/test-multiple-appender.js | 29 + .../log4node/test/test-no-cluster-append.js | 12 + .../test/test-no-cluster-logrotate.js | 12 + .../log4node/test/test-no-cluster-sig.js | 12 + .../test/test-no-cluster-stdout-sig.js | 13 + node_modules/log4node/test/test-no-cluster.js | 7 + .../log4node/test/test-not-reopening-file.js | 33 + .../log4node/test/test-send-master.js | 33 + .../log4node/test/test-set-loglevel.js | 30 + node_modules/log4node/test/test-set-prefix.js | 162 + .../log4node/test/test-strange-params.js | 28 + .../log4node/test/test-sub-logger-default.js | 9 + node_modules/log4node/test/test-sub-logger.js | 9 + node_modules/moment/.npmignore | 2 + node_modules/moment/.travis.yml | 5 + node_modules/moment/CONTRIBUTING.md | 45 + node_modules/moment/Gruntfile.js | 124 + node_modules/moment/LICENSE | 22 + node_modules/moment/component.json | 19 + node_modules/moment/composer.json | 18 + node_modules/moment/ender.js | 1 + node_modules/moment/lang/ar-ma.js | 46 + node_modules/moment/lang/ar.js | 46 + node_modules/moment/lang/bg.js | 76 + node_modules/moment/lang/br.js | 97 + node_modules/moment/lang/ca.js | 56 + node_modules/moment/lang/cs.js | 145 + node_modules/moment/lang/cv.js | 50 + node_modules/moment/lang/da.js | 46 + node_modules/moment/lang/de.js | 61 + node_modules/moment/lang/el.js | 69 + node_modules/moment/lang/en-ca.js | 49 + node_modules/moment/lang/en-gb.js | 53 + node_modules/moment/lang/eo.js | 55 + node_modules/moment/lang/es.js | 56 + node_modules/moment/lang/et.js | 50 + node_modules/moment/lang/eu.js | 50 + node_modules/moment/lang/fa.js | 86 + node_modules/moment/lang/fi.js | 93 + node_modules/moment/lang/fr-ca.js | 44 + node_modules/moment/lang/fr.js | 48 + node_modules/moment/lang/gl.js | 61 + node_modules/moment/lang/he.js | 46 + node_modules/moment/lang/hi.js | 95 + node_modules/moment/lang/hu.js | 87 + node_modules/moment/lang/id.js | 57 + node_modules/moment/lang/is.js | 114 + node_modules/moment/lang/it.js | 49 + node_modules/moment/lang/ja.js | 48 + node_modules/moment/lang/ka.js | 97 + node_modules/moment/lang/ko.js | 46 + node_modules/moment/lang/lv.js | 67 + node_modules/moment/lang/ms-my.js | 56 + node_modules/moment/lang/nb.js | 46 + node_modules/moment/lang/ne.js | 95 + node_modules/moment/lang/nl.js | 57 + node_modules/moment/lang/nn.js | 46 + node_modules/moment/lang/pl.js | 88 + node_modules/moment/lang/pt-br.js | 46 + node_modules/moment/lang/pt.js | 50 + node_modules/moment/lang/readme.md | 5 + node_modules/moment/lang/ro.js | 46 + node_modules/moment/lang/ru.js | 125 + node_modules/moment/lang/sk.js | 146 + node_modules/moment/lang/sl.js | 134 + node_modules/moment/lang/sq.js | 47 + node_modules/moment/lang/sv.js | 53 + node_modules/moment/lang/th.js | 48 + node_modules/moment/lang/tr.js | 82 + node_modules/moment/lang/tzm-la.js | 45 + node_modules/moment/lang/tzm.js | 45 + node_modules/moment/lang/uk.js | 132 + node_modules/moment/lang/zh-cn.js | 73 + node_modules/moment/lang/zh-tw.js | 73 + node_modules/moment/min/lang/ar-ma.js | 5 + node_modules/moment/min/lang/ar.js | 5 + node_modules/moment/min/lang/bg.js | 4 + node_modules/moment/min/lang/br.js | 4 + node_modules/moment/min/lang/ca.js | 4 + node_modules/moment/min/lang/cs.js | 4 + node_modules/moment/min/lang/cv.js | 4 + node_modules/moment/min/lang/da.js | 4 + node_modules/moment/min/lang/de.js | 5 + node_modules/moment/min/lang/el.js | 4 + node_modules/moment/min/lang/en-ca.js | 4 + node_modules/moment/min/lang/en-gb.js | 4 + node_modules/moment/min/lang/eo.js | 6 + node_modules/moment/min/lang/es.js | 4 + node_modules/moment/min/lang/et.js | 4 + node_modules/moment/min/lang/eu.js | 4 + node_modules/moment/min/lang/fa.js | 4 + node_modules/moment/min/lang/fi.js | 4 + node_modules/moment/min/lang/fr-ca.js | 4 + node_modules/moment/min/lang/fr.js | 4 + node_modules/moment/min/lang/gl.js | 4 + node_modules/moment/min/lang/he.js | 5 + node_modules/moment/min/lang/hi.js | 4 + node_modules/moment/min/lang/hu.js | 4 + node_modules/moment/min/lang/id.js | 5 + node_modules/moment/min/lang/is.js | 4 + node_modules/moment/min/lang/it.js | 5 + node_modules/moment/min/lang/ja.js | 4 + node_modules/moment/min/lang/ka.js | 4 + node_modules/moment/min/lang/ko.js | 4 + node_modules/moment/min/lang/lv.js | 4 + node_modules/moment/min/lang/ms-my.js | 4 + node_modules/moment/min/lang/nb.js | 4 + node_modules/moment/min/lang/ne.js | 4 + node_modules/moment/min/lang/nl.js | 4 + node_modules/moment/min/lang/nn.js | 4 + node_modules/moment/min/lang/pl.js | 4 + node_modules/moment/min/lang/pt-br.js | 4 + node_modules/moment/min/lang/pt.js | 4 + node_modules/moment/min/lang/ro.js | 5 + node_modules/moment/min/lang/ru.js | 5 + node_modules/moment/min/lang/sk.js | 5 + node_modules/moment/min/lang/sl.js | 4 + node_modules/moment/min/lang/sq.js | 5 + node_modules/moment/min/lang/sv.js | 4 + node_modules/moment/min/lang/th.js | 4 + node_modules/moment/min/lang/tr.js | 5 + node_modules/moment/min/lang/tzm-la.js | 4 + node_modules/moment/min/lang/tzm.js | 4 + node_modules/moment/min/lang/uk.js | 5 + node_modules/moment/min/lang/zh-cn.js | 4 + node_modules/moment/min/lang/zh-tw.js | 4 + node_modules/moment/min/langs.js | 3693 + node_modules/moment/min/langs.min.js | 3 + node_modules/moment/min/moment.min.js | 6 + node_modules/moment/moment.js | 1662 + node_modules/moment/package.js | 11 + node_modules/moment/package.json | 73 + node_modules/moment/readme.md | 269 + node_modules/moment/tasks/concat-lang.js | 47 + node_modules/moment/tasks/history.js | 123 + node_modules/moment/tasks/minify-lang.js | 82 + node_modules/moment/tasks/minify.js | 57 + node_modules/moment/tasks/size.js | 60 + node_modules/moment/tasks/zone.js | 123 + node_modules/moment/tasks/zones.js | 104 + node_modules/moment/test/lang/ar-ma.js | 349 + node_modules/moment/test/lang/ar.js | 349 + node_modules/moment/test/lang/bg.js | 370 + node_modules/moment/test/lang/br.js | 275 + node_modules/moment/test/lang/ca.js | 327 + node_modules/moment/test/lang/cs.js | 413 + node_modules/moment/test/lang/cv.js | 362 + node_modules/moment/test/lang/da.js | 292 + node_modules/moment/test/lang/de.js | 354 + node_modules/moment/test/lang/el.js | 383 + node_modules/moment/test/lang/en-ca.js | 378 + node_modules/moment/test/lang/en-gb.js | 358 + node_modules/moment/test/lang/en.js | 379 + node_modules/moment/test/lang/eo.js | 364 + node_modules/moment/test/lang/es.js | 359 + node_modules/moment/test/lang/et.js | 367 + node_modules/moment/test/lang/eu.js | 363 + node_modules/moment/test/lang/fa.js | 342 + node_modules/moment/test/lang/fi.js | 357 + node_modules/moment/test/lang/fr-ca.js | 372 + node_modules/moment/test/lang/fr.js | 358 + node_modules/moment/test/lang/gl.js | 342 + node_modules/moment/test/lang/he.js | 321 + node_modules/moment/test/lang/hi.js | 383 + node_modules/moment/test/lang/hu.js | 361 + node_modules/moment/test/lang/id.js | 318 + node_modules/moment/test/lang/is.js | 370 + node_modules/moment/test/lang/it.js | 359 + node_modules/moment/test/lang/ja.js | 323 + node_modules/moment/test/lang/ka.js | 379 + node_modules/moment/test/lang/ko.js | 370 + node_modules/moment/test/lang/lv.js | 362 + node_modules/moment/test/lang/ms-my.js | 379 + node_modules/moment/test/lang/nb.js | 362 + node_modules/moment/test/lang/ne.js | 382 + node_modules/moment/test/lang/nl.js | 373 + node_modules/moment/test/lang/nn.js | 362 + node_modules/moment/test/lang/pl.js | 375 + node_modules/moment/test/lang/pt-br.js | 364 + node_modules/moment/test/lang/pt.js | 354 + node_modules/moment/test/lang/ro.js | 363 + node_modules/moment/test/lang/ru.js | 393 + node_modules/moment/test/lang/sk.js | 413 + node_modules/moment/test/lang/sl.js | 389 + node_modules/moment/test/lang/sq.js | 378 + node_modules/moment/test/lang/sv.js | 356 + node_modules/moment/test/lang/th.js | 323 + node_modules/moment/test/lang/tr.js | 374 + node_modules/moment/test/lang/tzm-la.js | 359 + node_modules/moment/test/lang/tzm.js | 351 + node_modules/moment/test/lang/uk.js | 378 + node_modules/moment/test/lang/zh-cn.js | 356 + node_modules/moment/test/lang/zh-tw.js | 358 + .../moment/test/moment/add_subtract.js | 246 + node_modules/moment/test/moment/create.js | 463 + .../moment/test/moment/days_in_month.js | 28 + node_modules/moment/test/moment/diff.js | 239 + node_modules/moment/test/moment/duration.js | 409 + node_modules/moment/test/moment/format.js | 308 + .../moment/test/moment/getters_setters.js | 167 + node_modules/moment/test/moment/is_after.js | 188 + node_modules/moment/test/moment/is_before.js | 187 + node_modules/moment/test/moment/is_moment.js | 27 + node_modules/moment/test/moment/is_same.js | 163 + node_modules/moment/test/moment/is_valid.js | 164 + node_modules/moment/test/moment/lang.js | 236 + node_modules/moment/test/moment/leapyear.js | 13 + node_modules/moment/test/moment/min_max.js | 62 + node_modules/moment/test/moment/mutable.js | 55 + .../moment/test/moment/preparse_postformat.js | 91 + node_modules/moment/test/moment/sod_eod.js | 267 + .../moment/test/moment/string_prototype.js | 17 + node_modules/moment/test/moment/utc.js | 77 + node_modules/moment/test/moment/week_year.js | 72 + node_modules/moment/test/moment/weekday.js | 158 + node_modules/moment/test/moment/weeks.js | 205 + node_modules/moment/test/moment/zones.js | 420 + node_modules/mongoose-pureautoinc/.npmignore | 2 + node_modules/mongoose-pureautoinc/README.md | 73 + .../benchmarks/benchmark.js | 86 + .../mongoose-pureautoinc/examples/example.js | 40 + node_modules/mongoose-pureautoinc/index.js | 5 + .../mongoose-pureautoinc/lib/pureautoinc.js | 105 + .../mongoose-pureautoinc/package.json | 37 + .../mongoose-pureautoinc/tests/test.js | 138 + node_modules/mongoose/.npmignore | 13 + node_modules/mongoose/.travis.yml | 7 + node_modules/mongoose/CONTRIBUTING.md | 60 + node_modules/mongoose/History.md | 1673 + node_modules/mongoose/README.md | 269 + node_modules/mongoose/examples/README.md | 42 + node_modules/mongoose/examples/doc-methods.js | 70 + node_modules/mongoose/examples/hooks.js | 42 + .../population-across-three-collections.js | 135 + .../mongoose/examples/population-basic.js | 95 + .../examples/population-of-existing-doc.js | 101 + .../population-of-multiple-existing-docs.js | 112 + .../mongoose/examples/population-options.js | 124 + .../examples/population-plain-objects.js | 96 + node_modules/mongoose/examples/schema.js | 102 + node_modules/mongoose/index.js | 7 + node_modules/mongoose/lib/collection.js | 188 + node_modules/mongoose/lib/connection.js | 706 + node_modules/mongoose/lib/connectionstate.js | 24 + node_modules/mongoose/lib/document.js | 1712 + node_modules/mongoose/lib/drivers/SPEC.md | 4 + .../lib/drivers/node-mongodb-native/binary.js | 8 + .../drivers/node-mongodb-native/collection.js | 211 + .../drivers/node-mongodb-native/connection.js | 303 + .../drivers/node-mongodb-native/objectid.js | 29 + node_modules/mongoose/lib/error.js | 39 + node_modules/mongoose/lib/errors/cast.js | 35 + .../mongoose/lib/errors/divergentArray.js | 40 + node_modules/mongoose/lib/errors/document.js | 32 + .../mongoose/lib/errors/missingSchema.js | 32 + .../mongoose/lib/errors/overwriteModel.js | 30 + .../mongoose/lib/errors/validation.js | 49 + node_modules/mongoose/lib/errors/validator.js | 51 + node_modules/mongoose/lib/errors/version.js | 31 + node_modules/mongoose/lib/index.js | 580 + node_modules/mongoose/lib/internal.js | 31 + node_modules/mongoose/lib/model.js | 2254 + node_modules/mongoose/lib/namedscope.js | 70 + node_modules/mongoose/lib/promise.js | 231 + node_modules/mongoose/lib/query.js | 2612 + node_modules/mongoose/lib/queryhelpers.js | 35 + node_modules/mongoose/lib/querystream.js | 336 + node_modules/mongoose/lib/schema.js | 910 + node_modules/mongoose/lib/schema/array.js | 316 + node_modules/mongoose/lib/schema/boolean.js | 92 + node_modules/mongoose/lib/schema/buffer.js | 168 + node_modules/mongoose/lib/schema/date.js | 167 + .../mongoose/lib/schema/documentarray.js | 189 + node_modules/mongoose/lib/schema/index.js | 28 + node_modules/mongoose/lib/schema/mixed.js | 83 + node_modules/mongoose/lib/schema/number.js | 227 + node_modules/mongoose/lib/schema/objectid.js | 186 + node_modules/mongoose/lib/schema/string.js | 312 + node_modules/mongoose/lib/schemadefault.js | 34 + node_modules/mongoose/lib/schematype.js | 628 + node_modules/mongoose/lib/statemachine.js | 179 + node_modules/mongoose/lib/types/array.js | 679 + node_modules/mongoose/lib/types/buffer.js | 214 + .../mongoose/lib/types/documentarray.js | 192 + node_modules/mongoose/lib/types/embedded.js | 244 + node_modules/mongoose/lib/types/index.js | 13 + node_modules/mongoose/lib/types/objectid.js | 43 + node_modules/mongoose/lib/utils.js | 671 + node_modules/mongoose/lib/virtualtype.js | 103 + .../mongoose/node_modules/hooks/.npmignore | 2 + .../mongoose/node_modules/hooks/Makefile | 9 + .../mongoose/node_modules/hooks/README.md | 306 + .../mongoose/node_modules/hooks/hooks.alt.js | 134 + .../mongoose/node_modules/hooks/hooks.js | 161 + .../mongoose/node_modules/hooks/package.json | 50 + .../mongoose/node_modules/hooks/test.js | 691 + .../mongoose/node_modules/mongodb/.travis.yml | 5 + .../node_modules/mongodb/CONTRIBUTING.md | 23 + .../mongoose/node_modules/mongodb/LICENSE | 201 + .../mongoose/node_modules/mongodb/Makefile | 28 + .../mongoose/node_modules/mongodb/Readme.md | 421 + .../mongoose/node_modules/mongodb/index.js | 1 + .../mongoose/node_modules/mongodb/install.js | 40 + .../node_modules/mongodb/lib/mongodb/admin.js | 339 + .../mongodb/lib/mongodb/auth/mongodb_cr.js | 53 + .../lib/mongodb/auth/mongodb_gssapi.js | 149 + .../mongodb/lib/mongodb/auth/mongodb_plain.js | 66 + .../mongodb/lib/mongodb/auth/mongodb_sspi.js | 135 + .../mongodb/lib/mongodb/collection.js | 1780 + .../lib/mongodb/commands/base_command.js | 29 + .../lib/mongodb/commands/db_command.js | 245 + .../lib/mongodb/commands/delete_command.js | 114 + .../lib/mongodb/commands/get_more_command.js | 83 + .../lib/mongodb/commands/insert_command.js | 147 + .../mongodb/commands/kill_cursor_command.js | 98 + .../lib/mongodb/commands/query_command.js | 266 + .../lib/mongodb/commands/update_command.js | 174 + .../mongodb/lib/mongodb/connection/base.js | 466 + .../lib/mongodb/connection/connection.js | 505 + .../lib/mongodb/connection/connection_pool.js | 294 + .../mongodb/connection/connection_utils.js | 23 + .../mongodb/lib/mongodb/connection/mongos.js | 474 + .../lib/mongodb/connection/read_preference.js | 67 + .../lib/mongodb/connection/repl_set/ha.js | 411 + .../mongodb/connection/repl_set/options.js | 126 + .../mongodb/connection/repl_set/repl_set.js | 777 + .../connection/repl_set/repl_set_state.js | 70 + .../repl_set/strategies/ping_strategy.js | 304 + .../strategies/statistics_strategy.js | 80 + .../mongodb/lib/mongodb/connection/server.js | 1010 + .../lib/mongodb/connection/url_parser.js | 251 + .../mongodb/lib/mongodb/cursor.js | 948 + .../mongodb/lib/mongodb/cursorstream.js | 164 + .../node_modules/mongodb/lib/mongodb/db.js | 1946 + .../mongodb/lib/mongodb/gridfs/chunk.js | 221 + .../mongodb/lib/mongodb/gridfs/grid.js | 103 + .../mongodb/lib/mongodb/gridfs/gridstore.js | 1559 + .../mongodb/lib/mongodb/gridfs/readstream.js | 193 + .../node_modules/mongodb/lib/mongodb/index.js | 69 + .../mongodb/lib/mongodb/mongo_client.js | 371 + .../lib/mongodb/responses/mongo_reply.js | 144 + .../node_modules/mongodb/lib/mongodb/utils.js | 137 + .../mongodb/node_modules/bson/.travis.yml | 5 + .../mongodb/node_modules/bson/Makefile | 19 + .../mongodb/node_modules/bson/README.md | 45 + .../mongodb/node_modules/bson/binding.gyp | 17 + .../node_modules/bson/browser_build/bson.js | 4815 + .../bson/browser_build/package.json | 8 + .../mongodb/node_modules/bson/build/Makefile | 333 + .../build/Release/.deps/Release/bson.node.d | 1 + .../.deps/Release/obj.target/bson.node.d | 1 + .../Release/obj.target/bson/ext/bson.o.d | 28 + .../node_modules/bson/build/Release/bson.node | Bin 0 -> 57312 bytes .../bson/build/Release/linker.lock | 0 .../bson/build/Release/obj.target/bson.node | Bin 0 -> 57312 bytes .../build/Release/obj.target/bson/ext/bson.o | Bin 0 -> 67288 bytes .../node_modules/bson/build/binding.Makefile | 6 + .../node_modules/bson/build/bson.target.mk | 128 + .../node_modules/bson/build/config.gypi | 113 + .../node_modules/bson/build_browser.js | 7 + .../mongodb/node_modules/bson/ext/Makefile | 28 + .../mongodb/node_modules/bson/ext/bson.cc | 1006 + .../mongodb/node_modules/bson/ext/bson.h | 277 + .../mongodb/node_modules/bson/ext/index.js | 30 + .../bson/ext/win32/ia32/bson.node | Bin 0 -> 113152 bytes .../node_modules/bson/ext/win32/x64/bson.node | Bin 0 -> 118272 bytes .../mongodb/node_modules/bson/ext/wscript | 39 + .../node_modules/bson/lib/bson/binary.js | 339 + .../bson/lib/bson/binary_parser.js | 385 + .../node_modules/bson/lib/bson/bson.js | 1519 + .../node_modules/bson/lib/bson/code.js | 25 + .../node_modules/bson/lib/bson/db_ref.js | 31 + .../node_modules/bson/lib/bson/double.js | 33 + .../bson/lib/bson/float_parser.js | 121 + .../node_modules/bson/lib/bson/index.js | 74 + .../node_modules/bson/lib/bson/long.js | 854 + .../node_modules/bson/lib/bson/max_key.js | 13 + .../node_modules/bson/lib/bson/min_key.js | 13 + .../node_modules/bson/lib/bson/objectid.js | 253 + .../node_modules/bson/lib/bson/symbol.js | 48 + .../node_modules/bson/lib/bson/timestamp.js | 853 + .../mongodb/node_modules/bson/package.json | 56 + .../mongodb/node_modules/bson/tools/gleak.js | 21 + .../bson/tools/jasmine-1.1.0/MIT.LICENSE | 20 + .../bson/tools/jasmine-1.1.0/jasmine-html.js | 190 + .../bson/tools/jasmine-1.1.0/jasmine.css | 166 + .../bson/tools/jasmine-1.1.0/jasmine.js | 2476 + .../tools/jasmine-1.1.0/jasmine_favicon.png | Bin 0 -> 905 bytes .../mongodb/node_modules/kerberos/README.md | 4 + .../mongodb/node_modules/kerberos/binding.gyp | 41 + .../node_modules/kerberos/build/Makefile | 333 + .../Release/.deps/Release/kerberos.node.d | 1 + .../.deps/Release/obj.target/kerberos.node.d | 1 + .../kerberos/build/Release/kerberos.node | Bin 0 -> 5445 bytes .../kerberos/build/Release/linker.lock | 0 .../build/Release/obj.target/kerberos.node | Bin 0 -> 5445 bytes .../kerberos/build/binding.Makefile | 6 + .../node_modules/kerberos/build/config.gypi | 113 + .../kerberos/build/kerberos.target.mk | 42 + .../mongodb/node_modules/kerberos/index.js | 6 + .../kerberos/lib/auth_processes/mongodb.js | 281 + .../node_modules/kerberos/lib/base64.c | 120 + .../node_modules/kerberos/lib/base64.h | 18 + .../node_modules/kerberos/lib/kerberos.cc | 563 + .../node_modules/kerberos/lib/kerberos.h | 47 + .../node_modules/kerberos/lib/kerberos.js | 91 + .../kerberos/lib/kerberos_context.cc | 74 + .../kerberos/lib/kerberos_context.h | 48 + .../node_modules/kerberos/lib/kerberosgss.c | 668 + .../node_modules/kerberos/lib/kerberosgss.h | 70 + .../mongodb/node_modules/kerberos/lib/sspi.js | 15 + .../node_modules/kerberos/lib/win32/base64.c | 121 + .../node_modules/kerberos/lib/win32/base64.h | 18 + .../kerberos/lib/win32/kerberos.cc | 53 + .../kerberos/lib/win32/kerberos.h | 59 + .../kerberos/lib/win32/kerberos_sspi.c | 244 + .../kerberos/lib/win32/kerberos_sspi.h | 106 + .../node_modules/kerberos/lib/win32/worker.cc | 7 + .../node_modules/kerberos/lib/win32/worker.h | 37 + .../lib/win32/wrappers/security_buffer.cc | 110 + .../lib/win32/wrappers/security_buffer.h | 46 + .../lib/win32/wrappers/security_buffer.js | 12 + .../wrappers/security_buffer_descriptor.cc | 177 + .../wrappers/security_buffer_descriptor.h | 44 + .../wrappers/security_buffer_descriptor.js | 3 + .../lib/win32/wrappers/security_context.cc | 1211 + .../lib/win32/wrappers/security_context.h | 85 + .../lib/win32/wrappers/security_context.js | 3 + .../win32/wrappers/security_credentials.cc | 468 + .../lib/win32/wrappers/security_credentials.h | 67 + .../win32/wrappers/security_credentials.js | 22 + .../node_modules/kerberos/lib/worker.cc | 7 + .../node_modules/kerberos/lib/worker.h | 39 + .../node_modules/kerberos/package.json | 35 + .../kerberos/test/kerberos_tests.js | 34 + .../kerberos/test/kerberos_win32_test.js | 19 + .../win32/security_buffer_descriptor_tests.js | 41 + .../test/win32/security_buffer_tests.js | 22 + .../test/win32/security_credentials_tests.js | 55 + .../node_modules/mongodb/package.json | 229 + .../mongoose/node_modules/mpath/.npmignore | 2 + .../mongoose/node_modules/mpath/.travis.yml | 4 + .../mongoose/node_modules/mpath/History.md | 16 + .../mongoose/node_modules/mpath/LICENSE | 22 + .../mongoose/node_modules/mpath/Makefile | 5 + .../mongoose/node_modules/mpath/README.md | 278 + .../mongoose/node_modules/mpath/index.js | 1 + .../mongoose/node_modules/mpath/lib/index.js | 183 + .../mongoose/node_modules/mpath/package.json | 35 + .../mongoose/node_modules/mpath/test/index.js | 1630 + .../mongoose/node_modules/mpromise/.npmignore | 2 + .../node_modules/mpromise/.travis.yml | 4 + .../mongoose/node_modules/mpromise/History.md | 24 + .../mongoose/node_modules/mpromise/LICENSE | 22 + .../mongoose/node_modules/mpromise/Makefile | 12 + .../mongoose/node_modules/mpromise/README.md | 200 + .../mongoose/node_modules/mpromise/index.js | 1 + .../node_modules/mpromise/lib/promise.js | 268 + .../mpromise/node_modules/sliced/.npmignore | 2 + .../mpromise/node_modules/sliced/.travis.yml | 4 + .../mpromise/node_modules/sliced/History.md | 23 + .../mpromise/node_modules/sliced/LICENSE | 22 + .../mpromise/node_modules/sliced/Makefile | 5 + .../mpromise/node_modules/sliced/README.md | 62 + .../mpromise/node_modules/sliced/bench.js | 95 + .../node_modules/sliced/component.json | 13 + .../mpromise/node_modules/sliced/index.js | 1 + .../node_modules/sliced/lib/sliced.js | 37 + .../mpromise/node_modules/sliced/package.json | 35 + .../node_modules/sliced/test/index.js | 80 + .../node_modules/mpromise/package.json | 40 + .../mpromise/test/promise.test.js | 201 + .../node_modules/mpromise/test/promises-A.js | 35 + .../mongoose/node_modules/ms/.npmignore | 1 + .../mongoose/node_modules/ms/Makefile | 8 + .../mongoose/node_modules/ms/README.md | 65 + node_modules/mongoose/node_modules/ms/ms.js | 35 + .../mongoose/node_modules/ms/package.json | 19 + .../mongoose/node_modules/ms/test/index.html | 19 + .../node_modules/ms/test/support/jquery.js | 9266 ++ .../mongoose/node_modules/ms/test/test.js | 61 + .../mongoose/node_modules/muri/.npmignore | 2 + .../mongoose/node_modules/muri/.travis.yml | 4 + .../mongoose/node_modules/muri/History.md | 47 + .../mongoose/node_modules/muri/LICENSE | 22 + .../mongoose/node_modules/muri/Makefile | 5 + .../mongoose/node_modules/muri/README.md | 46 + .../mongoose/node_modules/muri/index.js | 1 + .../mongoose/node_modules/muri/lib/index.js | 235 + .../mongoose/node_modules/muri/package.json | 34 + .../mongoose/node_modules/muri/test/index.js | 312 + .../node_modules/regexp-clone/.npmignore | 2 + .../node_modules/regexp-clone/.travis.yml | 5 + .../node_modules/regexp-clone/History.md | 5 + .../node_modules/regexp-clone/LICENSE | 22 + .../node_modules/regexp-clone/Makefile | 5 + .../node_modules/regexp-clone/README.md | 18 + .../node_modules/regexp-clone/index.js | 20 + .../node_modules/regexp-clone/package.json | 33 + .../node_modules/regexp-clone/test/index.js | 112 + .../mongoose/node_modules/sliced/.npmignore | 2 + .../mongoose/node_modules/sliced/.travis.yml | 4 + .../mongoose/node_modules/sliced/History.md | 16 + .../mongoose/node_modules/sliced/LICENSE | 22 + .../mongoose/node_modules/sliced/Makefile | 5 + .../mongoose/node_modules/sliced/README.md | 62 + .../mongoose/node_modules/sliced/bench.js | 95 + .../mongoose/node_modules/sliced/index.js | 1 + .../node_modules/sliced/lib/sliced.js | 33 + .../mongoose/node_modules/sliced/package.json | 35 + .../node_modules/sliced/test/index.js | 80 + node_modules/mongoose/package.json | 70 + node_modules/mongoose/static.js | 18 + node_modules/mongoose/website.js | 60 + .../passport-google-oauth/.travis.yml | 5 + node_modules/passport-google-oauth/LICENSE | 20 + node_modules/passport-google-oauth/README.md | 114 + .../lib/passport-google-oauth/index.js | 18 + .../lib/passport-google-oauth/oauth.js | 118 + .../lib/passport-google-oauth/oauth2.js | 144 + .../node_modules/passport-oauth/.travis.yml | 5 + .../node_modules/passport-oauth/LICENSE | 20 + .../node_modules/passport-oauth/README.md | 89 + .../errors/internaloautherror.js | 46 + .../lib/passport-oauth/index.js | 20 + .../lib/passport-oauth/strategies/oauth.js | 300 + .../lib/passport-oauth/strategies/oauth2.js | 248 + .../lib/passport-oauth/strategies/utils.js | 46 + .../node_modules/oauth/.npmignore | 1 + .../passport-oauth/node_modules/oauth/LICENSE | 8 + .../node_modules/oauth/Makefile | 7 + .../node_modules/oauth/Readme.md | 99 + .../oauth/examples/express-gdata/server.js | 168 + .../express-gdata/views/google_calendars.ejs | 21 + .../express-gdata/views/google_contacts.ejs | 24 + .../examples/express-gdata/views/layout.ejs | 9 + .../oauth/examples/term.ie.oauth-HMAC-SHA1.js | 31 + .../node_modules/oauth/index.js | 3 + .../node_modules/oauth/lib/_utils.js | 4 + .../node_modules/oauth/lib/oauth.js | 556 + .../node_modules/oauth/lib/oauth2.js | 197 + .../node_modules/oauth/lib/sha1.js | 334 + .../node_modules/oauth/package.json | 37 + .../node_modules/oauth/tests/oauth.js | 792 + .../node_modules/oauth/tests/oauth2.js | 137 + .../node_modules/oauth/tests/sha1.js | 13 + .../node_modules/passport-oauth/package.json | 53 + .../node_modules/pkginfo/.npmignore | 2 + .../node_modules/pkginfo/README.md | 85 + .../node_modules/pkginfo/docs/docco.css | 194 + .../node_modules/pkginfo/docs/pkginfo.html | 101 + .../pkginfo/examples/all-properties.js | 19 + .../pkginfo/examples/array-argument.js | 20 + .../pkginfo/examples/multiple-properties.js | 19 + .../pkginfo/examples/object-argument.js | 22 + .../pkginfo/examples/package.json | 10 + .../pkginfo/examples/single-property.js | 19 + .../node_modules/pkginfo/lib/pkginfo.js | 132 + .../node_modules/pkginfo/package.json | 36 + .../node_modules/pkginfo/test/pkginfo-test.js | 69 + .../passport-google-oauth/package.json | 53 + node_modules/passport/.travis.yml | 5 + node_modules/passport/LICENSE | 20 + node_modules/passport/README.md | 138 + .../lib/passport/context/http/actions.js | 93 + .../lib/passport/context/http/context.js | 17 + .../passport/lib/passport/http/request.js | 91 + node_modules/passport/lib/passport/index.js | 453 + .../lib/passport/middleware/authenticate.js | 253 + .../lib/passport/middleware/initialize.js | 71 + .../lib/passport/strategies/session.js | 75 + .../passport/lib/passport/strategy.js | 33 + .../passport/node_modules/pause/.npmignore | 4 + .../passport/node_modules/pause/History.md | 5 + .../passport/node_modules/pause/Makefile | 7 + .../passport/node_modules/pause/Readme.md | 29 + .../passport/node_modules/pause/index.js | 29 + .../passport/node_modules/pause/package.json | 24 + .../passport/node_modules/pkginfo/.npmignore | 2 + .../passport/node_modules/pkginfo/README.md | 85 + .../node_modules/pkginfo/docs/docco.css | 194 + .../node_modules/pkginfo/docs/pkginfo.html | 101 + .../pkginfo/examples/all-properties.js | 19 + .../pkginfo/examples/array-argument.js | 20 + .../pkginfo/examples/multiple-properties.js | 19 + .../pkginfo/examples/object-argument.js | 22 + .../pkginfo/examples/package.json | 10 + .../pkginfo/examples/single-property.js | 19 + .../node_modules/pkginfo/lib/pkginfo.js | 132 + .../node_modules/pkginfo/package.json | 36 + .../node_modules/pkginfo/test/pkginfo-test.js | 69 + node_modules/passport/package.json | 53 + node_modules/piler/.npmignore | 2 + node_modules/piler/.travis.yml | 4 + node_modules/piler/LICENSE | 22 + node_modules/piler/README.md | 566 + node_modules/piler/examples/logger/.npmignore | 1 + node_modules/piler/examples/logger/README.md | 12 + node_modules/piler/examples/logger/app.js | 115 + .../piler/examples/logger/client/backbone.js | 1158 + .../piler/examples/logger/client/bar.coffee | 2 + .../piler/examples/logger/client/foo.coffee | 5 + .../piler/examples/logger/client/hello.coffee | 5 + .../piler/examples/logger/client/hello.js | 6 + .../examples/logger/client/underscore.js | 839 + node_modules/piler/examples/logger/share.js | 7 + node_modules/piler/examples/logger/style.css | 7 + node_modules/piler/examples/logger/style.less | 3 + node_modules/piler/examples/logger/style.styl | 9 + .../piler/examples/logger/views/index.jade | 8 + node_modules/piler/examples/simple/README.md | 14 + node_modules/piler/examples/simple/app.js | 68 + .../piler/examples/simple/client/backbone.js | 1158 + .../piler/examples/simple/client/bar.coffee | 2 + .../piler/examples/simple/client/foo.coffee | 5 + .../piler/examples/simple/client/hello.coffee | 5 + .../piler/examples/simple/client/hello.js | 6 + .../examples/simple/client/underscore.js | 839 + node_modules/piler/examples/simple/share.js | 7 + node_modules/piler/examples/simple/style.css | 7 + node_modules/piler/examples/simple/style.less | 3 + node_modules/piler/examples/simple/style.styl | 9 + .../piler/examples/simple/views/index.jade | 8 + node_modules/piler/index.js | 2 + node_modules/piler/lib/asseturlparse.coffee | 29 + node_modules/piler/lib/compilers.coffee | 57 + node_modules/piler/lib/livecss.coffee | 99 + node_modules/piler/lib/logger.coffee | 8 + node_modules/piler/lib/minify.coffee | 35 + node_modules/piler/lib/piler.coffee | 450 + node_modules/piler/lib/serialize.coffee | 40 + node_modules/piler/node_modules/.bin/cake | 1 + node_modules/piler/node_modules/.bin/coffee | 1 + node_modules/piler/node_modules/.bin/csso | 1 + node_modules/piler/node_modules/.bin/uglifyjs | 1 + .../piler/node_modules/async/.gitmodules | 9 + .../piler/node_modules/async/.npmignore | 4 + node_modules/piler/node_modules/async/LICENSE | 19 + .../piler/node_modules/async/Makefile | 25 + .../piler/node_modules/async/README.md | 1021 + .../piler/node_modules/async/index.js | 3 + .../piler/node_modules/async/lib/async.js | 692 + .../piler/node_modules/async/package.json | 35 + .../node_modules/coffee-script/.npmignore | 11 + .../piler/node_modules/coffee-script/CNAME | 1 + .../piler/node_modules/coffee-script/LICENSE | 22 + .../piler/node_modules/coffee-script/README | 51 + .../piler/node_modules/coffee-script/Rakefile | 78 + .../piler/node_modules/coffee-script/bin/cake | 7 + .../node_modules/coffee-script/bin/coffee | 7 + .../coffee-script/extras/jsl.conf | 44 + .../lib/coffee-script/browser.js | 92 + .../coffee-script/lib/coffee-script/cake.js | 111 + .../lib/coffee-script/coffee-script.js | 167 + .../lib/coffee-script/command.js | 500 + .../lib/coffee-script/grammar.js | 606 + .../lib/coffee-script/helpers.js | 77 + .../coffee-script/lib/coffee-script/index.js | 11 + .../coffee-script/lib/coffee-script/lexer.js | 788 + .../coffee-script/lib/coffee-script/nodes.js | 2986 + .../lib/coffee-script/optparse.js | 138 + .../coffee-script/lib/coffee-script/parser.js | 683 + .../coffee-script/lib/coffee-script/repl.js | 261 + .../lib/coffee-script/rewriter.js | 349 + .../coffee-script/lib/coffee-script/scope.js | 146 + .../node_modules/coffee-script/package.json | 49 + .../piler/node_modules/csso/GNUmakefile | 35 + .../piler/node_modules/csso/MANUAL.en.md | 619 + .../piler/node_modules/csso/MANUAL.ru.md | 789 + .../piler/node_modules/csso/MIT-LICENSE.txt | 19 + .../piler/node_modules/csso/README.md | 139 + .../piler/node_modules/csso/README.ru.md | 139 + node_modules/piler/node_modules/csso/USAGE | 37 + node_modules/piler/node_modules/csso/VERSION | 1 + node_modules/piler/node_modules/csso/bin/csso | 14 + .../csso/doc/compressflow.graphml | 320 + .../node_modules/csso/doc/compressflow.png | Bin 0 -> 30585 bytes .../piler/node_modules/csso/lib/compressor.js | 1453 + .../piler/node_modules/csso/lib/csso.js | 70 + .../piler/node_modules/csso/lib/cssoapi.js | 20 + .../piler/node_modules/csso/lib/parser.js | 902 + .../piler/node_modules/csso/lib/translator.js | 126 + .../piler/node_modules/csso/lib/util.js | 41 + .../piler/node_modules/csso/package.json | 35 + .../node_modules/csso/src/compressor.node.js | 6 + .../csso/src/compressor.shared.js | 1281 + .../node_modules/csso/src/compressor.web.js | 2 + .../piler/node_modules/csso/src/csso.other.js | 148 + .../piler/node_modules/csso/src/csso.pecode | 190 + .../node_modules/csso/src/parser.node.js | 3 + .../node_modules/csso/src/translator.node.js | 7 + .../csso/src/translator.shared.js | 119 + .../piler/node_modules/csso/src/trbl.js | 166 + .../piler/node_modules/csso/src/util.node.js | 9 + .../node_modules/csso/src/util.shared.js | 32 + .../test/data/test_atkeyword/atkeyword.0.css | 1 + .../test/data/test_atkeyword/atkeyword.0.l | 1 + .../test/data/test_atkeyword/atkeyword.0.p | 2 + .../test/data/test_atkeyword/atkeyword.1.css | 1 + .../test/data/test_atkeyword/atkeyword.1.l | 1 + .../test/data/test_atkeyword/atkeyword.1.p | 2 + .../csso/test/data/test_atruleb/atruleb.0.css | 1 + .../csso/test/data/test_atruleb/atruleb.0.l | 1 + .../csso/test/data/test_atruleb/atruleb.0.p | 9 + .../csso/test/data/test_atruleb/atruleb.1.css | 1 + .../csso/test/data/test_atruleb/atruleb.1.l | 1 + .../csso/test/data/test_atruleb/atruleb.1.p | 14 + .../csso/test/data/test_atruleb/atruleb.2.css | 1 + .../csso/test/data/test_atruleb/atruleb.2.l | 1 + .../csso/test/data/test_atruleb/atruleb.2.p | 22 + .../test/data/test_atruleb/atruleb.c.0.css | 1 + .../csso/test/data/test_atruleb/atruleb.c.0.l | 1 + .../csso/test/data/test_atruleb/atruleb.c.0.p | 14 + .../test/data/test_atruleb/atruleb.c.1.css | 1 + .../csso/test/data/test_atruleb/atruleb.c.1.l | 1 + .../csso/test/data/test_atruleb/atruleb.c.1.p | 18 + .../test/data/test_atruleb/atruleb.c.2.css | 1 + .../csso/test/data/test_atruleb/atruleb.c.2.l | 1 + .../csso/test/data/test_atruleb/atruleb.c.2.p | 31 + .../test/data/test_atruleb/atruleb.s.0.css | 1 + .../csso/test/data/test_atruleb/atruleb.s.0.l | 1 + .../csso/test/data/test_atruleb/atruleb.s.0.p | 14 + .../test/data/test_atruleb/atruleb.s.1.css | 1 + .../csso/test/data/test_atruleb/atruleb.s.1.l | 1 + .../csso/test/data/test_atruleb/atruleb.s.1.p | 18 + .../test/data/test_atruleb/atruleb.s.2.css | 1 + .../csso/test/data/test_atruleb/atruleb.s.2.l | 1 + .../csso/test/data/test_atruleb/atruleb.s.2.p | 31 + .../csso/test/data/test_atruler/atruler.0.css | 1 + .../csso/test/data/test_atruler/atruler.0.l | 1 + .../csso/test/data/test_atruler/atruler.0.p | 16 + .../csso/test/data/test_atruler/atruler.1.css | 1 + .../csso/test/data/test_atruler/atruler.1.l | 1 + .../csso/test/data/test_atruler/atruler.1.p | 20 + .../csso/test/data/test_atruler/atruler.2.css | 1 + .../csso/test/data/test_atruler/atruler.2.l | 1 + .../csso/test/data/test_atruler/atruler.2.p | 28 + .../test/data/test_atruler/atruler.c.0.css | 1 + .../csso/test/data/test_atruler/atruler.c.0.l | 1 + .../csso/test/data/test_atruler/atruler.c.0.p | 23 + .../test/data/test_atruler/atruler.c.1.css | 1 + .../csso/test/data/test_atruler/atruler.c.1.l | 1 + .../csso/test/data/test_atruler/atruler.c.1.p | 27 + .../test/data/test_atruler/atruler.c.2.css | 1 + .../csso/test/data/test_atruler/atruler.c.2.l | 1 + .../csso/test/data/test_atruler/atruler.c.2.p | 40 + .../test/data/test_atruler/atruler.s.0.css | 1 + .../csso/test/data/test_atruler/atruler.s.0.l | 1 + .../csso/test/data/test_atruler/atruler.s.0.p | 23 + .../test/data/test_atruler/atruler.s.1.css | 1 + .../csso/test/data/test_atruler/atruler.s.1.l | 1 + .../csso/test/data/test_atruler/atruler.s.1.p | 27 + .../test/data/test_atruler/atruler.s.2.css | 1 + .../csso/test/data/test_atruler/atruler.s.2.l | 1 + .../csso/test/data/test_atruler/atruler.s.2.p | 40 + .../data/test_atruler/webkit.keyfraymes.0.css | 1 + .../data/test_atruler/webkit.keyfraymes.0.l | 1 + .../data/test_atruler/webkit.keyfraymes.0.p | 47 + .../csso/test/data/test_atrules/atrules.0.css | 1 + .../csso/test/data/test_atrules/atrules.0.l | 1 + .../csso/test/data/test_atrules/atrules.0.p | 3 + .../csso/test/data/test_atrules/atrules.1.css | 1 + .../csso/test/data/test_atrules/atrules.1.l | 1 + .../csso/test/data/test_atrules/atrules.1.p | 7 + .../csso/test/data/test_atrules/atrules.2.css | 1 + .../csso/test/data/test_atrules/atrules.2.l | 1 + .../csso/test/data/test_atrules/atrules.2.p | 5 + .../test/data/test_atrules/atrules.c.0.css | 1 + .../csso/test/data/test_atrules/atrules.c.0.l | 1 + .../csso/test/data/test_atrules/atrules.c.0.p | 4 + .../test/data/test_atrules/atrules.c.1.css | 1 + .../csso/test/data/test_atrules/atrules.c.1.l | 1 + .../csso/test/data/test_atrules/atrules.c.1.p | 7 + .../test/data/test_atrules/atrules.s.0.css | 1 + .../csso/test/data/test_atrules/atrules.s.0.l | 1 + .../csso/test/data/test_atrules/atrules.s.0.p | 4 + .../test/data/test_atrules/atrules.s.1.css | 1 + .../csso/test/data/test_atrules/atrules.s.1.l | 1 + .../csso/test/data/test_atrules/atrules.s.1.p | 7 + .../csso/test/data/test_attrib/attrib.0.css | 1 + .../csso/test/data/test_attrib/attrib.0.l | 1 + .../csso/test/data/test_attrib/attrib.0.p | 4 + .../csso/test/data/test_attrib/attrib.1.css | 1 + .../csso/test/data/test_attrib/attrib.1.l | 1 + .../csso/test/data/test_attrib/attrib.1.p | 4 + .../csso/test/data/test_attrib/attrib.2.css | 1 + .../csso/test/data/test_attrib/attrib.2.l | 1 + .../csso/test/data/test_attrib/attrib.c.0.css | 1 + .../csso/test/data/test_attrib/attrib.c.0.l | 1 + .../csso/test/data/test_attrib/attrib.c.0.p | 8 + .../csso/test/data/test_attrib/attrib.c.1.css | 1 + .../csso/test/data/test_attrib/attrib.c.1.l | 1 + .../csso/test/data/test_attrib/attrib.c.1.p | 8 + .../csso/test/data/test_attrib/attrib.s.0.css | 1 + .../csso/test/data/test_attrib/attrib.s.0.l | 1 + .../csso/test/data/test_attrib/attrib.s.0.p | 8 + .../csso/test/data/test_attrib/attrib.s.1.css | 1 + .../csso/test/data/test_attrib/attrib.s.1.l | 1 + .../csso/test/data/test_attrib/attrib.s.1.p | 8 + .../data/test_attrselector/attrselector.0.css | 1 + .../data/test_attrselector/attrselector.0.l | 1 + .../data/test_attrselector/attrselector.0.p | 1 + .../data/test_attrselector/attrselector.1.css | 1 + .../data/test_attrselector/attrselector.1.l | 1 + .../data/test_attrselector/attrselector.1.p | 1 + .../data/test_attrselector/attrselector.2.css | 1 + .../data/test_attrselector/attrselector.2.l | 1 + .../data/test_attrselector/attrselector.2.p | 1 + .../data/test_attrselector/attrselector.3.css | 1 + .../data/test_attrselector/attrselector.3.l | 1 + .../data/test_attrselector/attrselector.3.p | 1 + .../data/test_attrselector/attrselector.4.css | 1 + .../data/test_attrselector/attrselector.4.l | 1 + .../data/test_attrselector/attrselector.4.p | 1 + .../csso/test/data/test_block/block.0.css | 1 + .../csso/test/data/test_block/block.0.l | 1 + .../csso/test/data/test_block/block.0.p | 1 + .../csso/test/data/test_block/block.1.css | 1 + .../csso/test/data/test_block/block.1.l | 1 + .../csso/test/data/test_block/block.1.p | 2 + .../csso/test/data/test_block/block.2.css | 1 + .../csso/test/data/test_block/block.2.l | 1 + .../csso/test/data/test_block/block.2.p | 6 + .../csso/test/data/test_block/block.3.css | 1 + .../csso/test/data/test_block/block.3.l | 1 + .../csso/test/data/test_block/block.3.p | 7 + .../csso/test/data/test_block/block.4.css | 1 + .../csso/test/data/test_block/block.4.l | 1 + .../csso/test/data/test_block/block.4.p | 12 + .../csso/test/data/test_block/block.c.0.css | 1 + .../csso/test/data/test_block/block.c.0.l | 1 + .../csso/test/data/test_block/block.c.0.p | 2 + .../csso/test/data/test_block/block.c.1.css | 1 + .../csso/test/data/test_block/block.c.1.l | 1 + .../csso/test/data/test_block/block.c.1.p | 4 + .../csso/test/data/test_block/block.c.2.css | 1 + .../csso/test/data/test_block/block.c.2.l | 1 + .../csso/test/data/test_block/block.c.2.p | 8 + .../csso/test/data/test_block/block.c.3.css | 1 + .../csso/test/data/test_block/block.c.3.l | 1 + .../csso/test/data/test_block/block.c.3.p | 10 + .../csso/test/data/test_block/block.c.4.css | 1 + .../csso/test/data/test_block/block.c.4.l | 1 + .../csso/test/data/test_block/block.c.4.p | 16 + .../csso/test/data/test_block/block.s.0.css | 1 + .../csso/test/data/test_block/block.s.0.l | 1 + .../csso/test/data/test_block/block.s.0.p | 2 + .../csso/test/data/test_block/block.s.1.css | 1 + .../csso/test/data/test_block/block.s.1.l | 1 + .../csso/test/data/test_block/block.s.1.p | 4 + .../csso/test/data/test_block/block.s.2.css | 1 + .../csso/test/data/test_block/block.s.2.l | 1 + .../csso/test/data/test_block/block.s.2.p | 8 + .../csso/test/data/test_block/block.s.3.css | 1 + .../csso/test/data/test_block/block.s.3.l | 1 + .../csso/test/data/test_block/block.s.3.p | 10 + .../csso/test/data/test_block/block.s.4.css | 1 + .../csso/test/data/test_block/block.s.4.l | 1 + .../csso/test/data/test_block/block.s.4.p | 16 + .../csso/test/data/test_braces/braces.0.css | 1 + .../csso/test/data/test_braces/braces.0.l | 1 + .../csso/test/data/test_braces/braces.0.p | 1 + .../csso/test/data/test_braces/braces.1.css | 1 + .../csso/test/data/test_braces/braces.1.l | 1 + .../csso/test/data/test_braces/braces.1.p | 2 + .../csso/test/data/test_braces/braces.2.css | 1 + .../csso/test/data/test_braces/braces.2.l | 1 + .../csso/test/data/test_braces/braces.2.p | 2 + .../csso/test/data/test_braces/braces.3.css | 1 + .../csso/test/data/test_braces/braces.3.l | 1 + .../csso/test/data/test_braces/braces.3.p | 4 + .../csso/test/data/test_braces/braces.4.css | 1 + .../csso/test/data/test_braces/braces.4.l | 1 + .../csso/test/data/test_braces/braces.4.p | 1 + .../csso/test/data/test_braces/braces.5.css | 1 + .../csso/test/data/test_braces/braces.5.l | 1 + .../csso/test/data/test_braces/braces.5.p | 2 + .../csso/test/data/test_braces/braces.6.css | 1 + .../csso/test/data/test_braces/braces.6.l | 1 + .../csso/test/data/test_braces/braces.6.p | 2 + .../csso/test/data/test_braces/braces.7.css | 1 + .../csso/test/data/test_braces/braces.7.l | 1 + .../csso/test/data/test_braces/braces.7.p | 4 + .../csso/test/data/test_braces/braces.8.css | 1 + .../csso/test/data/test_braces/braces.8.l | 1 + .../csso/test/data/test_braces/braces.8.p | 4 + .../csso/test/data/test_braces/braces.c.0.css | 1 + .../csso/test/data/test_braces/braces.c.0.l | 1 + .../csso/test/data/test_braces/braces.c.0.p | 2 + .../csso/test/data/test_braces/braces.c.1.css | 1 + .../csso/test/data/test_braces/braces.c.1.l | 1 + .../csso/test/data/test_braces/braces.c.1.p | 4 + .../csso/test/data/test_braces/braces.c.2.css | 1 + .../csso/test/data/test_braces/braces.c.2.l | 1 + .../csso/test/data/test_braces/braces.c.2.p | 4 + .../csso/test/data/test_braces/braces.c.3.css | 1 + .../csso/test/data/test_braces/braces.c.3.l | 1 + .../csso/test/data/test_braces/braces.c.3.p | 8 + .../csso/test/data/test_braces/braces.c.4.css | 1 + .../csso/test/data/test_braces/braces.c.4.l | 1 + .../csso/test/data/test_braces/braces.c.4.p | 2 + .../csso/test/data/test_braces/braces.c.5.css | 1 + .../csso/test/data/test_braces/braces.c.5.l | 1 + .../csso/test/data/test_braces/braces.c.5.p | 4 + .../csso/test/data/test_braces/braces.c.6.css | 1 + .../csso/test/data/test_braces/braces.c.6.l | 1 + .../csso/test/data/test_braces/braces.c.6.p | 4 + .../csso/test/data/test_braces/braces.c.7.css | 1 + .../csso/test/data/test_braces/braces.c.7.l | 1 + .../csso/test/data/test_braces/braces.c.7.p | 8 + .../csso/test/data/test_braces/braces.s.0.css | 1 + .../csso/test/data/test_braces/braces.s.0.l | 1 + .../csso/test/data/test_braces/braces.s.0.p | 2 + .../csso/test/data/test_braces/braces.s.1.css | 1 + .../csso/test/data/test_braces/braces.s.1.l | 1 + .../csso/test/data/test_braces/braces.s.1.p | 4 + .../csso/test/data/test_braces/braces.s.2.css | 1 + .../csso/test/data/test_braces/braces.s.2.l | 1 + .../csso/test/data/test_braces/braces.s.2.p | 4 + .../csso/test/data/test_braces/braces.s.3.css | 1 + .../csso/test/data/test_braces/braces.s.3.l | 1 + .../csso/test/data/test_braces/braces.s.3.p | 8 + .../csso/test/data/test_braces/braces.s.4.css | 1 + .../csso/test/data/test_braces/braces.s.4.l | 1 + .../csso/test/data/test_braces/braces.s.4.p | 2 + .../csso/test/data/test_braces/braces.s.5.css | 1 + .../csso/test/data/test_braces/braces.s.5.l | 1 + .../csso/test/data/test_braces/braces.s.5.p | 4 + .../csso/test/data/test_braces/braces.s.6.css | 1 + .../csso/test/data/test_braces/braces.s.6.l | 1 + .../csso/test/data/test_braces/braces.s.6.p | 4 + .../csso/test/data/test_braces/braces.s.7.css | 1 + .../csso/test/data/test_braces/braces.s.7.l | 1 + .../csso/test/data/test_braces/braces.s.7.p | 8 + .../csso/test/data/test_clazz/clazz.0.css | 1 + .../csso/test/data/test_clazz/clazz.0.l | 1 + .../csso/test/data/test_clazz/clazz.0.p | 2 + .../data/test_combinator/combinator.0.css | 1 + .../test/data/test_combinator/combinator.0.l | 1 + .../test/data/test_combinator/combinator.0.p | 1 + .../data/test_combinator/combinator.1.css | 1 + .../test/data/test_combinator/combinator.1.l | 1 + .../test/data/test_combinator/combinator.1.p | 1 + .../data/test_combinator/combinator.2.css | 1 + .../test/data/test_combinator/combinator.2.l | 1 + .../test/data/test_combinator/combinator.2.p | 1 + .../csso/test/data/test_comment/comment.0.css | 1 + .../csso/test/data/test_comment/comment.0.l | 1 + .../csso/test/data/test_comment/comment.0.p | 1 + .../data/test_declaration/declaration.0.css | 1 + .../data/test_declaration/declaration.0.l | 1 + .../data/test_declaration/declaration.0.p | 5 + .../data/test_declaration/declaration.1.css | 1 + .../data/test_declaration/declaration.1.l | 1 + .../data/test_declaration/declaration.1.p | 5 + .../data/test_declaration/declaration.c.0.css | 1 + .../data/test_declaration/declaration.c.0.l | 1 + .../data/test_declaration/declaration.c.0.p | 6 + .../data/test_declaration/declaration.c.1.css | 1 + .../data/test_declaration/declaration.c.1.l | 1 + .../data/test_declaration/declaration.c.1.p | 6 + .../data/test_declaration/declaration.c.2.css | 1 + .../data/test_declaration/declaration.c.2.l | 1 + .../data/test_declaration/declaration.c.2.p | 7 + .../data/test_declaration/declaration.c.3.css | 1 + .../data/test_declaration/declaration.c.3.l | 1 + .../data/test_declaration/declaration.c.3.p | 11 + .../data/test_declaration/declaration.s.0.css | 1 + .../data/test_declaration/declaration.s.0.l | 1 + .../data/test_declaration/declaration.s.0.p | 6 + .../data/test_declaration/declaration.s.1.css | 1 + .../data/test_declaration/declaration.s.1.l | 1 + .../data/test_declaration/declaration.s.1.p | 6 + .../data/test_declaration/declaration.s.2.css | 1 + .../data/test_declaration/declaration.s.2.l | 1 + .../data/test_declaration/declaration.s.2.p | 7 + .../data/test_declaration/declaration.s.3.css | 1 + .../data/test_declaration/declaration.s.3.l | 1 + .../data/test_declaration/declaration.s.3.p | 7 + .../test/data/test_decldelim/decldelim.0.css | 1 + .../test/data/test_decldelim/decldelim.0.l | 1 + .../test/data/test_decldelim/decldelim.0.p | 1 + .../csso/test/data/test_delim/delim.0.css | 1 + .../csso/test/data/test_delim/delim.0.l | 1 + .../csso/test/data/test_delim/delim.0.p | 1 + .../test/data/test_dimension/dimension.0.css | 1 + .../test/data/test_dimension/dimension.0.l | 1 + .../test/data/test_dimension/dimension.0.p | 3 + .../test/data/test_dimension/dimension.1.css | 1 + .../test/data/test_dimension/dimension.1.l | 1 + .../test/data/test_dimension/dimension.1.p | 3 + .../test/data/test_dimension/dimension.2.css | 1 + .../test/data/test_dimension/dimension.2.l | 1 + .../test/data/test_dimension/dimension.2.p | 3 + .../csso/test/data/test_filter/filter.0.css | 1 + .../csso/test/data/test_filter/filter.0.l | 1 + .../csso/test/data/test_filter/filter.0.p | 6 + .../csso/test/data/test_filter/filter.1.css | 1 + .../csso/test/data/test_filter/filter.1.l | 1 + .../csso/test/data/test_filter/filter.1.p | 8 + .../csso/test/data/test_filter/filter.2.css | 1 + .../csso/test/data/test_filter/filter.2.l | 1 + .../csso/test/data/test_filter/filter.2.p | 6 + .../csso/test/data/test_filter/filter.3.css | 1 + .../csso/test/data/test_filter/filter.3.l | 1 + .../csso/test/data/test_filter/filter.3.p | 6 + .../csso/test/data/test_filter/filter.4.css | 1 + .../csso/test/data/test_filter/filter.4.l | 1 + .../csso/test/data/test_filter/filter.4.p | 6 + .../csso/test/data/test_filter/filter.5.css | 1 + .../csso/test/data/test_filter/filter.5.l | 1 + .../csso/test/data/test_filter/filter.5.p | 6 + .../csso/test/data/test_filter/filter.c.0.css | 1 + .../csso/test/data/test_filter/filter.c.0.l | 1 + .../csso/test/data/test_filter/filter.c.0.p | 8 + .../csso/test/data/test_filter/filter.c.1.css | 1 + .../csso/test/data/test_filter/filter.c.1.l | 1 + .../csso/test/data/test_filter/filter.c.1.p | 8 + .../csso/test/data/test_filter/filter.s.0.css | 1 + .../csso/test/data/test_filter/filter.s.0.l | 1 + .../csso/test/data/test_filter/filter.s.0.p | 8 + .../csso/test/data/test_filter/filter.s.1.css | 2 + .../csso/test/data/test_filter/filter.s.1.l | 2 + .../csso/test/data/test_filter/filter.s.1.p | 10 + .../functionExpression.0.css | 1 + .../functionExpression.0.l | 1 + .../functionExpression.0.p | 1 + .../functionExpression.1.css | 1 + .../functionExpression.1.l | 1 + .../functionExpression.1.p | 1 + .../functionExpression.2.css | 1 + .../functionExpression.2.l | 1 + .../functionExpression.2.p | 1 + .../functionExpression.3.css | 1 + .../functionExpression.3.l | 1 + .../functionExpression.3.p | 1 + .../functionExpression.4.css | 1 + .../functionExpression.4.l | 1 + .../functionExpression.4.p | 1 + .../functionExpression.5.css | 1 + .../functionExpression.5.l | 1 + .../functionExpression.5.p | 1 + .../functionExpression.6.css | 1 + .../functionExpression.6.l | 1 + .../functionExpression.6.p | 1 + .../functionExpression.7.css | 3 + .../functionExpression.7.l | 3 + .../functionExpression.7.p | 3 + .../test/data/test_funktion/function.0.css | 1 + .../csso/test/data/test_funktion/function.0.l | 1 + .../csso/test/data/test_funktion/function.0.p | 3 + .../test/data/test_funktion/function.1.css | 1 + .../csso/test/data/test_funktion/function.1.l | 1 + .../csso/test/data/test_funktion/function.1.p | 4 + .../test/data/test_funktion/function.2.css | 1 + .../csso/test/data/test_funktion/function.2.l | 1 + .../csso/test/data/test_funktion/function.2.p | 4 + .../test/data/test_funktion/function.3.css | 1 + .../csso/test/data/test_funktion/function.3.l | 1 + .../csso/test/data/test_funktion/function.3.p | 6 + .../test/data/test_funktion/function.4.css | 1 + .../csso/test/data/test_funktion/function.4.l | 1 + .../csso/test/data/test_funktion/function.4.p | 6 + .../test/data/test_funktion/function.5.css | 1 + .../csso/test/data/test_funktion/function.5.l | 1 + .../csso/test/data/test_funktion/function.5.p | 16 + .../test/data/test_funktion/function.c.0.css | 1 + .../test/data/test_funktion/function.c.0.l | 1 + .../test/data/test_funktion/function.c.0.p | 4 + .../test/data/test_funktion/function.c.1.css | 1 + .../test/data/test_funktion/function.c.1.l | 1 + .../test/data/test_funktion/function.c.1.p | 6 + .../test/data/test_funktion/function.c.2.css | 1 + .../test/data/test_funktion/function.c.2.l | 1 + .../test/data/test_funktion/function.c.2.p | 6 + .../test/data/test_funktion/function.c.3.css | 1 + .../test/data/test_funktion/function.c.3.l | 1 + .../test/data/test_funktion/function.c.3.p | 10 + .../test/data/test_funktion/function.c.4.css | 1 + .../test/data/test_funktion/function.c.4.l | 1 + .../test/data/test_funktion/function.c.4.p | 10 + .../test/data/test_funktion/function.c.5.css | 1 + .../test/data/test_funktion/function.c.5.l | 1 + .../test/data/test_funktion/function.c.5.p | 24 + .../test/data/test_funktion/function.s.0.css | 1 + .../test/data/test_funktion/function.s.0.l | 1 + .../test/data/test_funktion/function.s.0.p | 4 + .../test/data/test_funktion/function.s.1.css | 1 + .../test/data/test_funktion/function.s.1.l | 1 + .../test/data/test_funktion/function.s.1.p | 6 + .../test/data/test_funktion/function.s.2.css | 1 + .../test/data/test_funktion/function.s.2.l | 1 + .../test/data/test_funktion/function.s.2.p | 6 + .../test/data/test_funktion/function.s.3.css | 1 + .../test/data/test_funktion/function.s.3.l | 1 + .../test/data/test_funktion/function.s.3.p | 10 + .../test/data/test_funktion/function.s.4.css | 1 + .../test/data/test_funktion/function.s.4.l | 1 + .../test/data/test_funktion/function.s.4.p | 10 + .../test/data/test_funktion/function.s.5.css | 1 + .../test/data/test_funktion/function.s.5.l | 1 + .../test/data/test_funktion/function.s.5.p | 24 + .../csso/test/data/test_ident/ident.0.css | 1 + .../csso/test/data/test_ident/ident.0.l | 1 + .../csso/test/data/test_ident/ident.0.p | 1 + .../csso/test/data/test_ident/ident.1.css | 1 + .../csso/test/data/test_ident/ident.1.l | 1 + .../csso/test/data/test_ident/ident.1.p | 1 + .../csso/test/data/test_ident/ident.2.css | 1 + .../csso/test/data/test_ident/ident.2.l | 1 + .../csso/test/data/test_ident/ident.2.p | 1 + .../csso/test/data/test_ident/ident.3.css | 1 + .../csso/test/data/test_ident/ident.3.l | 1 + .../csso/test/data/test_ident/ident.3.p | 1 + .../csso/test/data/test_ident/ident.4.css | 1 + .../csso/test/data/test_ident/ident.4.l | 1 + .../csso/test/data/test_ident/ident.4.p | 1 + .../csso/test/data/test_ident/ident.5.css | 1 + .../csso/test/data/test_ident/ident.5.l | 1 + .../csso/test/data/test_ident/ident.5.p | 1 + .../test/data/test_important/important.0.css | 1 + .../test/data/test_important/important.0.l | 1 + .../test/data/test_important/important.0.p | 1 + .../data/test_important/important.c.0.css | 1 + .../test/data/test_important/important.c.0.l | 1 + .../test/data/test_important/important.c.0.p | 2 + .../data/test_important/important.s.0.css | 1 + .../test/data/test_important/important.s.0.l | 1 + .../test/data/test_important/important.s.0.p | 2 + .../csso/test/data/test_nth/nth.0.css | 1 + .../csso/test/data/test_nth/nth.0.l | 1 + .../csso/test/data/test_nth/nth.0.p | 1 + .../csso/test/data/test_nth/nth.1.css | 1 + .../csso/test/data/test_nth/nth.1.l | 1 + .../csso/test/data/test_nth/nth.1.p | 1 + .../csso/test/data/test_nth/nth.2.css | 1 + .../csso/test/data/test_nth/nth.2.l | 1 + .../csso/test/data/test_nth/nth.2.p | 1 + .../csso/test/data/test_nth/nth.3.css | 1 + .../csso/test/data/test_nth/nth.3.l | 1 + .../csso/test/data/test_nth/nth.3.p | 1 + .../csso/test/data/test_nth/nth.4.css | 1 + .../csso/test/data/test_nth/nth.4.l | 1 + .../csso/test/data/test_nth/nth.4.p | 1 + .../data/test_nthselector/nthselector.0.css | 1 + .../data/test_nthselector/nthselector.0.l | 1 + .../data/test_nthselector/nthselector.0.p | 5 + .../data/test_nthselector/nthselector.1.css | 1 + .../data/test_nthselector/nthselector.1.l | 1 + .../data/test_nthselector/nthselector.1.p | 6 + .../data/test_nthselector/nthselector.c.0.css | 1 + .../data/test_nthselector/nthselector.c.0.l | 1 + .../data/test_nthselector/nthselector.c.0.p | 9 + .../data/test_nthselector/nthselector.c.1.css | 1 + .../data/test_nthselector/nthselector.c.1.l | 1 + .../data/test_nthselector/nthselector.c.1.p | 11 + .../data/test_nthselector/nthselector.s.0.css | 1 + .../data/test_nthselector/nthselector.s.0.l | 1 + .../data/test_nthselector/nthselector.s.0.p | 9 + .../data/test_nthselector/nthselector.s.1.css | 1 + .../data/test_nthselector/nthselector.s.1.l | 1 + .../data/test_nthselector/nthselector.s.1.p | 11 + .../csso/test/data/test_number/number.0.css | 1 + .../csso/test/data/test_number/number.0.l | 1 + .../csso/test/data/test_number/number.0.p | 1 + .../csso/test/data/test_number/number.1.css | 1 + .../csso/test/data/test_number/number.1.l | 1 + .../csso/test/data/test_number/number.1.p | 1 + .../csso/test/data/test_number/number.2.css | 1 + .../csso/test/data/test_number/number.2.l | 1 + .../csso/test/data/test_number/number.2.p | 1 + .../csso/test/data/test_number/number.3.css | 1 + .../csso/test/data/test_number/number.3.l | 1 + .../csso/test/data/test_number/number.4.css | 1 + .../csso/test/data/test_number/number.4.l | 1 + .../csso/test/data/test_number/number.5.css | 1 + .../csso/test/data/test_number/number.5.l | 1 + .../csso/test/data/test_number/number.6.css | 1 + .../csso/test/data/test_number/number.6.l | 1 + .../csso/test/data/test_number/number.7.css | 1 + .../csso/test/data/test_number/number.7.l | 1 + .../test/data/test_operator/operator.0.css | 1 + .../csso/test/data/test_operator/operator.0.l | 1 + .../csso/test/data/test_operator/operator.0.p | 1 + .../test/data/test_operator/operator.1.css | 1 + .../csso/test/data/test_operator/operator.1.l | 1 + .../csso/test/data/test_operator/operator.1.p | 1 + .../test/data/test_operator/operator.2.css | 1 + .../csso/test/data/test_operator/operator.2.l | 1 + .../csso/test/data/test_operator/operator.2.p | 1 + .../test/data/test_operator/operator.3.css | 1 + .../csso/test/data/test_operator/operator.3.l | 1 + .../csso/test/data/test_operator/operator.3.p | 1 + .../data/test_percentage/percentage.0.css | 1 + .../test/data/test_percentage/percentage.0.l | 1 + .../test/data/test_percentage/percentage.0.p | 2 + .../data/test_percentage/percentage.1.css | 1 + .../test/data/test_percentage/percentage.1.l | 1 + .../test/data/test_percentage/percentage.1.p | 2 + .../data/test_percentage/percentage.2.css | 1 + .../test/data/test_percentage/percentage.2.l | 1 + .../test/data/test_percentage/percentage.2.p | 2 + .../test/data/test_property/property.0.css | 1 + .../csso/test/data/test_property/property.0.l | 1 + .../csso/test/data/test_property/property.0.p | 2 + .../test/data/test_property/property.1.css | 1 + .../csso/test/data/test_property/property.1.l | 1 + .../csso/test/data/test_property/property.1.p | 2 + .../csso/test/data/test_pseudoc/pseudoc.0.css | 1 + .../csso/test/data/test_pseudoc/pseudoc.0.l | 1 + .../csso/test/data/test_pseudoc/pseudoc.0.p | 2 + .../csso/test/data/test_pseudoc/pseudoc.1.css | 1 + .../csso/test/data/test_pseudoc/pseudoc.1.l | 1 + .../csso/test/data/test_pseudoc/pseudoc.1.p | 2 + .../csso/test/data/test_pseudoe/pseudoe.0.css | 1 + .../csso/test/data/test_pseudoe/pseudoe.0.l | 1 + .../csso/test/data/test_pseudoe/pseudoe.0.p | 2 + .../csso/test/data/test_pseudoe/pseudoe.1.css | 1 + .../csso/test/data/test_pseudoe/pseudoe.1.l | 1 + .../csso/test/data/test_pseudoe/pseudoe.1.p | 2 + .../csso/test/data/test_ruleset/ruleset.0.css | 1 + .../csso/test/data/test_ruleset/ruleset.0.l | 1 + .../csso/test/data/test_ruleset/ruleset.0.p | 10 + .../csso/test/data/test_ruleset/ruleset.1.css | 1 + .../csso/test/data/test_ruleset/ruleset.1.l | 1 + .../csso/test/data/test_ruleset/ruleset.1.p | 16 + .../csso/test/data/test_ruleset/ruleset.2.css | 1 + .../csso/test/data/test_ruleset/ruleset.2.l | 1 + .../csso/test/data/test_ruleset/ruleset.2.p | 13 + .../csso/test/data/test_ruleset/ruleset.3.css | 1 + .../csso/test/data/test_ruleset/ruleset.3.l | 1 + .../csso/test/data/test_ruleset/ruleset.3.p | 19 + .../csso/test/data/test_ruleset/ruleset.4.css | 1 + .../csso/test/data/test_ruleset/ruleset.4.l | 1 + .../csso/test/data/test_ruleset/ruleset.4.p | 18 + .../csso/test/data/test_ruleset/ruleset.5.css | 1 + .../csso/test/data/test_ruleset/ruleset.5.l | 1 + .../csso/test/data/test_ruleset/ruleset.5.p | 20 + .../test/data/test_ruleset/ruleset.c.0.css | 1 + .../csso/test/data/test_ruleset/ruleset.c.0.l | 1 + .../csso/test/data/test_ruleset/ruleset.c.0.p | 15 + .../test/data/test_ruleset/ruleset.c.1.css | 1 + .../csso/test/data/test_ruleset/ruleset.c.1.l | 1 + .../csso/test/data/test_ruleset/ruleset.c.1.p | 25 + .../test/data/test_ruleset/ruleset.c.2.css | 1 + .../csso/test/data/test_ruleset/ruleset.c.2.l | 1 + .../csso/test/data/test_ruleset/ruleset.c.2.p | 20 + .../test/data/test_ruleset/ruleset.c.3.css | 1 + .../csso/test/data/test_ruleset/ruleset.c.3.l | 1 + .../csso/test/data/test_ruleset/ruleset.c.3.p | 30 + .../test/data/test_ruleset/ruleset.s.0.css | 1 + .../csso/test/data/test_ruleset/ruleset.s.0.l | 1 + .../csso/test/data/test_ruleset/ruleset.s.0.p | 15 + .../test/data/test_ruleset/ruleset.s.1.css | 1 + .../csso/test/data/test_ruleset/ruleset.s.1.l | 1 + .../csso/test/data/test_ruleset/ruleset.s.1.p | 25 + .../test/data/test_ruleset/ruleset.s.2.css | 1 + .../csso/test/data/test_ruleset/ruleset.s.2.l | 1 + .../csso/test/data/test_ruleset/ruleset.s.2.p | 20 + .../test/data/test_ruleset/ruleset.s.3.css | 1 + .../csso/test/data/test_ruleset/ruleset.s.3.l | 1 + .../csso/test/data/test_ruleset/ruleset.s.3.p | 30 + .../test/data/test_ruleset/ruleset.s.4.css | 4 + .../csso/test/data/test_ruleset/ruleset.s.4.l | 4 + .../csso/test/data/test_ruleset/ruleset.s.4.p | 25 + .../test/data/test_ruleset/ruleset.s.5.css | 5 + .../csso/test/data/test_ruleset/ruleset.s.5.l | 5 + .../csso/test/data/test_ruleset/ruleset.s.5.p | 29 + .../data/test_ruleset/value.color.ident.0.css | 1 + .../data/test_ruleset/value.color.ident.0.l | 1 + .../data/test_ruleset/value.color.ident.1.css | 1 + .../data/test_ruleset/value.color.ident.1.l | 1 + .../test/data/test_selector/selector.0.css | 1 + .../csso/test/data/test_selector/selector.0.l | 1 + .../csso/test/data/test_selector/selector.0.p | 6 + .../test/data/test_selector/selector.1.css | 1 + .../csso/test/data/test_selector/selector.1.l | 1 + .../csso/test/data/test_selector/selector.1.p | 8 + .../csso/test/data/test_shash/shash.0.css | 1 + .../csso/test/data/test_shash/shash.0.l | 1 + .../csso/test/data/test_shash/shash.0.p | 1 + .../csso/test/data/test_shash/shash.1.css | 1 + .../csso/test/data/test_shash/shash.1.l | 1 + .../csso/test/data/test_shash/shash.1.p | 1 + .../test_simpleselector/simpleselector.0.css | 1 + .../test_simpleselector/simpleselector.0.l | 1 + .../test_simpleselector/simpleselector.0.p | 2 + .../test_simpleselector/simpleselector.1.css | 1 + .../test_simpleselector/simpleselector.1.l | 1 + .../test_simpleselector/simpleselector.1.p | 3 + .../test_simpleselector/simpleselector.10.css | 1 + .../test_simpleselector/simpleselector.10.l | 1 + .../test_simpleselector/simpleselector.10.p | 4 + .../test_simpleselector/simpleselector.11.css | 1 + .../test_simpleselector/simpleselector.11.l | 1 + .../test_simpleselector/simpleselector.11.p | 10 + .../test_simpleselector/simpleselector.12.css | 1 + .../test_simpleselector/simpleselector.12.l | 1 + .../test_simpleselector/simpleselector.12.p | 9 + .../test_simpleselector/simpleselector.13.css | 1 + .../test_simpleselector/simpleselector.13.l | 1 + .../test_simpleselector/simpleselector.13.p | 9 + .../test_simpleselector/simpleselector.2.css | 1 + .../test_simpleselector/simpleselector.2.l | 1 + .../test_simpleselector/simpleselector.2.p | 2 + .../test_simpleselector/simpleselector.3.css | 1 + .../test_simpleselector/simpleselector.3.l | 1 + .../test_simpleselector/simpleselector.3.p | 5 + .../test_simpleselector/simpleselector.4.css | 1 + .../test_simpleselector/simpleselector.4.l | 1 + .../test_simpleselector/simpleselector.4.p | 9 + .../test_simpleselector/simpleselector.5.css | 1 + .../test_simpleselector/simpleselector.5.l | 1 + .../test_simpleselector/simpleselector.5.p | 4 + .../test_simpleselector/simpleselector.6.css | 1 + .../test_simpleselector/simpleselector.6.l | 1 + .../test_simpleselector/simpleselector.6.p | 4 + .../test_simpleselector/simpleselector.7.css | 1 + .../test_simpleselector/simpleselector.7.l | 1 + .../test_simpleselector/simpleselector.7.p | 4 + .../test_simpleselector/simpleselector.8.css | 1 + .../test_simpleselector/simpleselector.8.l | 1 + .../test_simpleselector/simpleselector.8.p | 4 + .../test_simpleselector/simpleselector.9.css | 1 + .../test_simpleselector/simpleselector.9.l | 1 + .../test_simpleselector/simpleselector.9.p | 7 + .../simpleselector.c.0.css | 1 + .../test_simpleselector/simpleselector.c.0.l | 1 + .../test_simpleselector/simpleselector.c.0.p | 4 + .../simpleselector.c.1.css | 1 + .../test_simpleselector/simpleselector.c.1.l | 1 + .../test_simpleselector/simpleselector.c.1.p | 6 + .../simpleselector.c.2.css | 1 + .../test_simpleselector/simpleselector.c.2.l | 1 + .../test_simpleselector/simpleselector.c.2.p | 6 + .../simpleselector.c.3.css | 1 + .../test_simpleselector/simpleselector.c.3.l | 1 + .../test_simpleselector/simpleselector.c.3.p | 6 + .../simpleselector.c.4.css | 1 + .../simpleselector.s.0.css | 1 + .../test_simpleselector/simpleselector.s.0.l | 1 + .../test_simpleselector/simpleselector.s.0.p | 4 + .../simpleselector.s.1.css | 1 + .../test_simpleselector/simpleselector.s.1.l | 1 + .../test_simpleselector/simpleselector.s.1.p | 6 + .../simpleselector.s.2.css | 1 + .../test_simpleselector/simpleselector.s.2.l | 1 + .../test_simpleselector/simpleselector.s.2.p | 6 + .../simpleselector.s.3.css | 1 + .../test_simpleselector/simpleselector.s.3.l | 1 + .../test_simpleselector/simpleselector.s.3.p | 6 + .../simpleselector.s.4.css | 1 + .../test_simpleselector/simpleselector.s.4.l | 1 + .../test_simpleselector/simpleselector.s.4.p | 16 + .../csso/test/data/test_string/string.0.css | 1 + .../csso/test/data/test_string/string.0.l | 1 + .../csso/test/data/test_string/string.0.p | 1 + .../csso/test/data/test_string/string.1.css | 1 + .../csso/test/data/test_string/string.1.l | 1 + .../csso/test/data/test_string/string.1.p | 1 + .../csso/test/data/test_string/string.2.css | 1 + .../csso/test/data/test_string/string.2.l | 1 + .../csso/test/data/test_string/string.2.p | 1 + .../csso/test/data/test_string/string.3.css | 1 + .../csso/test/data/test_string/string.3.l | 1 + .../csso/test/data/test_string/string.3.p | 1 + .../compress.attrib.string.test1.cl | 1 + .../compress.attrib.string.test1.css | 1 + .../compress.attrib.string.test2.cl | 1 + .../compress.attrib.string.test2.css | 1 + .../compress.colormark.test1.cl | 1 + .../compress.colormark.test1.css | 8 + .../compress.css21.part15.6.test1.cl | 1 + .../compress.css21.part15.6.test1.css | 11 + .../compress.css21.part4.3.2.test1.cl | 1 + .../compress.css21.part4.3.2.test1.css | 1 + .../compress.css21.part4.3.2.test10.cl | 1 + .../compress.css21.part4.3.2.test10.css | 10 + .../compress.css21.part4.3.2.test2.cl | 1 + .../compress.css21.part4.3.2.test2.css | 1 + .../compress.css21.part4.3.2.test3.cl | 1 + .../compress.css21.part4.3.2.test3.css | 1 + .../compress.css21.part4.3.2.test4.cl | 1 + .../compress.css21.part4.3.2.test4.css | 1 + .../compress.css21.part4.3.2.test5.cl | 1 + .../compress.css21.part4.3.2.test5.css | 1 + .../compress.css21.part4.3.2.test6.cl | 1 + .../compress.css21.part4.3.2.test6.css | 1 + .../compress.css21.part4.3.2.test7.cl | 1 + .../compress.css21.part4.3.2.test7.css | 1 + .../compress.css21.part4.3.2.test8.cl | 1 + .../compress.css21.part4.3.2.test8.css | 1 + .../compress.css21.part4.3.2.test9.cl | 1 + .../compress.css21.part4.3.2.test9.css | 10 + .../compress.css21.part4.3.4.test1.cl | 1 + .../compress.css21.part4.3.4.test1.css | 2 + .../compress.css21.part4.3.4.test2.cl | 1 + .../compress.css21.part4.3.4.test2.css | 2 + .../compress.css21.part4.3.4.test3.cl | 1 + .../compress.css21.part4.3.4.test3.css | 2 + .../compress.css21.part4.3.4.test4.cl | 1 + .../compress.css21.part4.3.4.test4.css | 2 + .../compress.css21.part4.3.4.test5.cl | 1 + .../compress.css21.part4.3.4.test5.css | 2 + .../compress.css21.part4.3.4.test6.cl | 1 + .../compress.css21.part4.3.4.test6.css | 2 + .../compress.css21.part4.3.4.test7.cl | 1 + .../compress.css21.part4.3.4.test7.css | 2 + .../compress.css21.part4.3.4.test8.cl | 1 + .../compress.css21.part4.3.4.test8.css | 2 + .../compress.css21.part4.3.4.test9.cl | 1 + .../compress.css21.part4.3.4.test9.css | 2 + .../compress.css21.part4.3.6.test1.cl | 1 + .../compress.css21.part4.3.6.test1.css | 1 + .../compress.css21.part4.3.6.test2.cl | 1 + .../compress.css21.part4.3.6.test2.css | 1 + .../compress.css21.part4.3.6.test3.cl | 1 + .../compress.css21.part4.3.6.test3.css | 1 + .../compress.css21.part4.3.6.test4.cl | 1 + .../compress.css21.part4.3.6.test4.css | 1 + .../compress.css21.part4.3.6.test5.cl | 1 + .../compress.css21.part4.3.6.test5.css | 1 + .../compress.css21.part4.3.6.test6.cl | 1 + .../compress.css21.part4.3.6.test6.css | 25 + .../compress.css21.part4.3.6.test7.cl | 1 + .../compress.css21.part4.3.6.test7.css | 18 + .../compress.css21.part4.3.6.test8.cl | 1 + .../compress.css21.part4.3.6.test8.css | 14 + .../compress.css21.part4.3.7.test1.cl | 1 + .../compress.css21.part4.3.7.test1.css | 1 + .../compress.css21.part4.3.7.test2.cl | 1 + .../compress.css21.part4.3.7.test2.css | 1 + .../compress.css21.part4.3.7.test3.cl | 1 + .../compress.css21.part4.3.7.test3.css | 1 + .../compress.css21.part4.3.7.test4.cl | 1 + .../compress.css21.part4.3.7.test4.css | 1 + .../compress.css21.part4.3.7.test5.cl | 1 + .../compress.css21.part4.3.7.test5.css | 4 + .../compress.css21.part4.3.7.test6.cl | 1 + .../compress.css21.part4.3.7.test6.css | 4 + .../compress.css21.part4.4.test1.cl | 1 + .../compress.css21.part4.4.test1.css | 1 + .../compress.css21.part4.4.test2.cl | 1 + .../compress.css21.part4.4.test2.css | 2 + .../compress.css21.part4.4.test3.cl | 1 + .../compress.css21.part4.4.test3.css | 2 + .../compress.css21.part6.3.test1.cl | 1 + .../compress.css21.part6.3.test1.css | 1 + .../compress.css21.part6.3.test2.cl | 1 + .../compress.css21.part6.3.test2.css | 1 + .../compress.css21.part6.3.test3.cl | 1 + .../compress.css21.part6.3.test3.css | 1 + .../compress.css21.part6.3.test4.cl | 1 + .../compress.css21.part6.3.test4.css | 1 + .../compress.css21.part6.3.test5.cl | 1 + .../compress.css21.part6.3.test5.css | 2 + .../compress.css21.part6.3.test6.cl | 1 + .../compress.css21.part6.3.test6.css | 5 + .../compress.css21.part6.4.2.test1.cl | 1 + .../compress.css21.part6.4.2.test1.css | 1 + .../compress.css21.part6.4.2.test2.cl | 1 + .../compress.css21.part6.4.2.test2.css | 4 + .../compress.css21.part6.4.2.test3.cl | 1 + .../compress.css21.part6.4.2.test3.css | 9 + .../compress.css21.part7.test1.cl | 1 + .../compress.css21.part7.test1.css | 1 + .../compress.css21.part7.test2.cl | 1 + .../compress.css21.part7.test2.css | 1 + .../compress.css3.selectors.part2.test1.c.cl | 1 + .../compress.css3.selectors.part2.test1.c.css | 1 + .../compress.css3.selectors.part2.test1.cl | 1 + .../compress.css3.selectors.part2.test1.css | 1 + .../compress.css3.selectors.part2.test10.c.cl | 1 + ...compress.css3.selectors.part2.test10.c.css | 1 + .../compress.css3.selectors.part2.test10.cl | 1 + .../compress.css3.selectors.part2.test10.css | 1 + .../compress.css3.selectors.part2.test11.c.cl | 1 + ...compress.css3.selectors.part2.test11.c.css | 1 + .../compress.css3.selectors.part2.test11.cl | 1 + .../compress.css3.selectors.part2.test11.css | 1 + .../compress.css3.selectors.part2.test12.c.cl | 1 + ...compress.css3.selectors.part2.test12.c.css | 1 + .../compress.css3.selectors.part2.test12.cl | 1 + .../compress.css3.selectors.part2.test12.css | 1 + .../compress.css3.selectors.part2.test13.c.cl | 1 + ...compress.css3.selectors.part2.test13.c.css | 1 + .../compress.css3.selectors.part2.test13.cl | 1 + .../compress.css3.selectors.part2.test13.css | 1 + .../compress.css3.selectors.part2.test14.c.cl | 1 + ...compress.css3.selectors.part2.test14.c.css | 1 + .../compress.css3.selectors.part2.test14.cl | 1 + .../compress.css3.selectors.part2.test14.css | 1 + .../compress.css3.selectors.part2.test15.c.cl | 1 + ...compress.css3.selectors.part2.test15.c.css | 1 + .../compress.css3.selectors.part2.test15.cl | 1 + .../compress.css3.selectors.part2.test15.css | 1 + .../compress.css3.selectors.part2.test16.c.cl | 1 + ...compress.css3.selectors.part2.test16.c.css | 1 + .../compress.css3.selectors.part2.test16.cl | 1 + .../compress.css3.selectors.part2.test16.css | 1 + .../compress.css3.selectors.part2.test17.c.cl | 1 + ...compress.css3.selectors.part2.test17.c.css | 1 + .../compress.css3.selectors.part2.test17.cl | 1 + .../compress.css3.selectors.part2.test17.css | 1 + .../compress.css3.selectors.part2.test18.c.cl | 1 + ...compress.css3.selectors.part2.test18.c.css | 1 + .../compress.css3.selectors.part2.test18.cl | 1 + .../compress.css3.selectors.part2.test18.css | 1 + .../compress.css3.selectors.part2.test19.c.cl | 1 + ...compress.css3.selectors.part2.test19.c.css | 1 + .../compress.css3.selectors.part2.test19.cl | 1 + .../compress.css3.selectors.part2.test19.css | 1 + .../compress.css3.selectors.part2.test2.c.cl | 1 + .../compress.css3.selectors.part2.test2.c.css | 1 + .../compress.css3.selectors.part2.test2.cl | 1 + .../compress.css3.selectors.part2.test2.css | 1 + .../compress.css3.selectors.part2.test20.c.cl | 1 + ...compress.css3.selectors.part2.test20.c.css | 1 + .../compress.css3.selectors.part2.test20.cl | 1 + .../compress.css3.selectors.part2.test20.css | 1 + .../compress.css3.selectors.part2.test21.c.cl | 1 + ...compress.css3.selectors.part2.test21.c.css | 1 + .../compress.css3.selectors.part2.test21.cl | 1 + .../compress.css3.selectors.part2.test21.css | 1 + .../compress.css3.selectors.part2.test22.c.cl | 1 + ...compress.css3.selectors.part2.test22.c.css | 1 + .../compress.css3.selectors.part2.test22.cl | 1 + .../compress.css3.selectors.part2.test22.css | 1 + .../compress.css3.selectors.part2.test23.c.cl | 1 + ...compress.css3.selectors.part2.test23.c.css | 1 + .../compress.css3.selectors.part2.test23.cl | 1 + .../compress.css3.selectors.part2.test23.css | 1 + .../compress.css3.selectors.part2.test24.c.cl | 1 + ...compress.css3.selectors.part2.test24.c.css | 1 + .../compress.css3.selectors.part2.test24.cl | 1 + .../compress.css3.selectors.part2.test24.css | 1 + .../compress.css3.selectors.part2.test25.c.cl | 1 + ...compress.css3.selectors.part2.test25.c.css | 1 + .../compress.css3.selectors.part2.test25.cl | 1 + .../compress.css3.selectors.part2.test25.css | 1 + .../compress.css3.selectors.part2.test26.c.cl | 1 + ...compress.css3.selectors.part2.test26.c.css | 1 + .../compress.css3.selectors.part2.test26.cl | 1 + .../compress.css3.selectors.part2.test26.css | 1 + .../compress.css3.selectors.part2.test27.c.cl | 1 + ...compress.css3.selectors.part2.test27.c.css | 1 + .../compress.css3.selectors.part2.test27.cl | 1 + .../compress.css3.selectors.part2.test27.css | 1 + .../compress.css3.selectors.part2.test28.c.cl | 1 + ...compress.css3.selectors.part2.test28.c.css | 1 + .../compress.css3.selectors.part2.test28.cl | 1 + .../compress.css3.selectors.part2.test28.css | 1 + .../compress.css3.selectors.part2.test29.c.cl | 1 + ...compress.css3.selectors.part2.test29.c.css | 1 + .../compress.css3.selectors.part2.test29.cl | 1 + .../compress.css3.selectors.part2.test29.css | 1 + .../compress.css3.selectors.part2.test3.c.cl | 1 + .../compress.css3.selectors.part2.test3.c.css | 1 + .../compress.css3.selectors.part2.test3.cl | 1 + .../compress.css3.selectors.part2.test3.css | 1 + .../compress.css3.selectors.part2.test30.c.cl | 1 + ...compress.css3.selectors.part2.test30.c.css | 1 + .../compress.css3.selectors.part2.test30.cl | 1 + .../compress.css3.selectors.part2.test30.css | 1 + .../compress.css3.selectors.part2.test31.c.cl | 1 + ...compress.css3.selectors.part2.test31.c.css | 1 + .../compress.css3.selectors.part2.test31.cl | 1 + .../compress.css3.selectors.part2.test31.css | 1 + .../compress.css3.selectors.part2.test32.c.cl | 1 + ...compress.css3.selectors.part2.test32.c.css | 1 + .../compress.css3.selectors.part2.test32.cl | 1 + .../compress.css3.selectors.part2.test32.css | 1 + .../compress.css3.selectors.part2.test33.c.cl | 1 + ...compress.css3.selectors.part2.test33.c.css | 1 + .../compress.css3.selectors.part2.test33.cl | 1 + .../compress.css3.selectors.part2.test33.css | 1 + .../compress.css3.selectors.part2.test34.c.cl | 1 + ...compress.css3.selectors.part2.test34.c.css | 1 + .../compress.css3.selectors.part2.test34.cl | 1 + .../compress.css3.selectors.part2.test34.css | 1 + .../compress.css3.selectors.part2.test35.c.cl | 1 + ...compress.css3.selectors.part2.test35.c.css | 1 + .../compress.css3.selectors.part2.test35.cl | 1 + .../compress.css3.selectors.part2.test35.css | 1 + .../compress.css3.selectors.part2.test36.c.cl | 1 + ...compress.css3.selectors.part2.test36.c.css | 1 + .../compress.css3.selectors.part2.test36.cl | 1 + .../compress.css3.selectors.part2.test36.css | 1 + .../compress.css3.selectors.part2.test37.c.cl | 1 + ...compress.css3.selectors.part2.test37.c.css | 1 + .../compress.css3.selectors.part2.test37.cl | 1 + .../compress.css3.selectors.part2.test37.css | 1 + .../compress.css3.selectors.part2.test38.c.cl | 1 + ...compress.css3.selectors.part2.test38.c.css | 1 + .../compress.css3.selectors.part2.test38.cl | 1 + .../compress.css3.selectors.part2.test38.css | 1 + .../compress.css3.selectors.part2.test39.c.cl | 1 + ...compress.css3.selectors.part2.test39.c.css | 1 + .../compress.css3.selectors.part2.test39.cl | 1 + .../compress.css3.selectors.part2.test39.css | 1 + .../compress.css3.selectors.part2.test4.c.cl | 1 + .../compress.css3.selectors.part2.test4.c.css | 1 + .../compress.css3.selectors.part2.test4.cl | 1 + .../compress.css3.selectors.part2.test4.css | 1 + .../compress.css3.selectors.part2.test40.c.cl | 1 + ...compress.css3.selectors.part2.test40.c.css | 1 + .../compress.css3.selectors.part2.test40.cl | 1 + .../compress.css3.selectors.part2.test40.css | 1 + .../compress.css3.selectors.part2.test41.c.cl | 1 + ...compress.css3.selectors.part2.test41.c.css | 1 + .../compress.css3.selectors.part2.test41.cl | 1 + .../compress.css3.selectors.part2.test41.css | 1 + .../compress.css3.selectors.part2.test42.c.cl | 1 + ...compress.css3.selectors.part2.test42.c.css | 1 + .../compress.css3.selectors.part2.test42.cl | 1 + .../compress.css3.selectors.part2.test42.css | 1 + .../compress.css3.selectors.part2.test5.c.cl | 1 + .../compress.css3.selectors.part2.test5.c.css | 1 + .../compress.css3.selectors.part2.test5.cl | 1 + .../compress.css3.selectors.part2.test5.css | 1 + .../compress.css3.selectors.part2.test6.c.cl | 1 + .../compress.css3.selectors.part2.test6.c.css | 1 + .../compress.css3.selectors.part2.test6.cl | 1 + .../compress.css3.selectors.part2.test6.css | 1 + .../compress.css3.selectors.part2.test7.c.cl | 1 + .../compress.css3.selectors.part2.test7.c.css | 1 + .../compress.css3.selectors.part2.test7.cl | 1 + .../compress.css3.selectors.part2.test7.css | 1 + .../compress.css3.selectors.part2.test8.c.cl | 1 + .../compress.css3.selectors.part2.test8.c.css | 1 + .../compress.css3.selectors.part2.test8.cl | 1 + .../compress.css3.selectors.part2.test8.css | 1 + .../compress.css3.selectors.part2.test9.c.cl | 1 + .../compress.css3.selectors.part2.test9.c.css | 1 + .../compress.css3.selectors.part2.test9.cl | 1 + .../compress.css3.selectors.part2.test9.css | 1 + .../compress.dont.background.test1.cl | 1 + .../compress.dont.background.test1.css | 5 + .../compress.dont.background.test2.cl | 1 + .../compress.dont.background.test2.css | 12 + .../compress.dont.background.test3.cl | 1 + .../compress.dont.background.test3.css | 11 + .../test_stylesheet/compress.dont.test1.cl | 1 + .../test_stylesheet/compress.dont.test1.css | 8 + .../compress.initial.background.test1.cl | 1 + .../compress.initial.background.test1.css | 9 + .../compress.initial.font.test1.cl | 1 + .../compress.initial.font.test1.css | 12 + .../compress.initial.font.test1.l | 12 + .../test_stylesheet/compress.mess.test1.cl | 1 + .../test_stylesheet/compress.mess.test1.css | 7 + .../test_stylesheet/compress.mess.test2.cl | 1 + .../test_stylesheet/compress.mess.test2.css | 17 + .../test_stylesheet/compress.mess.test3.cl | 6 + .../test_stylesheet/compress.mess.test3.css | 12 + .../test_stylesheet/compress.mess.test3.l | 12 + .../compress.restructure.background.test3.cl | 1 + .../compress.restructure.background.test3.css | 4 + ...compress.restructure.empty.atrule.test1.cl | 1 + ...ompress.restructure.empty.atrule.test1.css | 3 + ...compress.restructure.empty.atrule.test2.cl | 1 + ...ompress.restructure.empty.atrule.test2.css | 7 + ...press.restructure.equal.selectors.test1.cl | 1 + ...ress.restructure.equal.selectors.test1.css | 3 + ...press.restructure.equal.selectors.test2.cl | 1 + ...ress.restructure.equal.selectors.test2.css | 6 + ...press.restructure.equal.selectors.test3.cl | 1 + ...ress.restructure.equal.selectors.test3.css | 9 + .../compress.restructure.equal.test1.cl | 1 + .../compress.restructure.equal.test1.css | 6 + .../compress.restructure.equal.test2.cl | 1 + .../compress.restructure.equal.test2.css | 9 + .../compress.restructure.equal.test3.cl | 1 + .../compress.restructure.equal.test3.css | 12 + .../compress.restructure.equal.test4.cl | 1 + .../compress.restructure.equal.test4.css | 12 + .../compress.restructure.equal.test5.cl | 1 + .../compress.restructure.equal.test5.css | 12 + .../compress.restructure.equal.test6.cl | 1 + .../compress.restructure.equal.test6.css | 9 + .../compress.restructure.equal.test7.cl | 1 + .../compress.restructure.equal.test7.css | 7 + .../compress.restructure.filter.test1.cl | 1 + .../compress.restructure.filter.test1.css | 7 + .../compress.restructure.margin.test1.cl | 1 + .../compress.restructure.margin.test1.css | 5 + .../compress.restructure.margin.test2.cl | 1 + .../compress.restructure.margin.test2.css | 12 + .../compress.restructure.margin.test3.cl | 1 + .../compress.restructure.margin.test3.css | 18 + .../compress.restructure.merge.test1.cl | 1 + .../compress.restructure.merge.test1.css | 7 + .../compress.restructure.merge.test2.cl | 1 + .../compress.restructure.merge.test2.css | 7 + .../compress.restructure.merge.test3.cl | 1 + .../compress.restructure.merge.test3.css | 10 + .../compress.restructure.merge.test4.cl | 1 + .../compress.restructure.merge.test4.css | 10 + .../compress.restructure.padding.test1.cl | 1 + .../compress.restructure.padding.test1.css | 5 + .../compress.restructure.padding.test2.cl | 1 + .../compress.restructure.padding.test2.css | 12 + ...compress.shorthand.margin.padding.test1.cl | 1 + ...ompress.shorthand.margin.padding.test1.css | 14 + .../compress.shorthand.margin.test1.cl | 1 + .../compress.shorthand.margin.test1.css | 12 + .../compress.shorthand.margin.test2.cl | 1 + .../compress.shorthand.margin.test2.css | 5 + .../compress.shorthand.margin.test3.cl | 1 + .../compress.shorthand.margin.test3.css | 6 + .../compress.shorthand.margin.test4.cl | 1 + .../compress.shorthand.margin.test4.css | 31 + .../compress.shorthand.margin.test5.cl | 1 + .../compress.shorthand.margin.test5.css | 11 + .../compress.shorthand.margin.test6.cl | 1 + .../compress.shorthand.margin.test6.css | 6 + .../compress.shorthand.margin.test7.cl | 1 + .../compress.shorthand.margin.test7.css | 6 + .../compress.shorthand.margin.unary.test1.cl | 1 + .../compress.shorthand.margin.unary.test1.css | 12 + .../compress.shorthand.margin.unary.test2.cl | 1 + .../compress.shorthand.margin.unary.test2.css | 5 + .../compress.shorthand.margin.unary.test3.cl | 1 + .../compress.shorthand.margin.unary.test3.css | 6 + .../compress.shorthand.margin.unary.test4.cl | 1 + .../compress.shorthand.margin.unary.test4.css | 31 + .../compress.shorthand.margin.unary.test5.cl | 1 + .../compress.shorthand.margin.unary.test5.css | 11 + .../compress.shorthand.margin.unary.test6.cl | 1 + .../compress.shorthand.margin.unary.test6.css | 6 + .../compress.shorthand.margin.unary.test7.cl | 1 + .../compress.shorthand.margin.unary.test7.css | 6 + .../compress.shorthand.padding.test1.cl | 1 + .../compress.shorthand.padding.test1.css | 12 + .../compress.shorthand.padding.test2.cl | 1 + .../compress.shorthand.padding.test2.css | 5 + .../compress.shorthand.padding.test3.cl | 1 + .../compress.shorthand.padding.test3.css | 6 + .../compress.shorthand.padding.test4.cl | 1 + .../compress.shorthand.padding.test4.css | 31 + .../compress.shorthand.padding.test5.cl | 1 + .../compress.shorthand.padding.test5.css | 11 + .../compress.shorthand.padding.test6.cl | 1 + .../compress.shorthand.padding.test6.css | 6 + .../compress.shorthand.padding.test7.cl | 1 + .../compress.shorthand.padding.test7.css | 6 + .../data/test_stylesheet/issue16.test1.cl | 1 + .../data/test_stylesheet/issue16.test1.css | 3 + .../data/test_stylesheet/issue39.test1.cl | 1 + .../data/test_stylesheet/issue39.test1.css | 6 + .../data/test_stylesheet/issue39.test10.cl | 1 + .../data/test_stylesheet/issue39.test10.css | 6 + .../data/test_stylesheet/issue39.test11.cl | 1 + .../data/test_stylesheet/issue39.test11.css | 6 + .../data/test_stylesheet/issue39.test12.cl | 1 + .../data/test_stylesheet/issue39.test12.css | 6 + .../data/test_stylesheet/issue39.test13.cl | 1 + .../data/test_stylesheet/issue39.test13.css | 6 + .../data/test_stylesheet/issue39.test14.cl | 1 + .../data/test_stylesheet/issue39.test14.css | 6 + .../data/test_stylesheet/issue39.test15.cl | 1 + .../data/test_stylesheet/issue39.test15.css | 6 + .../data/test_stylesheet/issue39.test16.cl | 1 + .../data/test_stylesheet/issue39.test16.css | 6 + .../data/test_stylesheet/issue39.test17.cl | 1 + .../data/test_stylesheet/issue39.test17.css | 6 + .../data/test_stylesheet/issue39.test18.cl | 1 + .../data/test_stylesheet/issue39.test18.css | 6 + .../data/test_stylesheet/issue39.test19.cl | 1 + .../data/test_stylesheet/issue39.test19.css | 6 + .../data/test_stylesheet/issue39.test2.cl | 1 + .../data/test_stylesheet/issue39.test2.css | 6 + .../data/test_stylesheet/issue39.test20.cl | 1 + .../data/test_stylesheet/issue39.test20.css | 6 + .../data/test_stylesheet/issue39.test21.cl | 1 + .../data/test_stylesheet/issue39.test21.css | 3 + .../data/test_stylesheet/issue39.test22.cl | 1 + .../data/test_stylesheet/issue39.test22.css | 9 + .../data/test_stylesheet/issue39.test23.cl | 1 + .../data/test_stylesheet/issue39.test23.css | 6 + .../data/test_stylesheet/issue39.test24.cl | 1 + .../data/test_stylesheet/issue39.test24.css | 7 + .../data/test_stylesheet/issue39.test25.cl | 1 + .../data/test_stylesheet/issue39.test25.css | 6 + .../data/test_stylesheet/issue39.test26.cl | 1 + .../data/test_stylesheet/issue39.test26.css | 6 + .../data/test_stylesheet/issue39.test27.cl | 1 + .../data/test_stylesheet/issue39.test27.css | 6 + .../data/test_stylesheet/issue39.test28.cl | 1 + .../data/test_stylesheet/issue39.test28.css | 9 + .../data/test_stylesheet/issue39.test29.cl | 1 + .../data/test_stylesheet/issue39.test29.css | 9 + .../data/test_stylesheet/issue39.test3.cl | 1 + .../data/test_stylesheet/issue39.test3.css | 7 + .../data/test_stylesheet/issue39.test30.cl | 1 + .../data/test_stylesheet/issue39.test30.css | 12 + .../data/test_stylesheet/issue39.test31.cl | 1 + .../data/test_stylesheet/issue39.test31.css | 8 + .../data/test_stylesheet/issue39.test4.cl | 1 + .../data/test_stylesheet/issue39.test4.css | 7 + .../data/test_stylesheet/issue39.test5.cl | 1 + .../data/test_stylesheet/issue39.test5.css | 6 + .../data/test_stylesheet/issue39.test6.cl | 1 + .../data/test_stylesheet/issue39.test6.css | 10 + .../data/test_stylesheet/issue39.test7.cl | 1 + .../data/test_stylesheet/issue39.test7.css | 6 + .../data/test_stylesheet/issue39.test8.cl | 1 + .../data/test_stylesheet/issue39.test8.css | 6 + .../data/test_stylesheet/issue39.test9.cl | 1 + .../data/test_stylesheet/issue39.test9.css | 6 + .../data/test_stylesheet/issue45.test1.cl | 1 + .../data/test_stylesheet/issue45.test1.css | 2 + .../data/test_stylesheet/issue48.test1.cl | 1 + .../data/test_stylesheet/issue48.test1.css | 6 + .../data/test_stylesheet/issue50.test1.cl | 1 + .../data/test_stylesheet/issue50.test1.css | 4 + .../data/test_stylesheet/issue50.test2.cl | 1 + .../data/test_stylesheet/issue50.test2.css | 7 + .../data/test_stylesheet/issue52.test1.cl | 1 + .../data/test_stylesheet/issue52.test1.css | 1 + .../data/test_stylesheet/issue52.test2.cl | 1 + .../data/test_stylesheet/issue52.test2.css | 6 + .../data/test_stylesheet/issue53.test1.cl | 1 + .../data/test_stylesheet/issue53.test1.css | 1 + .../data/test_stylesheet/issue53.test2.cl | 1 + .../data/test_stylesheet/issue53.test2.css | 1 + .../data/test_stylesheet/issue54.test1.cl | 1 + .../data/test_stylesheet/issue54.test1.css | 15 + .../data/test_stylesheet/issue57.test1.cl | 1 + .../data/test_stylesheet/issue57.test1.css | 4 + .../data/test_stylesheet/issue57.test2.cl | 1 + .../data/test_stylesheet/issue57.test2.css | 11 + .../data/test_stylesheet/issue71.test1.cl | 1 + .../data/test_stylesheet/issue71.test1.css | 5 + .../data/test_stylesheet/issue76.test1.cl | 1 + .../data/test_stylesheet/issue76.test1.css | 5 + .../data/test_stylesheet/issue76.test2.cl | 1 + .../data/test_stylesheet/issue76.test2.css | 6 + .../data/test_stylesheet/issue76.test3.cl | 1 + .../data/test_stylesheet/issue76.test3.css | 9 + .../data/test_stylesheet/issue76.test4.cl | 1 + .../data/test_stylesheet/issue76.test4.css | 18 + .../data/test_stylesheet/issue76.test5.cl | 1 + .../data/test_stylesheet/issue76.test5.css | 14 + .../data/test_stylesheet/issue78.test1.cl | 1 + .../data/test_stylesheet/issue78.test1.css | 7 + .../data/test_stylesheet/issue78.test2.cl | 1 + .../data/test_stylesheet/issue78.test2.css | 6 + .../data/test_stylesheet/issue78.test3.cl | 1 + .../data/test_stylesheet/issue78.test3.css | 6 + .../data/test_stylesheet/issue78.test4.cl | 1 + .../data/test_stylesheet/issue78.test4.css | 8 + .../data/test_stylesheet/issue79.test1.cl | 1 + .../data/test_stylesheet/issue79.test1.css | 9 + .../data/test_stylesheet/issue79.test2.cl | 1 + .../data/test_stylesheet/issue79.test2.css | 7 + .../data/test_stylesheet/issue81.test1.cl | 1 + .../data/test_stylesheet/issue81.test1.css | 7 + .../data/test_stylesheet/issue81.test2.cl | 1 + .../data/test_stylesheet/issue81.test2.css | 6 + .../data/test_stylesheet/issue81.test3.cl | 1 + .../data/test_stylesheet/issue81.test3.css | 8 + .../data/test_stylesheet/issue82.test1.cl | 1 + .../data/test_stylesheet/issue82.test1.css | 4 + .../data/test_stylesheet/stylesheet.0.css | 1 + .../test/data/test_stylesheet/stylesheet.0.l | 1 + .../test/data/test_stylesheet/stylesheet.0.p | 11 + .../data/test_stylesheet/stylesheet.1.css | 1 + .../test/data/test_stylesheet/stylesheet.1.l | 1 + .../test/data/test_stylesheet/stylesheet.1.p | 21 + .../data/test_stylesheet/stylesheet.2.css | 1 + .../test/data/test_stylesheet/stylesheet.2.l | 1 + .../test/data/test_stylesheet/stylesheet.2.p | 4 + .../data/test_stylesheet/stylesheet.3.css | 1 + .../test/data/test_stylesheet/stylesheet.3.l | 1 + .../test/data/test_stylesheet/stylesheet.3.p | 7 + .../data/test_stylesheet/stylesheet.4.css | 1 + .../test/data/test_stylesheet/stylesheet.4.l | 1 + .../test/data/test_stylesheet/stylesheet.4.p | 14 + .../data/test_stylesheet/stylesheet.c.0.css | 5 + .../data/test_stylesheet/stylesheet.c.0.l | 5 + .../data/test_stylesheet/stylesheet.c.0.p | 23 + .../data/test_stylesheet/stylesheet.s.0.css | 3 + .../data/test_stylesheet/stylesheet.s.0.l | 3 + .../data/test_stylesheet/stylesheet.s.0.p | 17 + .../data/test_stylesheet/stylesheet.s.1.css | 7 + .../data/test_stylesheet/stylesheet.s.1.l | 7 + .../data/test_stylesheet/stylesheet.s.1.p | 36 + .../data/test_stylesheet/stylesheet.s.2.css | 2 + .../data/test_stylesheet/stylesheet.s.2.l | 2 + .../data/test_stylesheet/stylesheet.s.2.p | 9 + .../data/test_stylesheet/stylesheet.s.3.css | 5 + .../data/test_stylesheet/stylesheet.s.3.l | 5 + .../data/test_stylesheet/stylesheet.s.3.p | 22 + .../csso/test/data/test_unary/unary.0.css | 1 + .../csso/test/data/test_unary/unary.0.l | 1 + .../csso/test/data/test_unary/unary.0.p | 1 + .../csso/test/data/test_unary/unary.1.css | 1 + .../csso/test/data/test_unary/unary.1.l | 1 + .../csso/test/data/test_unary/unary.1.p | 1 + .../csso/test/data/test_unknown/unknown.0.css | 1 + .../csso/test/data/test_unknown/unknown.0.l | 1 + .../csso/test/data/test_unknown/unknown.1.css | 1 + .../csso/test/data/test_unknown/unknown.1.l | 1 + .../csso/test/data/test_unknown/unknown.2.css | 1 + .../csso/test/data/test_unknown/unknown.2.l | 1 + .../csso/test/data/test_uri/uri.0.css | 1 + .../csso/test/data/test_uri/uri.0.l | 1 + .../csso/test/data/test_uri/uri.0.p | 2 + .../csso/test/data/test_uri/uri.1.css | 1 + .../csso/test/data/test_uri/uri.1.l | 1 + .../csso/test/data/test_uri/uri.1.p | 2 + .../csso/test/data/test_uri/uri.c.0.css | 1 + .../csso/test/data/test_uri/uri.c.0.l | 1 + .../csso/test/data/test_uri/uri.c.0.p | 4 + .../csso/test/data/test_uri/uri.c.1.css | 1 + .../csso/test/data/test_uri/uri.c.1.l | 1 + .../csso/test/data/test_uri/uri.c.1.p | 3 + .../csso/test/data/test_uri/uri.s.0.css | 1 + .../csso/test/data/test_uri/uri.s.0.l | 1 + .../csso/test/data/test_uri/uri.s.0.p | 4 + .../csso/test/data/test_uri/uri.s.1.css | 1 + .../csso/test/data/test_uri/uri.s.1.l | 1 + .../csso/test/data/test_uri/uri.s.1.p | 4 + .../csso/test/data/test_value/value.0.css | 1 + .../csso/test/data/test_value/value.0.l | 1 + .../csso/test/data/test_value/value.0.p | 2 + .../csso/test/data/test_value/value.1.css | 1 + .../csso/test/data/test_value/value.1.l | 1 + .../csso/test/data/test_value/value.1.p | 2 + .../csso/test/data/test_value/value.2.css | 1 + .../csso/test/data/test_value/value.2.l | 1 + .../csso/test/data/test_value/value.2.p | 5 + .../csso/test/data/test_value/value.3.css | 1 + .../csso/test/data/test_value/value.3.l | 1 + .../csso/test/data/test_value/value.3.p | 4 + .../csso/test/data/test_value/value.4.css | 1 + .../csso/test/data/test_value/value.4.l | 1 + .../csso/test/data/test_value/value.4.p | 4 + .../data/test_value/value.dimension.0.css | 1 + .../test/data/test_value/value.dimension.0.l | 1 + .../data/test_value/value.dimension.1.css | 1 + .../test/data/test_value/value.dimension.1.l | 1 + .../data/test_value/value.dimension.2.css | 1 + .../test/data/test_value/value.dimension.2.l | 1 + .../csso/test/data/test_value/value.rgb.0.css | 1 + .../csso/test/data/test_value/value.rgb.0.l | 1 + .../csso/test/data/test_value/value.rgb.1.css | 1 + .../csso/test/data/test_value/value.rgb.1.l | 1 + .../csso/test/data/test_value/value.rgb.2.css | 1 + .../csso/test/data/test_value/value.rgb.2.l | 1 + .../test/data/test_value/value.vhash.0.css | 1 + .../csso/test/data/test_value/value.vhash.0.l | 1 + .../test/data/test_value/value.vhash.1.css | 1 + .../csso/test/data/test_value/value.vhash.1.l | 1 + .../test/data/test_value/value.vhash.2.css | 1 + .../csso/test/data/test_value/value.vhash.2.l | 1 + .../test/data/test_value/value.vhash.3.css | 1 + .../csso/test/data/test_value/value.vhash.3.l | 1 + .../csso/test/data/test_vhash/vhash.0.css | 1 + .../csso/test/data/test_vhash/vhash.0.l | 1 + .../csso/test/data/test_vhash/vhash.0.p | 1 + .../csso/test/data/test_vhash/vhash.1.css | 1 + .../csso/test/data/test_vhash/vhash.1.l | 1 + .../csso/test/data/test_vhash/vhash.1.p | 1 + .../piler/node_modules/csso/test/test.js | 67 + .../piler/node_modules/csso/web/csso.css | 8 + .../piler/node_modules/csso/web/csso.html | 43 + .../piler/node_modules/csso/web/csso.web.js | 2499 + .../piler/node_modules/uglify-js/.npmignore | 6 + .../piler/node_modules/uglify-js/README.html | 1016 + .../piler/node_modules/uglify-js/README.org | 596 + .../piler/node_modules/uglify-js/bin/uglifyjs | 334 + .../piler/node_modules/uglify-js/docstyle.css | 75 + .../uglify-js/lib/consolidator.js | 1220 + .../node_modules/uglify-js/lib/parse-js.js | 1369 + .../node_modules/uglify-js/lib/process.js | 2120 + .../uglify-js/lib/squeeze-more.js | 78 + .../piler/node_modules/uglify-js/package.json | 32 + .../node_modules/uglify-js/test/beautify.js | 28 + .../uglify-js/test/testconsolidator.js | 1391 + .../node_modules/uglify-js/test/testparser.js | 409 + .../test/unit/compress/expected/1e21.js | 1 + .../test/unit/compress/expected/array1.js | 1 + .../test/unit/compress/expected/array2.js | 1 + .../test/unit/compress/expected/array3.js | 1 + .../test/unit/compress/expected/array4.js | 1 + .../test/unit/compress/expected/assignment.js | 1 + .../unit/compress/expected/concatstring.js | 1 + .../test/unit/compress/expected/const.js | 1 + .../unit/compress/expected/div-with-regexp.js | 1 + .../unit/compress/expected/empty-blocks.js | 1 + .../unit/compress/expected/forstatement.js | 1 + .../test/unit/compress/expected/if-not.js | 1 + .../test/unit/compress/expected/if.js | 1 + .../test/unit/compress/expected/ifreturn.js | 1 + .../test/unit/compress/expected/ifreturn2.js | 1 + .../test/unit/compress/expected/infinite.js | 1 + .../test/unit/compress/expected/issue10.js | 1 + .../test/unit/compress/expected/issue11.js | 1 + .../test/unit/compress/expected/issue13.js | 1 + .../test/unit/compress/expected/issue14.js | 1 + .../test/unit/compress/expected/issue16.js | 1 + .../test/unit/compress/expected/issue17.js | 1 + .../test/unit/compress/expected/issue20.js | 1 + .../test/unit/compress/expected/issue21.js | 1 + .../test/unit/compress/expected/issue25.js | 1 + .../test/unit/compress/expected/issue27.js | 1 + .../test/unit/compress/expected/issue278.js | 1 + .../test/unit/compress/expected/issue28.js | 1 + .../test/unit/compress/expected/issue29.js | 1 + .../test/unit/compress/expected/issue30.js | 1 + .../test/unit/compress/expected/issue34.js | 1 + .../test/unit/compress/expected/issue349.js | 1 + .../test/unit/compress/expected/issue353.js | 1 + .../test/unit/compress/expected/issue372.js | 1 + .../test/unit/compress/expected/issue4.js | 1 + .../test/unit/compress/expected/issue471.js | 1 + .../test/unit/compress/expected/issue48.js | 1 + .../test/unit/compress/expected/issue50.js | 1 + .../test/unit/compress/expected/issue53.js | 1 + .../test/unit/compress/expected/issue54.1.js | 1 + .../test/unit/compress/expected/issue68.js | 1 + .../test/unit/compress/expected/issue69.js | 1 + .../test/unit/compress/expected/issue9.js | 1 + .../unit/compress/expected/issues222_324.js | 1 + .../test/unit/compress/expected/mangle.js | 1 + .../unit/compress/expected/null_string.js | 1 + .../unit/compress/expected/strict-equals.js | 1 + .../test/unit/compress/expected/var.js | 1 + .../test/unit/compress/expected/whitespace.js | 1 + .../test/unit/compress/expected/with.js | 1 + .../uglify-js/test/unit/compress/test/1e21.js | 1 + .../test/unit/compress/test/array1.js | 3 + .../test/unit/compress/test/array2.js | 4 + .../test/unit/compress/test/array3.js | 4 + .../test/unit/compress/test/array4.js | 6 + .../test/unit/compress/test/assignment.js | 20 + .../test/unit/compress/test/concatstring.js | 3 + .../test/unit/compress/test/const.js | 5 + .../unit/compress/test/div-with-regexp.js | 1 + .../test/unit/compress/test/empty-blocks.js | 4 + .../test/unit/compress/test/forstatement.js | 10 + .../test/unit/compress/test/if-not.js | 1 + .../uglify-js/test/unit/compress/test/if.js | 6 + .../test/unit/compress/test/ifreturn.js | 9 + .../test/unit/compress/test/ifreturn2.js | 16 + .../test/unit/compress/test/infinite.js | 1 + .../test/unit/compress/test/issue10.js | 1 + .../test/unit/compress/test/issue11.js | 3 + .../test/unit/compress/test/issue13.js | 1 + .../test/unit/compress/test/issue14.js | 1 + .../test/unit/compress/test/issue16.js | 1 + .../test/unit/compress/test/issue17.js | 4 + .../test/unit/compress/test/issue20.js | 1 + .../test/unit/compress/test/issue21.js | 6 + .../test/unit/compress/test/issue25.js | 7 + .../test/unit/compress/test/issue27.js | 1 + .../test/unit/compress/test/issue278.js | 1 + .../test/unit/compress/test/issue28.js | 3 + .../test/unit/compress/test/issue29.js | 1 + .../test/unit/compress/test/issue30.js | 3 + .../test/unit/compress/test/issue34.js | 3 + .../test/unit/compress/test/issue349.js | 25 + .../test/unit/compress/test/issue353.js | 4 + .../test/unit/compress/test/issue372.js | 32 + .../test/unit/compress/test/issue4.js | 3 + .../test/unit/compress/test/issue471.js | 1 + .../test/unit/compress/test/issue48.js | 1 + .../test/unit/compress/test/issue50.js | 9 + .../test/unit/compress/test/issue53.js | 1 + .../test/unit/compress/test/issue54.1.js | 3 + .../test/unit/compress/test/issue68.js | 5 + .../test/unit/compress/test/issue69.js | 1 + .../test/unit/compress/test/issue9.js | 4 + .../test/unit/compress/test/issues222_324.js | 82 + .../test/unit/compress/test/mangle.js | 5 + .../test/unit/compress/test/null_string.js | 1 + .../test/unit/compress/test/strict-equals.js | 3 + .../uglify-js/test/unit/compress/test/var.js | 3 + .../test/unit/compress/test/whitespace.js | 21 + .../uglify-js/test/unit/compress/test/with.js | 2 + .../uglify-js/test/unit/scripts.js | 57 + .../piler/node_modules/uglify-js/tmp/hoist.js | 33 + .../node_modules/uglify-js/tmp/instrument.js | 97 + .../piler/node_modules/uglify-js/tmp/test.js | 30 + .../piler/node_modules/uglify-js/uglify-js.js | 18 + .../underscore.string/.travis.yml | 8 + .../node_modules/underscore.string/Gemfile | 5 + .../underscore.string/Gemfile.lock | 34 + .../underscore.string/README.markdown | 668 + .../node_modules/underscore.string/Rakefile | 28 + .../dist/underscore.string.min.js | 1 + .../node_modules/underscore.string/foo.js | 10 + .../lib/underscore.string.js | 525 + .../underscore.string/package.json | 76 + .../underscore.string/test/run-qunit.js | 44 + .../underscore.string/test/speed.js | 138 + .../underscore.string/test/strings.js | 438 + .../test/strings_standalone.js | 12 + .../underscore.string/test/test.html | 31 + .../test/test_standalone.html | 18 + .../test/test_underscore/arrays.js | 166 + .../test/test_underscore/chaining.js | 59 + .../test/test_underscore/collections.js | 270 + .../test/test_underscore/functions.js | 198 + .../test/test_underscore/objects.js | 535 + .../test/test_underscore/speed.js | 70 + .../test/test_underscore/temp.js | 27 + .../test/test_underscore/temp_tests.html | 19 + .../test/test_underscore/test.html | 43 + .../test/test_underscore/utility.js | 155 + .../test/test_underscore/vendor/jquery.js | 19 + .../test/test_underscore/vendor/jslitmus.js | 670 + .../test/test_underscore/vendor/qunit.css | 196 + .../test/test_underscore/vendor/qunit.js | 2360 + .../underscore.string/test/underscore.js | 999 + .../piler/node_modules/underscore/.npmignore | 3 + .../piler/node_modules/underscore/CNAME | 1 + .../piler/node_modules/underscore/LICENSE | 22 + .../piler/node_modules/underscore/README.md | 19 + .../piler/node_modules/underscore/favicon.ico | Bin 0 -> 1406 bytes .../piler/node_modules/underscore/index.html | 2109 + .../piler/node_modules/underscore/index.js | 1 + .../node_modules/underscore/package.json | 30 + .../underscore/raw/underscore.psd | Bin 0 -> 215540 bytes .../node_modules/underscore/underscore-min.js | 32 + .../node_modules/underscore/underscore.js | 1059 + node_modules/piler/package.json | 55 + node_modules/piler/run-tests-travis.sh | 13 + node_modules/piler/run-tests.sh | 10 + .../piler/spec/acceptance.spec.coffee | 115 + .../piler/spec/asseturlparser.spec.coffee | 92 + node_modules/piler/spec/basepile.spec.coffee | 33 + .../piler/spec/hrefupdater.spec.coffee | 13 + node_modules/piler/spec/testapp/app.coffee | 68 + .../spec/testapp/clientscripts/global.coffee | 3 + .../spec/testapp/clientscripts/global.js | 2 + .../spec/testapp/clientscripts/jquery.js | 8981 ++ .../spec/testapp/clientscripts/namespace.js | 4 + .../spec/testapp/clientscripts/remote.js | 3 + .../spec/testapp/stylesheets/import.less | 5 + .../spec/testapp/stylesheets/import.styl | 4 + .../spec/testapp/stylesheets/namespaced.css | 3 + .../piler/spec/testapp/stylesheets/style.css | 6 + .../piler/spec/testapp/stylesheets/style.less | 10 + .../piler/spec/testapp/stylesheets/style.styl | 9 + .../piler/spec/testapp/views/index.jade | 11 + .../piler/spec/testapp/views/layout.jade | 9 + .../piler/spec/testapp/views/namespace.jade | 7 + node_modules/socket.io/.npmignore | 3 + node_modules/socket.io/.travis.yml | 6 + node_modules/socket.io/History.md | 325 + node_modules/socket.io/LICENSE | 22 + node_modules/socket.io/Makefile | 31 + node_modules/socket.io/Readme.md | 364 + .../socket.io/benchmarks/decode.bench.js | 64 + .../socket.io/benchmarks/encode.bench.js | 90 + node_modules/socket.io/benchmarks/runner.js | 55 + node_modules/socket.io/index.js | 8 + node_modules/socket.io/lib/logger.js | 97 + node_modules/socket.io/lib/manager.js | 1027 + node_modules/socket.io/lib/namespace.js | 355 + node_modules/socket.io/lib/parser.js | 249 + node_modules/socket.io/lib/socket.io.js | 143 + node_modules/socket.io/lib/socket.js | 369 + node_modules/socket.io/lib/static.js | 395 + node_modules/socket.io/lib/store.js | 98 + node_modules/socket.io/lib/stores/memory.js | 143 + node_modules/socket.io/lib/stores/redis.js | 269 + node_modules/socket.io/lib/transport.js | 534 + .../socket.io/lib/transports/flashsocket.js | 129 + .../socket.io/lib/transports/htmlfile.js | 83 + .../socket.io/lib/transports/http-polling.js | 147 + node_modules/socket.io/lib/transports/http.js | 121 + .../socket.io/lib/transports/index.js | 12 + .../socket.io/lib/transports/jsonp-polling.js | 97 + .../socket.io/lib/transports/websocket.js | 36 + .../lib/transports/websocket/default.js | 362 + .../lib/transports/websocket/hybi-07-12.js | 622 + .../lib/transports/websocket/hybi-16.js | 622 + .../lib/transports/websocket/index.js | 11 + .../socket.io/lib/transports/xhr-polling.js | 69 + node_modules/socket.io/lib/util.js | 50 + .../node_modules/base64id/.npmignore | 3 + .../socket.io/node_modules/base64id/README.md | 18 + .../node_modules/base64id/lib/base64id.js | 103 + .../node_modules/base64id/package.json | 25 + .../node_modules/policyfile/.npmignore | 1 + .../socket.io/node_modules/policyfile/LICENSE | 19 + .../node_modules/policyfile/Makefile | 7 + .../node_modules/policyfile/README.md | 98 + .../node_modules/policyfile/doc/index.html | 375 + .../policyfile/examples/basic.fallback.js | 8 + .../node_modules/policyfile/examples/basic.js | 5 + .../node_modules/policyfile/index.js | 1 + .../node_modules/policyfile/lib/server.js | 289 + .../node_modules/policyfile/package.json | 48 + .../node_modules/policyfile/tests/ssl/ssl.crt | 21 + .../policyfile/tests/ssl/ssl.private.key | 27 + .../policyfile/tests/unit.test.js | 231 + .../socket.io/node_modules/redis/.npmignore | 1 + .../socket.io/node_modules/redis/README.md | 691 + .../redis/benches/buffer_bench.js | 89 + .../redis/benches/hiredis_parser.js | 38 + .../node_modules/redis/benches/re_sub_test.js | 14 + .../redis/benches/reconnect_test.js | 29 + .../redis/benches/stress/codec.js | 16 + .../redis/benches/stress/pubsub/pub.js | 38 + .../redis/benches/stress/pubsub/run | 10 + .../redis/benches/stress/pubsub/server.js | 23 + .../redis/benches/stress/rpushblpop/pub.js | 49 + .../redis/benches/stress/rpushblpop/run | 6 + .../redis/benches/stress/rpushblpop/server.js | 30 + .../redis/benches/stress/speed/00 | 13 + .../redis/benches/stress/speed/plot | 13 + .../redis/benches/stress/speed/size-rate.png | Bin 0 -> 6672 bytes .../redis/benches/stress/speed/speed.js | 84 + .../redis/benches/sub_quit_test.js | 18 + .../socket.io/node_modules/redis/changelog.md | 219 + .../redis/diff_multi_bench_output.js | 87 + .../node_modules/redis/examples/auth.js | 5 + .../redis/examples/backpressure_drain.js | 33 + .../node_modules/redis/examples/eval.js | 9 + .../node_modules/redis/examples/extend.js | 24 + .../node_modules/redis/examples/file.js | 32 + .../node_modules/redis/examples/mget.js | 5 + .../node_modules/redis/examples/monitor.js | 10 + .../node_modules/redis/examples/multi.js | 46 + .../node_modules/redis/examples/multi2.js | 29 + .../node_modules/redis/examples/psubscribe.js | 33 + .../node_modules/redis/examples/pub_sub.js | 41 + .../node_modules/redis/examples/simple.js | 24 + .../node_modules/redis/examples/sort.js | 17 + .../node_modules/redis/examples/subqueries.js | 15 + .../node_modules/redis/examples/subquery.js | 19 + .../redis/examples/unix_socket.js | 29 + .../node_modules/redis/examples/web_server.js | 31 + .../node_modules/redis/generate_commands.js | 39 + .../socket.io/node_modules/redis/index.js | 1113 + .../node_modules/redis/lib/commands.js | 147 + .../node_modules/redis/lib/parser/hiredis.js | 46 + .../redis/lib/parser/javascript.js | 317 + .../socket.io/node_modules/redis/lib/queue.js | 61 + .../node_modules/redis/lib/to_array.js | 12 + .../socket.io/node_modules/redis/lib/util.js | 11 + .../socket.io/node_modules/redis/mem.js | 11 + .../node_modules/redis/multi_bench.js | 225 + .../socket.io/node_modules/redis/package.json | 35 + .../socket.io/node_modules/redis/test.js | 1618 + .../node_modules/socket.io-client/.npmignore | 2 + .../node_modules/socket.io-client/History.md | 237 + .../node_modules/socket.io-client/Makefile | 20 + .../node_modules/socket.io-client/README.md | 246 + .../socket.io-client/bin/builder.js | 303 + .../components/component-bind/component.json | 14 + .../components/component-bind/index.js | 24 + .../component-emitter/component.json | 13 + .../components/component-emitter/index.js | 147 + .../component-json-fallback/component.json | 15 + .../component-json-fallback/index.js | 486 + .../components/component-json/component.json | 17 + .../components/component-json/index.js | 4 + .../component.json | 24 + .../lib/emitter.js | 52 + .../learnboost-engine.io-client/lib/index.js | 2 + .../learnboost-engine.io-client/lib/parser.js | 163 + .../learnboost-engine.io-client/lib/socket.js | 492 + .../lib/transport.js | 141 + .../lib/transports/flashsocket.js | 254 + .../lib/transports/index.js | 62 + .../lib/transports/polling-jsonp.js | 221 + .../lib/transports/polling-xhr.js | 288 + .../lib/transports/polling.js | 210 + .../lib/transports/websocket.js | 158 + .../learnboost-engine.io-client/lib/util.js | 265 + .../component.json | 12 + .../learnboost-socket.io-protocol/index.js | 177 + .../timoxley-to-array/component.json | 16 + .../components/timoxley-to-array/index.js | 27 + .../visionmedia-debug/component.json | 16 + .../components/visionmedia-debug/debug.js | 122 + .../components/visionmedia-debug/index.js | 5 + .../socket.io-client/dist/WebSocketMain.swf | Bin 0 -> 175830 bytes .../dist/WebSocketMainInsecure.swf | Bin 0 -> 175953 bytes .../socket.io-client/dist/socket.io.js | 3873 + .../socket.io-client/dist/socket.io.min.js | 2 + .../socket.io-client/lib/events.js | 182 + .../node_modules/socket.io-client/lib/io.js | 206 + .../node_modules/socket.io-client/lib/json.js | 322 + .../socket.io-client/lib/namespace.js | 242 + .../socket.io-client/lib/parser.js | 262 + .../socket.io-client/lib/socket.js | 579 + .../socket.io-client/lib/transport.js | 256 + .../lib/transports/flashsocket.js | 191 + .../lib/transports/htmlfile.js | 173 + .../lib/transports/jsonp-polling.js | 256 + .../lib/transports/websocket.js | 197 + .../lib/transports/xhr-polling.js | 177 + .../socket.io-client/lib/transports/xhr.js | 217 + .../node_modules/socket.io-client/lib/util.js | 365 + .../lib/vendor/web-socket-js/.npmignore | 1 + .../lib/vendor/web-socket-js/README.md | 157 + .../vendor/web-socket-js/WebSocketMain.swf | Bin 0 -> 175830 bytes .../web-socket-js/WebSocketMainInsecure.zip | Bin 0 -> 166610 bytes .../flash-src/IWebSocketLogger.as | 8 + .../web-socket-js/flash-src/WebSocket.as | 464 + .../web-socket-js/flash-src/WebSocketEvent.as | 33 + .../web-socket-js/flash-src/WebSocketMain.as | 150 + .../flash-src/WebSocketMainInsecure.as | 19 + .../vendor/web-socket-js/flash-src/build.sh | 10 + .../com/adobe/net/proxies/RFC2817Socket.as | 204 + .../flash-src/com/gsolo/encryption/MD5.as | 375 + .../flash-src/com/hurlant/crypto/Crypto.as | 287 + .../crypto/cert/MozillaRootCertificates.as | 3235 + .../hurlant/crypto/cert/X509Certificate.as | 218 + .../crypto/cert/X509CertificateCollection.as | 57 + .../flash-src/com/hurlant/crypto/hash/HMAC.as | 82 + .../com/hurlant/crypto/hash/IHMAC.as | 27 + .../com/hurlant/crypto/hash/IHash.as | 21 + .../flash-src/com/hurlant/crypto/hash/MAC.as | 137 + .../flash-src/com/hurlant/crypto/hash/MD2.as | 124 + .../flash-src/com/hurlant/crypto/hash/MD5.as | 204 + .../flash-src/com/hurlant/crypto/hash/SHA1.as | 106 + .../com/hurlant/crypto/hash/SHA224.as | 28 + .../com/hurlant/crypto/hash/SHA256.as | 115 + .../com/hurlant/crypto/hash/SHABase.as | 71 + .../flash-src/com/hurlant/crypto/prng/ARC4.as | 90 + .../com/hurlant/crypto/prng/IPRNG.as | 20 + .../com/hurlant/crypto/prng/Random.as | 119 + .../com/hurlant/crypto/prng/TLSPRF.as | 142 + .../com/hurlant/crypto/rsa/RSAKey.as | 339 + .../com/hurlant/crypto/symmetric/AESKey.as | 2797 + .../hurlant/crypto/symmetric/BlowFishKey.as | 375 + .../com/hurlant/crypto/symmetric/CBCMode.as | 55 + .../com/hurlant/crypto/symmetric/CFB8Mode.as | 61 + .../com/hurlant/crypto/symmetric/CFBMode.as | 64 + .../com/hurlant/crypto/symmetric/CTRMode.as | 58 + .../com/hurlant/crypto/symmetric/DESKey.as | 365 + .../com/hurlant/crypto/symmetric/ECBMode.as | 86 + .../com/hurlant/crypto/symmetric/ICipher.as | 21 + .../com/hurlant/crypto/symmetric/IMode.as | 15 + .../com/hurlant/crypto/symmetric/IPad.as | 32 + .../hurlant/crypto/symmetric/IStreamCipher.as | 21 + .../hurlant/crypto/symmetric/ISymmetricKey.as | 35 + .../com/hurlant/crypto/symmetric/IVMode.as | 110 + .../com/hurlant/crypto/symmetric/NullPad.as | 34 + .../com/hurlant/crypto/symmetric/OFBMode.as | 52 + .../com/hurlant/crypto/symmetric/PKCS5.as | 44 + .../com/hurlant/crypto/symmetric/SSLPad.as | 44 + .../hurlant/crypto/symmetric/SimpleIVMode.as | 60 + .../com/hurlant/crypto/symmetric/TLSPad.as | 42 + .../hurlant/crypto/symmetric/TripleDESKey.as | 88 + .../com/hurlant/crypto/symmetric/XTeaKey.as | 94 + .../com/hurlant/crypto/symmetric/aeskey.pl | 29 + .../com/hurlant/crypto/symmetric/dump.txt | 2304 + .../com/hurlant/crypto/tests/AESKeyTest.as | 1220 + .../com/hurlant/crypto/tests/ARC4Test.as | 58 + .../hurlant/crypto/tests/BigIntegerTest.as | 39 + .../hurlant/crypto/tests/BlowFishKeyTest.as | 148 + .../com/hurlant/crypto/tests/CBCModeTest.as | 160 + .../com/hurlant/crypto/tests/CFB8ModeTest.as | 71 + .../com/hurlant/crypto/tests/CFBModeTest.as | 98 + .../com/hurlant/crypto/tests/CTRModeTest.as | 109 + .../com/hurlant/crypto/tests/DESKeyTest.as | 112 + .../com/hurlant/crypto/tests/ECBModeTest.as | 151 + .../com/hurlant/crypto/tests/HMACTest.as | 184 + .../com/hurlant/crypto/tests/ITestHarness.as | 20 + .../com/hurlant/crypto/tests/MD2Test.as | 56 + .../com/hurlant/crypto/tests/MD5Test.as | 58 + .../com/hurlant/crypto/tests/OFBModeTest.as | 101 + .../com/hurlant/crypto/tests/RSAKeyTest.as | 92 + .../com/hurlant/crypto/tests/SHA1Test.as | 198 + .../com/hurlant/crypto/tests/SHA224Test.as | 58 + .../com/hurlant/crypto/tests/SHA256Test.as | 60 + .../com/hurlant/crypto/tests/TLSPRFTest.as | 51 + .../com/hurlant/crypto/tests/TestCase.as | 42 + .../hurlant/crypto/tests/TripleDESKeyTest.as | 59 + .../com/hurlant/crypto/tests/XTeaKeyTest.as | 66 + .../com/hurlant/crypto/tls/BulkCiphers.as | 102 + .../com/hurlant/crypto/tls/CipherSuites.as | 117 + .../hurlant/crypto/tls/IConnectionState.as | 14 + .../hurlant/crypto/tls/ISecurityParameters.as | 29 + .../com/hurlant/crypto/tls/KeyExchanges.as | 24 + .../flash-src/com/hurlant/crypto/tls/MACs.as | 38 + .../hurlant/crypto/tls/SSLConnectionState.as | 171 + .../com/hurlant/crypto/tls/SSLEvent.as | 26 + .../crypto/tls/SSLSecurityParameters.as | 340 + .../com/hurlant/crypto/tls/TLSConfig.as | 70 + .../hurlant/crypto/tls/TLSConnectionState.as | 151 + .../com/hurlant/crypto/tls/TLSEngine.as | 895 + .../com/hurlant/crypto/tls/TLSError.as | 39 + .../com/hurlant/crypto/tls/TLSEvent.as | 27 + .../crypto/tls/TLSSecurityParameters.as | 197 + .../com/hurlant/crypto/tls/TLSSocket.as | 370 + .../com/hurlant/crypto/tls/TLSSocketEvent.as | 26 + .../com/hurlant/crypto/tls/TLSTest.as | 180 + .../com/hurlant/math/BarrettReduction.as | 90 + .../flash-src/com/hurlant/math/BigInteger.as | 1543 + .../com/hurlant/math/ClassicReduction.as | 35 + .../flash-src/com/hurlant/math/IReduction.as | 11 + .../com/hurlant/math/MontgomeryReduction.as | 85 + .../com/hurlant/math/NullReduction.as | 34 + .../flash-src/com/hurlant/math/bi_internal.as | 11 + .../flash-src/com/hurlant/util/ArrayUtil.as | 25 + .../flash-src/com/hurlant/util/Base64.as | 189 + .../flash-src/com/hurlant/util/Hex.as | 66 + .../flash-src/com/hurlant/util/Memory.as | 28 + .../com/hurlant/util/der/ByteString.as | 43 + .../flash-src/com/hurlant/util/der/DER.as | 210 + .../com/hurlant/util/der/IAsn1Type.as | 21 + .../flash-src/com/hurlant/util/der/Integer.as | 44 + .../flash-src/com/hurlant/util/der/OID.as | 35 + .../com/hurlant/util/der/ObjectIdentifier.as | 112 + .../flash-src/com/hurlant/util/der/PEM.as | 118 + .../com/hurlant/util/der/PrintableString.as | 49 + .../com/hurlant/util/der/Sequence.as | 90 + .../flash-src/com/hurlant/util/der/Set.as | 27 + .../flash-src/com/hurlant/util/der/Type.as | 94 + .../flash-src/com/hurlant/util/der/UTCTime.as | 60 + .../lib/vendor/web-socket-js/sample.html | 75 + .../lib/vendor/web-socket-js/swfobject.js | 6 + .../lib/vendor/web-socket-js/web_socket.js | 349 + .../node_modules/.bin/uglifyjs | 1 + .../socket.io-client/node_modules/.bin/wscat | 1 + .../active-x-obfuscator/.npmignore | 2 + .../active-x-obfuscator/Readme.md | 33 + .../node_modules/active-x-obfuscator/index.js | 83 + .../node_modules/zeparser/.npmignore | 1 + .../node_modules/zeparser/LICENSE | 19 + .../node_modules/zeparser/README | 37 + .../node_modules/zeparser/Tokenizer.js | 646 + .../node_modules/zeparser/ZeParser.js | 2180 + .../node_modules/zeparser/benchmark.html | 111608 +++++++++++++++ .../node_modules/zeparser/index.js | 1 + .../node_modules/zeparser/package.json | 28 + .../node_modules/zeparser/test-parser.html | 26 + .../node_modules/zeparser/test-tokenizer.html | 23 + .../node_modules/zeparser/tests.js | 478 + .../zeparser/unicodecategories.js | 49 + .../active-x-obfuscator/package.json | 35 + .../node_modules/active-x-obfuscator/test.js | 53 + .../node_modules/uglify-js/.npmignore | 4 + .../node_modules/uglify-js/README.html | 981 + .../node_modules/uglify-js/README.org | 574 + .../node_modules/uglify-js/bin/uglifyjs | 323 + .../node_modules/uglify-js/docstyle.css | 75 + .../node_modules/uglify-js/lib/object-ast.js | 75 + .../node_modules/uglify-js/lib/parse-js.js | 1342 + .../node_modules/uglify-js/lib/process.js | 2011 + .../uglify-js/lib/squeeze-more.js | 69 + .../node_modules/uglify-js/package.json | 26 + .../node_modules/uglify-js/package.json~ | 24 + .../node_modules/uglify-js/test/beautify.js | 28 + .../node_modules/uglify-js/test/testparser.js | 403 + .../test/unit/compress/expected/array1.js | 1 + .../test/unit/compress/expected/array2.js | 1 + .../test/unit/compress/expected/array3.js | 1 + .../test/unit/compress/expected/array4.js | 1 + .../test/unit/compress/expected/assignment.js | 1 + .../unit/compress/expected/concatstring.js | 1 + .../test/unit/compress/expected/const.js | 1 + .../unit/compress/expected/empty-blocks.js | 1 + .../unit/compress/expected/forstatement.js | 1 + .../test/unit/compress/expected/if.js | 1 + .../test/unit/compress/expected/ifreturn.js | 1 + .../test/unit/compress/expected/ifreturn2.js | 1 + .../test/unit/compress/expected/issue10.js | 1 + .../test/unit/compress/expected/issue11.js | 1 + .../test/unit/compress/expected/issue13.js | 1 + .../test/unit/compress/expected/issue14.js | 1 + .../test/unit/compress/expected/issue16.js | 1 + .../test/unit/compress/expected/issue17.js | 1 + .../test/unit/compress/expected/issue20.js | 1 + .../test/unit/compress/expected/issue21.js | 1 + .../test/unit/compress/expected/issue25.js | 1 + .../test/unit/compress/expected/issue27.js | 1 + .../test/unit/compress/expected/issue278.js | 1 + .../test/unit/compress/expected/issue28.js | 1 + .../test/unit/compress/expected/issue29.js | 1 + .../test/unit/compress/expected/issue30.js | 1 + .../test/unit/compress/expected/issue34.js | 1 + .../test/unit/compress/expected/issue4.js | 1 + .../test/unit/compress/expected/issue48.js | 1 + .../test/unit/compress/expected/issue50.js | 1 + .../test/unit/compress/expected/issue53.js | 1 + .../test/unit/compress/expected/issue54.1.js | 1 + .../test/unit/compress/expected/issue68.js | 1 + .../test/unit/compress/expected/issue69.js | 1 + .../test/unit/compress/expected/issue9.js | 1 + .../test/unit/compress/expected/mangle.js | 1 + .../unit/compress/expected/null_string.js | 1 + .../unit/compress/expected/strict-equals.js | 1 + .../test/unit/compress/expected/var.js | 1 + .../test/unit/compress/expected/whitespace.js | 1 + .../test/unit/compress/expected/with.js | 1 + .../test/unit/compress/test/array1.js | 3 + .../test/unit/compress/test/array2.js | 4 + .../test/unit/compress/test/array3.js | 4 + .../test/unit/compress/test/array4.js | 6 + .../test/unit/compress/test/assignment.js | 20 + .../test/unit/compress/test/concatstring.js | 3 + .../test/unit/compress/test/const.js | 5 + .../test/unit/compress/test/empty-blocks.js | 4 + .../test/unit/compress/test/forstatement.js | 10 + .../uglify-js/test/unit/compress/test/if.js | 6 + .../test/unit/compress/test/ifreturn.js | 9 + .../test/unit/compress/test/ifreturn2.js | 16 + .../test/unit/compress/test/issue10.js | 1 + .../test/unit/compress/test/issue11.js | 3 + .../test/unit/compress/test/issue13.js | 1 + .../test/unit/compress/test/issue14.js | 1 + .../test/unit/compress/test/issue16.js | 1 + .../test/unit/compress/test/issue17.js | 4 + .../test/unit/compress/test/issue20.js | 1 + .../test/unit/compress/test/issue21.js | 6 + .../test/unit/compress/test/issue25.js | 7 + .../test/unit/compress/test/issue27.js | 1 + .../test/unit/compress/test/issue278.js | 1 + .../test/unit/compress/test/issue28.js | 3 + .../test/unit/compress/test/issue29.js | 1 + .../test/unit/compress/test/issue30.js | 3 + .../test/unit/compress/test/issue34.js | 3 + .../test/unit/compress/test/issue4.js | 3 + .../test/unit/compress/test/issue48.js | 1 + .../test/unit/compress/test/issue50.js | 9 + .../test/unit/compress/test/issue53.js | 1 + .../test/unit/compress/test/issue54.1.js | 3 + .../test/unit/compress/test/issue68.js | 5 + .../test/unit/compress/test/issue69.js | 1 + .../test/unit/compress/test/issue9.js | 4 + .../test/unit/compress/test/mangle.js | 5 + .../test/unit/compress/test/null_string.js | 1 + .../test/unit/compress/test/strict-equals.js | 3 + .../uglify-js/test/unit/compress/test/var.js | 3 + .../test/unit/compress/test/whitespace.js | 21 + .../uglify-js/test/unit/compress/test/with.js | 2 + .../uglify-js/test/unit/scripts.js | 55 + .../node_modules/uglify-js/tmp/269.js | 13 + .../node_modules/uglify-js/tmp/app.js | 22315 +++ .../uglify-js/tmp/embed-tokens.js | 15 + .../node_modules/uglify-js/tmp/goto.js | 26 + .../node_modules/uglify-js/tmp/goto2.js | 8 + .../node_modules/uglify-js/tmp/hoist.js | 33 + .../node_modules/uglify-js/tmp/instrument.js | 97 + .../node_modules/uglify-js/tmp/instrument2.js | 138 + .../node_modules/uglify-js/tmp/liftvars.js | 8 + .../node_modules/uglify-js/tmp/test.js | 30 + .../uglify-js/tmp/uglify-hangs.js | 3930 + .../uglify-js/tmp/uglify-hangs2.js | 166 + .../node_modules/uglify-js/uglify-js.js | 17 + .../node_modules/ws/.npmignore | 6 + .../node_modules/ws/.travis.yml | 6 + .../node_modules/ws/History.md | 260 + .../socket.io-client/node_modules/ws/Makefile | 38 + .../node_modules/ws/README.md | 159 + .../node_modules/ws/bench/parser.benchmark.js | 115 + .../node_modules/ws/bench/sender.benchmark.js | 66 + .../node_modules/ws/bench/speed.js | 105 + .../node_modules/ws/bench/util.js | 105 + .../node_modules/ws/bin/wscat | 190 + .../node_modules/ws/binding.gyp | 14 + .../node_modules/ws/build/Makefile | 338 + .../Release/.deps/Release/bufferutil.node.d | 1 + .../Release/obj.target/bufferutil.node.d | 1 + .../obj.target/bufferutil/src/bufferutil.o.d | 25 + .../Release/obj.target/validation.node.d | 1 + .../obj.target/validation/src/validation.o.d | 25 + .../Release/.deps/Release/validation.node.d | 1 + .../ws/build/Release/bufferutil.node | Bin 0 -> 19331 bytes .../node_modules/ws/build/Release/linker.lock | 0 .../build/Release/obj.target/bufferutil.node | Bin 0 -> 19331 bytes .../obj.target/bufferutil/src/bufferutil.o | Bin 0 -> 19216 bytes .../build/Release/obj.target/validation.node | Bin 0 -> 18950 bytes .../obj.target/validation/src/validation.o | Bin 0 -> 17096 bytes .../ws/build/Release/validation.node | Bin 0 -> 18950 bytes .../node_modules/ws/build/binding.Makefile | 6 + .../ws/build/bufferutil.target.mk | 131 + .../node_modules/ws/build/config.gypi | 113 + .../ws/build/validation.target.mk | 131 + .../node_modules/ws/doc/ws.md | 179 + .../ws/examples/fileapi/.npmignore | 1 + .../ws/examples/fileapi/package.json | 18 + .../ws/examples/fileapi/public/app.js | 39 + .../ws/examples/fileapi/public/index.html | 22 + .../ws/examples/fileapi/public/uploader.js | 55 + .../ws/examples/fileapi/server.js | 103 + .../serverstats-express_3/package.json | 17 + .../serverstats-express_3/public/index.html | 33 + .../examples/serverstats-express_3/server.js | 21 + .../ws/examples/serverstats/package.json | 17 + .../ws/examples/serverstats/public/index.html | 33 + .../ws/examples/serverstats/server.js | 19 + .../node_modules/ws/examples/ssl.js | 59 + .../socket.io-client/node_modules/ws/index.js | 26 + .../node_modules/ws/lib/BufferPool.js | 59 + .../ws/lib/BufferUtil.fallback.js | 47 + .../node_modules/ws/lib/BufferUtil.js | 16 + .../node_modules/ws/lib/ErrorCodes.js | 24 + .../node_modules/ws/lib/Receiver.hixie.js | 180 + .../node_modules/ws/lib/Receiver.js | 591 + .../node_modules/ws/lib/Sender.hixie.js | 123 + .../node_modules/ws/lib/Sender.js | 226 + .../ws/lib/Validation.fallback.js | 12 + .../node_modules/ws/lib/Validation.js | 16 + .../node_modules/ws/lib/WebSocket.js | 766 + .../node_modules/ws/lib/WebSocketServer.js | 460 + .../node_modules/ws/lib/browser.js | 5 + .../ws/node_modules/commander/.npmignore | 4 + .../ws/node_modules/commander/.travis.yml | 4 + .../ws/node_modules/commander/History.md | 107 + .../ws/node_modules/commander/Makefile | 7 + .../ws/node_modules/commander/Readme.md | 262 + .../ws/node_modules/commander/index.js | 2 + .../node_modules/commander/lib/commander.js | 1026 + .../ws/node_modules/commander/package.json | 39 + .../ws/node_modules/options/.npmignore | 5 + .../ws/node_modules/options/Makefile | 12 + .../ws/node_modules/options/README.md | 28 + .../ws/node_modules/options/lib/options.js | 86 + .../ws/node_modules/options/package.json | 33 + .../options/test/fixtures/test.conf | 4 + .../node_modules/options/test/options.test.js | 140 + .../ws/node_modules/tinycolor/.npmignore | 5 + .../ws/node_modules/tinycolor/README.md | 3 + .../ws/node_modules/tinycolor/example.js | 3 + .../ws/node_modules/tinycolor/package.json | 28 + .../ws/node_modules/tinycolor/tinycolor.js | 31 + .../node_modules/ws/package.json | 45 + .../node_modules/ws/src/bufferutil.cc | 115 + .../node_modules/ws/src/validation.cc | 143 + .../node_modules/ws/test/BufferPool.test.js | 63 + .../ws/test/Receiver.hixie.test.js | 158 + .../node_modules/ws/test/Receiver.test.js | 255 + .../node_modules/ws/test/Sender.hixie.test.js | 134 + .../node_modules/ws/test/Sender.test.js | 24 + .../node_modules/ws/test/Validation.test.js | 23 + .../ws/test/WebSocket.integration.js | 42 + .../node_modules/ws/test/WebSocket.test.js | 1609 + .../ws/test/WebSocketServer.test.js | 1103 + .../node_modules/ws/test/autobahn-server.js | 29 + .../node_modules/ws/test/autobahn.js | 52 + .../ws/test/fixtures/agent1-cert.pem | 16 + .../ws/test/fixtures/agent1-key.pem | 15 + .../ws/test/fixtures/ca1-cert.pem | 15 + .../node_modules/ws/test/fixtures/ca1-key.pem | 17 + .../ws/test/fixtures/certificate.pem | 13 + .../node_modules/ws/test/fixtures/key.pem | 15 + .../node_modules/ws/test/fixtures/request.pem | 11 + .../node_modules/ws/test/fixtures/textfile | 9 + .../node_modules/ws/test/hybi-common.js | 99 + .../node_modules/ws/test/testserver.js | 180 + .../node_modules/xmlhttprequest/README.md | 53 + .../xmlhttprequest/autotest.watchr | 8 + .../xmlhttprequest/example/demo.js | 16 + .../xmlhttprequest/lib/XMLHttpRequest.js | 548 + .../node_modules/xmlhttprequest/package.json | 40 + .../xmlhttprequest/tests/test-constants.js | 13 + .../xmlhttprequest/tests/test-events.js | 50 + .../xmlhttprequest/tests/test-exceptions.js | 62 + .../xmlhttprequest/tests/test-headers.js | 61 + .../tests/test-request-methods.js | 62 + .../tests/test-request-protocols.js | 34 + .../xmlhttprequest/tests/testdata.txt | 1 + .../socket.io-client/package.json | 68 + .../socket.io-client/test/events.test.js | 120 + .../socket.io-client/test/io.test.js | 31 + .../socket.io-client/test/parser.test.js | 360 + .../socket.io-client/test/socket.test.js | 422 + .../socket.io-client/test/util.test.js | 156 + .../socket.io-client/test/worker.js | 20 + node_modules/socket.io/package.json | 71 + node_modules/sprintf/README.md | 14 + node_modules/sprintf/lib/sprintf.js | 189 + node_modules/sprintf/package.json | 23 + node_modules/supervisor/LICENSE | 27 + node_modules/supervisor/README.md | 104 + node_modules/supervisor/lib/cli-wrapper.js | 14 + node_modules/supervisor/lib/supervisor.js | 312 + node_modules/supervisor/package.json | 118 + 4870 files changed, 670395 insertions(+) create mode 120000 node_modules/.bin/express create mode 120000 node_modules/.bin/jade create mode 120000 node_modules/.bin/lessc create mode 120000 node_modules/.bin/node-supervisor create mode 120000 node_modules/.bin/supervisor create mode 100644 node_modules/async/LICENSE create mode 100644 node_modules/async/README.md create mode 100644 node_modules/async/component.json create mode 100755 node_modules/async/lib/async.js create mode 100644 node_modules/async/package.json create mode 100644 node_modules/emailjs/LICENSE create mode 100644 node_modules/emailjs/Readme.md create mode 100644 node_modules/emailjs/email.js create mode 100644 node_modules/emailjs/node_modules/bufferjs/add-chunk.js create mode 100644 node_modules/emailjs/node_modules/bufferjs/concat.js create mode 100644 node_modules/emailjs/node_modules/bufferjs/index.js create mode 100644 node_modules/emailjs/node_modules/bufferjs/indexOf.js create mode 100644 node_modules/emailjs/node_modules/bufferjs/package.json create mode 100644 node_modules/emailjs/node_modules/mimelib/.npmignore create mode 100644 node_modules/emailjs/node_modules/mimelib/LICENSE create mode 100644 node_modules/emailjs/node_modules/mimelib/README.md create mode 100644 node_modules/emailjs/node_modules/mimelib/index.js create mode 100644 node_modules/emailjs/node_modules/mimelib/lib/content-types-reversed.js create mode 100644 node_modules/emailjs/node_modules/mimelib/lib/content-types.js create mode 100644 node_modules/emailjs/node_modules/mimelib/lib/mimelib.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/.npmignore create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/README.md create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/index.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/package.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/test.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/.npmignore create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/README.md create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/lib/encoding.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.npmignore create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.travis.yml create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/Changelog.md create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/LICENSE create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md~ create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-codec.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-data.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/index.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/internal.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-codec.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data-generated.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/big5-added.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp936.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp949.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp950.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/eucjp.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gbk-added.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/shiftjis.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf16.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf7.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/extend-node.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/index.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/streams.js create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/package.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/package.json create mode 100644 node_modules/emailjs/node_modules/mimelib/node_modules/encoding/test/test.js create mode 100644 node_modules/emailjs/node_modules/mimelib/package.json create mode 100644 node_modules/emailjs/node_modules/moment/.jshintrc create mode 100644 node_modules/emailjs/node_modules/moment/.npmignore create mode 100644 node_modules/emailjs/node_modules/moment/.travis.yml create mode 100644 node_modules/emailjs/node_modules/moment/LICENSE create mode 100644 node_modules/emailjs/node_modules/moment/Makefile create mode 100644 node_modules/emailjs/node_modules/moment/ender.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/bg.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/ca.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/cv.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/da.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/de.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/en-ca.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/en-gb.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/es.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/eu.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/fi.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/fr-ca.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/fr.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/gl.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/hu.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/is.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/it.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/ja.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/jp.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/ko.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/kr.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/nb.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/nl.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/pl.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/pt-br.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/pt.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/ru.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/sv.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/tr.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/zh-cn.js create mode 100644 node_modules/emailjs/node_modules/moment/lang/zh-tw.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang-all.min.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/bg.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/ca.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/cv.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/da.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/de.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/en-ca.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/en-gb.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/es.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/eu.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/fi.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/fr-ca.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/fr.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/gl.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/hu.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/is.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/it.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/ja.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/jp.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/ko.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/kr.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/nb.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/nl.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/pl.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/pt-br.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/pt.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/ru.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/sv.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/tr.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/zh-cn.js create mode 100644 node_modules/emailjs/node_modules/moment/min/lang/zh-tw.js create mode 100644 node_modules/emailjs/node_modules/moment/min/moment.min.js create mode 100644 node_modules/emailjs/node_modules/moment/min/moment.min.pretty.js create mode 100644 node_modules/emailjs/node_modules/moment/moment.js create mode 100755 node_modules/emailjs/node_modules/moment/package.json create mode 100755 node_modules/emailjs/node_modules/moment/readme.md create mode 100644 node_modules/emailjs/node_modules/moment/test/filesize-diff.js create mode 100644 node_modules/emailjs/node_modules/moment/test/filesize-history.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/bg.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/ca.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/cv.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/da.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/de.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/en-ca.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/en-gb.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/en.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/es.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/eu.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/fi.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/fr-ca.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/fr.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/gl.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/hu.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/is.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/it.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/ja.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/jp.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/ko.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/kr.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/nb.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/nl.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/pl.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/pt-br.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/pt.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/ru.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/sv.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/tr.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/zh-cn.js create mode 100644 node_modules/emailjs/node_modules/moment/test/lang/zh-tw.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/add_subtract.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/create.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/days_in_month.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/diff.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/duration.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/format.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/getters_setters.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/humanize_duration.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/is_moment.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/is_valid.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/lang.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/leapyear.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/mutable.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/sod_eod.js create mode 100644 node_modules/emailjs/node_modules/moment/test/moment/utc.js create mode 100644 node_modules/emailjs/node_modules/moment/test/zone.js create mode 100644 node_modules/emailjs/package.json create mode 100644 node_modules/emailjs/smtp/address.js create mode 100644 node_modules/emailjs/smtp/client.js create mode 100644 node_modules/emailjs/smtp/error.js create mode 100644 node_modules/emailjs/smtp/message.js create mode 100644 node_modules/emailjs/smtp/response.js create mode 100644 node_modules/emailjs/smtp/smtp.js create mode 100644 node_modules/emailjs/smtp/tls.js create mode 100644 node_modules/express/.npmignore create mode 100644 node_modules/express/.travis.yml create mode 100644 node_modules/express/History.md create mode 100644 node_modules/express/LICENSE create mode 100644 node_modules/express/Makefile create mode 100644 node_modules/express/Readme.md create mode 100755 node_modules/express/bin/express create mode 100644 node_modules/express/index.js create mode 100644 node_modules/express/lib/application.js create mode 100644 node_modules/express/lib/express.js create mode 100644 node_modules/express/lib/middleware.js create mode 100644 node_modules/express/lib/request.js create mode 100644 node_modules/express/lib/response.js create mode 100644 node_modules/express/lib/router/index.js create mode 100644 node_modules/express/lib/router/route.js create mode 100644 node_modules/express/lib/utils.js create mode 100644 node_modules/express/lib/view.js create mode 100644 node_modules/express/node_modules/buffer-crc32/.npmignore create mode 100644 node_modules/express/node_modules/buffer-crc32/.travis.yml create mode 100644 node_modules/express/node_modules/buffer-crc32/README.md create mode 100644 node_modules/express/node_modules/buffer-crc32/index.js create mode 100644 node_modules/express/node_modules/buffer-crc32/package.json create mode 100644 node_modules/express/node_modules/buffer-crc32/tests/crc.test.js create mode 100644 node_modules/express/node_modules/commander/History.md create mode 100644 node_modules/express/node_modules/commander/Readme.md create mode 100644 node_modules/express/node_modules/commander/index.js create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/README.md create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/index.js create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/package.json create mode 100644 node_modules/express/node_modules/commander/node_modules/keypress/test.js create mode 100644 node_modules/express/node_modules/commander/package.json create mode 100644 node_modules/express/node_modules/connect/.npmignore create mode 100644 node_modules/express/node_modules/connect/.travis.yml create mode 100644 node_modules/express/node_modules/connect/LICENSE create mode 100644 node_modules/express/node_modules/connect/Readme.md create mode 100644 node_modules/express/node_modules/connect/index.js create mode 100644 node_modules/express/node_modules/connect/lib/cache.js create mode 100644 node_modules/express/node_modules/connect/lib/connect.js create mode 100644 node_modules/express/node_modules/connect/lib/index.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/basicAuth.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/bodyParser.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/compress.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/cookieParser.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/cookieSession.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/csrf.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/directory.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/errorHandler.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/favicon.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/json.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/limit.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/logger.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/methodOverride.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/multipart.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/query.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/responseTime.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/cookie.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/memory.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/session.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/session/store.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/static.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/staticCache.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/timeout.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/urlencoded.js create mode 100644 node_modules/express/node_modules/connect/lib/middleware/vhost.js create mode 100644 node_modules/express/node_modules/connect/lib/patch.js create mode 100644 node_modules/express/node_modules/connect/lib/proto.js create mode 100644 node_modules/express/node_modules/connect/lib/public/directory.html create mode 100644 node_modules/express/node_modules/connect/lib/public/error.html create mode 100644 node_modules/express/node_modules/connect/lib/public/favicon.ico create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_add.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_attach.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_code.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_copy.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_delete.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_edit.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_error.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_excel.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_find.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_gear.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_go.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_green.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_key.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_link.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_paste.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_red.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_save.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_word.png create mode 100644 node_modules/express/node_modules/connect/lib/public/icons/page_world.png create mode 100644 node_modules/express/node_modules/connect/lib/public/style.css create mode 100644 node_modules/express/node_modules/connect/lib/utils.js create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/History.md create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/Makefile create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/component.json create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/bytes/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/LICENSE create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/example/json.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/example/post.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/common.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/binaryfile.tar.gz create mode 100755 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js create mode 100755 node_modules/express/node_modules/connect/node_modules/formidable/test/run.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js create mode 100644 node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/History.md create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/Makefile create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/pause/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/.gitmodules create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/.npmignore create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/Readme.md create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/qs/package.json create mode 100644 node_modules/express/node_modules/connect/node_modules/uid2/index.js create mode 100644 node_modules/express/node_modules/connect/node_modules/uid2/package.json create mode 100644 node_modules/express/node_modules/connect/package.json create mode 100644 node_modules/express/node_modules/connect/test.js create mode 100644 node_modules/express/node_modules/cookie-signature/.npmignore create mode 100644 node_modules/express/node_modules/cookie-signature/History.md create mode 100644 node_modules/express/node_modules/cookie-signature/Makefile create mode 100644 node_modules/express/node_modules/cookie-signature/Readme.md create mode 100644 node_modules/express/node_modules/cookie-signature/index.js create mode 100644 node_modules/express/node_modules/cookie-signature/package.json create mode 100644 node_modules/express/node_modules/cookie/.npmignore create mode 100644 node_modules/express/node_modules/cookie/.travis.yml create mode 100644 node_modules/express/node_modules/cookie/LICENSE create mode 100644 node_modules/express/node_modules/cookie/README.md create mode 100644 node_modules/express/node_modules/cookie/index.js create mode 100644 node_modules/express/node_modules/cookie/package.json create mode 100644 node_modules/express/node_modules/cookie/test/mocha.opts create mode 100644 node_modules/express/node_modules/cookie/test/parse.js create mode 100644 node_modules/express/node_modules/cookie/test/serialize.js create mode 100644 node_modules/express/node_modules/debug/.npmignore create mode 100644 node_modules/express/node_modules/debug/History.md create mode 100644 node_modules/express/node_modules/debug/Readme.md create mode 100644 node_modules/express/node_modules/debug/component.json create mode 100644 node_modules/express/node_modules/debug/debug.js create mode 100644 node_modules/express/node_modules/debug/example/app.js create mode 100644 node_modules/express/node_modules/debug/example/browser.html create mode 100644 node_modules/express/node_modules/debug/example/wildcards.js create mode 100644 node_modules/express/node_modules/debug/example/worker.js create mode 100644 node_modules/express/node_modules/debug/index.js create mode 100644 node_modules/express/node_modules/debug/lib/debug.js create mode 100644 node_modules/express/node_modules/debug/package.json create mode 100644 node_modules/express/node_modules/fresh/.npmignore create mode 100644 node_modules/express/node_modules/fresh/Makefile create mode 100644 node_modules/express/node_modules/fresh/Readme.md create mode 100644 node_modules/express/node_modules/fresh/index.js create mode 100644 node_modules/express/node_modules/fresh/package.json create mode 100644 node_modules/express/node_modules/methods/index.js create mode 100644 node_modules/express/node_modules/methods/package.json create mode 100644 node_modules/express/node_modules/mkdirp/.npmignore create mode 100644 node_modules/express/node_modules/mkdirp/.travis.yml create mode 100644 node_modules/express/node_modules/mkdirp/LICENSE create mode 100644 node_modules/express/node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/express/node_modules/mkdirp/index.js create mode 100644 node_modules/express/node_modules/mkdirp/package.json create mode 100644 node_modules/express/node_modules/mkdirp/readme.markdown create mode 100644 node_modules/express/node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/express/node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/express/node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/express/node_modules/mkdirp/test/perm.js create mode 100644 node_modules/express/node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/express/node_modules/mkdirp/test/race.js create mode 100644 node_modules/express/node_modules/mkdirp/test/rel.js create mode 100644 node_modules/express/node_modules/mkdirp/test/return.js create mode 100644 node_modules/express/node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/express/node_modules/mkdirp/test/root.js create mode 100644 node_modules/express/node_modules/mkdirp/test/sync.js create mode 100644 node_modules/express/node_modules/mkdirp/test/umask.js create mode 100644 node_modules/express/node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/express/node_modules/range-parser/.npmignore create mode 100644 node_modules/express/node_modules/range-parser/History.md create mode 100644 node_modules/express/node_modules/range-parser/Makefile create mode 100644 node_modules/express/node_modules/range-parser/Readme.md create mode 100644 node_modules/express/node_modules/range-parser/index.js create mode 100644 node_modules/express/node_modules/range-parser/package.json create mode 100644 node_modules/express/node_modules/send/.npmignore create mode 100644 node_modules/express/node_modules/send/History.md create mode 100644 node_modules/express/node_modules/send/Makefile create mode 100644 node_modules/express/node_modules/send/Readme.md create mode 100644 node_modules/express/node_modules/send/index.js create mode 100644 node_modules/express/node_modules/send/lib/send.js create mode 100644 node_modules/express/node_modules/send/lib/utils.js create mode 100644 node_modules/express/node_modules/send/node_modules/mime/LICENSE create mode 100644 node_modules/express/node_modules/send/node_modules/mime/README.md create mode 100644 node_modules/express/node_modules/send/node_modules/mime/mime.js create mode 100644 node_modules/express/node_modules/send/node_modules/mime/package.json create mode 100644 node_modules/express/node_modules/send/node_modules/mime/test.js create mode 100644 node_modules/express/node_modules/send/node_modules/mime/types/mime.types create mode 100644 node_modules/express/node_modules/send/node_modules/mime/types/node.types create mode 100644 node_modules/express/node_modules/send/package.json create mode 100644 node_modules/express/package.json create mode 100644 node_modules/express/test.js create mode 100644 node_modules/googleapis/.cache/admindirectory_v1 create mode 100644 node_modules/googleapis/.cache/calendarv3 create mode 100644 node_modules/googleapis/.npmignore create mode 100644 node_modules/googleapis/.travis.yml create mode 100644 node_modules/googleapis/COPYING create mode 100644 node_modules/googleapis/README.md create mode 100644 node_modules/googleapis/lib/auth/authclient.js create mode 100644 node_modules/googleapis/lib/auth/computeclient.js create mode 100644 node_modules/googleapis/lib/auth/oauth2client.js create mode 100644 node_modules/googleapis/lib/cache.js create mode 100644 node_modules/googleapis/lib/client.js create mode 100644 node_modules/googleapis/lib/googleapis.js create mode 100644 node_modules/googleapis/lib/requests.js create mode 100644 node_modules/googleapis/lib/transporters.js create mode 100644 node_modules/googleapis/node_modules/async/LICENSE create mode 100644 node_modules/googleapis/node_modules/async/README.md create mode 100755 node_modules/googleapis/node_modules/async/lib/async.js create mode 100644 node_modules/googleapis/node_modules/async/package.json create mode 100644 node_modules/googleapis/node_modules/request/LICENSE create mode 100644 node_modules/googleapis/node_modules/request/README.md create mode 100644 node_modules/googleapis/node_modules/request/aws.js create mode 100644 node_modules/googleapis/node_modules/request/forever.js create mode 100644 node_modules/googleapis/node_modules/request/main.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/.npmignore create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/License create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/Makefile create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/Readme.md create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/lib/form_data.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/.gitmodules create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/.npmignore create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/LICENSE create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/Makefile create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/README.md create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/index.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/package.json create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/License create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js create mode 100755 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js create mode 100755 node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/package.json create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/common.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/bacon.txt create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-http-response.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-pipe.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit.js create mode 100755 node_modules/googleapis/node_modules/request/node_modules/form-data/test/run.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/LICENSE create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/README.md create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/mime.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/package.json create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/test.js create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/types/mime.types create mode 100644 node_modules/googleapis/node_modules/request/node_modules/mime/types/node.types create mode 100644 node_modules/googleapis/node_modules/request/oauth.js create mode 100644 node_modules/googleapis/node_modules/request/package.json create mode 100644 node_modules/googleapis/node_modules/request/tests/googledoodle.png create mode 100644 node_modules/googleapis/node_modules/request/tests/run.js create mode 100644 node_modules/googleapis/node_modules/request/tests/server.js create mode 100644 node_modules/googleapis/node_modules/request/tests/squid.conf create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.cnf create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crl create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crt create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.csr create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.key create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.srl create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/server.cnf create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/server.crt create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/server.csr create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/server.js create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/ca/server.key create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/npm-ca.crt create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/test.crt create mode 100644 node_modules/googleapis/node_modules/request/tests/ssl/test.key create mode 100644 node_modules/googleapis/node_modules/request/tests/test-basic-auth.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-body.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-cookie.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-cookiejar.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-defaults.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-digest-auth.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-errors.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-follow-all-303.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-follow-all.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-form.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-headers.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-httpModule.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-https-strict.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-https.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-oauth.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-params.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-piped-redirect.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-pipes.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-pool.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-protocol-changing-redirect.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-proxy.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-qs.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-redirect.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-s3.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-timeout.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-toJSON.js create mode 100644 node_modules/googleapis/node_modules/request/tests/test-tunnel.js create mode 100644 node_modules/googleapis/node_modules/request/tests/unicycle.jpg create mode 100644 node_modules/googleapis/node_modules/request/tunnel.js create mode 100644 node_modules/googleapis/node_modules/request/uuid.js create mode 100644 node_modules/googleapis/node_modules/request/vendor/cookie/index.js create mode 100644 node_modules/googleapis/node_modules/request/vendor/cookie/jar.js create mode 100644 node_modules/googleapis/package.json create mode 100644 node_modules/jade/.npmignore create mode 100644 node_modules/jade/LICENSE create mode 100644 node_modules/jade/Readme.md create mode 100644 node_modules/jade/Readme_zh-cn.md create mode 100755 node_modules/jade/bin/jade create mode 100644 node_modules/jade/component.json create mode 100644 node_modules/jade/index.js create mode 100644 node_modules/jade/jade.js create mode 100644 node_modules/jade/jade.md create mode 100644 node_modules/jade/lib/compiler.js create mode 100644 node_modules/jade/lib/doctypes.js create mode 100644 node_modules/jade/lib/filters-client.js create mode 100644 node_modules/jade/lib/filters.js create mode 100644 node_modules/jade/lib/index.js create mode 100644 node_modules/jade/lib/inline-tags.js create mode 100644 node_modules/jade/lib/jade.js create mode 100644 node_modules/jade/lib/lexer.js create mode 100644 node_modules/jade/lib/nodes/attrs.js create mode 100644 node_modules/jade/lib/nodes/block-comment.js create mode 100644 node_modules/jade/lib/nodes/block.js create mode 100644 node_modules/jade/lib/nodes/case.js create mode 100644 node_modules/jade/lib/nodes/code.js create mode 100644 node_modules/jade/lib/nodes/comment.js create mode 100644 node_modules/jade/lib/nodes/doctype.js create mode 100644 node_modules/jade/lib/nodes/each.js create mode 100644 node_modules/jade/lib/nodes/filter.js create mode 100644 node_modules/jade/lib/nodes/index.js create mode 100644 node_modules/jade/lib/nodes/literal.js create mode 100644 node_modules/jade/lib/nodes/mixin.js create mode 100644 node_modules/jade/lib/nodes/node.js create mode 100644 node_modules/jade/lib/nodes/tag.js create mode 100644 node_modules/jade/lib/nodes/text.js create mode 100644 node_modules/jade/lib/parser.js create mode 100644 node_modules/jade/lib/runtime.js create mode 100644 node_modules/jade/lib/self-closing.js create mode 100644 node_modules/jade/lib/utils.js create mode 100644 node_modules/jade/node_modules/character-parser/.npmignore create mode 100644 node_modules/jade/node_modules/character-parser/.travis.yml create mode 100644 node_modules/jade/node_modules/character-parser/README.md create mode 100644 node_modules/jade/node_modules/character-parser/index.js create mode 100644 node_modules/jade/node_modules/character-parser/package.json create mode 100644 node_modules/jade/node_modules/character-parser/test/index.js create mode 100644 node_modules/jade/node_modules/commander/History.md create mode 100644 node_modules/jade/node_modules/commander/Readme.md create mode 100644 node_modules/jade/node_modules/commander/index.js create mode 100644 node_modules/jade/node_modules/commander/node_modules/keypress/README.md create mode 100644 node_modules/jade/node_modules/commander/node_modules/keypress/index.js create mode 100644 node_modules/jade/node_modules/commander/node_modules/keypress/package.json create mode 100644 node_modules/jade/node_modules/commander/node_modules/keypress/test.js create mode 100644 node_modules/jade/node_modules/commander/package.json create mode 100644 node_modules/jade/node_modules/constantinople/.gitattributes create mode 100644 node_modules/jade/node_modules/constantinople/.npmignore create mode 100644 node_modules/jade/node_modules/constantinople/.travis.yml create mode 100644 node_modules/jade/node_modules/constantinople/LICENSE create mode 100644 node_modules/jade/node_modules/constantinople/README.md create mode 100644 node_modules/jade/node_modules/constantinople/index.js create mode 120000 node_modules/jade/node_modules/constantinople/node_modules/.bin/uglifyjs create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.npmignore create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.travis.yml create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/LICENSE create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/README.md create mode 100755 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/ast.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/compress.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/mozilla-ast.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/output.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/parse.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/scope.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/sourcemap.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/transform.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/utils.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/.travis.yml create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/LICENSE create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/bool.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_hash.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_singles.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/divide.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/nonopt.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/reflect.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/short.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/string.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/usage-options.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/xup.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/index.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/package.json create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/readme.markdown create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/argv.js create mode 100755 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/bin.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/parse.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/usage.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.npmignore create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.travis.yml create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/LICENSE create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/README.md create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/mini-require.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/package.json create mode 100755 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/run-tests.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/package.json create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/arrays.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/blocks.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/conditionals.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/dead-code.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/debugger.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/drop-unused.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-105.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-12.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-143.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-22.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-44.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-59.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/labels.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/loops.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/properties.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/sequences.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/switch.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/typeof.js create mode 100755 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/run-tests.js create mode 100644 node_modules/jade/node_modules/constantinople/node_modules/uglify-js/tools/node.js create mode 100644 node_modules/jade/node_modules/constantinople/package.json create mode 100644 node_modules/jade/node_modules/constantinople/test/index.js create mode 100644 node_modules/jade/node_modules/mkdirp/.npmignore create mode 100644 node_modules/jade/node_modules/mkdirp/.travis.yml create mode 100644 node_modules/jade/node_modules/mkdirp/LICENSE create mode 100644 node_modules/jade/node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/jade/node_modules/mkdirp/index.js create mode 100644 node_modules/jade/node_modules/mkdirp/package.json create mode 100644 node_modules/jade/node_modules/mkdirp/readme.markdown create mode 100644 node_modules/jade/node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/perm.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/race.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/rel.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/return.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/root.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/sync.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/umask.js create mode 100644 node_modules/jade/node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/jade/node_modules/monocle/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/LICENSE create mode 100644 node_modules/jade/node_modules/monocle/README.md create mode 100644 node_modules/jade/node_modules/monocle/logo.png create mode 100644 node_modules/jade/node_modules/monocle/monocle.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/LICENSE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/README.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/Readme.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/callback-api.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/grep.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/LICENCE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/examples/pretty.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/LICENCE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/Makefile create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/README.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/test.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.APACHE2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.MIT create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/test/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/LICENCE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/examples/pretty.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/test/simple-map.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/LICENSE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/README.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/bool.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_double.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_single.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_hash.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_singles.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/divide.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_options.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_wrap.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/nonopt.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/reflect.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/short.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/string.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/usage-options.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/xup.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/README.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/center.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/meat.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/break.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/argv.js create mode 100755 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/bin.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/parse.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/usage.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/pause-end.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/LICENCE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/examples/pretty.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.APACHE2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.MIT create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/test/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/test/split.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.APACHE2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.MIT create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/buffering.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/end.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/connect.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/merge.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pause.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pipeline.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readArray.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readable.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/replace.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/simple-map.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/spec.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/split.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/stringify.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/writeArray.asynct.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/README.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/examples/tap-nested-objects.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/.travis.yml create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.APACHE2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.MIT create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/readme.markdown create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/buffering.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/end.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/index.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/test/tap-stream.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api-pipe.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/LICENSE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/README.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/minimatch.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/.npmignore create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/AUTHORS create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/LICENSE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/README.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/s.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/basic.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/foreach.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/LICENSE create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/README.md create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/bench.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/sigmund.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/test/basic.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/basic.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/brace-expand.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/caching.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/defaults.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/package.json create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/readdirp.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/stream-api.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file1.ext1 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file2.ext2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file3.ext3 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_subdir1/root1_dir1_subdir1_file1.ext1 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir2/root_dir2_file1.ext1 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir2/root_dir2_file2.ext2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file1.ext1 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file2.ext2 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file3.ext3 create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp-stream.js create mode 100644 node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp.js create mode 100644 node_modules/jade/node_modules/monocle/package.json create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/creation3.txt create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/creation4.txt create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/creation5.txt create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/foo.txt create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/longbow.js create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/nestedDir/servent.txt create mode 100644 node_modules/jade/node_modules/monocle/test/sample_files/zap.bat create mode 100644 node_modules/jade/node_modules/monocle/test/tester.js create mode 100644 node_modules/jade/node_modules/transformers/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/.travis.yml create mode 100644 node_modules/jade/node_modules/transformers/README.md create mode 100644 node_modules/jade/node_modules/transformers/history.md create mode 100644 node_modules/jade/node_modules/transformers/lib/shared.js create mode 100644 node_modules/jade/node_modules/transformers/lib/transformers.js create mode 120000 node_modules/jade/node_modules/transformers/node_modules/.bin/uglifyjs create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/History.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/Makefile create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/Readme.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/benchmark.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/component.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/History.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Makefile create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Readme.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/component.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/History.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Makefile create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Readme.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/component.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/css/test.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/Readme.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/readme.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/promise/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md create mode 100755 node_modules/jade/node_modules/transformers/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/compress.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/mozilla-ast.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/output.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/parse.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/scope.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/sourcemap.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/transform.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/utils.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/.travis.yml create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/LICENSE create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/bool.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_hash.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_singles.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/divide.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/nonopt.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/reflect.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/short.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/string.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/usage-options.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/xup.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/readme.markdown create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/argv.js create mode 100755 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/bin.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/parse.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/usage.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.npmignore create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.travis.yml create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/LICENSE create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/README.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/mini-require.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/package.json create mode 100755 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/run-tests.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/package.json create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/arrays.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/blocks.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/conditionals.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/dead-code.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/debugger.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/drop-unused.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/issue-105.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/issue-12.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/issue-22.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/issue-44.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/issue-59.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/labels.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/loops.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/properties.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/sequences.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/compress/switch.js create mode 100755 node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/run-tests.js create mode 100644 node_modules/jade/node_modules/transformers/node_modules/uglify-js/tools/node.js create mode 100644 node_modules/jade/node_modules/transformers/package.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.css create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/component.json create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/index.css create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/index.js create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/component/second.css create mode 100644 node_modules/jade/node_modules/transformers/test/fixtures/uglify-js/script.js create mode 100644 node_modules/jade/node_modules/transformers/test/simple/atpl/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/atpl/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cson/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cson/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cson/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/cson/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/dot/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/dot/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/dust/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/dust/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/eco/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/eco/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/ect/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/ect/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/ejs/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/ejs/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/haml/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/haml/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/haml/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/haml/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/hogan/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/hogan/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/jade/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/jade/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/jazz/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/jazz/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/just/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/just/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/less/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/less/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/less/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/less/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/liquor/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/liquor/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/mote/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/mote/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/mustache/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/mustache/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/plates/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/plates/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/plates/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/plates/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/qejs/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/qejs/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/sass/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/sass/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/sass/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/sass/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/swig/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/swig/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/templayed/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/templayed/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/toffee/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/toffee/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b-expected.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/underscore/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/underscore/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/walrus/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/walrus/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-a.txt create mode 100644 node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-b.txt create mode 100644 node_modules/jade/node_modules/transformers/test/test.js create mode 100644 node_modules/jade/node_modules/transformers/test/update-package.js create mode 100644 node_modules/jade/node_modules/with/.npmignore create mode 100644 node_modules/jade/node_modules/with/.travis.yml create mode 100644 node_modules/jade/node_modules/with/README.md create mode 100644 node_modules/jade/node_modules/with/index.js create mode 120000 node_modules/jade/node_modules/with/node_modules/.bin/uglifyjs create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/.npmignore create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/.travis.yml create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/LICENSE create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/README.md create mode 100755 node_modules/jade/node_modules/with/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/ast.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/compress.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/mozilla-ast.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/output.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/parse.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/scope.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/sourcemap.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/transform.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/lib/utils.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/.travis.yml create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/LICENSE create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/bool.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_hash.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_singles.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/divide.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/nonopt.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/reflect.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/short.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/string.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/usage-options.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/xup.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/index.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/package.json create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/readme.markdown create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/argv.js create mode 100755 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/bin.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/parse.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/usage.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.npmignore create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.travis.yml create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/LICENSE create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/README.md create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/mini-require.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/package.json create mode 100755 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/run-tests.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/package.json create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/arrays.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/blocks.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/conditionals.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/dead-code.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/debugger.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/drop-unused.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-105.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-12.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-143.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-22.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-44.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-59.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/labels.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/loops.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/properties.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/sequences.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/switch.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/typeof.js create mode 100755 node_modules/jade/node_modules/with/node_modules/uglify-js/test/run-tests.js create mode 100644 node_modules/jade/node_modules/with/node_modules/uglify-js/tools/node.js create mode 100644 node_modules/jade/node_modules/with/package.json create mode 100644 node_modules/jade/node_modules/with/test/index.js create mode 100644 node_modules/jade/package.json create mode 100644 node_modules/jade/runtime.js create mode 100644 node_modules/less/.gitattributes create mode 100644 node_modules/less/.npmignore create mode 100644 node_modules/less/CHANGELOG.md create mode 100644 node_modules/less/CONTRIBUTING.md create mode 100644 node_modules/less/LICENSE create mode 100644 node_modules/less/Makefile create mode 100644 node_modules/less/README.md create mode 100644 node_modules/less/benchmark/benchmark.less create mode 100644 node_modules/less/benchmark/less-benchmark.js create mode 100755 node_modules/less/bin/lessc create mode 100644 node_modules/less/build/amd.js create mode 100644 node_modules/less/build/header.js create mode 100644 node_modules/less/build/require-rhino.js create mode 100644 node_modules/less/build/require.js create mode 100644 node_modules/less/dist/less-1.1.0.js create mode 100644 node_modules/less/dist/less-1.1.0.min.js create mode 100644 node_modules/less/dist/less-1.1.1.js create mode 100644 node_modules/less/dist/less-1.1.1.min.js create mode 100644 node_modules/less/dist/less-1.1.2.js create mode 100644 node_modules/less/dist/less-1.1.2.min.js create mode 100644 node_modules/less/dist/less-1.1.3.js create mode 100644 node_modules/less/dist/less-1.1.3.min.js create mode 100644 node_modules/less/dist/less-1.1.4.js create mode 100644 node_modules/less/dist/less-1.1.4.min.js create mode 100644 node_modules/less/dist/less-1.1.5.js create mode 100644 node_modules/less/dist/less-1.1.5.min.js create mode 100644 node_modules/less/dist/less-1.1.6.js create mode 100644 node_modules/less/dist/less-1.1.6.min.js create mode 100644 node_modules/less/dist/less-1.2.0.js create mode 100644 node_modules/less/dist/less-1.2.0.min.js create mode 100644 node_modules/less/dist/less-1.2.1.js create mode 100644 node_modules/less/dist/less-1.2.1.min.js create mode 100644 node_modules/less/dist/less-1.2.2.js create mode 100644 node_modules/less/dist/less-1.2.2.min.js create mode 100644 node_modules/less/dist/less-1.3.0.js create mode 100644 node_modules/less/dist/less-1.3.0.min.js create mode 100644 node_modules/less/dist/less-1.3.1.js create mode 100644 node_modules/less/dist/less-1.3.1.min.js create mode 100644 node_modules/less/dist/less-1.3.2.js create mode 100644 node_modules/less/dist/less-1.3.2.min.js create mode 100644 node_modules/less/dist/less-1.3.3.js create mode 100644 node_modules/less/dist/less-1.3.3.min.js create mode 100644 node_modules/less/dist/less-1.4.0-beta.js create mode 100644 node_modules/less/dist/less-1.4.0-beta.min.js create mode 100644 node_modules/less/dist/less-1.4.0.js create mode 100644 node_modules/less/dist/less-1.4.0.min.js create mode 100644 node_modules/less/dist/less-1.4.1.js create mode 100644 node_modules/less/dist/less-1.4.1.min.js create mode 100644 node_modules/less/dist/less-rhino-1.1.3.js create mode 100644 node_modules/less/dist/less-rhino-1.1.5.js create mode 100644 node_modules/less/dist/less-rhino-1.3.1.js create mode 100644 node_modules/less/dist/less-rhino-1.3.2.js create mode 100644 node_modules/less/dist/less-rhino-1.3.3.js create mode 100644 node_modules/less/dist/less-rhino-1.4.0.js create mode 100644 node_modules/less/lib/less/browser.js create mode 100644 node_modules/less/lib/less/colors.js create mode 100644 node_modules/less/lib/less/env.js create mode 100644 node_modules/less/lib/less/extend-visitor.js create mode 100644 node_modules/less/lib/less/functions.js create mode 100644 node_modules/less/lib/less/import-visitor.js create mode 100644 node_modules/less/lib/less/index.js create mode 100644 node_modules/less/lib/less/join-selector-visitor.js create mode 100644 node_modules/less/lib/less/lessc_helper.js create mode 100644 node_modules/less/lib/less/parser.js create mode 100644 node_modules/less/lib/less/rhino.js create mode 100644 node_modules/less/lib/less/tree.js create mode 100644 node_modules/less/lib/less/tree/alpha.js create mode 100644 node_modules/less/lib/less/tree/anonymous.js create mode 100644 node_modules/less/lib/less/tree/assignment.js create mode 100644 node_modules/less/lib/less/tree/call.js create mode 100644 node_modules/less/lib/less/tree/color.js create mode 100644 node_modules/less/lib/less/tree/comment.js create mode 100644 node_modules/less/lib/less/tree/condition.js create mode 100644 node_modules/less/lib/less/tree/dimension.js create mode 100644 node_modules/less/lib/less/tree/directive.js create mode 100644 node_modules/less/lib/less/tree/element.js create mode 100644 node_modules/less/lib/less/tree/expression.js create mode 100644 node_modules/less/lib/less/tree/extend.js create mode 100644 node_modules/less/lib/less/tree/import.js create mode 100644 node_modules/less/lib/less/tree/javascript.js create mode 100644 node_modules/less/lib/less/tree/keyword.js create mode 100644 node_modules/less/lib/less/tree/media.js create mode 100644 node_modules/less/lib/less/tree/mixin.js create mode 100644 node_modules/less/lib/less/tree/negative.js create mode 100644 node_modules/less/lib/less/tree/operation.js create mode 100644 node_modules/less/lib/less/tree/paren.js create mode 100644 node_modules/less/lib/less/tree/quoted.js create mode 100644 node_modules/less/lib/less/tree/rule.js create mode 100644 node_modules/less/lib/less/tree/ruleset.js create mode 100644 node_modules/less/lib/less/tree/selector.js create mode 100644 node_modules/less/lib/less/tree/unicode-descriptor.js create mode 100644 node_modules/less/lib/less/tree/url.js create mode 100644 node_modules/less/lib/less/tree/value.js create mode 100644 node_modules/less/lib/less/tree/variable.js create mode 100644 node_modules/less/lib/less/visitor.js create mode 120000 node_modules/less/node_modules/.bin/ycssmin create mode 100644 node_modules/less/node_modules/mime/LICENSE create mode 100644 node_modules/less/node_modules/mime/README.md create mode 100644 node_modules/less/node_modules/mime/mime.js create mode 100644 node_modules/less/node_modules/mime/package.json create mode 100644 node_modules/less/node_modules/mime/test.js create mode 100644 node_modules/less/node_modules/mime/types/mime.types create mode 100644 node_modules/less/node_modules/mime/types/node.types create mode 100644 node_modules/less/node_modules/mkdirp/.npmignore create mode 100644 node_modules/less/node_modules/mkdirp/.travis.yml create mode 100644 node_modules/less/node_modules/mkdirp/LICENSE create mode 100644 node_modules/less/node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/less/node_modules/mkdirp/index.js create mode 100644 node_modules/less/node_modules/mkdirp/package.json create mode 100644 node_modules/less/node_modules/mkdirp/readme.markdown create mode 100644 node_modules/less/node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/less/node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/less/node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/less/node_modules/mkdirp/test/perm.js create mode 100644 node_modules/less/node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/less/node_modules/mkdirp/test/race.js create mode 100644 node_modules/less/node_modules/mkdirp/test/rel.js create mode 100644 node_modules/less/node_modules/mkdirp/test/return.js create mode 100644 node_modules/less/node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/less/node_modules/mkdirp/test/root.js create mode 100644 node_modules/less/node_modules/mkdirp/test/sync.js create mode 100644 node_modules/less/node_modules/mkdirp/test/umask.js create mode 100644 node_modules/less/node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/less/node_modules/request/LICENSE create mode 100644 node_modules/less/node_modules/request/README.md create mode 100755 node_modules/less/node_modules/request/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/aws-sign/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/aws-sign/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/aws-sign/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/aws-sign/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/jar.js create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/tests/run.js create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js create mode 100644 node_modules/less/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js create mode 100644 node_modules/less/node_modules/request/node_modules/forever-agent/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/forever-agent/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/forever-agent/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/forever-agent/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/.travis.yml create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/License create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/Makefile create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/Readme.md create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/lib/form_data.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node-form-data.sublime-project create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node-form-data.sublime-workspace create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/License create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js create mode 100755 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js create mode 100755 node_modules/less/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/sftp-config.json create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/common.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/fixture/bacon.txt create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-custom-filename.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-http-response.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-pipe.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js create mode 100644 node_modules/less/node_modules/request/node_modules/form-data/test/integration/test-submit.js create mode 100755 node_modules/less/node_modules/request/node_modules/form-data/test/run.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/Makefile create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/example/usage.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/images/hawk.png create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/images/logo.png create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/lib/browser.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/lib/client.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/lib/crypto.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/lib/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/lib/server.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/lib/utils.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/Makefile create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/images/boom.png create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/Makefile create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/images/hoek.png create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/escape.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/escaper.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test1.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test2.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test3.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/package.json create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/images/hoek.png create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.npmignore create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.travis.yml create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/LICENSE create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/Makefile create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/README.md create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/images/hoek.png create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/escape.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/escaper.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test1.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test2.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test3.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/package.json create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/package.json create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/browser.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/client.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/crypto.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/index.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/readme.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/server.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/uri.js create mode 100755 node_modules/less/node_modules/request/node_modules/hawk/test/utils.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/.dir-locals.el create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/http_signing.md create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/lib/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/lib/parser.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/lib/signer.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/lib/util.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/lib/verify.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/README create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json create mode 100755 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf create mode 100755 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js create mode 100644 node_modules/less/node_modules/request/node_modules/http-signature/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/json-stringify-safe/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/json-stringify-safe/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/json-stringify-safe/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/json-stringify-safe/stringify.js create mode 100644 node_modules/less/node_modules/request/node_modules/json-stringify-safe/test.js create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/LICENSE.md create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu create mode 100755 node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/bench.sh create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/test/compare_v1.js create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/test/test.html create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js create mode 100644 node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js create mode 100644 node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/oauth-sign/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/oauth-sign/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/oauth-sign/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/oauth-sign/test.js create mode 100644 node_modules/less/node_modules/request/node_modules/qs/.gitmodules create mode 100644 node_modules/less/node_modules/request/node_modules/qs/.npmignore create mode 100644 node_modules/less/node_modules/request/node_modules/qs/Readme.md create mode 100644 node_modules/less/node_modules/request/node_modules/qs/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/qs/package.json create mode 100644 node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE create mode 100644 node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md create mode 100644 node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js create mode 100644 node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json create mode 100755 node_modules/less/node_modules/request/package.json create mode 100644 node_modules/less/node_modules/request/tests/googledoodle.jpg create mode 100644 node_modules/less/node_modules/request/tests/run.js create mode 100644 node_modules/less/node_modules/request/tests/server.js create mode 100644 node_modules/less/node_modules/request/tests/squid.conf create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/ca.cnf create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/ca.crl create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/ca.crt create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/ca.csr create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/ca.key create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/ca.srl create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/server.cnf create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/server.crt create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/server.csr create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/server.js create mode 100644 node_modules/less/node_modules/request/tests/ssl/ca/server.key create mode 100644 node_modules/less/node_modules/request/tests/ssl/npm-ca.crt create mode 100644 node_modules/less/node_modules/request/tests/ssl/test.crt create mode 100644 node_modules/less/node_modules/request/tests/ssl/test.key create mode 100644 node_modules/less/node_modules/request/tests/test-agentOptions.js create mode 100644 node_modules/less/node_modules/request/tests/test-basic-auth.js create mode 100644 node_modules/less/node_modules/request/tests/test-body.js create mode 100644 node_modules/less/node_modules/request/tests/test-defaults.js create mode 100644 node_modules/less/node_modules/request/tests/test-digest-auth.js create mode 100644 node_modules/less/node_modules/request/tests/test-emptyBody.js create mode 100644 node_modules/less/node_modules/request/tests/test-errors.js create mode 100644 node_modules/less/node_modules/request/tests/test-follow-all-303.js create mode 100644 node_modules/less/node_modules/request/tests/test-follow-all.js create mode 100644 node_modules/less/node_modules/request/tests/test-form.js create mode 100755 node_modules/less/node_modules/request/tests/test-hawk.js create mode 100644 node_modules/less/node_modules/request/tests/test-headers.js create mode 100755 node_modules/less/node_modules/request/tests/test-http-signature.js create mode 100644 node_modules/less/node_modules/request/tests/test-httpModule.js create mode 100644 node_modules/less/node_modules/request/tests/test-https-strict.js create mode 100644 node_modules/less/node_modules/request/tests/test-https.js create mode 100644 node_modules/less/node_modules/request/tests/test-localAddress.js create mode 100644 node_modules/less/node_modules/request/tests/test-oauth.js create mode 100644 node_modules/less/node_modules/request/tests/test-onelineproxy.js create mode 100644 node_modules/less/node_modules/request/tests/test-params.js create mode 100644 node_modules/less/node_modules/request/tests/test-piped-redirect.js create mode 100644 node_modules/less/node_modules/request/tests/test-pipes.js create mode 100644 node_modules/less/node_modules/request/tests/test-pool.js create mode 100644 node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js create mode 100644 node_modules/less/node_modules/request/tests/test-proxy.js create mode 100644 node_modules/less/node_modules/request/tests/test-qs.js create mode 100644 node_modules/less/node_modules/request/tests/test-redirect.js create mode 100644 node_modules/less/node_modules/request/tests/test-s3.js create mode 100644 node_modules/less/node_modules/request/tests/test-timeout.js create mode 100644 node_modules/less/node_modules/request/tests/test-toJSON.js create mode 100644 node_modules/less/node_modules/request/tests/test-tunnel.js create mode 100644 node_modules/less/node_modules/request/tests/unicycle.jpg create mode 100644 node_modules/less/node_modules/ycssmin/.npmignore create mode 100644 node_modules/less/node_modules/ycssmin/.travis.yml create mode 100644 node_modules/less/node_modules/ycssmin/LICENSE create mode 100644 node_modules/less/node_modules/ycssmin/Makefile create mode 100644 node_modules/less/node_modules/ycssmin/README.md create mode 100755 node_modules/less/node_modules/ycssmin/bin/cssmin create mode 100755 node_modules/less/node_modules/ycssmin/cssmin.js create mode 100755 node_modules/less/node_modules/ycssmin/package.json create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/background-position.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/background-position.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/border-none.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/border-none.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/charset-media.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/charset-media.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/color-simple.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/color-simple.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/color.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/color.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/comment.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/comment.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/decimals.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/decimals.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/font-face.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/font-face.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/media-multi.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/media-multi.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/media-test.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/media-test.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/pseudo.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/pseudo.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/special-comments.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/special-comments.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/zeros.css create mode 100644 node_modules/less/node_modules/ycssmin/tests/files/zeros.css.min create mode 100644 node_modules/less/node_modules/ycssmin/tests/tests.js create mode 100644 node_modules/less/package.json create mode 100644 node_modules/less/test/browser-test-prepare.js create mode 100644 node_modules/less/test/browser/common.js create mode 100644 node_modules/less/test/browser/css/relative-urls/urls.css create mode 100644 node_modules/less/test/browser/css/rootpath-relative/urls.css create mode 100644 node_modules/less/test/browser/css/rootpath/urls.css create mode 100644 node_modules/less/test/browser/css/urls.css create mode 100644 node_modules/less/test/browser/jasmine-html.js create mode 100644 node_modules/less/test/browser/jasmine.css create mode 100644 node_modules/less/test/browser/jasmine.js create mode 100644 node_modules/less/test/browser/less/imports/urls.less create mode 100644 node_modules/less/test/browser/less/imports/urls2.less create mode 100644 node_modules/less/test/browser/less/relative-urls/urls.less create mode 100644 node_modules/less/test/browser/less/rootpath-relative/urls.less create mode 100644 node_modules/less/test/browser/less/rootpath/urls.less create mode 100644 node_modules/less/test/browser/less/urls.less create mode 100644 node_modules/less/test/browser/phantom-runner.js create mode 100644 node_modules/less/test/browser/runner-browser.js create mode 100644 node_modules/less/test/browser/runner-errors.js create mode 100644 node_modules/less/test/browser/runner-legacy.js create mode 100644 node_modules/less/test/browser/runner-main.js create mode 100644 node_modules/less/test/browser/runner-production.js create mode 100644 node_modules/less/test/browser/runner-relative-urls.js create mode 100644 node_modules/less/test/browser/runner-rootpath-relative.js create mode 100644 node_modules/less/test/browser/runner-rootpath.js create mode 100644 node_modules/less/test/browser/template.htm create mode 100644 node_modules/less/test/css/charsets.css create mode 100644 node_modules/less/test/css/colors.css create mode 100644 node_modules/less/test/css/comments.css create mode 100644 node_modules/less/test/css/compression/compression.css create mode 100644 node_modules/less/test/css/css-3.css create mode 100644 node_modules/less/test/css/css-escapes.css create mode 100644 node_modules/less/test/css/css.css create mode 100644 node_modules/less/test/css/debug/linenumbers-all.css create mode 100644 node_modules/less/test/css/debug/linenumbers-comments.css create mode 100644 node_modules/less/test/css/debug/linenumbers-mediaquery.css create mode 100644 node_modules/less/test/css/extend-chaining.css create mode 100644 node_modules/less/test/css/extend-clearfix.css create mode 100644 node_modules/less/test/css/extend-exact.css create mode 100644 node_modules/less/test/css/extend-media.css create mode 100644 node_modules/less/test/css/extend-nest.css create mode 100644 node_modules/less/test/css/extend-selector.css create mode 100644 node_modules/less/test/css/extend.css create mode 100644 node_modules/less/test/css/functions.css create mode 100644 node_modules/less/test/css/ie-filters.css create mode 100644 node_modules/less/test/css/import-interpolation.css create mode 100644 node_modules/less/test/css/import-once.css create mode 100644 node_modules/less/test/css/import.css create mode 100644 node_modules/less/test/css/javascript.css create mode 100644 node_modules/less/test/css/lazy-eval.css create mode 100644 node_modules/less/test/css/legacy/legacy.css create mode 100644 node_modules/less/test/css/media.css create mode 100644 node_modules/less/test/css/mixins-args.css create mode 100644 node_modules/less/test/css/mixins-closure.css create mode 100644 node_modules/less/test/css/mixins-guards.css create mode 100644 node_modules/less/test/css/mixins-important.css create mode 100644 node_modules/less/test/css/mixins-named-args.css create mode 100644 node_modules/less/test/css/mixins-nested.css create mode 100644 node_modules/less/test/css/mixins-pattern.css create mode 100644 node_modules/less/test/css/mixins.css create mode 100644 node_modules/less/test/css/operations.css create mode 100644 node_modules/less/test/css/parens.css create mode 100644 node_modules/less/test/css/rulesets.css create mode 100644 node_modules/less/test/css/scope.css create mode 100644 node_modules/less/test/css/selectors.css create mode 100644 node_modules/less/test/css/static-urls/urls.css create mode 100644 node_modules/less/test/css/strings.css create mode 100644 node_modules/less/test/css/urls.css create mode 100644 node_modules/less/test/css/variables.css create mode 100644 node_modules/less/test/css/whitespace.css create mode 100644 node_modules/less/test/data/data-uri-fail.png create mode 100644 node_modules/less/test/data/image.jpg create mode 100644 node_modules/less/test/data/page.html create mode 100644 node_modules/less/test/less-test.js create mode 100644 node_modules/less/test/less/charsets.less create mode 100644 node_modules/less/test/less/colors.less create mode 100644 node_modules/less/test/less/comments.less create mode 100644 node_modules/less/test/less/compression/compression.less create mode 100644 node_modules/less/test/less/css-3.less create mode 100644 node_modules/less/test/less/css-escapes.less create mode 100644 node_modules/less/test/less/css.less create mode 100644 node_modules/less/test/less/debug/import/test.less create mode 100644 node_modules/less/test/less/debug/linenumbers.less create mode 100644 node_modules/less/test/less/errors/add-mixed-units.less create mode 100644 node_modules/less/test/less/errors/add-mixed-units.txt create mode 100644 node_modules/less/test/less/errors/add-mixed-units2.less create mode 100644 node_modules/less/test/less/errors/add-mixed-units2.txt create mode 100644 node_modules/less/test/less/errors/bad-variable-declaration1.less create mode 100644 node_modules/less/test/less/errors/bad-variable-declaration1.txt create mode 100644 node_modules/less/test/less/errors/color-operation-error.less create mode 100644 node_modules/less/test/less/errors/color-operation-error.txt create mode 100644 node_modules/less/test/less/errors/comment-in-selector.less create mode 100644 node_modules/less/test/less/errors/comment-in-selector.txt create mode 100644 node_modules/less/test/less/errors/divide-mixed-units.less create mode 100644 node_modules/less/test/less/errors/divide-mixed-units.txt create mode 100644 node_modules/less/test/less/errors/extend-no-selector.less create mode 100644 node_modules/less/test/less/errors/extend-no-selector.txt create mode 100644 node_modules/less/test/less/errors/extend-not-at-end.less create mode 100644 node_modules/less/test/less/errors/extend-not-at-end.txt create mode 100644 node_modules/less/test/less/errors/import-missing.less create mode 100644 node_modules/less/test/less/errors/import-missing.txt create mode 100644 node_modules/less/test/less/errors/import-no-semi.less create mode 100644 node_modules/less/test/less/errors/import-no-semi.txt create mode 100644 node_modules/less/test/less/errors/import-subfolder1.less create mode 100644 node_modules/less/test/less/errors/import-subfolder1.txt create mode 100644 node_modules/less/test/less/errors/import-subfolder2.less create mode 100644 node_modules/less/test/less/errors/import-subfolder2.txt create mode 100644 node_modules/less/test/less/errors/imports/import-subfolder1.less create mode 100644 node_modules/less/test/less/errors/imports/import-subfolder2.less create mode 100644 node_modules/less/test/less/errors/imports/import-test.less create mode 100644 node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less create mode 100644 node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less create mode 100644 node_modules/less/test/less/errors/javascript-error.less create mode 100644 node_modules/less/test/less/errors/javascript-error.txt create mode 100644 node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less create mode 100644 node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt create mode 100644 node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less create mode 100644 node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt create mode 100644 node_modules/less/test/less/errors/mixin-not-defined.less create mode 100644 node_modules/less/test/less/errors/mixin-not-defined.txt create mode 100644 node_modules/less/test/less/errors/mixin-not-matched.less create mode 100644 node_modules/less/test/less/errors/mixin-not-matched.txt create mode 100644 node_modules/less/test/less/errors/mixin-not-matched2.less create mode 100644 node_modules/less/test/less/errors/mixin-not-matched2.txt create mode 100644 node_modules/less/test/less/errors/multiply-mixed-units.less create mode 100644 node_modules/less/test/less/errors/multiply-mixed-units.txt create mode 100644 node_modules/less/test/less/errors/parens-error-1.less create mode 100644 node_modules/less/test/less/errors/parens-error-1.txt create mode 100644 node_modules/less/test/less/errors/parens-error-2.less create mode 100644 node_modules/less/test/less/errors/parens-error-2.txt create mode 100644 node_modules/less/test/less/errors/parens-error-3.less create mode 100644 node_modules/less/test/less/errors/parens-error-3.txt create mode 100644 node_modules/less/test/less/errors/parse-error-curly-bracket.less create mode 100644 node_modules/less/test/less/errors/parse-error-curly-bracket.txt create mode 100644 node_modules/less/test/less/errors/parse-error-missing-bracket.less create mode 100644 node_modules/less/test/less/errors/parse-error-missing-bracket.txt create mode 100644 node_modules/less/test/less/errors/parse-error-with-import.less create mode 100644 node_modules/less/test/less/errors/parse-error-with-import.txt create mode 100644 node_modules/less/test/less/errors/property-ie5-hack.less create mode 100644 node_modules/less/test/less/errors/property-ie5-hack.txt create mode 100644 node_modules/less/test/less/errors/property-in-root.less create mode 100644 node_modules/less/test/less/errors/property-in-root.txt create mode 100644 node_modules/less/test/less/errors/property-in-root2.less create mode 100644 node_modules/less/test/less/errors/property-in-root2.txt create mode 100644 node_modules/less/test/less/errors/property-in-root3.less create mode 100644 node_modules/less/test/less/errors/property-in-root3.txt create mode 100644 node_modules/less/test/less/errors/recursive-variable.less create mode 100644 node_modules/less/test/less/errors/recursive-variable.txt create mode 100644 node_modules/less/test/less/extend-chaining.less create mode 100644 node_modules/less/test/less/extend-clearfix.less create mode 100644 node_modules/less/test/less/extend-exact.less create mode 100644 node_modules/less/test/less/extend-media.less create mode 100644 node_modules/less/test/less/extend-nest.less create mode 100644 node_modules/less/test/less/extend-selector.less create mode 100644 node_modules/less/test/less/extend.less create mode 100644 node_modules/less/test/less/functions.less create mode 100644 node_modules/less/test/less/ie-filters.less create mode 100644 node_modules/less/test/less/import-interpolation.less create mode 100644 node_modules/less/test/less/import-once.less create mode 100644 node_modules/less/test/less/import.less create mode 100644 node_modules/less/test/less/import/deeper/import-once-test-a.less create mode 100644 node_modules/less/test/less/import/import-and-relative-paths-test.less create mode 100644 node_modules/less/test/less/import/import-charset-test.less create mode 100644 node_modules/less/test/less/import/import-interpolation.less create mode 100644 node_modules/less/test/less/import/import-interpolation2.less create mode 100644 node_modules/less/test/less/import/import-once-test-c.less create mode 100644 node_modules/less/test/less/import/import-test-a.less create mode 100644 node_modules/less/test/less/import/import-test-b.less create mode 100644 node_modules/less/test/less/import/import-test-c.less create mode 100644 node_modules/less/test/less/import/import-test-d.css create mode 100644 node_modules/less/test/less/import/import-test-e.less create mode 100644 node_modules/less/test/less/import/imports/font.less create mode 100644 node_modules/less/test/less/import/imports/logo.less create mode 100644 node_modules/less/test/less/import/urls.less create mode 100644 node_modules/less/test/less/javascript.less create mode 100644 node_modules/less/test/less/lazy-eval.less create mode 100644 node_modules/less/test/less/legacy/legacy.less create mode 100644 node_modules/less/test/less/media.less create mode 100644 node_modules/less/test/less/mixins-args.less create mode 100644 node_modules/less/test/less/mixins-closure.less create mode 100644 node_modules/less/test/less/mixins-guards.less create mode 100644 node_modules/less/test/less/mixins-important.less create mode 100644 node_modules/less/test/less/mixins-named-args.less create mode 100644 node_modules/less/test/less/mixins-nested.less create mode 100644 node_modules/less/test/less/mixins-pattern.less create mode 100644 node_modules/less/test/less/mixins.less create mode 100644 node_modules/less/test/less/operations.less create mode 100644 node_modules/less/test/less/parens.less create mode 100644 node_modules/less/test/less/rulesets.less create mode 100644 node_modules/less/test/less/scope.less create mode 100644 node_modules/less/test/less/selectors.less create mode 100644 node_modules/less/test/less/static-urls/urls.less create mode 100644 node_modules/less/test/less/strings.less create mode 100644 node_modules/less/test/less/urls.less create mode 100644 node_modules/less/test/less/variables.less create mode 100644 node_modules/less/test/less/whitespace.less create mode 100644 node_modules/log4node/.npmignore create mode 100644 node_modules/log4node/CHANGELOG create mode 100644 node_modules/log4node/Readme.markdown create mode 100644 node_modules/log4node/lib/log4node.js create mode 100644 node_modules/log4node/license.txt create mode 100644 node_modules/log4node/package.json create mode 100755 node_modules/log4node/test-runner.sh create mode 100644 node_modules/log4node/test/cluster-logger-after-fork/output1 create mode 100644 node_modules/log4node/test/cluster-logger-after-fork/test1.js create mode 100644 node_modules/log4node/test/cluster-logrotate/logrotate.conf create mode 100644 node_modules/log4node/test/cluster-logrotate/output1 create mode 100644 node_modules/log4node/test/cluster-logrotate/output2 create mode 100644 node_modules/log4node/test/cluster-logrotate/test1.js create mode 100644 node_modules/log4node/test/cluster-stdout-sig/output1 create mode 100644 node_modules/log4node/test/cluster-stdout-sig/test1.js create mode 100644 node_modules/log4node/test/cluster-sub-logger-logrotate/logrotate.conf create mode 100644 node_modules/log4node/test/cluster-sub-logger-logrotate/output1 create mode 100644 node_modules/log4node/test/cluster-sub-logger-logrotate/output2 create mode 100644 node_modules/log4node/test/cluster-sub-logger-logrotate/test1.js create mode 100644 node_modules/log4node/test/cluster-sub-logger/output1 create mode 100644 node_modules/log4node/test/cluster-sub-logger/test1.js create mode 100644 node_modules/log4node/test/cluster/output1 create mode 100644 node_modules/log4node/test/cluster/test1.js create mode 100644 node_modules/log4node/test/helper.js create mode 100644 node_modules/log4node/test/multiple-appender/logrotate.conf create mode 100644 node_modules/log4node/test/multiple-appender/output1 create mode 100644 node_modules/log4node/test/multiple-appender/output2 create mode 100644 node_modules/log4node/test/multiple-appender/test1.js create mode 100644 node_modules/log4node/test/no-cluster-append/output1 create mode 100644 node_modules/log4node/test/no-cluster-append/output2 create mode 100644 node_modules/log4node/test/no-cluster-append/test1.js create mode 100644 node_modules/log4node/test/no-cluster-logrotate/logrotate.conf create mode 100644 node_modules/log4node/test/no-cluster-logrotate/output1 create mode 100644 node_modules/log4node/test/no-cluster-logrotate/output2 create mode 100644 node_modules/log4node/test/no-cluster-logrotate/test1.js create mode 100644 node_modules/log4node/test/no-cluster-sig/output1 create mode 100644 node_modules/log4node/test/no-cluster-sig/output2 create mode 100644 node_modules/log4node/test/no-cluster-sig/test1.js create mode 100644 node_modules/log4node/test/no-cluster-stdout-sig/output1 create mode 100644 node_modules/log4node/test/no-cluster-stdout-sig/test1.js create mode 100644 node_modules/log4node/test/no-cluster/output1 create mode 100644 node_modules/log4node/test/no-cluster/output2 create mode 100644 node_modules/log4node/test/no-cluster/test1.js create mode 100644 node_modules/log4node/test/sub-logger-default/output1 create mode 100644 node_modules/log4node/test/sub-logger-default/output2 create mode 100644 node_modules/log4node/test/sub-logger-default/test1.js create mode 100644 node_modules/log4node/test/sub-logger/output1 create mode 100644 node_modules/log4node/test/sub-logger/output2 create mode 100644 node_modules/log4node/test/sub-logger/test1.js create mode 100644 node_modules/log4node/test/test-cluster-logger-after-fork.js create mode 100644 node_modules/log4node/test/test-cluster-logrotate.js create mode 100644 node_modules/log4node/test/test-cluster-stdout-sig.js create mode 100644 node_modules/log4node/test/test-cluster-sub-logger-logrotate.js create mode 100644 node_modules/log4node/test/test-cluster-sub-logger.js create mode 100644 node_modules/log4node/test/test-cluster.js create mode 100644 node_modules/log4node/test/test-multiple-appender.js create mode 100644 node_modules/log4node/test/test-no-cluster-append.js create mode 100644 node_modules/log4node/test/test-no-cluster-logrotate.js create mode 100644 node_modules/log4node/test/test-no-cluster-sig.js create mode 100644 node_modules/log4node/test/test-no-cluster-stdout-sig.js create mode 100644 node_modules/log4node/test/test-no-cluster.js create mode 100644 node_modules/log4node/test/test-not-reopening-file.js create mode 100644 node_modules/log4node/test/test-send-master.js create mode 100644 node_modules/log4node/test/test-set-loglevel.js create mode 100644 node_modules/log4node/test/test-set-prefix.js create mode 100644 node_modules/log4node/test/test-strange-params.js create mode 100644 node_modules/log4node/test/test-sub-logger-default.js create mode 100644 node_modules/log4node/test/test-sub-logger.js create mode 100644 node_modules/moment/.npmignore create mode 100644 node_modules/moment/.travis.yml create mode 100644 node_modules/moment/CONTRIBUTING.md create mode 100644 node_modules/moment/Gruntfile.js create mode 100644 node_modules/moment/LICENSE create mode 100644 node_modules/moment/component.json create mode 100644 node_modules/moment/composer.json create mode 100644 node_modules/moment/ender.js create mode 100644 node_modules/moment/lang/ar-ma.js create mode 100644 node_modules/moment/lang/ar.js create mode 100644 node_modules/moment/lang/bg.js create mode 100644 node_modules/moment/lang/br.js create mode 100644 node_modules/moment/lang/ca.js create mode 100644 node_modules/moment/lang/cs.js create mode 100644 node_modules/moment/lang/cv.js create mode 100644 node_modules/moment/lang/da.js create mode 100644 node_modules/moment/lang/de.js create mode 100644 node_modules/moment/lang/el.js create mode 100644 node_modules/moment/lang/en-ca.js create mode 100644 node_modules/moment/lang/en-gb.js create mode 100644 node_modules/moment/lang/eo.js create mode 100644 node_modules/moment/lang/es.js create mode 100644 node_modules/moment/lang/et.js create mode 100644 node_modules/moment/lang/eu.js create mode 100755 node_modules/moment/lang/fa.js create mode 100644 node_modules/moment/lang/fi.js create mode 100644 node_modules/moment/lang/fr-ca.js create mode 100644 node_modules/moment/lang/fr.js create mode 100644 node_modules/moment/lang/gl.js create mode 100644 node_modules/moment/lang/he.js create mode 100644 node_modules/moment/lang/hi.js create mode 100644 node_modules/moment/lang/hu.js create mode 100644 node_modules/moment/lang/id.js create mode 100644 node_modules/moment/lang/is.js create mode 100644 node_modules/moment/lang/it.js create mode 100644 node_modules/moment/lang/ja.js create mode 100644 node_modules/moment/lang/ka.js create mode 100644 node_modules/moment/lang/ko.js create mode 100644 node_modules/moment/lang/lv.js create mode 100644 node_modules/moment/lang/ms-my.js create mode 100644 node_modules/moment/lang/nb.js create mode 100644 node_modules/moment/lang/ne.js create mode 100644 node_modules/moment/lang/nl.js create mode 100644 node_modules/moment/lang/nn.js create mode 100644 node_modules/moment/lang/pl.js create mode 100644 node_modules/moment/lang/pt-br.js create mode 100644 node_modules/moment/lang/pt.js create mode 100644 node_modules/moment/lang/readme.md create mode 100644 node_modules/moment/lang/ro.js create mode 100644 node_modules/moment/lang/ru.js create mode 100644 node_modules/moment/lang/sk.js create mode 100644 node_modules/moment/lang/sl.js create mode 100644 node_modules/moment/lang/sq.js create mode 100644 node_modules/moment/lang/sv.js create mode 100644 node_modules/moment/lang/th.js create mode 100644 node_modules/moment/lang/tr.js create mode 100644 node_modules/moment/lang/tzm-la.js create mode 100644 node_modules/moment/lang/tzm.js create mode 100644 node_modules/moment/lang/uk.js create mode 100644 node_modules/moment/lang/zh-cn.js create mode 100644 node_modules/moment/lang/zh-tw.js create mode 100644 node_modules/moment/min/lang/ar-ma.js create mode 100644 node_modules/moment/min/lang/ar.js create mode 100644 node_modules/moment/min/lang/bg.js create mode 100644 node_modules/moment/min/lang/br.js create mode 100644 node_modules/moment/min/lang/ca.js create mode 100644 node_modules/moment/min/lang/cs.js create mode 100644 node_modules/moment/min/lang/cv.js create mode 100644 node_modules/moment/min/lang/da.js create mode 100644 node_modules/moment/min/lang/de.js create mode 100644 node_modules/moment/min/lang/el.js create mode 100644 node_modules/moment/min/lang/en-ca.js create mode 100644 node_modules/moment/min/lang/en-gb.js create mode 100644 node_modules/moment/min/lang/eo.js create mode 100644 node_modules/moment/min/lang/es.js create mode 100644 node_modules/moment/min/lang/et.js create mode 100644 node_modules/moment/min/lang/eu.js create mode 100644 node_modules/moment/min/lang/fa.js create mode 100644 node_modules/moment/min/lang/fi.js create mode 100644 node_modules/moment/min/lang/fr-ca.js create mode 100644 node_modules/moment/min/lang/fr.js create mode 100644 node_modules/moment/min/lang/gl.js create mode 100644 node_modules/moment/min/lang/he.js create mode 100644 node_modules/moment/min/lang/hi.js create mode 100644 node_modules/moment/min/lang/hu.js create mode 100644 node_modules/moment/min/lang/id.js create mode 100644 node_modules/moment/min/lang/is.js create mode 100644 node_modules/moment/min/lang/it.js create mode 100644 node_modules/moment/min/lang/ja.js create mode 100644 node_modules/moment/min/lang/ka.js create mode 100644 node_modules/moment/min/lang/ko.js create mode 100644 node_modules/moment/min/lang/lv.js create mode 100644 node_modules/moment/min/lang/ms-my.js create mode 100644 node_modules/moment/min/lang/nb.js create mode 100644 node_modules/moment/min/lang/ne.js create mode 100644 node_modules/moment/min/lang/nl.js create mode 100644 node_modules/moment/min/lang/nn.js create mode 100644 node_modules/moment/min/lang/pl.js create mode 100644 node_modules/moment/min/lang/pt-br.js create mode 100644 node_modules/moment/min/lang/pt.js create mode 100644 node_modules/moment/min/lang/ro.js create mode 100644 node_modules/moment/min/lang/ru.js create mode 100644 node_modules/moment/min/lang/sk.js create mode 100644 node_modules/moment/min/lang/sl.js create mode 100644 node_modules/moment/min/lang/sq.js create mode 100644 node_modules/moment/min/lang/sv.js create mode 100644 node_modules/moment/min/lang/th.js create mode 100644 node_modules/moment/min/lang/tr.js create mode 100644 node_modules/moment/min/lang/tzm-la.js create mode 100644 node_modules/moment/min/lang/tzm.js create mode 100644 node_modules/moment/min/lang/uk.js create mode 100644 node_modules/moment/min/lang/zh-cn.js create mode 100644 node_modules/moment/min/lang/zh-tw.js create mode 100644 node_modules/moment/min/langs.js create mode 100644 node_modules/moment/min/langs.min.js create mode 100644 node_modules/moment/min/moment.min.js create mode 100644 node_modules/moment/moment.js create mode 100644 node_modules/moment/package.js create mode 100644 node_modules/moment/package.json create mode 100644 node_modules/moment/readme.md create mode 100644 node_modules/moment/tasks/concat-lang.js create mode 100644 node_modules/moment/tasks/history.js create mode 100644 node_modules/moment/tasks/minify-lang.js create mode 100644 node_modules/moment/tasks/minify.js create mode 100644 node_modules/moment/tasks/size.js create mode 100644 node_modules/moment/tasks/zone.js create mode 100644 node_modules/moment/tasks/zones.js create mode 100644 node_modules/moment/test/lang/ar-ma.js create mode 100644 node_modules/moment/test/lang/ar.js create mode 100644 node_modules/moment/test/lang/bg.js create mode 100644 node_modules/moment/test/lang/br.js create mode 100644 node_modules/moment/test/lang/ca.js create mode 100644 node_modules/moment/test/lang/cs.js create mode 100644 node_modules/moment/test/lang/cv.js create mode 100644 node_modules/moment/test/lang/da.js create mode 100644 node_modules/moment/test/lang/de.js create mode 100644 node_modules/moment/test/lang/el.js create mode 100644 node_modules/moment/test/lang/en-ca.js create mode 100644 node_modules/moment/test/lang/en-gb.js create mode 100644 node_modules/moment/test/lang/en.js create mode 100644 node_modules/moment/test/lang/eo.js create mode 100644 node_modules/moment/test/lang/es.js create mode 100644 node_modules/moment/test/lang/et.js create mode 100644 node_modules/moment/test/lang/eu.js create mode 100755 node_modules/moment/test/lang/fa.js create mode 100644 node_modules/moment/test/lang/fi.js create mode 100644 node_modules/moment/test/lang/fr-ca.js create mode 100644 node_modules/moment/test/lang/fr.js create mode 100644 node_modules/moment/test/lang/gl.js create mode 100644 node_modules/moment/test/lang/he.js create mode 100644 node_modules/moment/test/lang/hi.js create mode 100644 node_modules/moment/test/lang/hu.js create mode 100644 node_modules/moment/test/lang/id.js create mode 100644 node_modules/moment/test/lang/is.js create mode 100644 node_modules/moment/test/lang/it.js create mode 100644 node_modules/moment/test/lang/ja.js create mode 100644 node_modules/moment/test/lang/ka.js create mode 100644 node_modules/moment/test/lang/ko.js create mode 100644 node_modules/moment/test/lang/lv.js create mode 100644 node_modules/moment/test/lang/ms-my.js create mode 100644 node_modules/moment/test/lang/nb.js create mode 100644 node_modules/moment/test/lang/ne.js create mode 100644 node_modules/moment/test/lang/nl.js create mode 100644 node_modules/moment/test/lang/nn.js create mode 100644 node_modules/moment/test/lang/pl.js create mode 100644 node_modules/moment/test/lang/pt-br.js create mode 100644 node_modules/moment/test/lang/pt.js create mode 100644 node_modules/moment/test/lang/ro.js create mode 100644 node_modules/moment/test/lang/ru.js create mode 100644 node_modules/moment/test/lang/sk.js create mode 100644 node_modules/moment/test/lang/sl.js create mode 100644 node_modules/moment/test/lang/sq.js create mode 100644 node_modules/moment/test/lang/sv.js create mode 100644 node_modules/moment/test/lang/th.js create mode 100644 node_modules/moment/test/lang/tr.js create mode 100644 node_modules/moment/test/lang/tzm-la.js create mode 100644 node_modules/moment/test/lang/tzm.js create mode 100644 node_modules/moment/test/lang/uk.js create mode 100644 node_modules/moment/test/lang/zh-cn.js create mode 100644 node_modules/moment/test/lang/zh-tw.js create mode 100644 node_modules/moment/test/moment/add_subtract.js create mode 100644 node_modules/moment/test/moment/create.js create mode 100644 node_modules/moment/test/moment/days_in_month.js create mode 100644 node_modules/moment/test/moment/diff.js create mode 100644 node_modules/moment/test/moment/duration.js create mode 100644 node_modules/moment/test/moment/format.js create mode 100644 node_modules/moment/test/moment/getters_setters.js create mode 100644 node_modules/moment/test/moment/is_after.js create mode 100644 node_modules/moment/test/moment/is_before.js create mode 100644 node_modules/moment/test/moment/is_moment.js create mode 100644 node_modules/moment/test/moment/is_same.js create mode 100644 node_modules/moment/test/moment/is_valid.js create mode 100644 node_modules/moment/test/moment/lang.js create mode 100644 node_modules/moment/test/moment/leapyear.js create mode 100644 node_modules/moment/test/moment/min_max.js create mode 100644 node_modules/moment/test/moment/mutable.js create mode 100644 node_modules/moment/test/moment/preparse_postformat.js create mode 100644 node_modules/moment/test/moment/sod_eod.js create mode 100644 node_modules/moment/test/moment/string_prototype.js create mode 100644 node_modules/moment/test/moment/utc.js create mode 100644 node_modules/moment/test/moment/week_year.js create mode 100644 node_modules/moment/test/moment/weekday.js create mode 100644 node_modules/moment/test/moment/weeks.js create mode 100644 node_modules/moment/test/moment/zones.js create mode 100644 node_modules/mongoose-pureautoinc/.npmignore create mode 100644 node_modules/mongoose-pureautoinc/README.md create mode 100644 node_modules/mongoose-pureautoinc/benchmarks/benchmark.js create mode 100644 node_modules/mongoose-pureautoinc/examples/example.js create mode 100644 node_modules/mongoose-pureautoinc/index.js create mode 100644 node_modules/mongoose-pureautoinc/lib/pureautoinc.js create mode 100644 node_modules/mongoose-pureautoinc/package.json create mode 100644 node_modules/mongoose-pureautoinc/tests/test.js create mode 100644 node_modules/mongoose/.npmignore create mode 100644 node_modules/mongoose/.travis.yml create mode 100644 node_modules/mongoose/CONTRIBUTING.md create mode 100644 node_modules/mongoose/History.md create mode 100644 node_modules/mongoose/README.md create mode 100644 node_modules/mongoose/examples/README.md create mode 100644 node_modules/mongoose/examples/doc-methods.js create mode 100644 node_modules/mongoose/examples/hooks.js create mode 100644 node_modules/mongoose/examples/population-across-three-collections.js create mode 100644 node_modules/mongoose/examples/population-basic.js create mode 100644 node_modules/mongoose/examples/population-of-existing-doc.js create mode 100644 node_modules/mongoose/examples/population-of-multiple-existing-docs.js create mode 100644 node_modules/mongoose/examples/population-options.js create mode 100644 node_modules/mongoose/examples/population-plain-objects.js create mode 100644 node_modules/mongoose/examples/schema.js create mode 100644 node_modules/mongoose/index.js create mode 100644 node_modules/mongoose/lib/collection.js create mode 100644 node_modules/mongoose/lib/connection.js create mode 100644 node_modules/mongoose/lib/connectionstate.js create mode 100644 node_modules/mongoose/lib/document.js create mode 100644 node_modules/mongoose/lib/drivers/SPEC.md create mode 100644 node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js create mode 100644 node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js create mode 100644 node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js create mode 100644 node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js create mode 100644 node_modules/mongoose/lib/error.js create mode 100644 node_modules/mongoose/lib/errors/cast.js create mode 100644 node_modules/mongoose/lib/errors/divergentArray.js create mode 100644 node_modules/mongoose/lib/errors/document.js create mode 100644 node_modules/mongoose/lib/errors/missingSchema.js create mode 100644 node_modules/mongoose/lib/errors/overwriteModel.js create mode 100644 node_modules/mongoose/lib/errors/validation.js create mode 100644 node_modules/mongoose/lib/errors/validator.js create mode 100644 node_modules/mongoose/lib/errors/version.js create mode 100644 node_modules/mongoose/lib/index.js create mode 100644 node_modules/mongoose/lib/internal.js create mode 100644 node_modules/mongoose/lib/model.js create mode 100644 node_modules/mongoose/lib/namedscope.js create mode 100644 node_modules/mongoose/lib/promise.js create mode 100644 node_modules/mongoose/lib/query.js create mode 100644 node_modules/mongoose/lib/queryhelpers.js create mode 100644 node_modules/mongoose/lib/querystream.js create mode 100644 node_modules/mongoose/lib/schema.js create mode 100644 node_modules/mongoose/lib/schema/array.js create mode 100644 node_modules/mongoose/lib/schema/boolean.js create mode 100644 node_modules/mongoose/lib/schema/buffer.js create mode 100644 node_modules/mongoose/lib/schema/date.js create mode 100644 node_modules/mongoose/lib/schema/documentarray.js create mode 100644 node_modules/mongoose/lib/schema/index.js create mode 100644 node_modules/mongoose/lib/schema/mixed.js create mode 100644 node_modules/mongoose/lib/schema/number.js create mode 100644 node_modules/mongoose/lib/schema/objectid.js create mode 100644 node_modules/mongoose/lib/schema/string.js create mode 100644 node_modules/mongoose/lib/schemadefault.js create mode 100644 node_modules/mongoose/lib/schematype.js create mode 100644 node_modules/mongoose/lib/statemachine.js create mode 100644 node_modules/mongoose/lib/types/array.js create mode 100644 node_modules/mongoose/lib/types/buffer.js create mode 100644 node_modules/mongoose/lib/types/documentarray.js create mode 100644 node_modules/mongoose/lib/types/embedded.js create mode 100644 node_modules/mongoose/lib/types/index.js create mode 100644 node_modules/mongoose/lib/types/objectid.js create mode 100644 node_modules/mongoose/lib/utils.js create mode 100644 node_modules/mongoose/lib/virtualtype.js create mode 100644 node_modules/mongoose/node_modules/hooks/.npmignore create mode 100644 node_modules/mongoose/node_modules/hooks/Makefile create mode 100644 node_modules/mongoose/node_modules/hooks/README.md create mode 100644 node_modules/mongoose/node_modules/hooks/hooks.alt.js create mode 100644 node_modules/mongoose/node_modules/hooks/hooks.js create mode 100644 node_modules/mongoose/node_modules/hooks/package.json create mode 100644 node_modules/mongoose/node_modules/hooks/test.js create mode 100644 node_modules/mongoose/node_modules/mongodb/.travis.yml create mode 100644 node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md create mode 100644 node_modules/mongoose/node_modules/mongodb/LICENSE create mode 100644 node_modules/mongoose/node_modules/mongodb/Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/Readme.md create mode 100755 node_modules/mongoose/node_modules/mongodb/index.js create mode 100644 node_modules/mongoose/node_modules/mongodb/install.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/url_parser.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursorstream.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/chunk.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js create mode 100644 node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/bson.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/package.json create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson.node.d create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d create mode 100755 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/bson.node create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/linker.lock create mode 100755 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson.node create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/binding.Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/bson.target.mk create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/config.gypi create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/build_browser.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/index.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/win32/x64/bson.node create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/wscript create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/bson.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/code.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/double.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/index.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/long.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/package.json create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/gleak.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/README.md create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/binding.gyp create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/kerberos.node.d create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos.node.d create mode 100755 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/kerberos.node create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/linker.lock create mode 100755 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/obj.target/kerberos.node create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/config.gypi create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/index.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/base64.c create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/base64.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/sspi.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.cc create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.h create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/package.json create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js create mode 100644 node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js create mode 100755 node_modules/mongoose/node_modules/mongodb/package.json create mode 100644 node_modules/mongoose/node_modules/mpath/.npmignore create mode 100644 node_modules/mongoose/node_modules/mpath/.travis.yml create mode 100644 node_modules/mongoose/node_modules/mpath/History.md create mode 100644 node_modules/mongoose/node_modules/mpath/LICENSE create mode 100644 node_modules/mongoose/node_modules/mpath/Makefile create mode 100644 node_modules/mongoose/node_modules/mpath/README.md create mode 100644 node_modules/mongoose/node_modules/mpath/index.js create mode 100644 node_modules/mongoose/node_modules/mpath/lib/index.js create mode 100644 node_modules/mongoose/node_modules/mpath/package.json create mode 100644 node_modules/mongoose/node_modules/mpath/test/index.js create mode 100644 node_modules/mongoose/node_modules/mpromise/.npmignore create mode 100644 node_modules/mongoose/node_modules/mpromise/.travis.yml create mode 100644 node_modules/mongoose/node_modules/mpromise/History.md create mode 100644 node_modules/mongoose/node_modules/mpromise/LICENSE create mode 100644 node_modules/mongoose/node_modules/mpromise/Makefile create mode 100644 node_modules/mongoose/node_modules/mpromise/README.md create mode 100644 node_modules/mongoose/node_modules/mpromise/index.js create mode 100644 node_modules/mongoose/node_modules/mpromise/lib/promise.js create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.npmignore create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.travis.yml create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/History.md create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/LICENSE create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/Makefile create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/README.md create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/bench.js create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/component.json create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/index.js create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/lib/sliced.js create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/package.json create mode 100644 node_modules/mongoose/node_modules/mpromise/node_modules/sliced/test/index.js create mode 100644 node_modules/mongoose/node_modules/mpromise/package.json create mode 100644 node_modules/mongoose/node_modules/mpromise/test/promise.test.js create mode 100644 node_modules/mongoose/node_modules/mpromise/test/promises-A.js create mode 100644 node_modules/mongoose/node_modules/ms/.npmignore create mode 100644 node_modules/mongoose/node_modules/ms/Makefile create mode 100644 node_modules/mongoose/node_modules/ms/README.md create mode 100644 node_modules/mongoose/node_modules/ms/ms.js create mode 100644 node_modules/mongoose/node_modules/ms/package.json create mode 100644 node_modules/mongoose/node_modules/ms/test/index.html create mode 100644 node_modules/mongoose/node_modules/ms/test/support/jquery.js create mode 100644 node_modules/mongoose/node_modules/ms/test/test.js create mode 100644 node_modules/mongoose/node_modules/muri/.npmignore create mode 100644 node_modules/mongoose/node_modules/muri/.travis.yml create mode 100644 node_modules/mongoose/node_modules/muri/History.md create mode 100644 node_modules/mongoose/node_modules/muri/LICENSE create mode 100644 node_modules/mongoose/node_modules/muri/Makefile create mode 100644 node_modules/mongoose/node_modules/muri/README.md create mode 100644 node_modules/mongoose/node_modules/muri/index.js create mode 100644 node_modules/mongoose/node_modules/muri/lib/index.js create mode 100644 node_modules/mongoose/node_modules/muri/package.json create mode 100644 node_modules/mongoose/node_modules/muri/test/index.js create mode 100644 node_modules/mongoose/node_modules/regexp-clone/.npmignore create mode 100644 node_modules/mongoose/node_modules/regexp-clone/.travis.yml create mode 100644 node_modules/mongoose/node_modules/regexp-clone/History.md create mode 100644 node_modules/mongoose/node_modules/regexp-clone/LICENSE create mode 100644 node_modules/mongoose/node_modules/regexp-clone/Makefile create mode 100644 node_modules/mongoose/node_modules/regexp-clone/README.md create mode 100644 node_modules/mongoose/node_modules/regexp-clone/index.js create mode 100644 node_modules/mongoose/node_modules/regexp-clone/package.json create mode 100644 node_modules/mongoose/node_modules/regexp-clone/test/index.js create mode 100644 node_modules/mongoose/node_modules/sliced/.npmignore create mode 100644 node_modules/mongoose/node_modules/sliced/.travis.yml create mode 100644 node_modules/mongoose/node_modules/sliced/History.md create mode 100644 node_modules/mongoose/node_modules/sliced/LICENSE create mode 100644 node_modules/mongoose/node_modules/sliced/Makefile create mode 100644 node_modules/mongoose/node_modules/sliced/README.md create mode 100644 node_modules/mongoose/node_modules/sliced/bench.js create mode 100644 node_modules/mongoose/node_modules/sliced/index.js create mode 100644 node_modules/mongoose/node_modules/sliced/lib/sliced.js create mode 100644 node_modules/mongoose/node_modules/sliced/package.json create mode 100644 node_modules/mongoose/node_modules/sliced/test/index.js create mode 100644 node_modules/mongoose/package.json create mode 100644 node_modules/mongoose/static.js create mode 100644 node_modules/mongoose/website.js create mode 100644 node_modules/passport-google-oauth/.travis.yml create mode 100644 node_modules/passport-google-oauth/LICENSE create mode 100644 node_modules/passport-google-oauth/README.md create mode 100644 node_modules/passport-google-oauth/lib/passport-google-oauth/index.js create mode 100644 node_modules/passport-google-oauth/lib/passport-google-oauth/oauth.js create mode 100644 node_modules/passport-google-oauth/lib/passport-google-oauth/oauth2.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/.travis.yml create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/LICENSE create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/README.md create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/lib/passport-oauth/errors/internaloautherror.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/lib/passport-oauth/index.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth2.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/lib/passport-oauth/strategies/utils.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/.npmignore create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/LICENSE create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/Makefile create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/Readme.md create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/examples/express-gdata/server.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/examples/express-gdata/views/google_calendars.ejs create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/examples/express-gdata/views/google_contacts.ejs create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/examples/express-gdata/views/layout.ejs create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/examples/term.ie.oauth-HMAC-SHA1.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/index.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/lib/_utils.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/lib/oauth.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/lib/oauth2.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/lib/sha1.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/package.json create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/tests/oauth.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/tests/oauth2.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/node_modules/oauth/tests/sha1.js create mode 100644 node_modules/passport-google-oauth/node_modules/passport-oauth/package.json create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/.npmignore create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/README.md create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/docs/docco.css create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/docs/pkginfo.html create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/examples/all-properties.js create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/examples/array-argument.js create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/examples/multiple-properties.js create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/examples/object-argument.js create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/examples/package.json create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/examples/single-property.js create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/lib/pkginfo.js create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/package.json create mode 100644 node_modules/passport-google-oauth/node_modules/pkginfo/test/pkginfo-test.js create mode 100644 node_modules/passport-google-oauth/package.json create mode 100644 node_modules/passport/.travis.yml create mode 100644 node_modules/passport/LICENSE create mode 100644 node_modules/passport/README.md create mode 100644 node_modules/passport/lib/passport/context/http/actions.js create mode 100644 node_modules/passport/lib/passport/context/http/context.js create mode 100644 node_modules/passport/lib/passport/http/request.js create mode 100644 node_modules/passport/lib/passport/index.js create mode 100644 node_modules/passport/lib/passport/middleware/authenticate.js create mode 100644 node_modules/passport/lib/passport/middleware/initialize.js create mode 100644 node_modules/passport/lib/passport/strategies/session.js create mode 100644 node_modules/passport/lib/passport/strategy.js create mode 100644 node_modules/passport/node_modules/pause/.npmignore create mode 100644 node_modules/passport/node_modules/pause/History.md create mode 100644 node_modules/passport/node_modules/pause/Makefile create mode 100644 node_modules/passport/node_modules/pause/Readme.md create mode 100644 node_modules/passport/node_modules/pause/index.js create mode 100644 node_modules/passport/node_modules/pause/package.json create mode 100644 node_modules/passport/node_modules/pkginfo/.npmignore create mode 100644 node_modules/passport/node_modules/pkginfo/README.md create mode 100644 node_modules/passport/node_modules/pkginfo/docs/docco.css create mode 100644 node_modules/passport/node_modules/pkginfo/docs/pkginfo.html create mode 100644 node_modules/passport/node_modules/pkginfo/examples/all-properties.js create mode 100644 node_modules/passport/node_modules/pkginfo/examples/array-argument.js create mode 100644 node_modules/passport/node_modules/pkginfo/examples/multiple-properties.js create mode 100644 node_modules/passport/node_modules/pkginfo/examples/object-argument.js create mode 100644 node_modules/passport/node_modules/pkginfo/examples/package.json create mode 100644 node_modules/passport/node_modules/pkginfo/examples/single-property.js create mode 100644 node_modules/passport/node_modules/pkginfo/lib/pkginfo.js create mode 100644 node_modules/passport/node_modules/pkginfo/package.json create mode 100644 node_modules/passport/node_modules/pkginfo/test/pkginfo-test.js create mode 100644 node_modules/passport/package.json create mode 100644 node_modules/piler/.npmignore create mode 100644 node_modules/piler/.travis.yml create mode 100644 node_modules/piler/LICENSE create mode 100644 node_modules/piler/README.md create mode 100644 node_modules/piler/examples/logger/.npmignore create mode 100644 node_modules/piler/examples/logger/README.md create mode 100644 node_modules/piler/examples/logger/app.js create mode 100644 node_modules/piler/examples/logger/client/backbone.js create mode 100644 node_modules/piler/examples/logger/client/bar.coffee create mode 100644 node_modules/piler/examples/logger/client/foo.coffee create mode 100644 node_modules/piler/examples/logger/client/hello.coffee create mode 100644 node_modules/piler/examples/logger/client/hello.js create mode 100644 node_modules/piler/examples/logger/client/underscore.js create mode 100644 node_modules/piler/examples/logger/share.js create mode 100644 node_modules/piler/examples/logger/style.css create mode 100644 node_modules/piler/examples/logger/style.less create mode 100644 node_modules/piler/examples/logger/style.styl create mode 100644 node_modules/piler/examples/logger/views/index.jade create mode 100644 node_modules/piler/examples/simple/README.md create mode 100644 node_modules/piler/examples/simple/app.js create mode 100644 node_modules/piler/examples/simple/client/backbone.js create mode 100644 node_modules/piler/examples/simple/client/bar.coffee create mode 100644 node_modules/piler/examples/simple/client/foo.coffee create mode 100644 node_modules/piler/examples/simple/client/hello.coffee create mode 100644 node_modules/piler/examples/simple/client/hello.js create mode 100644 node_modules/piler/examples/simple/client/underscore.js create mode 100644 node_modules/piler/examples/simple/share.js create mode 100644 node_modules/piler/examples/simple/style.css create mode 100644 node_modules/piler/examples/simple/style.less create mode 100644 node_modules/piler/examples/simple/style.styl create mode 100644 node_modules/piler/examples/simple/views/index.jade create mode 100644 node_modules/piler/index.js create mode 100644 node_modules/piler/lib/asseturlparse.coffee create mode 100644 node_modules/piler/lib/compilers.coffee create mode 100644 node_modules/piler/lib/livecss.coffee create mode 100644 node_modules/piler/lib/logger.coffee create mode 100644 node_modules/piler/lib/minify.coffee create mode 100644 node_modules/piler/lib/piler.coffee create mode 100644 node_modules/piler/lib/serialize.coffee create mode 120000 node_modules/piler/node_modules/.bin/cake create mode 120000 node_modules/piler/node_modules/.bin/coffee create mode 120000 node_modules/piler/node_modules/.bin/csso create mode 120000 node_modules/piler/node_modules/.bin/uglifyjs create mode 100644 node_modules/piler/node_modules/async/.gitmodules create mode 100644 node_modules/piler/node_modules/async/.npmignore create mode 100644 node_modules/piler/node_modules/async/LICENSE create mode 100644 node_modules/piler/node_modules/async/Makefile create mode 100644 node_modules/piler/node_modules/async/README.md create mode 100644 node_modules/piler/node_modules/async/index.js create mode 100644 node_modules/piler/node_modules/async/lib/async.js create mode 100644 node_modules/piler/node_modules/async/package.json create mode 100644 node_modules/piler/node_modules/coffee-script/.npmignore create mode 100644 node_modules/piler/node_modules/coffee-script/CNAME create mode 100644 node_modules/piler/node_modules/coffee-script/LICENSE create mode 100644 node_modules/piler/node_modules/coffee-script/README create mode 100644 node_modules/piler/node_modules/coffee-script/Rakefile create mode 100755 node_modules/piler/node_modules/coffee-script/bin/cake create mode 100755 node_modules/piler/node_modules/coffee-script/bin/coffee create mode 100644 node_modules/piler/node_modules/coffee-script/extras/jsl.conf create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/browser.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/cake.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/coffee-script.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/command.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/grammar.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/helpers.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/index.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/lexer.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/nodes.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/optparse.js create mode 100755 node_modules/piler/node_modules/coffee-script/lib/coffee-script/parser.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/repl.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/rewriter.js create mode 100644 node_modules/piler/node_modules/coffee-script/lib/coffee-script/scope.js create mode 100644 node_modules/piler/node_modules/coffee-script/package.json create mode 100644 node_modules/piler/node_modules/csso/GNUmakefile create mode 100644 node_modules/piler/node_modules/csso/MANUAL.en.md create mode 100644 node_modules/piler/node_modules/csso/MANUAL.ru.md create mode 100644 node_modules/piler/node_modules/csso/MIT-LICENSE.txt create mode 100644 node_modules/piler/node_modules/csso/README.md create mode 100644 node_modules/piler/node_modules/csso/README.ru.md create mode 100644 node_modules/piler/node_modules/csso/USAGE create mode 100644 node_modules/piler/node_modules/csso/VERSION create mode 100755 node_modules/piler/node_modules/csso/bin/csso create mode 100644 node_modules/piler/node_modules/csso/doc/compressflow.graphml create mode 100644 node_modules/piler/node_modules/csso/doc/compressflow.png create mode 100644 node_modules/piler/node_modules/csso/lib/compressor.js create mode 100644 node_modules/piler/node_modules/csso/lib/csso.js create mode 100644 node_modules/piler/node_modules/csso/lib/cssoapi.js create mode 100644 node_modules/piler/node_modules/csso/lib/parser.js create mode 100644 node_modules/piler/node_modules/csso/lib/translator.js create mode 100644 node_modules/piler/node_modules/csso/lib/util.js create mode 100644 node_modules/piler/node_modules/csso/package.json create mode 100644 node_modules/piler/node_modules/csso/src/compressor.node.js create mode 100644 node_modules/piler/node_modules/csso/src/compressor.shared.js create mode 100644 node_modules/piler/node_modules/csso/src/compressor.web.js create mode 100644 node_modules/piler/node_modules/csso/src/csso.other.js create mode 100644 node_modules/piler/node_modules/csso/src/csso.pecode create mode 100644 node_modules/piler/node_modules/csso/src/parser.node.js create mode 100644 node_modules/piler/node_modules/csso/src/translator.node.js create mode 100644 node_modules/piler/node_modules/csso/src/translator.shared.js create mode 100644 node_modules/piler/node_modules/csso/src/trbl.js create mode 100644 node_modules/piler/node_modules/csso/src/util.node.js create mode 100644 node_modules/piler/node_modules/csso/src/util.shared.js create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atkeyword/atkeyword.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atkeyword/atkeyword.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atkeyword/atkeyword.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atkeyword/atkeyword.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atkeyword/atkeyword.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atkeyword/atkeyword.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruleb/atruleb.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/atruler.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/webkit.keyfraymes.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/webkit.keyfraymes.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atruler/webkit.keyfraymes.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_atrules/atrules.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrib/attrib.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_attrselector/attrselector.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.c.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_block/block.s.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.6.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.6.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.7.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.7.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.8.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.8.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.6.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.6.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.7.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.c.7.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.6.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.6.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.7.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_braces/braces.s.7.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_clazz/clazz.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_clazz/clazz.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_clazz/clazz.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_combinator/combinator.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_comment/comment.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_comment/comment.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_comment/comment.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.c.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_declaration/declaration.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_decldelim/decldelim.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_decldelim/decldelim.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_decldelim/decldelim.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_delim/delim.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_delim/delim.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_delim/delim.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_dimension/dimension.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_filter/filter.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.6.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.6.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.7.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_functionExpression/functionExpression.7.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.c.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_funktion/function.s.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ident/ident.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_important/important.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nth/nth.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_nthselector/nthselector.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.6.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_number/number.7.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_operator/operator.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_percentage/percentage.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_property/property.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_property/property.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_property/property.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_property/property.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_property/property.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_property/property.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoc/pseudoc.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoc/pseudoc.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoc/pseudoc.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoc/pseudoc.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoc/pseudoc.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoc/pseudoc.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoe/pseudoe.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoe/pseudoe.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoe/pseudoe.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoe/pseudoe.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoe/pseudoe.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_pseudoe/pseudoe.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.c.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/ruleset.s.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/value.color.ident.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/value.color.ident.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/value.color.ident.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_ruleset/value.color.ident.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_selector/selector.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_selector/selector.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_selector/selector.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_selector/selector.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_selector/selector.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_selector/selector.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_shash/shash.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_shash/shash.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_shash/shash.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_shash/shash.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_shash/shash.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_shash/shash.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.10.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.10.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.10.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.11.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.11.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.11.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.12.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.12.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.12.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.13.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.13.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.13.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.5.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.5.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.6.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.6.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.7.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.7.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.8.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.8.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.9.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.9.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.9.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.c.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_simpleselector/simpleselector.s.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_string/string.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.attrib.string.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.attrib.string.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.attrib.string.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.attrib.string.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.colormark.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.colormark.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part15.6.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part15.6.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test10.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test10.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test8.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test9.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.2.test9.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test8.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test9.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.4.test9.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test8.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.6.test8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.3.7.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.4.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.4.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.4.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.4.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.4.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part4.4.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.3.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.4.2.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.4.2.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.4.2.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.4.2.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.4.2.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part6.4.2.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part7.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part7.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part7.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css21.part7.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test1.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test1.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test10.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test10.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test10.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test10.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test11.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test11.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test11.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test11.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test12.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test12.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test12.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test12.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test13.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test13.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test13.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test13.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test14.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test14.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test14.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test14.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test15.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test15.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test15.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test15.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test16.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test16.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test16.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test16.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test17.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test17.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test17.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test17.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test18.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test18.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test18.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test18.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test19.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test19.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test19.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test19.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test2.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test2.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test20.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test20.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test20.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test20.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test21.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test21.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test21.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test21.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test22.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test22.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test22.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test22.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test23.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test23.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test23.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test23.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test24.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test24.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test24.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test24.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test25.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test25.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test25.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test25.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test26.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test26.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test26.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test26.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test27.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test27.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test27.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test27.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test28.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test28.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test28.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test28.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test29.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test29.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test29.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test29.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test3.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test3.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test30.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test30.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test30.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test30.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test31.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test31.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test31.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test31.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test32.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test32.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test32.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test32.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test33.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test33.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test33.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test33.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test34.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test34.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test34.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test34.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test35.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test35.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test35.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test35.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test36.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test36.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test36.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test36.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test37.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test37.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test37.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test37.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test38.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test38.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test38.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test38.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test39.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test39.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test39.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test39.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test4.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test4.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test40.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test40.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test40.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test40.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test41.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test41.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test41.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test41.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test42.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test42.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test42.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test42.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test5.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test5.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test6.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test6.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test7.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test7.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test8.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test8.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test8.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test9.c.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test9.c.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test9.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.css3.selectors.part2.test9.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.background.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.background.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.background.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.background.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.background.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.background.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.dont.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.initial.background.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.initial.background.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.initial.font.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.initial.font.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.initial.font.test1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.mess.test3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.background.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.background.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.empty.atrule.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.empty.atrule.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.empty.atrule.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.empty.atrule.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.selectors.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.selectors.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.selectors.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.selectors.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.selectors.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.selectors.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.equal.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.filter.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.filter.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.margin.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.margin.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.margin.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.margin.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.margin.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.margin.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.merge.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.padding.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.padding.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.padding.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.restructure.padding.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.padding.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.padding.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.margin.unary.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/compress.shorthand.padding.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue16.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue16.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test10.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test10.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test11.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test11.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test12.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test12.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test13.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test13.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test14.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test14.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test15.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test15.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test16.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test16.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test17.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test17.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test18.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test18.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test19.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test19.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test20.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test20.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test21.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test21.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test22.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test22.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test23.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test23.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test24.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test24.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test25.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test25.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test26.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test26.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test27.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test27.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test28.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test28.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test29.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test29.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test30.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test30.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test31.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test31.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test6.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test6.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test7.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test7.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test8.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test8.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test9.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue39.test9.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue45.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue45.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue48.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue48.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue50.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue50.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue50.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue50.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue52.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue52.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue52.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue52.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue53.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue53.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue53.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue53.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue54.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue54.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue57.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue57.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue57.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue57.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue71.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue71.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test5.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue76.test5.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test4.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue78.test4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue79.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue79.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue79.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue79.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue81.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue81.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue81.test2.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue81.test2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue81.test3.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue81.test3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue82.test1.cl create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/issue82.test1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_stylesheet/stylesheet.s.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unary/unary.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unary/unary.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unary/unary.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unary/unary.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unary/unary.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unary/unary.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unknown/unknown.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unknown/unknown.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unknown/unknown.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unknown/unknown.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unknown/unknown.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_unknown/unknown.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.c.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.c.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.c.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.c.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.c.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.c.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.s.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.s.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.s.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.s.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.s.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_uri/uri.s.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.1.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.2.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.3.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.4.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.4.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.4.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.dimension.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.dimension.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.dimension.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.dimension.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.dimension.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.dimension.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.rgb.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.rgb.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.rgb.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.rgb.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.rgb.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.rgb.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.2.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.2.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.3.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_value/value.vhash.3.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_vhash/vhash.0.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_vhash/vhash.0.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_vhash/vhash.0.p create mode 100644 node_modules/piler/node_modules/csso/test/data/test_vhash/vhash.1.css create mode 100644 node_modules/piler/node_modules/csso/test/data/test_vhash/vhash.1.l create mode 100644 node_modules/piler/node_modules/csso/test/data/test_vhash/vhash.1.p create mode 100644 node_modules/piler/node_modules/csso/test/test.js create mode 100644 node_modules/piler/node_modules/csso/web/csso.css create mode 100644 node_modules/piler/node_modules/csso/web/csso.html create mode 100644 node_modules/piler/node_modules/csso/web/csso.web.js create mode 100644 node_modules/piler/node_modules/uglify-js/.npmignore create mode 100644 node_modules/piler/node_modules/uglify-js/README.html create mode 100644 node_modules/piler/node_modules/uglify-js/README.org create mode 100755 node_modules/piler/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/piler/node_modules/uglify-js/docstyle.css create mode 100644 node_modules/piler/node_modules/uglify-js/lib/consolidator.js create mode 100644 node_modules/piler/node_modules/uglify-js/lib/parse-js.js create mode 100644 node_modules/piler/node_modules/uglify-js/lib/process.js create mode 100644 node_modules/piler/node_modules/uglify-js/lib/squeeze-more.js create mode 100644 node_modules/piler/node_modules/uglify-js/package.json create mode 100755 node_modules/piler/node_modules/uglify-js/test/beautify.js create mode 100755 node_modules/piler/node_modules/uglify-js/test/testconsolidator.js create mode 100755 node_modules/piler/node_modules/uglify-js/test/testparser.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/1e21.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/array1.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/array2.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/array3.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/array4.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/assignment.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/concatstring.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/const.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/div-with-regexp.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/forstatement.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/if-not.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/if.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/infinite.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue10.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue11.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue13.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue14.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue16.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue17.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue20.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue21.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue25.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue27.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue278.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue28.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue29.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue30.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue34.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue349.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue353.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue372.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue4.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue471.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue48.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue50.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue53.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue68.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue69.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issue9.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/issues222_324.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/mangle.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/null_string.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/var.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/whitespace.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/expected/with.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/1e21.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/array1.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/array2.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/array3.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/array4.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/assignment.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/concatstring.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/const.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/div-with-regexp.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/forstatement.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/if-not.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/if.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/ifreturn.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/infinite.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue10.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue11.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue13.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue14.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue16.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue17.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue20.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue21.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue25.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue27.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue278.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue28.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue29.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue30.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue34.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue349.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue353.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue372.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue4.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue471.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue48.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue50.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue53.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue54.1.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue68.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue69.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issue9.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/issues222_324.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/mangle.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/null_string.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/strict-equals.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/var.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/whitespace.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/compress/test/with.js create mode 100644 node_modules/piler/node_modules/uglify-js/test/unit/scripts.js create mode 100644 node_modules/piler/node_modules/uglify-js/tmp/hoist.js create mode 100644 node_modules/piler/node_modules/uglify-js/tmp/instrument.js create mode 100755 node_modules/piler/node_modules/uglify-js/tmp/test.js create mode 100644 node_modules/piler/node_modules/uglify-js/uglify-js.js create mode 100644 node_modules/piler/node_modules/underscore.string/.travis.yml create mode 100644 node_modules/piler/node_modules/underscore.string/Gemfile create mode 100644 node_modules/piler/node_modules/underscore.string/Gemfile.lock create mode 100644 node_modules/piler/node_modules/underscore.string/README.markdown create mode 100644 node_modules/piler/node_modules/underscore.string/Rakefile create mode 100644 node_modules/piler/node_modules/underscore.string/dist/underscore.string.min.js create mode 100644 node_modules/piler/node_modules/underscore.string/foo.js create mode 100644 node_modules/piler/node_modules/underscore.string/lib/underscore.string.js create mode 100644 node_modules/piler/node_modules/underscore.string/package.json create mode 100644 node_modules/piler/node_modules/underscore.string/test/run-qunit.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/speed.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/strings.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/strings_standalone.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test.html create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_standalone.html create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/arrays.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/chaining.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/collections.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/functions.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/objects.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/speed.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/temp.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/temp_tests.html create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/test.html create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/utility.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/jquery.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/jslitmus.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.css create mode 100644 node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.js create mode 100644 node_modules/piler/node_modules/underscore.string/test/underscore.js create mode 100644 node_modules/piler/node_modules/underscore/.npmignore create mode 100644 node_modules/piler/node_modules/underscore/CNAME create mode 100644 node_modules/piler/node_modules/underscore/LICENSE create mode 100644 node_modules/piler/node_modules/underscore/README.md create mode 100755 node_modules/piler/node_modules/underscore/favicon.ico create mode 100644 node_modules/piler/node_modules/underscore/index.html create mode 100644 node_modules/piler/node_modules/underscore/index.js create mode 100644 node_modules/piler/node_modules/underscore/package.json create mode 100644 node_modules/piler/node_modules/underscore/raw/underscore.psd create mode 100644 node_modules/piler/node_modules/underscore/underscore-min.js create mode 100644 node_modules/piler/node_modules/underscore/underscore.js create mode 100644 node_modules/piler/package.json create mode 100755 node_modules/piler/run-tests-travis.sh create mode 100755 node_modules/piler/run-tests.sh create mode 100644 node_modules/piler/spec/acceptance.spec.coffee create mode 100644 node_modules/piler/spec/asseturlparser.spec.coffee create mode 100644 node_modules/piler/spec/basepile.spec.coffee create mode 100644 node_modules/piler/spec/hrefupdater.spec.coffee create mode 100644 node_modules/piler/spec/testapp/app.coffee create mode 100644 node_modules/piler/spec/testapp/clientscripts/global.coffee create mode 100644 node_modules/piler/spec/testapp/clientscripts/global.js create mode 100644 node_modules/piler/spec/testapp/clientscripts/jquery.js create mode 100644 node_modules/piler/spec/testapp/clientscripts/namespace.js create mode 100644 node_modules/piler/spec/testapp/clientscripts/remote.js create mode 100644 node_modules/piler/spec/testapp/stylesheets/import.less create mode 100644 node_modules/piler/spec/testapp/stylesheets/import.styl create mode 100644 node_modules/piler/spec/testapp/stylesheets/namespaced.css create mode 100644 node_modules/piler/spec/testapp/stylesheets/style.css create mode 100644 node_modules/piler/spec/testapp/stylesheets/style.less create mode 100644 node_modules/piler/spec/testapp/stylesheets/style.styl create mode 100644 node_modules/piler/spec/testapp/views/index.jade create mode 100644 node_modules/piler/spec/testapp/views/layout.jade create mode 100644 node_modules/piler/spec/testapp/views/namespace.jade create mode 100644 node_modules/socket.io/.npmignore create mode 100644 node_modules/socket.io/.travis.yml create mode 100644 node_modules/socket.io/History.md create mode 100644 node_modules/socket.io/LICENSE create mode 100644 node_modules/socket.io/Makefile create mode 100644 node_modules/socket.io/Readme.md create mode 100644 node_modules/socket.io/benchmarks/decode.bench.js create mode 100644 node_modules/socket.io/benchmarks/encode.bench.js create mode 100644 node_modules/socket.io/benchmarks/runner.js create mode 100644 node_modules/socket.io/index.js create mode 100644 node_modules/socket.io/lib/logger.js create mode 100644 node_modules/socket.io/lib/manager.js create mode 100644 node_modules/socket.io/lib/namespace.js create mode 100644 node_modules/socket.io/lib/parser.js create mode 100644 node_modules/socket.io/lib/socket.io.js create mode 100644 node_modules/socket.io/lib/socket.js create mode 100644 node_modules/socket.io/lib/static.js create mode 100644 node_modules/socket.io/lib/store.js create mode 100644 node_modules/socket.io/lib/stores/memory.js create mode 100644 node_modules/socket.io/lib/stores/redis.js create mode 100644 node_modules/socket.io/lib/transport.js create mode 100644 node_modules/socket.io/lib/transports/flashsocket.js create mode 100644 node_modules/socket.io/lib/transports/htmlfile.js create mode 100644 node_modules/socket.io/lib/transports/http-polling.js create mode 100644 node_modules/socket.io/lib/transports/http.js create mode 100644 node_modules/socket.io/lib/transports/index.js create mode 100644 node_modules/socket.io/lib/transports/jsonp-polling.js create mode 100644 node_modules/socket.io/lib/transports/websocket.js create mode 100644 node_modules/socket.io/lib/transports/websocket/default.js create mode 100644 node_modules/socket.io/lib/transports/websocket/hybi-07-12.js create mode 100644 node_modules/socket.io/lib/transports/websocket/hybi-16.js create mode 100644 node_modules/socket.io/lib/transports/websocket/index.js create mode 100644 node_modules/socket.io/lib/transports/xhr-polling.js create mode 100644 node_modules/socket.io/lib/util.js create mode 100644 node_modules/socket.io/node_modules/base64id/.npmignore create mode 100644 node_modules/socket.io/node_modules/base64id/README.md create mode 100644 node_modules/socket.io/node_modules/base64id/lib/base64id.js create mode 100644 node_modules/socket.io/node_modules/base64id/package.json create mode 100644 node_modules/socket.io/node_modules/policyfile/.npmignore create mode 100644 node_modules/socket.io/node_modules/policyfile/LICENSE create mode 100644 node_modules/socket.io/node_modules/policyfile/Makefile create mode 100644 node_modules/socket.io/node_modules/policyfile/README.md create mode 100644 node_modules/socket.io/node_modules/policyfile/doc/index.html create mode 100644 node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js create mode 100644 node_modules/socket.io/node_modules/policyfile/examples/basic.js create mode 100644 node_modules/socket.io/node_modules/policyfile/index.js create mode 100644 node_modules/socket.io/node_modules/policyfile/lib/server.js create mode 100644 node_modules/socket.io/node_modules/policyfile/package.json create mode 100644 node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt create mode 100644 node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key create mode 100644 node_modules/socket.io/node_modules/policyfile/tests/unit.test.js create mode 100644 node_modules/socket.io/node_modules/redis/.npmignore create mode 100644 node_modules/socket.io/node_modules/redis/README.md create mode 100644 node_modules/socket.io/node_modules/redis/benches/buffer_bench.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/re_sub_test.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/reconnect_test.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/codec.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js create mode 100755 node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js create mode 100755 node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/speed/00 create mode 100755 node_modules/socket.io/node_modules/redis/benches/stress/speed/plot create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png create mode 100644 node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js create mode 100644 node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js create mode 100644 node_modules/socket.io/node_modules/redis/changelog.md create mode 100755 node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/auth.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/eval.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/extend.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/file.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/mget.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/monitor.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/multi.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/multi2.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/psubscribe.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/pub_sub.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/simple.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/sort.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/subqueries.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/subquery.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/unix_socket.js create mode 100644 node_modules/socket.io/node_modules/redis/examples/web_server.js create mode 100644 node_modules/socket.io/node_modules/redis/generate_commands.js create mode 100644 node_modules/socket.io/node_modules/redis/index.js create mode 100644 node_modules/socket.io/node_modules/redis/lib/commands.js create mode 100644 node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js create mode 100644 node_modules/socket.io/node_modules/redis/lib/parser/javascript.js create mode 100644 node_modules/socket.io/node_modules/redis/lib/queue.js create mode 100644 node_modules/socket.io/node_modules/redis/lib/to_array.js create mode 100644 node_modules/socket.io/node_modules/redis/lib/util.js create mode 100644 node_modules/socket.io/node_modules/redis/mem.js create mode 100644 node_modules/socket.io/node_modules/redis/multi_bench.js create mode 100644 node_modules/socket.io/node_modules/redis/package.json create mode 100644 node_modules/socket.io/node_modules/redis/test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/History.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/Makefile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/README.md create mode 100755 node_modules/socket.io/node_modules/socket.io-client/bin/builder.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-xhr.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/websocket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/util.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-socket.io-protocol/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/learnboost-socket.io-protocol/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/timoxley-to-array/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/timoxley-to-array/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/visionmedia-debug/component.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/visionmedia-debug/debug.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/components/visionmedia-debug/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/dist/WebSocketMain.swf create mode 100644 node_modules/socket.io/node_modules/socket.io-client/dist/WebSocketMainInsecure.swf create mode 100644 node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/events.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/io.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/json.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/namespace.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/parser.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/socket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transport.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transports/flashsocket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transports/htmlfile.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transports/jsonp-polling.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transports/websocket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transports/xhr-polling.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/transports/xhr.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/util.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/README.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/WebSocketMain.swf create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/WebSocketMainInsecure.zip create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/IWebSocketLogger.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocket.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocketEvent.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocketMain.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/WebSocketMainInsecure.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/build.sh create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/adobe/net/proxies/RFC2817Socket.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/gsolo/encryption/MD5.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/Crypto.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/MozillaRootCertificates.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/X509Certificate.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/X509CertificateCollection.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/HMAC.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/IHMAC.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/IHash.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/MAC.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/MD2.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/MD5.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHA1.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHA224.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHA256.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/hash/SHABase.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/ARC4.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/IPRNG.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/Random.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/prng/TLSPRF.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/rsa/RSAKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/AESKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/BlowFishKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CBCMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CFB8Mode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CFBMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/CTRMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/DESKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/ECBMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/ICipher.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IPad.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IStreamCipher.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/ISymmetricKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/IVMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/NullPad.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/OFBMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/PKCS5.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/SSLPad.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/SimpleIVMode.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/TLSPad.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/TripleDESKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/XTeaKey.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/aeskey.pl create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/symmetric/dump.txt create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/AESKeyTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/ARC4Test.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/BigIntegerTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/BlowFishKeyTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CBCModeTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CFB8ModeTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CFBModeTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/CTRModeTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/DESKeyTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/ECBModeTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/HMACTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/ITestHarness.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/MD2Test.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/MD5Test.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/OFBModeTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/RSAKeyTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/SHA1Test.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/SHA224Test.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/SHA256Test.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/TLSPRFTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/TestCase.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/TripleDESKeyTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tests/XTeaKeyTest.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/BulkCiphers.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/CipherSuites.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/IConnectionState.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/ISecurityParameters.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/KeyExchanges.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/MACs.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLEvent.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLSecurityParameters.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConfig.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSConnectionState.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEngine.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSError.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSEvent.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocket.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSocketEvent.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSTest.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/BarrettReduction.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/BigInteger.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/ClassicReduction.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/IReduction.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/MontgomeryReduction.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/NullReduction.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/math/bi_internal.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/ArrayUtil.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/Base64.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/Hex.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/Memory.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/ByteString.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/DER.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/IAsn1Type.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Integer.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/OID.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/ObjectIdentifier.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/PEM.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/PrintableString.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Sequence.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Set.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/Type.as create mode 100755 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/util/der/UTCTime.as create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/sample.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/swfobject.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/web_socket.js create mode 120000 node_modules/socket.io/node_modules/socket.io-client/node_modules/.bin/uglifyjs create mode 120000 node_modules/socket.io/node_modules/socket.io-client/node_modules/.bin/wscat create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/Readme.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/LICENSE create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/README create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/Tokenizer.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/ZeParser.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/benchmark.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/unicodecategories.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/docstyle.css create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/object-ast.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/parse-js.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/process.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/lib/squeeze-more.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array1.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array3.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/array4.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/assignment.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/concatstring.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/const.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/forstatement.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/if.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue10.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue11.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue13.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue14.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue16.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue17.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue20.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue21.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue25.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue27.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue278.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue28.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue29.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue30.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue34.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue4.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue48.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue50.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue53.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue68.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue69.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/issue9.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/mangle.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/null_string.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/var.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/whitespace.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/expected/with.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array1.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array3.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/array4.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/assignment.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/concatstring.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/const.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/forstatement.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/if.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/ifreturn.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue10.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue11.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue13.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue14.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue16.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue17.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue20.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue21.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue25.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue27.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue278.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue28.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue29.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue30.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs2.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/uglify-js.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/.travis.yml create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/History.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/Makefile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/README.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/parser.benchmark.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/sender.benchmark.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/speed.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bench/util.js create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/bin/wscat create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/binding.gyp create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Makefile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/bufferutil.node.d create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/bufferutil.node.d create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/validation.node.d create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/obj.target/validation/src/validation.o.d create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/.deps/Release/validation.node.d create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/bufferutil.node create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/linker.lock create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/bufferutil.node create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/bufferutil/src/bufferutil.o create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/validation.node create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/obj.target/validation/src/validation.o create mode 100755 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/Release/validation.node create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/binding.Makefile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/bufferutil.target.mk create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/config.gypi create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/build/validation.target.mk create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/doc/ws.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/app.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/index.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/public/uploader.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/fileapi/server.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/public/index.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats-express_3/server.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/public/index.html create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/serverstats/server.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/examples/ssl.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferPool.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.fallback.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/BufferUtil.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/ErrorCodes.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.hixie.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Receiver.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.hixie.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Sender.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.fallback.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/Validation.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/WebSocketServer.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/lib/browser.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/.travis.yml create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/History.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Makefile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/Readme.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/index.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/lib/commander.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/commander/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/Makefile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/README.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/lib/options.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/fixtures/test.conf create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/options/test/options.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/.npmignore create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/README.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/example.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/node_modules/tinycolor/tinycolor.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/bufferutil.cc create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/src/validation.cc create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/BufferPool.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.hixie.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Receiver.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.hixie.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Sender.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/Validation.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.integration.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocket.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/WebSocketServer.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn-server.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/autobahn.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-cert.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/agent1-key.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-cert.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/ca1-key.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/certificate.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/key.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/request.pem create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/fixtures/textfile create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/hybi-common.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/ws/test/testserver.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/README.md create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/autotest.watchr create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/example/demo.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/lib/XMLHttpRequest.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-constants.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-events.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-exceptions.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-headers.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-methods.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/test-request-protocols.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/node_modules/xmlhttprequest/tests/testdata.txt create mode 100644 node_modules/socket.io/node_modules/socket.io-client/package.json create mode 100644 node_modules/socket.io/node_modules/socket.io-client/test/events.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/test/io.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/test/parser.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/test/socket.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/test/util.test.js create mode 100644 node_modules/socket.io/node_modules/socket.io-client/test/worker.js create mode 100644 node_modules/socket.io/package.json create mode 100644 node_modules/sprintf/README.md create mode 100644 node_modules/sprintf/lib/sprintf.js create mode 100644 node_modules/sprintf/package.json create mode 100644 node_modules/supervisor/LICENSE create mode 100644 node_modules/supervisor/README.md create mode 100755 node_modules/supervisor/lib/cli-wrapper.js create mode 100644 node_modules/supervisor/lib/supervisor.js create mode 100644 node_modules/supervisor/package.json diff --git a/node_modules/.bin/express b/node_modules/.bin/express new file mode 120000 index 0000000..b741d99 --- /dev/null +++ b/node_modules/.bin/express @@ -0,0 +1 @@ +../express/bin/express \ No newline at end of file diff --git a/node_modules/.bin/jade b/node_modules/.bin/jade new file mode 120000 index 0000000..571fae7 --- /dev/null +++ b/node_modules/.bin/jade @@ -0,0 +1 @@ +../jade/bin/jade \ No newline at end of file diff --git a/node_modules/.bin/lessc b/node_modules/.bin/lessc new file mode 120000 index 0000000..87a5294 --- /dev/null +++ b/node_modules/.bin/lessc @@ -0,0 +1 @@ +../less/bin/lessc \ No newline at end of file diff --git a/node_modules/.bin/node-supervisor b/node_modules/.bin/node-supervisor new file mode 120000 index 0000000..7c99776 --- /dev/null +++ b/node_modules/.bin/node-supervisor @@ -0,0 +1 @@ +../supervisor/lib/cli-wrapper.js \ No newline at end of file diff --git a/node_modules/.bin/supervisor b/node_modules/.bin/supervisor new file mode 120000 index 0000000..7c99776 --- /dev/null +++ b/node_modules/.bin/supervisor @@ -0,0 +1 @@ +../supervisor/lib/cli-wrapper.js \ No newline at end of file diff --git a/node_modules/async/LICENSE b/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +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/async/README.md b/node_modules/async/README.md new file mode 100644 index 0000000..9ff1acf --- /dev/null +++ b/node_modules/async/README.md @@ -0,0 +1,1414 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. Also supports [component](https://github.com/component/component). + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, each…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls + +### Binding a context to an iterator + +This section is really about bind, not about async. If you are wondering how to +make async execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](http://github.com/caolan/async). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [each](#each) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [doWhilst](#doWhilst) +* [until](#until) +* [doUntil](#doUntil) +* [forever](#forever) +* [waterfall](#waterfall) +* [compose](#compose) +* [applyEach](#applyEach) +* [queue](#queue) +* [cargo](#cargo) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) +* [times](#times) +* [timesSeries](#timesSeries) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the each function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as each only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as each only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as reject, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then it's probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback(err, reduction) which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main callback is + immediately called with the error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, sortValue) which must be called once it + has completed with an error (which can be null) and a value to use as the sort + criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, results) which must be called once it + has completed with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as parallel only the tasks are executed in parallel with a maximum of "limit" +tasks executing at any time. + +Note that the tasks are not executed in batches, so there is no guarantee that +the first "limit" tasks will complete before any others are started. + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* limit - The maximum number of tasks to run at any time. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback(err) which must be called once it has completed with an + optional error argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### forever(fn, callback) + +Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. +If an error is passed to fn's callback then 'callback' is called with the +error, otherwise it will never be called. + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a + callback(err, result1, result2, ...) it must call on completion. The first + argument is an error (which can be null) and any further arguments will be + passed as arguments in order to the next task. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions f(), g() and h() would produce the result of +f(g(h())), only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling the +callback after all functions have completed. If you only provide the first +argument then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* fns - the asynchronous functions to all call with the same arguments +* args... - any number of separate arguments to pass to the function +* callback - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### applyEachSeries(arr, iterator, callback) + +The same as applyEach only the functions are applied in series. + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task, which must call its callback(err) argument when finished, with an + optional error as an argument. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* unshift(task, [callback]) - add a new task to the front of the queue. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a cargo object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the payload limit). If the +worker is in progress, the task is queued until it is available. Once +the worker has completed some tasks, each callback of those tasks is called. + +__Arguments__ + +* worker(tasks, callback) - An asynchronous function for processing an array of + queued tasks, which must call its callback(err) argument when finished, with + an optional error as an argument. +* payload - An optional integer for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The cargo object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* payload - an integer for determining how many tasks should be + process per round. This property can be changed after a cargo is created to + alter the payload on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +Note, all functions are called with a results object as a second argument, +so it is unsafe to pass functions in the tasks object which cannot handle the +extra argument. For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8'); +}, callback); +``` + +will have the effect of calling readFile with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to readFile in a function which does not forward the +results object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + function receives two arguments: (1) a callback(err, result) which must be + called when finished, passing an error (which can be null) and the result of + the function's execution, and (2) a results object, containing the results of + the previously executed functions. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. Results will always be passed + but if an error occurred, no other tasks will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } +], +function(err, results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + function(callback){ + // once the file is written let's email a link to it... + } + ]); +}); +``` + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. It's also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setImmediate(callback) +if available, otherwise setTimeout(callback, 0), which means other higher priority +events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the callback n times and accumulates results in the same manner +you would use with async.map. + +__Arguments__ + +* n - The number of times to run the function. +* callback - The function to call n times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as times only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/async/component.json b/node_modules/async/component.json new file mode 100644 index 0000000..bbb0115 --- /dev/null +++ b/node_modules/async/component.json @@ -0,0 +1,11 @@ +{ + "name": "async", + "repo": "caolan/async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.1.23", + "keywords": [], + "dependencies": {}, + "development": {}, + "main": "lib/async.js", + "scripts": [ "lib/async.js" ] +} diff --git a/node_modules/async/lib/async.js b/node_modules/async/lib/async.js new file mode 100755 index 0000000..cb6320d --- /dev/null +++ b/node_modules/async/lib/async.js @@ -0,0 +1,955 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = setImmediate; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via \n\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback(err, reduction) which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main callback is \n immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, sortValue) which must be called once it\n has completed with an error (which can be null) and a value to use as the sort\n criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, results) which must be called once it \n has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback(err) which must be called once it has completed with an \n optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n callback(err, result1, result2, ...) it must call on completion. The first\n argument is an error (which can be null) and any further arguments will be \n passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n queued tasks, which must call its callback(err) argument when finished, with \n an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n process per round. This property can be changed after a cargo is created to\n alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8');\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The \n function receives two arguments: (1) a callback(err, result) which must be \n called when finished, passing an error (which can be null) and the result of \n the function's execution, and (2) a results object, containing the results of\n the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n \n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", + "readmeFilename": "README.md", + "_id": "async@0.2.9", + "dist": { + "shasum": "29d568ecfad5e88ee2010c899bcc35372dd35d77" + }, + "_from": "async@", + "_resolved": "https://registry.npmjs.org/async/-/async-0.2.9.tgz" +} diff --git a/node_modules/emailjs/LICENSE b/node_modules/emailjs/LICENSE new file mode 100644 index 0000000..ce1a7e9 --- /dev/null +++ b/node_modules/emailjs/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) <2011> + +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/emailjs/Readme.md b/node_modules/emailjs/Readme.md new file mode 100644 index 0000000..5d3a7f3 --- /dev/null +++ b/node_modules/emailjs/Readme.md @@ -0,0 +1,183 @@ +# emailjs [![Build Status](https://secure.travis-ci.org/eleith/emailjs.png)](http://travis-ci.org/eleith/emailjs) + +send emails, html and attachments (files, streams and strings) from node.js to any smtp server + +## INSTALLING + + npm install emailjs + +## FEATURES + - works with SSL and TLS smtp servers + - supports smtp authentication (PLAIN, LOGIN, CRAMMD5) + - emails are queued and the queue is sent asynchronously + - supports sending html emails and emails with multiple attachments (MIME) + - attachments can be added as strings, streams or file paths + - supports utf-8 headers and body + +## REQUIRES + - auth access to an SMTP Server + - if your service (ex: gmail) uses two-step authentication, use an applicaiton specific password + +## EXAMPLE USAGE - text only emails + +```javascript +var email = require("./path/to/emailjs/email"); +var server = email.server.connect({ + user: "username", + password:"password", + host: "smtp.your-email.com", + ssl: true +}); + +// send the message and get a callback with an error or details of the message that was sent +server.send({ + text: "i hope this works", + from: "you ", + to: "someone , another ", + cc: "else ", + subject: "testing emailjs" +}, function(err, message) { console.log(err || message); }); +``` + +## EXAMPLE USAGE - html emails and attachments + +```javascript +var email = require("./path/to/emailjs/email"); +var server = email.server.connect({ + user: "username", + password:"password", + host: "smtp.your-email.com", + ssl: true +}); + +var message = { + text: "i hope this works", + from: "you ", + to: "someone , another ", + cc: "else ", + subject: "testing emailjs", + attachment: + [ + {data:"i hope this works!", alternative:true}, + {path:"path/to/file.zip", type:"application/zip", name:"renamed.zip"} + ] +}; + +// send the message and get a callback with an error or details of the message that was sent +server.send(message, function(err, message) { console.log(err || message); }); + +// you can continue to send more messages with successive calls to 'server.send', +// they will be queued on the same smtp connection + +// or you can create a new server connection with 'email.server.connect' +// to asynchronously send individual emails instead of a queue +``` + +## EXAMPLE USAGE - sending through hotmail/outlook + +```javascript +var email = require("./path/to/emailjs/email"); +var server = email.server.connect({ + user: "username", + password:"password", + host: "smtp-mail.outlook.com", + tls: {ciphers: "SSLv3"} +}); + +var message = { + text: "i hope this works", + from: "you ", + to: "someone , another ", + cc: "else ", + subject: "testing emailjs", + attachment: + [ + {data:"i hope this works!", alternative:true}, + {path:"path/to/file.zip", type:"application/zip", name:"renamed.zip"} + ] +}; + +// send the message and get a callback with an error or details of the message that was sent +server.send(message, function(err, message) { console.log(err || message); }); +``` + +# API + +## email.server.connect(options) + + // options is an object with the following keys + options = + { + user // username for logging into smtp + password // password for logging into smtp + host // smtp host + port // smtp port (if null a standard port number will be used) + ssl // boolean or object {key, ca, cert} (if true or object, ssl connection will be made) + tls // boolean or object (if true or object, starttls will be initiated) + timeout // max number of milliseconds to wait for smtp responses (defaults to 5000) + domain // domain to greet smtp with (defaults to os.hostname) + } + +## email.server.send(message, callback) + + // message can be a smtp.Message (as returned by email.message.create) + // or an object identical to the first argument accepted by email.message.create + + // callback will be executed with (err, message) + // either when message is sent or an error has occurred + +## message + + // headers is an object ('from' and 'to' are required) + // returns a Message object + + // you can actually pass more message headers than listed, the below are just the + // most common ones you would want to use + + headers = + { + text // text of the email + from // sender of the format (address or name
or "name"
) + to // recipients (same format as above), multiple recipients are separated by a comma + cc // carbon copied recipients (same format as above) + bcc // blind carbon copied recipients (same format as above) + subject // string subject of the email + attachment // one attachment or array of attachments + } + +## attachment + + // can be called multiple times, each adding a new attachment + // options is an object with the following possible keys: + + options = + { + // one of these fields is required + path // string to where the file is located + data // string of the data you want to attach + stream // binary stream that will provide attachment data (make sure it is in the paused state) + // better performance for binary streams is achieved if buffer.length % (76*6) == 0 + // current max size of buffer must be no larger than Message.BUFFERSIZE + + // optionally these fields are also accepted + type // string of the file mime type + name // name to give the file as perceived by the recipient + alternative // if true, will be attached inline as an alternative (also defaults type='text/html') + inline // if true, will be attached inline + encoded // set this to true if the data is already base64 encoded, (avoid this if possible) + headers // object containing header=>value pairs for inclusion in this attachment's header + related // an array of attachments that you want to be related to the parent attachment + } + +## Authors + +eleith + +## Testing + + npm install -d + npm test + +## Contributions + +issues and pull requests are welcome diff --git a/node_modules/emailjs/email.js b/node_modules/emailjs/email.js new file mode 100644 index 0000000..9e3966c --- /dev/null +++ b/node_modules/emailjs/email.js @@ -0,0 +1,3 @@ +exports.server = require('./smtp/client'); +exports.message = require('./smtp/message'); +exports.SMTP = require('./smtp/smtp'); diff --git a/node_modules/emailjs/node_modules/bufferjs/add-chunk.js b/node_modules/emailjs/node_modules/bufferjs/add-chunk.js new file mode 100644 index 0000000..a1f71c9 --- /dev/null +++ b/node_modules/emailjs/node_modules/bufferjs/add-chunk.js @@ -0,0 +1,29 @@ +(function () { + "use strict"; + + Buffer.prototype.__addchunk_index = 0; + + Buffer.prototype.addChunk = function (chunk) { + var len = Math.min(chunk.length, this.length - this.__addchunk_index); + + if (this.__addchunk_index === this.length) { + //throw new Error("Buffer is full"); + return false; + } + + chunk.copy(this, this.__addchunk_index, 0, len); + + this.__addchunk_index += len; + + if (len < chunk.length) { + //remnant = new Buffer(chunk.length - len); + //chunk.copy(remnant, 0, len, chunk.length); + // return remnant; + return chunk.slice(len, chunk.length); + } + + if (this.__addchunk_index === this.length) { + return true; + } + }; +}()); diff --git a/node_modules/emailjs/node_modules/bufferjs/concat.js b/node_modules/emailjs/node_modules/bufferjs/concat.js new file mode 100644 index 0000000..33dabc7 --- /dev/null +++ b/node_modules/emailjs/node_modules/bufferjs/concat.js @@ -0,0 +1,31 @@ +(function () { + "use strict"; + + function concat(bufs) { + if (!Array.isArray(bufs)) { + bufs = Array.prototype.slice.call(arguments); + } + + var bufsToConcat = [], length = 0; + bufs.forEach(function (buf) { + if (buf) { + if (!Buffer.isBuffer(buf)) { + buf = new Buffer(buf); + } + length += buf.length; + bufsToConcat.push(buf); + } + }); + + var concatBuf = new Buffer(length), index = 0; + bufsToConcat.forEach(function (buf) { + buf.copy(concatBuf, index, 0, buf.length); + index += buf.length; + }); + + return concatBuf; + } + + Buffer.concat = concat; + +}()); diff --git a/node_modules/emailjs/node_modules/bufferjs/index.js b/node_modules/emailjs/node_modules/bufferjs/index.js new file mode 100644 index 0000000..e234e3a --- /dev/null +++ b/node_modules/emailjs/node_modules/bufferjs/index.js @@ -0,0 +1,7 @@ +(function () { + "use strict"; + + require('./concat'); + require('./add-chunk'); + require('./indexOf'); +}()); diff --git a/node_modules/emailjs/node_modules/bufferjs/indexOf.js b/node_modules/emailjs/node_modules/bufferjs/indexOf.js new file mode 100644 index 0000000..7e45596 --- /dev/null +++ b/node_modules/emailjs/node_modules/bufferjs/indexOf.js @@ -0,0 +1,30 @@ +(function () { + "use strict"; + + /** + * A naiive 'Buffer.indexOf' function. Requires both the + * needle and haystack to be Buffer instances. + */ + function indexOf(haystack, needle, i) { + if (!Buffer.isBuffer(needle)) needle = new Buffer(needle); + if (typeof i === 'undefined') i = 0; + var l = haystack.length - needle.length + 1; + while (i=0.2.0" + }, + "_id": "bufferjs@1.1.0", + "readme": "ERROR: No README.md file found!", + "dist": { + "shasum": "99c9ef972d33c6b326ede90f76cbb98274b4adb9" + }, + "_from": "bufferjs@=1.1.0", + "_resolved": "https://registry.npmjs.org/bufferjs/-/bufferjs-1.1.0.tgz" +} diff --git a/node_modules/emailjs/node_modules/mimelib/.npmignore b/node_modules/emailjs/node_modules/mimelib/.npmignore new file mode 100644 index 0000000..0bb7f9c --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/.npmignore @@ -0,0 +1,2 @@ +/benchmark +/test diff --git a/node_modules/emailjs/node_modules/mimelib/LICENSE b/node_modules/emailjs/node_modules/mimelib/LICENSE new file mode 100644 index 0000000..dca6ebe --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/LICENSE @@ -0,0 +1,16 @@ +Copyright (c) 2011-2012 Andris Reinman + +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 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. \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/README.md b/node_modules/emailjs/node_modules/mimelib/README.md new file mode 100644 index 0000000..0fe99ed --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/README.md @@ -0,0 +1,212 @@ +# mimelib + +*mimelib* is a collection of useful functions to deal with mime-encoded data. + +## Installation + +Install with *npm* + + npm install mimelib + +## Usage + + var mimelib = require("mimelib"); + +## Reference + +### foldLine + +Folds a long line according to the RFC 5322 + + mimelib.foldLine(str [, maxLength][, foldAnywhere][, afterSpace]) -> String + + - `str` (String): mime string that might need folding + - `maxLength` (Number): max length for a line, defaults to 78 + - `foldAnywhere` (Boolean): can fold at any location (ie. in base64) + - `afterSpace` (Boolean): If `true` fold after the space + + +For example: + + Content-Type: multipart/alternative; boundary="----zzzz----" + +will become + + Content-Type: multipart/alternative; + boundary="----zzzz----" + +### encodeMimeWord + +Encodes a string into mime encoded word format (see also `decodeMimeWord`) + + mimelib.encodeMimeWord = function(str [, encoding][, charset]) + + - `str` (String): String to be encoded + - `encoding` (String): Encoding Q for quoted printable or B (def.) for base64 + - `charset` (String): Charset to be used + +For example: + + See on õhin test + +Becomes with UTF-8 and Quoted-printable encoding + + =?UTF-8?Q?See_on_=C3=B5hin_test?= + +### decodeMimeWord + +Decodes a string from mime encoded word format (see also `encodeMimeWord`) + + mimelib.decodeMimeWord(str) -> String + + - `str` (String): String to be decoded + +For example + + mimelib.decodeMimeWord("=?UTF-8?Q?See_on_=C3=B5hin_test?="); + +will become + + See on õhin test + +### encodeQuotedPrintable + +Encodes a string into Quoted-printable format (see also `decodeQuotedPrintable`) + + mimelib.encodeQuotedPrintable(str [, mimeWord][, charset]) -> String + + - `str` (String): String to be encoded into Quoted-printable + - `mimeWord` (Boolean): Deprecated, has no effect, ignore it + - `charset` (String): Destination charset, defaults to UTF-8 + +### decodeQuotedPrintable + +Decodes a string from Quoted-printable format (see also `encodeQuotedPrintable`) + + mimelib.decodeQuotedPrintable(str [, mimeWord][, charset]) -> String + + - `str` (String): String to be decoded + - `mimeWord` (Boolean): Deprecated, has no effect, ignore it + - `charset` (String): Charset to be used, defaults to UTF-8 + +### encodeBase64 + +Encodes a string into Base64 format. Base64 is mime-word safe (see also `decodeBase64`) + + mimelib.encodeBase64(str [, charset]) -> String + + - `str` (String): String to be encoded into Base64 + - `charset` (String): Destination charset, defaults to UTF-8 + +### decodeBase64 + +Decodes a string from Base64 format. Base64 is mime-word safe (see also `encodeBase64`) + +NB! Always returns UTF-8 + + mimelib.decodeBase64(str) -> String + + - `str` (String): String to be decoded from Base64 + - `charset` (String): Source charset, defaults to UTF-8 + +### parseHeaders + +Parses header lines into an array of objects (see `parseHeaderLine`) + + mimelib.parseHeaders(headers) -> Array + + - `headers` (String): header section of the e-mail + +Example: + + var headers = [ + "From: andris@node.ee", + "To: juulius@node.ee", + "To: juulius2@node.ee", + "Content-type: text/html;", + " charset=utf-8" + ].join("\r\n"); + mimelib.parseHeaders(headers); + +Results in + + {"from": [ 'andris@node.ee' ], + "to": [ 'juulius@node.ee', 'juulius2@node.ee' ], + "content-type": [ 'text/html; charset=utf-8' ] } + +### parseAddresses + +Parses names and addresses from a from, to, cc or bcc line + + mimelib.parseAddresses(addresses) -> Array + + - `addresses` (String): string with comma separated e-mail addresses + +Example: + + var to = '"Andris Reinman" , juulius@node.ee' + mimelib.parseAddresses(to); + +Results in + + [{ address: 'andris@node.ee', name: 'Andris Reinman' }, + { address: 'juulius@node.ee', name: false }] + +### parseMimeWords + +Parses mime-words into UTF-8 strings + + mimelib.parseMimeWords(str) -> String + + - `str` (String): string to be parsed, if includes any mime words, then these are converted to UTF-8 strings + + +For example: + + mimelib.parseMimeWords("Hello: =?UTF-8?Q?See_on_=C3=B5hin_test?="); + +Results in + + "Hello: See on õhin test" + +### parseHeaderLine + +Parses a header line to search for additional parameters. + + mimelib.parseHeaderLine(line) -> Object + + - `line` (String): a line from a message headers + +For example: + + mimelib.parseHeaderLine("text/plain; charset=utf-8")imelib + +Results in + + {"defaultValue": 'text/plain', + "charset": 'utf-8' } + +### contentTypes + +**NB! this feature is deprecated**, use [mime](https://github.com/broofa/node-mime) module instead to detect content types and extensions + +`mimelib.contentTypes` is an object to provide content type strings for common +file extensions + + mimelib.contentTypes["xls"]; // "application/vnd.ms-excel" + +## iconv support + +By default only iconv-lite support is bundled. If you need node-iconv support, you need to add it +as an additional dependency for your project: + + ..., + "dependencies":{ + "mimelib": "*", + "iconv": "*" + }, + ... + +## License + +mimelib license is \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/index.js b/node_modules/emailjs/node_modules/mimelib/index.js new file mode 100644 index 0000000..168c72b --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/index.js @@ -0,0 +1,4 @@ + +module.exports = require("./lib/mimelib"); +module.exports.contentTypes = require("./lib/content-types"); +module.exports.contentTypesReversed = require("./lib/content-types-reversed"); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/lib/content-types-reversed.js b/node_modules/emailjs/node_modules/mimelib/lib/content-types-reversed.js new file mode 100644 index 0000000..77802f7 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/lib/content-types-reversed.js @@ -0,0 +1,40 @@ +// list of mime types +module.exports = { + "application/msword": "doc", + "application/pdf": "pdf", + "application/rss+xml": "rss", + "application/vnd.ms-excel": "xls", + "application/vnd.ms-powerpoint": "ppt", + "application/vnd.oasis.opendocument.presentation": "odp", + "application/vnd.oasis.opendocument.spreadsheet": "ods", + "application/vnd.oasis.opendocument.text": "odt", + "application/vnd.sun.xml.calc": "sxc", + "application/vnd.sun.xml.writer": "sxw", + "audio/basic": "au", + "audio/flac": "flac", + "audio/mid": "mid", + "audio/mp4": "m4a", + "audio/mpeg": "mp3", + "audio/ogg": "ogg", + "audio/x-aiff": "aif", + "audio/x-wav": "wav", + "image/gif": "gif", + "image/jpeg": "jpg", + "image/png": "png", + "image/tiff": "tif", + "image/vnd.wap.wbmp": "wbmp", + "image/x-ms-bmp": "bmp", + "text/calendar": "ics", + "text/comma-separated-values": "csv", + "text/css": "css", + "text/html": "html", + "text/plain": "txt", + "text/x-vcard": "vcf", + "video/mp4": "mp4", + "video/mpeg": "mpeg", + "video/ogg": "ogv", + "video/quicktime": "mov", + "video/x-msvideo": "avi", + "application/zip": "zip", + "application/x-rar-compressed": "rar" +}; \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/lib/content-types.js b/node_modules/emailjs/node_modules/mimelib/lib/content-types.js new file mode 100644 index 0000000..cbf0d80 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/lib/content-types.js @@ -0,0 +1,60 @@ +// list of mime types +module.exports = { + "doc": "application/msword", + "docx": "application/msword", + "pdf": "application/pdf", + "rss": "application/rss+xml", + "xls": "application/vnd.ms-excel", + "xlsx": "application/vnd.ms-excel", + "pps": "application/vnd.ms-powerpoint", + "ppt": "application/vnd.ms-powerpoint", + "pptx": "application/vnd.ms-powerpoint", + "odp": "application/vnd.oasis.opendocument.presentation", + "ods": "application/vnd.oasis.opendocument.spreadsheet", + "odt": "application/vnd.oasis.opendocument.text", + "sxc": "application/vnd.sun.xml.calc", + "sxw": "application/vnd.sun.xml.writer", + "au": "audio/basic", + "snd": "audio/basic", + "flac": "audio/flac", + "mid": "audio/mid", + "rmi": "audio/mid", + "m4a": "audio/mp4", + "mp3": "audio/mpeg", + "oga": "audio/ogg", + "ogg": "audio/ogg", + "aif": "audio/x-aiff", + "aifc": "audio/x-aiff", + "aiff": "audio/x-aiff", + "wav": "audio/x-wav", + "gif": "image/gif", + "jpeg": "image/jpeg", + "jpg": "image/jpeg", + "jpe": "image/jpeg", + "png": "image/png", + "tiff": "image/tiff", + "tif": "image/tiff", + "wbmp": "image/vnd.wap.wbmp", + "bmp": "image/x-ms-bmp", + "ics": "text/calendar", + "csv": "text/comma-separated-values", + "css": "text/css", + "htm": "text/html", + "html": "text/html", + "text": "text/plain", + "txt": "text/plain", + "asc": "text/plain", + "diff": "text/plain", + "pot": "text/plain", + "vcf": "text/x-vcard", + "mp4": "video/mp4", + "mpeg": "video/mpeg", + "mpg": "video/mpeg", + "mpe": "video/mpeg", + "ogv": "video/ogg", + "qt": "video/quicktime", + "mov": "video/quicktime", + "avi": "video/x-msvideo", + "zip": "application/zip", + "rar": "application/x-rar-compressed" +}; \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/lib/mimelib.js b/node_modules/emailjs/node_modules/mimelib/lib/mimelib.js new file mode 100644 index 0000000..01469b3 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/lib/mimelib.js @@ -0,0 +1,576 @@ +var convert = require("encoding").convert, + addressparser = require("addressparser"); + +/** + * Folds a long line according to the RFC 5322 http://tools.ietf.org/html/rfc5322#section-2.1.1 + * + * @param {String} str Mime string that might need folding + * @param {Number} [maxLength=76] max length for a line + * @param {Boolean} [foldAnywhere] If true, can fold at any location (ie. in base64) + * @param {Boolean} [afterSpace] If true fold after the space (default is before) + * @return {String} Folded string + */ +this.foldLine = function(str, maxLength, foldAnywhere, afterSpace, lineMargin){ + if(foldAnywhere){ + return addBase64SoftLinebreaks(str, maxLength || 76); + } + return module.exports.mimeFunctions.foldLine(str, maxLength, !!afterSpace, lineMargin); +}; + +/** + * Encodes a string into mime encoded word format http://en.wikipedia.org/wiki/MIME#Encoded-Word + * + * @param {String} str String to be encoded + * @param {String} encoding Encoding Q for quoted printable or B for base64 + * @param {String} [charset="UTF-8"] Charset to be used + * @param {Number} [maxLength] If set, split on maxLength + * @return {String} Mime word encoded string + */ +module.exports.encodeMimeWord = function(str, encoding, charset, maxLength){ + return module.exports.mimeFunctions.encodeMimeWord(str, encoding, maxLength || 0, charset); +}; + +/** + * Encodes need parts of a string to mime word format + * + * @param {String} str String to be encoded + * @param {String} encoding Encoding Q for quoted printable or B for base64 + * @param {Number} [maxLength] If set, split on maxLength + * @param {String} [charset="UTF-8"] Charset to be used + * @return {String} String with possible mime word encoded parts + */ +module.exports.encodeMimeWords = function(str, encoding, maxLength, charset){ + return module.exports.mimeFunctions.encodeMimeWords(str, encoding, maxLength || 0, charset); +}; + +/** + * Decodes a string from mime encoded word + * + * @param {String} str Mime word encoded string + * @return {String} Decoded string + */ +module.exports.decodeMimeWord = function(str){ + return module.exports.mimeFunctions.decodeMimeWord(str).toString("utf-8"); +}; + +/** + * Decodes all mime words from a string to an unencoded string + * + * @param {String} str String that may include mime words + * @return {String} Unencoded string + */ +module.exports.parseMimeWords = function(str){ + return module.exports.mimeFunctions.decodeMimeWords(str).toString("utf-8"); +}; + +/** + * Encodes a string into Quoted-printable format. Maximum line length for the + * encoded string is always 76+2 bytes + * + * @param {String} str String to be encoded into Quoted-printable + * @param {Boolean} [mimeWord] legacy parameter, not used + * @param {String} [charset="UTF-8"] Destination charset + * @return {String} Quoted printable encoded string + */ +module.exports.encodeQuotedPrintable = function(str, mimeWord, charset){ + if(typeof mimeWord == "string" && !charset){ + charset = mimeWord; + mimeWord = undefined; + } + return module.exports.mimeFunctions.encodeQuotedPrintable(str, charset); +}; + +/** + * Decodes a string from Quoted-printable format + * + * @param {String} str String to be decoded from Quoted-printable + * @param {Boolean} [mimeWord] legacy parameter, not used + * @param {String} [charset="UTF-8"] Source charset + * @return {String} Decoded string + */ +module.exports.decodeQuotedPrintable = function(str, mimeWord, charset){ + if(typeof mimeWord == "string" && !charset){ + charset = mimeWord; + mimeWord = undefined; + } + charset = (charset || "").toString().toUpperCase().trim(); + var decodedString = module.exports.mimeFunctions.decodeQuotedPrintable(str, "utf-8", charset); + return charset == "BINARY" ? decodedString : decodedString.toString("utf-8"); +}; + +/** + * Encodes a string into Base64 format. Base64 is mime-word safe + * + * @param {String} str String to be encoded into Base64 + * @param {String} [charset="UTF-8"] Destination charset + * @return {String} Base64 encoded string + */ +module.exports.encodeBase64 = function(str, charset){ + return module.exports.mimeFunctions.encodeBase64(str, charset); +}; + +/** + * Decodes a string from Base64 format + * + * @param {String} str String to be decoded from Base64 + * @param {String} [charset="UTF-8"] Source charset + * @return {String} Decoded string + */ +module.exports.decodeBase64 = function(str, charset){ + return module.exports.mimeFunctions.decodeBase64(str, "utf-8", charset).toString("utf-8"); +}; + +/** + * Parses names and addresses from a from, to, cc or bcc line + * For example: 'Andris Reinman , someone@else.com' + * will be parsed into: [{name:"Andris Reinman", address:"andris@tr.ee"}, {address: "someone@else.com"}] + * + * @param {String|Array} addresses Address line string or an array of strings + * @return {Array} An array of parsed e-mails addresses in the form of [{name, address}] + */ +module.exports.parseAddresses = function(addresses){ + return [].concat.apply([], [].concat(addresses).map(addressparser)).map(function(address){ + address.name = module.exports.parseMimeWords(address.name); + if(address.group){ + address.group.forEach(function(groupAddress){ + groupAddress.name = module.exports.parseMimeWords(groupAddress.name); + }); + } + return address; + }); +}; + +/** + * Parses header lines into an array of objects. Output: {'x-header': ['value']} + * + * @param {String} headers Full header part to be parsed + * @return {Object} Parsed headers + */ +module.exports.parseHeaders = function(headers){ + return module.exports.mimeFunctions.parseHeaderLines(headers); +}; + +/** + * Parses a header line to search for additional parameters. For example + * parseHeaderLine('text/plain; charset=utf-8') + * will be parsed into + * {defaultValue: 'text/plain', charset: 'utf-8'} + * + * @param {String} line Single header value without key part to be parsed + * @return {Object} Parsed value + */ +module.exports.parseHeaderLine = function(line){ + if(!line) + return {}; + var result = {}, parts = line.split(";"), pos; + for(var i=0, len = parts.length; i 7 + toCharset.length){ + maxLength -= (7 + toCharset.length); + } + + if(encoding == "Q"){ + encodedStr = this.mimeEncode(str, toCharset, fromCharset); + encodedStr = encodedStr.replace(/[\r\n\t_]/g, function(chr){ + var code = chr.charCodeAt(0); + return "=" + (code<0x10?"0":"") + code.toString(16).toUpperCase(); + }).replace(/\s/g, "_"); + }else if(encoding == "B"){ + encodedStr = convert(str || "", toCharset, fromCharset).toString("base64").trim(); + } + + if(maxLength && encodedStr.length > maxLength){ + if(encoding == "Q"){ + encodedStr = this.splitEncodedString(encodedStr, maxLength).join("?= =?"+toCharset+"?"+encoding+"?"); + }else{ + encodedStr = encodedStr.replace(new RegExp(".{"+maxLength+"}","g"),"$&?= =?"+toCharset+"?"+encoding+"?"); + if(encodedStr.substr(-(" =?"+toCharset+"?"+encoding+"?=").length) == " =?"+toCharset+"?"+encoding+"?="){ + encodedStr = encodedStr.substr(0, encodedStr.length -(" =?"+toCharset+"?"+encoding+"?=").length); + } + if(encodedStr.substr(-(" =?"+toCharset+"?"+encoding+"?").length) == " =?"+toCharset+"?"+encoding+"?"){ + encodedStr = encodedStr.substr(0, encodedStr.length -(" =?"+toCharset+"?"+encoding+"?").length); + } + } + } + + return "=?"+toCharset+"?"+encoding+"?"+encodedStr+ (encodedStr.substr(-2)=="?="?"":"?="); + }, + + decodeMimeWord: function(str, toCharset){ + str = (str || "").toString().trim(); + + var fromCharset, encoding, match; + + match = str.match(/^\=\?([\w_\-]+)\?([QqBb])\?([^\?]+)\?\=$/i); + if(!match){ + return convert(str, toCharset); + } + + fromCharset = match[1]; + encoding = (match[2] || "Q").toString().toUpperCase(); + str = (match[3] || "").replace(/_/g, " "); + + if(encoding == "B"){ + return this.decodeBase64(str, toCharset, fromCharset); + }else if(encoding == "Q"){ + return this.mimeDecode(str, toCharset, fromCharset); + }else{ + return str; + } + + + }, + + decodeMimeWords: function(str, toCharset){ + var remainder = "", lastCharset, curCharset; + str = (str || "").toString(); + + str = str. + replace(/(=\?[^?]+\?[QqBb]\?[^?]+\?=)\s+(?==\?[^?]+\?[QqBb]\?[^?]+\?=)/g, "$1"). + replace(/\=\?([\w_\-]+)\?([QqBb])\?[^\?]+\?\=/g, (function(mimeWord, charset, encoding){ + + curCharset = charset + encoding; + + return this.decodeMimeWord(mimeWord); + }).bind(this)); + + return convert(str, toCharset); + }, + + foldLine: function(str, lineLengthMax, afterSpace, lineMargin){ + lineLengthMax = lineLengthMax || 76; + lineMargin = lineMargin || Math.floor(lineLengthMax/5); + str = (str || "").toString().trim(); + + var pos = 0, len = str.length, result = "", line, match; + + while(pos < len){ + line = str.substr(pos, lineLengthMax); + if(line.length < lineLengthMax){ + result += line; + break; + } + if((match = line.match(/^[^\n\r]*(\r?\n|\r)/))){ + line = match[0]; + result += line; + pos += line.length; + continue; + }else if((match = line.substr(-lineMargin).match(/(\s+)[^\s]*$/))){ + line = line.substr(0, line.length - (match[0].length - (!!afterSpace ? (match[1] || "").length : 0))); + }else if((match = str.substr(pos + line.length).match(/^[^\s]+(\s*)/))){ + line = line + match[0].substr(0, match[0].length - (!afterSpace ? (match[1] || "").length : 0)); + } + result += line; + pos += line.length; + if(pos < len){ + result += "\r\n"; + } + } + + return result; + }, + + encodeMimeWords: function(value, encoding, maxLength, toCharset, fromCharset){ + var decodedValue = convert((value || ""), "utf-8", fromCharset).toString("utf-8"), + encodedValue; + + encodedValue = decodedValue.replace(/([^\s\u0080-\uFFFF]*[\u0080-\uFFFF]+[^\s\u0080-\uFFFF]*(?:\s+[^\s\u0080-\uFFFF]*[\u0080-\uFFFF]+[^\s\u0080-\uFFFF]*\s*)?)+/g, (function(str, o){ + return str.length?this.encodeMimeWord(str, encoding || "Q", maxLength, toCharset):""; + }).bind(this)); + + return encodedValue; + }, + + encodeHeaderLine: function(key, value, toCharset, fromCharset){ + var encodedValue = this.encodeMimeWords(value, 52, toCharset, fromCharset); + return this.foldLine(key+": "+encodedValue, 76); + }, + + parseHeaderLines: function(headers, toCharset){ + var lines = headers.split(/\r?\n|\r/), + headersObj = {}, + key, value, + header, + i, len; + + for(i=lines.length-1; i>=0; i--){ + if(i && lines[i].match(/^\s/)){ + lines[i-1] += "\r\n" + lines[i]; + lines.splice(i, 1); + } + } + + for(i=0, len = lines.length; i 0x7F){ + curLine = curLine.substr(0, curLine.length-3); + done = false; + } + } + } + + if(curLine.length){ + lines.push(curLine); + } + str = str.substr(curLine.length); + } + + return lines; + }, + + parseAddresses: addressparser + +}; + +// Lines can't be longer that 76 + = 78 bytes +// http://tools.ietf.org/html/rfc2045#section-6.7 +function addSoftLinebreaks(str, encoding){ + var lineLengthMax = 76; + + encoding = (encoding || "base64").toString().toLowerCase().trim(); + + if(encoding == "qp"){ + return addQPSoftLinebreaks(str, lineLengthMax); + }else{ + return addBase64SoftLinebreaks(str, lineLengthMax); + } +} + +function addBase64SoftLinebreaks(base64EncodedStr, lineLengthMax){ + base64EncodedStr = (base64EncodedStr || "").toString().trim(); + return base64EncodedStr.replace(new RegExp(".{" +lineLengthMax+ "}", "g"),"$&\r\n").trim(); +} + +function addQPSoftLinebreaks(mimeEncodedStr, lineLengthMax){ + var pos = 0, len = mimeEncodedStr.length, + match, code, line, + lineMargin = Math.floor(lineLengthMax/3), + result = ""; + + // insert soft linebreaks where needed + while(pos < len){ + line = mimeEncodedStr.substr(pos, lineLengthMax); + if((match = line.match(/\r\n/))){ + line = line.substr(0, match.index + match[0].length); + result += line; + pos += line.length; + continue; + } + + if(line.substr(-1)=="\n"){ + // nothing to change here + result += line; + pos += line.length; + continue; + }else if((match = line.substr(-lineMargin).match(/\n.*?$/))){ + // truncate to nearest line break + line = line.substr(0, line.length - (match[0].length - 1)); + result += line; + pos += line.length; + continue; + }else if(line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t\.,!\?][^ \t\.,!\?]*$/))){ + // truncate to nearest space + line = line.substr(0, line.length - (match[0].length - 1)); + }else if(line.substr(-1)=="\r"){ + line = line.substr(0, line.length-1); + }else{ + if(line.match(/\=[\da-f]{0,2}$/i)){ + + // push incomplete encoding sequences to the next line + if((match = line.match(/\=[\da-f]{0,1}$/i))){ + line = line.substr(0, line.length - match[0].length); + } + + // ensure that utf-8 sequences are not split + while(line.length>3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/ig))){ + code = parseInt(match[0].substr(1,2), 16); + if(code<128){ + break; + } + + line = line.substr(0, line.length-3); + + if(code >=0xC0){ + break; + } + } + + } + } + + if(pos + line.length < len && line.substr(-1)!="\n"){ + if(line.length==76 && line.match(/\=[\da-f]{2}$/i)){ + line = line.substr(0, line.length-3); + } + else if(line.length==76){ + line = line.substr(0, line.length-1); + } + pos += line.length; + line += "=\r\n"; + }else{ + pos += line.length; + } + + result += line; + } + + return result; +} + +function checkRanges(nr, ranges){ + for(var i = ranges.length - 1; i >= 0; i--){ + if(!ranges[i].length){ + continue; + } + if(ranges[i].length == 1 && nr == ranges[i][0]){ + return true; + } + if(ranges[i].length == 2 && nr >= ranges[i][0] && nr <= ranges[i][1]){ + return true; + } + } + return false; +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/.npmignore b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/.npmignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/README.md b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/README.md new file mode 100644 index 0000000..a00e183 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/README.md @@ -0,0 +1,51 @@ +# addressparser + +Parse e-mail address fields + +## Installation + +Install with npm + + npm install addressparser + +## Usage + +Include the module + + var addressparser = require("addressparser"); + +Parse some address strings with addressparser(field) + + var addresses = addressparser("andris "); + console.log(addresses); // [{name: "andris", address:"andris@tr.ee"}] + +And when using groups + + addressparser('Composers:"Bach, Sebastian" , mozart@example.com (Mozzie);'); + +the result is + + [ + { + name: "Composers", + group: [ + { + address: "sebu@example.com", + name: "Bach, Sebastian" + }, + { + address: "mozart@example.com", + name: "Mozzie" + } + ] + } + ] + + +## Notes + + * **NB!** this module does not decode any mime-word or punycode encoded strings, it is only a basic parser for parsing the base data, you need to decode the encoded parts later by yourself + +## License + +**MIT** \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/index.js b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/index.js new file mode 100644 index 0000000..f60a6ae --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/index.js @@ -0,0 +1,288 @@ +"use strict"; + +/** + * Defines an object as a namespace for the parsing function + */ +var addressparser = {}; + +// expose to the world +module.exports = function(address){ + return addressparser.parse(address); +}; + +/** + * Parses structured e-mail addresses from an address field + * + * Example: + * + * "Name " + * + * will be converted to + * + * [{name: "Name", address: "address@domain"}] + * + * @param {String} str Address field + * @return {Array} An array of address objects + */ +addressparser.parse = function(str){ + var tokenizer = new addressparser.Tokenizer(str), + tokens = tokenizer.tokenize(); + + var addresses = [], + address = [], + parsedAddresses = []; + + tokens.forEach(function(token){ + if(token.type == "operator" && (token.value =="," || token.value ==";")){ + if(address.length){ + addresses.push(address); + } + address = []; + }else{ + address.push(token); + } + }); + + if(address.length){ + addresses.push(address); + } + + addresses.forEach(function(address){ + address = addressparser._handleAddress(address); + if(address.length){ + parsedAddresses = parsedAddresses.concat(address); + } + }); + + return parsedAddresses; +}; + +/** + * Converts tokens for a single address into an address object + * + * @param {Array} tokens Tokens object + * @return {Object} Address object + */ +addressparser._handleAddress = function(tokens){ + var token, + isGroup = false, + state = "text", + address, + addresses = [], + data = { + address: [], + comment: [], + group: [], + text: [] + }, + i, len; + + // Filter out , (comments) and regular text + for(i=0, len = tokens.length; i=0; i--){ + if(data.text[i].match(/^[^@\s]+@[^@\s]+$/)){ + data.address = data.text.splice(i,1); + break; + } + } + + var _regexHandler = function(address){ + if(!data.address.length){ + data.address = [address.trim()]; + return " "; + }else{ + return address; + } + }; + + // still no address + if(!data.address.length){ + for(i = data.text.length - 1; i>=0; i--){ + data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^@\s]+\b\s*/, _regexHandler).trim(); + if(data.address.length){ + break; + } + } + } + } + + // If there's still is no text but a comment exixts, replace the two + if(!data.text.length && data.comment.length){ + data.text = data.comment; + data.comment = []; + } + + // Keep only the first address occurence, push others to regular text + if(data.address.length > 1){ + data.text = data.text.concat(data.address.splice(1)); + } + + // Join values with spaces + data.text = data.text.join(" "); + data.address = data.address.join(" "); + + if(!data.address && isGroup){ + return []; + }else{ + address = { + address: data.address || data.text || "", + name: data.text || data.address || "" + }; + + if(address.address == address.name){ + if((address.address || "").match(/@/)){ + address.name = ""; + }else{ + address.address = ""; + } + + } + + addresses.push(address); + } + } + + return addresses; +}; + +/** + * Creates a Tokenizer object for tokenizing address field strings + * + * @constructor + * @param {String} str Address field string + */ +addressparser.Tokenizer = function(str){ + + this.str = (str || "").toString(); + this.operatorCurrent = ""; + this.operatorExpecting = ""; + this.node = null; + this.escaped = false; + + this.list = []; + +}; + +/** + * Operator tokens and which tokens are expected to end the sequence + */ +addressparser.Tokenizer.prototype.operators = { + "\"": "\"", + "(": ")", + "<": ">", + ",": "", + ":": ";" +}; + +/** + * Tokenizes the original input string + * + * @return {Array} An array of operator|text tokens + */ +addressparser.Tokenizer.prototype.tokenize = function(){ + var chr, list = []; + for(var i=0, len = this.str.length; i\");\n console.log(addresses); // [{name: \"andris\", address:\"andris@tr.ee\"}]\n\nAnd when using groups\n\n addressparser('Composers:\"Bach, Sebastian\" , mozart@example.com (Mozzie);');\n\nthe result is\n\n [\n {\n name: \"Composers\",\n group: [\n {\n address: \"sebu@example.com\",\n name: \"Bach, Sebastian\"\n },\n {\n address: \"mozart@example.com\",\n name: \"Mozzie\"\n }\n ]\n }\n ]\n\n\n## Notes\n\n * **NB!** this module does not decode any mime-word or punycode encoded strings, it is only a basic parser for parsing the base data, you need to decode the encoded parts later by yourself\n\n## License\n\n**MIT**", + "readmeFilename": "README.md", + "_id": "addressparser@0.2.1", + "dist": { + "shasum": "f34ffc5926d038f57181440ab7f1e1af7a5a52db" + }, + "_from": "addressparser@~0.2.0", + "_resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.2.1.tgz" +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/test.js b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/test.js new file mode 100644 index 0000000..7023199 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/addressparser/test.js @@ -0,0 +1,87 @@ +var testCase = require('nodeunit').testCase, + addressparser = require("./index"); + +exports["General tests"] = { + "Single address": function(test){ + var input = "andris@tr.ee", + expected = [{address:"andris@tr.ee", name:""}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Multiple addresses": function(test){ + var input = "andris@tr.ee, andris@example.com", + expected = [{address:"andris@tr.ee", name:""}, {address:"andris@example.com", name:""}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "With unquoted name": function(test){ + var input = "andris ", + expected = [{name: "andris", address:"andris@tr.ee"}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "With quoted name": function(test){ + var input = "\"reinman, andris\" ", + expected = [{name: "reinman, andris", address:"andris@tr.ee"}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Unquoted name, unquoted address": function(test){ + var input = "andris andris@tr.ee", + expected = [{name: "andris", address:"andris@tr.ee"}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Emtpy group": function(test){ + var input = "Undisclosed:;", + expected = [{name: 'Undisclosed', group: []}]; + + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Address group": function(test){ + var input = "Disclosed:andris@tr.ee, andris@example.com;", + expected = [{name: 'Disclosed', group:[{address: 'andris@tr.ee', name: ''},{address: 'andris@example.com', name: ''}]}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Mixed group": function(test){ + var input = "Test User , Disclosed:andris@tr.ee, andris@example.com;,,,, Undisclosed:;", + expected = [{"address":"test.user@mail.ee","name":"Test User"}, {"name":"Disclosed","group":[{"address":"andris@tr.ee","name":""}, {"address":"andris@example.com","name":""}]}, {"name":"Undisclosed","group":[]}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Name from comment": function(test){ + var input = "andris@tr.ee (andris)", + expected = [{name: "andris", address:"andris@tr.ee"}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Skip comment": function(test){ + var input = "andris@tr.ee (reinman) andris", + expected = [{name: "andris", address:"andris@tr.ee"}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "No address": function(test){ + var input = "andris", + expected = [{name: "andris", address:""}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Apostophe in name": function(test){ + var input = "O'Neill", + expected = [{name: "O'Neill", address:""}]; + test.deepEqual(addressparser(input), expected); + test.done(); + }, + "Colon in name": function(test){ + var input = "FirstName Surname-WithADash :: Company ", + expected = [ { name: 'FirstName Surname-WithADash', + group: + [ { name: undefined, + group: [ { address: 'firstname@company.com', name: 'Company' } ] } ] } ]; + test.deepEqual(addressparser(input), expected); + test.done(); + } +} \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/.npmignore b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/.npmignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/README.md b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/README.md new file mode 100644 index 0000000..8b0b899 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/README.md @@ -0,0 +1,49 @@ +# Encoding + +**encoding** is a simple wrapper around [node-iconv](https://github.com/bnoordhuis/node-iconv) and [iconv-lite](https://github.com/ashtuchkin/iconv-lite/) to convert strings from one encoding to another. If node-iconv is not available for some reason, +iconv-lite will be used instead of it as a fallback. + +## Install + +Install through npm + + npm install encoding + +## Usage + +Require the module + + var encoding = require("encoding"); + +Convert with encoding.convert() + + var resultBuffer = encoding.convert(text, toCharset, fromCharset); + +Where + + * **text** is either a Buffer or a String to be converted + * **toCharset** is the characterset to convert the string + * **fromCharset** (*optional*, defaults to UTF-8) is the source charset + +Output of the conversion is always a Buffer object. + +Example + + var result = encoding.convert("ÕÄÖÜ", "Latin_1"); + console.log(result); // + +## iconv support + +By default only iconv-lite is bundled. If you need node-iconv support, you need to add it +as an additional dependency for your project: + + ..., + "dependencies":{ + "encoding": "*", + "iconv": "*" + }, + ... + +## License + +**MIT** \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/lib/encoding.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/lib/encoding.js new file mode 100644 index 0000000..d976d08 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/lib/encoding.js @@ -0,0 +1,118 @@ +'use strict'; + +var iconvLite = require('iconv-lite'); +var Iconv; + +try { + Iconv = require('iconv').Iconv; +} catch (E) { + // node-iconv not present +} + +// Expose to the world +module.exports.convert = convert; + +/** + * Convert encoding of an UTF-8 string or a buffer + * + * @param {String|Buffer} str String to be converted + * @param {String} to Encoding to be converted to + * @param {String} [from='UTF-8'] Encoding to be converted from + * @param {Boolean} useLite If set to ture, force to use iconvLite + * @return {Buffer} Encoded string + */ +function convert(str, to, from, useLite) { + from = checkEncoding(from || 'UTF-8'); + to = checkEncoding(to || 'UTF-8'); + str = str || ''; + + var result; + + if (from != 'UTF-8' && typeof str == 'string') { + str = new Buffer(str, 'binary'); + } + + if (from === to) { + if (typeof str === 'string') { + result = new Buffer(str); + } else { + result = str; + } + } else { + if (Iconv && !useLite) { + try { + result = convertIconv(str, to, from); + } catch (E) { + console.log(E); + try { + result = convertIconvLite(str, to, from); + } catch (E) { + console.log(E); + result = str; + } + } + } else { + try { + result = convertIconvLite(str, to, from); + } catch (E) { + console.log(E); + result = str; + } + } + } + + if (typeof result == 'string') { + result = new Buffer(result, 'utf-8'); + } + + return result; +} + +/** + * Convert encoding of a string with node-iconv (if available) + * + * @param {String|Buffer} str String to be converted + * @param {String} to Encoding to be converted to + * @param {String} [from='UTF-8'] Encoding to be converted from + * @return {Buffer} Encoded string + */ +function convertIconv(str, to, from) { + var response, iconv; + iconv = new Iconv(from, to + '//TRANSLIT//IGNORE'); + response = iconv.convert(str); + return response.slice(0, response.length); +} + +/** + * Convert encoding of astring with iconv-lite + * + * @param {String|Buffer} str String to be converted + * @param {String} to Encoding to be converted to + * @param {String} [from='UTF-8'] Encoding to be converted from + * @return {Buffer} Encoded string + */ +function convertIconvLite(str, to, from) { + if (to == 'UTF-8') { + return iconvLite.decode(str, from); + } else if (from == 'UTF-8') { + return iconvLite.encode(str, to); + } else { + return iconvLite.encode(iconvLite.decode(str, from), to); + } +} + +/** + * Converts charset name if needed + * + * @param {String} name Character set + * @return {String} Character set name + */ +function checkEncoding(name) { + return (name || '').toString().trim(). + replace(/^latin[\-_]?(\d+)$/i, 'ISO-8859-$1'). + replace(/^win(?:dows)?[\-_]?(\d+)$/i, 'WINDOWS-$1'). + replace(/^utf[\-_]?(\d+)$/i, 'UTF-$1'). + replace(/^ks_c_5601\-1987$/i, 'CP949'). + replace(/^us[\-_]?ascii$/i, 'ASCII'). + toUpperCase(); +} \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.npmignore b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.npmignore new file mode 100644 index 0000000..6c69ea0 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.npmignore @@ -0,0 +1,5 @@ +*~ +*sublime-* +generation +test +wiki diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.travis.yml b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.travis.yml new file mode 100644 index 0000000..9169b9f --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/.travis.yml @@ -0,0 +1,5 @@ + language: node_js + node_js: + - 0.8 + - 0.10 + - 0.11 diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/Changelog.md b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/Changelog.md new file mode 100644 index 0000000..75db5f9 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/Changelog.md @@ -0,0 +1,29 @@ + +# 0.4.4 / 2014-07-16 + + * added encodings UTF-7 (RFC2152) and UTF-7-IMAP (RFC3501 Section 5.1.3) + * fixed streaming base64 encoding + +# 0.4.3 / 2014-06-14 + + * added encodings UTF-16BE and UTF-16 with BOM + +# 0.4.2 / 2014-06-12 + + * don't throw exception if `extendNodeEncodings()` is called more than once + +# 0.4.1 / 2014-06-11 + + * codepage 808 added + + +# 0.4.0 / 2014-06-10 + + * code is rewritten from scratch + * all widespread encodings are supported + * streaming interface added + * browserify compatibility added + * (optional) extend core primitive encodings to make usage even simpler + * moved from vows to mocha as the testing framework + + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/LICENSE b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/LICENSE new file mode 100644 index 0000000..d518d83 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2011 Alexander Shtuchkin + +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/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md new file mode 100644 index 0000000..f8d0845 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md @@ -0,0 +1,137 @@ +## Pure JS character encoding conversion + + + + * Doesn't need native code compilation. Works on Windows and in sandboxed environments like [Cloud9](http://c9.io). + * Used in popular projects like [Grunt](http://gruntjs.com/), [Nodemailer](http://www.nodemailer.com/), [Yeoman](http://yeoman.io/) and others. + * Faster than [node-iconv](https://github.com/bnoordhuis/node-iconv) (see below for performance comparison). + * Intuitive encode/decode API + * Streaming support for Node v0.10+ + * Can extend Node.js primitives (buffers, streams) to support all iconv-lite encodings. + * In-browser usage via [Browserify](https://github.com/substack/node-browserify) (~180k gzip compressed with Buffer shim included). + * License: MIT. + +[![NPM Stats](https://nodei.co/npm/iconv-lite.png?downloads=true)](https://npmjs.org/packages/iconv-lite/) + +## Usage +### Basic API +```javascript +var iconv = require('iconv-lite'); + +// Convert from an encoded buffer to js string. +str = iconv.decode(new Buffer([0x68, 0x65, 0x6c, 0x6c, 0x6f]), 'win1251'); + +// Convert from js string to an encoded buffer. +buf = iconv.encode("Sample input string", 'win1251'); + +// Check if encoding is supported +iconv.encodingExists("us-ascii") +``` + +### Streaming API (Node v0.10+) +```javascript + +// Decode stream (from binary stream to js strings) +http.createServer(function(req, res) { + var converterStream = iconv.decodeStream('win1251'); + req.pipe(converterStream); + + converterStream.on('data', function(str) { + console.log(str); // Do something with decoded strings, chunk-by-chunk. + }); +}); + +// Convert encoding streaming example +fs.createReadStream('file-in-win1251.txt') + .pipe(iconv.decodeStream('win1251')) + .pipe(iconv.encodeStream('ucs2')) + .pipe(fs.createWriteStream('file-in-ucs2.txt')); + +// Sugar: all encode/decode streams have .collect(cb) method to accumulate data. +http.createServer(function(req, res) { + req.pipe(iconv.decodeStream('win1251')).collect(function(err, body) { + assert(typeof body == 'string'); + console.log(body); // full request body string + }); +}); +``` + +### Extend Node.js own encodings +```javascript +// After this call all Node basic primitives will understand iconv-lite encodings. +iconv.extendNodeEncodings(); + +// Examples: +buf = new Buffer(str, 'win1251'); +buf.write(str, 'gbk'); +str = buf.toString('latin1'); +assert(Buffer.isEncoding('iso-8859-15')); +Buffer.byteLength(str, 'us-ascii'); + +http.createServer(function(req, res) { + req.setEncoding('big5'); + req.collect(function(err, body) { + console.log(body); + }); +}); + +fs.createReadStream("file.txt", "shift_jis"); + +// External modules are also supported (if they use Node primitives, which they probably do). +request = require('request'); +request({ + url: "http://github.com/", + encoding: "cp932" +}); + +// To remove extensions +iconv.undoExtendNodeEncodings(); +``` + +## Supported encodings + + * All node.js native encodings: utf8, ucs2 / utf16-le, ascii, binary, base64, hex. + * Additional unicode encodings: utf16, utf16-be, utf-7, utf-7-imap. + * All widespread singlebyte encodings: Windows 125x family, ISO-8859 family, + IBM/DOS codepages, Macintosh family, KOI8 family, all others supported by iconv library. + Aliases like 'latin1', 'us-ascii' also supported. + * All widespread multibyte encodings: CP932, CP936, CP949, CP950, GB2313, GBK, GB18030, Big5, Shift_JIS, EUC-JP. + +See [all supported encodings on wiki](https://github.com/ashtuchkin/iconv-lite/wiki/Supported-Encodings). + +Most singlebyte encodings are generated automatically from [node-iconv](https://github.com/bnoordhuis/node-iconv). Thank you Ben Noordhuis and libiconv authors! + +Multibyte encodings are generated from [Unicode.org mappings](http://www.unicode.org/Public/MAPPINGS/) and [WHATWG Encoding Standard mappings](http://encoding.spec.whatwg.org/). Thank you, respective authors! + + +## Encoding/decoding speed + +Comparison with node-iconv module (1000x256kb, on MacBook Pro, Core i5/2.6 GHz, Node v0.10.26). +Note: your results may vary, so please always check on your hardware. + + operation iconv@2.1.4 iconv-lite@0.4.0 + ---------------------------------------------------------- + encode('win1251') ~130 Mb/s ~380 Mb/s + decode('win1251') ~127 Mb/s ~210 Mb/s + + +## Notes + +When decoding, be sure to supply a Buffer to decode() method, otherwise [bad things usually happen](https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding). +Untranslatable characters are set to � or ?. No transliteration is currently supported. + +## Testing + +```bash +$ git clone git@github.com:ashtuchkin/iconv-lite.git +$ cd iconv-lite +$ npm install +$ npm test + +$ # To view performance: +$ node test/performance.js +``` + +## Adoption +[![NPM](https://nodei.co/npm-dl/iconv-lite.png)](https://nodei.co/npm/iconv-lite/) + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md~ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md~ new file mode 100644 index 0000000..5f57561 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/README.md~ @@ -0,0 +1,54 @@ +iconv-lite - native javascript conversion between character encodings. +====================================================================== + +## Usage + + var iconv = require('iconv-lite'); + + // Convert from an encoded buffer to string. + str = iconv.fromEncoding(buf, 'win-1251'); + // Or + str = iconv.decode(buf, 'win-1251'); + + // Convert from string to an encoded buffer. + buf = iconv.toEncoding("Sample input string", 'win-1251'); + // Or + buf = iconv.encode("Sample input string", 'win-1251'); + +## Supported encodings + +Currently only a small part of encodings supported: + +* All node.js native encodings: 'utf8', 'ucs2', 'ascii', 'binary', 'base64'. +* 'latin1' +* Cyrillic encodings: 'windows-1251', 'koi8-r', 'iso 8859-5'. + +Other encodings are easy to add, see the source. Please, participate. + + +## Encoding/decoding speed + +Comparison with iconv module (1000 times 256kb, on Core i5/2.5 GHz). + + Operation\module iconv iconv-lite (this) + toEncoding('win1251') 19.57 mb/s 49.04 mb/s + fromEncoding('win1251') 16.39 mb/s 24.11 mb/s + + +## Notes + +This module is JavaScript-only, thus can be used in a sandboxed environment like [Cloud9](http://c9.io). + +Untranslatable characters are set to '?'. No transliteration is currently supported, pull requests are welcome. + +## Testing + + npm install --dev iconv-lite + vows + +## TODO + +* Support streaming character conversion, something like util.pipe(req, iconv.fromEncodingStream('latin1')). +* Add more encodings. +* Add transliteration (best fit char). +* Add tests and correct support of variable-byte encodings (currently work is delegated to node). diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-codec.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-codec.js new file mode 100644 index 0000000..fd3681c --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-codec.js @@ -0,0 +1,564 @@ + +// Multibyte codec. In this scheme, a character is represented by 1 or more bytes. +// Our codec supports UTF-16 surrogates, extensions for GB18030 and unicode sequences. +// To save memory and loading time, we read table files only when requested. + +exports._dbcs = function(options) { + return new DBCSCodec(options); +} + +var UNASSIGNED = -1, + GB18030_CODE = -2, + SEQ_START = -10, + NODE_START = -1000, + UNASSIGNED_NODE = new Array(0x100), + DEF_CHAR = -1; + +for (var i = 0; i < 0x100; i++) + UNASSIGNED_NODE[i] = UNASSIGNED; + + +// Class DBCSCodec reads and initializes mapping tables. +function DBCSCodec(options) { + this.options = options; + if (!options) + throw new Error("DBCS codec is called without the data.") + if (!options.table) + throw new Error("Encoding '" + options.encodingName + "' has no data."); + + // Load tables. + var mappingTable = options.table(); + + + // Decode tables: MBCS -> Unicode. + + // decodeTables is a trie, encoded as an array of arrays of integers. Internal arrays are trie nodes and all have len = 256. + // Trie root is decodeTables[0]. + // Values: >= 0 -> unicode character code. can be > 0xFFFF + // == UNASSIGNED -> unknown/unassigned sequence. + // == GB18030_CODE -> this is the end of a GB18030 4-byte sequence. + // <= NODE_START -> index of the next node in our trie to process next byte. + // <= SEQ_START -> index of the start of a character code sequence, in decodeTableSeq. + this.decodeTables = []; + this.decodeTables[0] = UNASSIGNED_NODE.slice(0); // Create root node. + + // Sometimes a MBCS char corresponds to a sequence of unicode chars. We store them as arrays of integers here. + this.decodeTableSeq = []; + + // Actual mapping tables consist of chunks. Use them to fill up decode tables. + for (var i = 0; i < mappingTable.length; i++) + this._addDecodeChunk(mappingTable[i]); + + this.defaultCharUnicode = options.iconv.defaultCharUnicode; + + + // Encode tables: Unicode -> DBCS. + + // `encodeTable` is array mapping from unicode char to encoded char. All its values are integers for performance. + // Because it can be sparse, it is represented as array of buckets by 256 chars each. Bucket can be null. + // Values: >= 0 -> it is a normal char. Write the value (if <=256 then 1 byte, if <=65536 then 2 bytes, etc.). + // == UNASSIGNED -> no conversion found. Output a default char. + // <= SEQ_START -> it's an index in encodeTableSeq, see below. The character starts a sequence. + this.encodeTable = []; + + // `encodeTableSeq` is used when a sequence of unicode characters is encoded as a single code. We use a tree of + // objects where keys correspond to characters in sequence and leafs are the encoded dbcs values. A special DEF_CHAR key + // means end of sequence (needed when one sequence is a strict subsequence of another). + // Objects are kept separately from encodeTable to increase performance. + this.encodeTableSeq = []; + + // Some chars can be decoded, but need not be encoded. + var skipEncodeChars = {}; + if (options.encodeSkipVals) + for (var i = 0; i < options.encodeSkipVals.length; i++) { + var range = options.encodeSkipVals[i]; + for (var j = range.from; j <= range.to; j++) + skipEncodeChars[j] = true; + } + + // Use decode trie to recursively fill out encode tables. + this._fillEncodeTable(0, 0, skipEncodeChars); + + // Add more encoding pairs when needed. + for (var uChar in options.encodeAdd || {}) + this._setEncodeChar(uChar.charCodeAt(0), options.encodeAdd[uChar]); + + this.defCharSB = this.encodeTable[0][options.iconv.defaultCharSingleByte.charCodeAt(0)]; + if (this.defCharSB === UNASSIGNED) this.defCharSB = this.encodeTable[0]['?']; + if (this.defCharSB === UNASSIGNED) this.defCharSB = "?".charCodeAt(0); + + + // Load & create GB18030 tables when needed. + if (typeof options.gb18030 === 'function') { + this.gb18030 = options.gb18030(); // Load GB18030 ranges. + + // Add GB18030 decode tables. + var thirdByteNodeIdx = this.decodeTables.length; + var thirdByteNode = this.decodeTables[thirdByteNodeIdx] = UNASSIGNED_NODE.slice(0); + + var fourthByteNodeIdx = this.decodeTables.length; + var fourthByteNode = this.decodeTables[fourthByteNodeIdx] = UNASSIGNED_NODE.slice(0); + + for (var i = 0x81; i <= 0xFE; i++) { + var secondByteNodeIdx = NODE_START - this.decodeTables[0][i]; + var secondByteNode = this.decodeTables[secondByteNodeIdx]; + for (var j = 0x30; j <= 0x39; j++) + secondByteNode[j] = NODE_START - thirdByteNodeIdx; + } + for (var i = 0x81; i <= 0xFE; i++) + thirdByteNode[i] = NODE_START - fourthByteNodeIdx; + for (var i = 0x30; i <= 0x39; i++) + fourthByteNode[i] = GB18030_CODE + } +} + +// Public interface: create encoder and decoder objects. +// The methods (write, end) are simple functions to not inhibit optimizations. +DBCSCodec.prototype.encoder = function encoderDBCS(options) { + return { + // Methods + write: encoderDBCSWrite, + end: encoderDBCSEnd, + + // Encoder state + leadSurrogate: -1, + seqObj: undefined, + + // Static data + encodeTable: this.encodeTable, + encodeTableSeq: this.encodeTableSeq, + defaultCharSingleByte: this.defCharSB, + gb18030: this.gb18030, + + // Export for testing + findIdx: findIdx, + } +} + +DBCSCodec.prototype.decoder = function decoderDBCS(options) { + return { + // Methods + write: decoderDBCSWrite, + end: decoderDBCSEnd, + + // Decoder state + nodeIdx: 0, + prevBuf: new Buffer(0), + + // Static data + decodeTables: this.decodeTables, + decodeTableSeq: this.decodeTableSeq, + defaultCharUnicode: this.defaultCharUnicode, + gb18030: this.gb18030, + } +} + + + +// Decoder helpers +DBCSCodec.prototype._getDecodeTrieNode = function(addr) { + var bytes = []; + for (; addr > 0; addr >>= 8) + bytes.push(addr & 0xFF); + if (bytes.length == 0) + bytes.push(0); + + var node = this.decodeTables[0]; + for (var i = bytes.length-1; i > 0; i--) { // Traverse nodes deeper into the trie. + var val = node[bytes[i]]; + + if (val == UNASSIGNED) { // Create new node. + node[bytes[i]] = NODE_START - this.decodeTables.length; + this.decodeTables.push(node = UNASSIGNED_NODE.slice(0)); + } + else if (val <= NODE_START) { // Existing node. + node = this.decodeTables[NODE_START - val]; + } + else + throw new Error("Overwrite byte in " + this.options.encodingName + ", addr: " + addr.toString(16)); + } + return node; +} + + +DBCSCodec.prototype._addDecodeChunk = function(chunk) { + // First element of chunk is the hex mbcs code where we start. + var curAddr = parseInt(chunk[0], 16); + + // Choose the decoding node where we'll write our chars. + var writeTable = this._getDecodeTrieNode(curAddr); + curAddr = curAddr & 0xFF; + + // Write all other elements of the chunk to the table. + for (var k = 1; k < chunk.length; k++) { + var part = chunk[k]; + if (typeof part === "string") { // String, write as-is. + for (var l = 0; l < part.length;) { + var code = part.charCodeAt(l++); + if (0xD800 <= code && code < 0xDC00) { // Decode surrogate + var codeTrail = part.charCodeAt(l++); + if (0xDC00 <= codeTrail && codeTrail < 0xE000) + writeTable[curAddr++] = 0x10000 + (code - 0xD800) * 0x400 + (codeTrail - 0xDC00); + else + throw new Error("Incorrect surrogate pair in " + this.options.encodingName + " at chunk " + chunk[0]); + } + else if (0x0FF0 < code && code <= 0x0FFF) { // Character sequence (our own encoding used) + var len = 0xFFF - code + 2; + var seq = []; + for (var m = 0; m < len; m++) + seq.push(part.charCodeAt(l++)); // Simple variation: don't support surrogates or subsequences in seq. + + writeTable[curAddr++] = SEQ_START - this.decodeTableSeq.length; + this.decodeTableSeq.push(seq); + } + else + writeTable[curAddr++] = code; // Basic char + } + } + else if (typeof part === "number") { // Integer, meaning increasing sequence starting with prev character. + var charCode = writeTable[curAddr - 1] + 1; + for (var l = 0; l < part; l++) + writeTable[curAddr++] = charCode++; + } + else + throw new Error("Incorrect type '" + typeof part + "' given in " + this.options.encodingName + " at chunk " + chunk[0]); + } + if (curAddr > 0xFF) + throw new Error("Incorrect chunk in " + this.options.encodingName + " at addr " + chunk[0] + ": too long" + curAddr); +} + +// Encoder helpers +DBCSCodec.prototype._getEncodeBucket = function(uCode) { + var high = uCode >> 8; // This could be > 0xFF because of astral characters. + if (this.encodeTable[high] === undefined) + this.encodeTable[high] = UNASSIGNED_NODE.slice(0); // Create bucket on demand. + return this.encodeTable[high]; +} + +DBCSCodec.prototype._setEncodeChar = function(uCode, dbcsCode) { + var bucket = this._getEncodeBucket(uCode); + var low = uCode & 0xFF; + if (bucket[low] <= SEQ_START) + this.encodeTableSeq[SEQ_START-bucket[low]][DEF_CHAR] = dbcsCode; // There's already a sequence, set a single-char subsequence of it. + else if (bucket[low] == UNASSIGNED) + bucket[low] = dbcsCode; +} + +DBCSCodec.prototype._setEncodeSequence = function(seq, dbcsCode) { + + // Get the root of character tree according to first character of the sequence. + var uCode = seq[0]; + var bucket = this._getEncodeBucket(uCode); + var low = uCode & 0xFF; + + var node; + if (bucket[low] <= SEQ_START) { + // There's already a sequence with - use it. + node = this.encodeTableSeq[SEQ_START-bucket[low]]; + } + else { + // There was no sequence object - allocate a new one. + node = {}; + if (bucket[low] !== UNASSIGNED) node[DEF_CHAR] = bucket[low]; // If a char was set before - make it a single-char subsequence. + bucket[low] = SEQ_START - this.encodeTableSeq.length; + this.encodeTableSeq.push(node); + } + + // Traverse the character tree, allocating new nodes as needed. + for (var j = 1; j < seq.length-1; j++) { + var oldVal = node[uCode]; + if (typeof oldVal === 'object') + node = oldVal; + else { + node = node[uCode] = {} + if (oldVal !== undefined) + node[DEF_CHAR] = oldVal + } + } + + // Set the leaf to given dbcsCode. + uCode = seq[seq.length-1]; + node[uCode] = dbcsCode; +} + +DBCSCodec.prototype._fillEncodeTable = function(nodeIdx, prefix, skipEncodeChars) { + var node = this.decodeTables[nodeIdx]; + for (var i = 0; i < 0x100; i++) { + var uCode = node[i]; + var mbCode = prefix + i; + if (skipEncodeChars[mbCode]) + continue; + + if (uCode >= 0) + this._setEncodeChar(uCode, mbCode); + else if (uCode <= NODE_START) + this._fillEncodeTable(NODE_START - uCode, mbCode << 8, skipEncodeChars); + else if (uCode <= SEQ_START) + this._setEncodeSequence(this.decodeTableSeq[SEQ_START - uCode], mbCode); + } +} + + + +// == Actual Encoding ========================================================== + + +function encoderDBCSWrite(str) { + var newBuf = new Buffer(str.length * (this.gb18030 ? 4 : 3)), + leadSurrogate = this.leadSurrogate, + seqObj = this.seqObj, nextChar = -1, + i = 0, j = 0; + + while (true) { + // 0. Get next character. + if (nextChar === -1) { + if (i == str.length) break; + var uCode = str.charCodeAt(i++); + } + else { + var uCode = nextChar; + nextChar = -1; + } + + // 1. Handle surrogates. + if (0xD800 <= uCode && uCode < 0xE000) { // Char is one of surrogates. + if (uCode < 0xDC00) { // We've got lead surrogate. + if (leadSurrogate === -1) { + leadSurrogate = uCode; + continue; + } else { + leadSurrogate = uCode; + // Double lead surrogate found. + uCode = UNASSIGNED; + } + } else { // We've got trail surrogate. + if (leadSurrogate !== -1) { + uCode = 0x10000 + (leadSurrogate - 0xD800) * 0x400 + (uCode - 0xDC00); + leadSurrogate = -1; + } else { + // Incomplete surrogate pair - only trail surrogate found. + uCode = UNASSIGNED; + } + + } + } + else if (leadSurrogate !== -1) { + // Incomplete surrogate pair - only lead surrogate found. + nextChar = uCode; uCode = UNASSIGNED; // Write an error, then current char. + leadSurrogate = -1; + } + + // 2. Convert uCode character. + var dbcsCode = UNASSIGNED; + if (seqObj !== undefined && uCode != UNASSIGNED) { // We are in the middle of the sequence + var resCode = seqObj[uCode]; + if (typeof resCode === 'object') { // Sequence continues. + seqObj = resCode; + continue; + + } else if (typeof resCode == 'number') { // Sequence finished. Write it. + dbcsCode = resCode; + + } else if (resCode == undefined) { // Current character is not part of the sequence. + + // Try default character for this sequence + resCode = seqObj[DEF_CHAR]; + if (resCode !== undefined) { + dbcsCode = resCode; // Found. Write it. + nextChar = uCode; // Current character will be written too in the next iteration. + + } else { + // TODO: What if we have no default? (resCode == undefined) + // Then, we should write first char of the sequence as-is and try the rest recursively. + // Didn't do it for now because no encoding has this situation yet. + // Currently, just skip the sequence and write current char. + } + } + seqObj = undefined; + } + else if (uCode >= 0) { // Regular character + var subtable = this.encodeTable[uCode >> 8]; + if (subtable !== undefined) + dbcsCode = subtable[uCode & 0xFF]; + + if (dbcsCode <= SEQ_START) { // Sequence start + seqObj = this.encodeTableSeq[SEQ_START-dbcsCode]; + continue; + } + + if (dbcsCode == UNASSIGNED && this.gb18030) { + // Use GB18030 algorithm to find character(s) to write. + var idx = findIdx(this.gb18030.uChars, uCode); + if (idx != -1) { + var dbcsCode = this.gb18030.gbChars[idx] + (uCode - this.gb18030.uChars[idx]); + newBuf[j++] = 0x81 + Math.floor(dbcsCode / 12600); dbcsCode = dbcsCode % 12600; + newBuf[j++] = 0x30 + Math.floor(dbcsCode / 1260); dbcsCode = dbcsCode % 1260; + newBuf[j++] = 0x81 + Math.floor(dbcsCode / 10); dbcsCode = dbcsCode % 10; + newBuf[j++] = 0x30 + dbcsCode; + continue; + } + } + } + + // 3. Write dbcsCode character. + if (dbcsCode === UNASSIGNED) + dbcsCode = this.defaultCharSingleByte; + + if (dbcsCode < 0x100) { + newBuf[j++] = dbcsCode; + } + else if (dbcsCode < 0x10000) { + newBuf[j++] = dbcsCode >> 8; // high byte + newBuf[j++] = dbcsCode & 0xFF; // low byte + } + else { + newBuf[j++] = dbcsCode >> 16; + newBuf[j++] = (dbcsCode >> 8) & 0xFF; + newBuf[j++] = dbcsCode & 0xFF; + } + } + + this.seqObj = seqObj; + this.leadSurrogate = leadSurrogate; + return newBuf.slice(0, j); +} + +function encoderDBCSEnd() { + if (this.leadSurrogate === -1 && this.seqObj === undefined) + return; // All clean. Most often case. + + var newBuf = new Buffer(10), j = 0; + + if (this.seqObj) { // We're in the sequence. + var dbcsCode = this.seqObj[DEF_CHAR]; + if (dbcsCode !== undefined) { // Write beginning of the sequence. + if (dbcsCode < 0x100) { + newBuf[j++] = dbcsCode; + } + else { + newBuf[j++] = dbcsCode >> 8; // high byte + newBuf[j++] = dbcsCode & 0xFF; // low byte + } + } else { + // See todo above. + } + this.seqObj = undefined; + } + + if (this.leadSurrogate !== -1) { + // Incomplete surrogate pair - only lead surrogate found. + newBuf[j++] = this.defaultCharSingleByte; + this.leadSurrogate = -1; + } + + return newBuf.slice(0, j); +} + + +// == Actual Decoding ========================================================== + + +function decoderDBCSWrite(buf) { + var newBuf = new Buffer(buf.length*2), + nodeIdx = this.nodeIdx, + prevBuf = this.prevBuf, prevBufOffset = this.prevBuf.length, + seqStart = -this.prevBuf.length, // idx of the start of current parsed sequence. + uCode; + + if (prevBufOffset > 0) // Make prev buf overlap a little to make it easier to slice later. + prevBuf = Buffer.concat([prevBuf, buf.slice(0, 10)]); + + for (var i = 0, j = 0; i < buf.length; i++) { + var curByte = (i >= 0) ? buf[i] : prevBuf[i + prevBufOffset]; + + // Lookup in current trie node. + var uCode = this.decodeTables[nodeIdx][curByte]; + + if (uCode >= 0) { + // Normal character, just use it. + } + else if (uCode === UNASSIGNED) { // Unknown char. + // TODO: Callback with seq. + //var curSeq = (seqStart >= 0) ? buf.slice(seqStart, i+1) : prevBuf.slice(seqStart + prevBufOffset, i+1 + prevBufOffset); + i = seqStart; // Try to parse again, after skipping first byte of the sequence ('i' will be incremented by 'for' cycle). + uCode = this.defaultCharUnicode.charCodeAt(0); + } + else if (uCode === GB18030_CODE) { + var curSeq = (seqStart >= 0) ? buf.slice(seqStart, i+1) : prevBuf.slice(seqStart + prevBufOffset, i+1 + prevBufOffset); + var ptr = (curSeq[0]-0x81)*12600 + (curSeq[1]-0x30)*1260 + (curSeq[2]-0x81)*10 + (curSeq[3]-0x30); + var idx = findIdx(this.gb18030.gbChars, ptr); + uCode = this.gb18030.uChars[idx] + ptr - this.gb18030.gbChars[idx]; + } + else if (uCode <= NODE_START) { // Go to next trie node. + nodeIdx = NODE_START - uCode; + continue; + } + else if (uCode <= SEQ_START) { // Output a sequence of chars. + var seq = this.decodeTableSeq[SEQ_START - uCode]; + for (var k = 0; k < seq.length - 1; k++) { + uCode = seq[k]; + newBuf[j++] = uCode & 0xFF; + newBuf[j++] = uCode >> 8; + } + uCode = seq[seq.length-1]; + } + else + throw new Error("Unknown table value when decoding: " + val); + + // Write the character to buffer, handling higher planes using surrogate pair. + if (uCode > 0xFFFF) { + uCode -= 0x10000; + var uCodeLead = 0xD800 + Math.floor(uCode / 0x400); + newBuf[j++] = uCodeLead & 0xFF; + newBuf[j++] = uCodeLead >> 8; + + uCode = 0xDC00 + uCode % 0x400; + } + newBuf[j++] = uCode & 0xFF; + newBuf[j++] = uCode >> 8; + + // Reset trie node. + nodeIdx = 0; seqStart = i+1; + } + + this.nodeIdx = nodeIdx; + this.prevBuf = (seqStart >= 0) ? buf.slice(seqStart) : prevBuf.slice(seqStart + prevBufOffset); + return newBuf.slice(0, j).toString('ucs2'); +} + +function decoderDBCSEnd() { + var ret = ''; + + // Try to parse all remaining chars. + while (this.prevBuf.length > 0) { + // Skip 1 character in the buffer. + ret += this.defaultCharUnicode; + var buf = this.prevBuf.slice(1); + + // Parse remaining as usual. + this.prevBuf = new Buffer(0); + this.nodeIdx = 0; + if (buf.length > 0) + ret += decoderDBCSWrite.call(this, buf); + } + + this.nodeIdx = 0; + return ret; +} + +// Binary search for GB18030. Returns largest i such that table[i] <= val. +function findIdx(table, val) { + if (table[0] > val) + return -1; + + var l = 0, r = table.length; + while (l < r-1) { // always table[l] <= val < table[r] + var mid = l + Math.floor((r-l+1)/2); + if (table[mid] <= val) + l = mid; + else + r = mid; + } + return l; +} + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-data.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-data.js new file mode 100644 index 0000000..44be66c --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-data.js @@ -0,0 +1,168 @@ + +// Description of supported double byte encodings and aliases. +// Tables are not require()-d until they are needed to speed up library load. +// require()-s are direct to support Browserify. + +module.exports = { + + // == Japanese/ShiftJIS ==================================================== + // All japanese encodings are based on JIS X set of standards: + // JIS X 0201 - Single-byte encoding of ASCII + ¥ + Kana chars at 0xA1-0xDF. + // JIS X 0208 - Main set of 6879 characters, placed in 94x94 plane, to be encoded by 2 bytes. + // Has several variations in 1978, 1983, 1990 and 1997. + // JIS X 0212 - Supplementary plane of 6067 chars in 94x94 plane. 1990. Effectively dead. + // JIS X 0213 - Extension and modern replacement of 0208 and 0212. Total chars: 11233. + // 2 planes, first is superset of 0208, second - revised 0212. + // Introduced in 2000, revised 2004. Some characters are in Unicode Plane 2 (0x2xxxx) + + // Byte encodings are: + // * Shift_JIS: Compatible with 0201, uses not defined chars in top half as lead bytes for double-byte + // encoding of 0208. Lead byte ranges: 0x81-0x9F, 0xE0-0xEF; Trail byte ranges: 0x40-0x7E, 0x80-0x9E, 0x9F-0xFC. + // Windows CP932 is a superset of Shift_JIS. Some companies added more chars, notably KDDI. + // * EUC-JP: Up to 3 bytes per character. Used mostly on *nixes. + // 0x00-0x7F - lower part of 0201 + // 0x8E, 0xA1-0xDF - upper part of 0201 + // (0xA1-0xFE)x2 - 0208 plane (94x94). + // 0x8F, (0xA1-0xFE)x2 - 0212 plane (94x94). + // * JIS X 208: 7-bit, direct encoding of 0208. Byte ranges: 0x21-0x7E (94 values). Uncommon. + // Used as-is in ISO2022 family. + // * ISO2022-JP: Stateful encoding, with escape sequences to switch between ASCII, + // 0201-1976 Roman, 0208-1978, 0208-1983. + // * ISO2022-JP-1: Adds esc seq for 0212-1990. + // * ISO2022-JP-2: Adds esc seq for GB2313-1980, KSX1001-1992, ISO8859-1, ISO8859-7. + // * ISO2022-JP-3: Adds esc seq for 0201-1976 Kana set, 0213-2000 Planes 1, 2. + // * ISO2022-JP-2004: Adds 0213-2004 Plane 1. + // + // After JIS X 0213 appeared, Shift_JIS-2004, EUC-JISX0213 and ISO2022-JP-2004 followed, with just changing the planes. + // + // Overall, it seems that it's a mess :( http://www8.plala.or.jp/tkubota1/unicode-symbols-map2.html + + + 'shiftjis': { + type: '_dbcs', + table: function() { return require('./tables/shiftjis.json') }, + encodeAdd: {'\u00a5': 0x5C, '\u203E': 0x7E}, + encodeSkipVals: [{from: 0xED40, to: 0xF940}], + }, + 'csshiftjis': 'shiftjis', + 'mskanji': 'shiftjis', + 'sjis': 'shiftjis', + 'windows-31j': 'shiftjis', + 'x-sjis': 'shiftjis', + 'windows932': 'shiftjis', + '932': 'shiftjis', + 'cp932': 'shiftjis', + + 'eucjp': { + type: '_dbcs', + table: function() { return require('./tables/eucjp.json') }, + encodeAdd: {'\u00a5': 0x5C, '\u203E': 0x7E}, + }, + + // TODO: KDDI extension to Shift_JIS + // TODO: IBM CCSID 942 = CP932, but F0-F9 custom chars and other char changes. + // TODO: IBM CCSID 943 = Shift_JIS = CP932 with original Shift_JIS lower 128 chars. + + // == Chinese/GBK ========================================================== + // http://en.wikipedia.org/wiki/GBK + + // Oldest GB2312 (1981, ~7600 chars) is a subset of CP936 + 'gb2312': 'cp936', + 'gb231280': 'cp936', + 'gb23121980': 'cp936', + 'csgb2312': 'cp936', + 'csiso58gb231280': 'cp936', + 'euccn': 'cp936', + 'isoir58': 'gbk', + + // Microsoft's CP936 is a subset and approximation of GBK. + // TODO: Euro = 0x80 in cp936, but not in GBK (where it's valid but undefined) + 'windows936': 'cp936', + '936': 'cp936', + 'cp936': { + type: '_dbcs', + table: function() { return require('./tables/cp936.json') }, + }, + + // GBK (~22000 chars) is an extension of CP936 that added user-mapped chars and some other. + 'gbk': { + type: '_dbcs', + table: function() { return require('./tables/cp936.json').concat(require('./tables/gbk-added.json')) }, + }, + 'xgbk': 'gbk', + + // GB18030 is an algorithmic extension of GBK. + 'gb18030': { + type: '_dbcs', + table: function() { return require('./tables/cp936.json').concat(require('./tables/gbk-added.json')) }, + gb18030: function() { return require('./tables/gb18030-ranges.json') }, + }, + + 'chinese': 'gb18030', + + // TODO: Support GB18030 (~27000 chars + whole unicode mapping, cp54936) + // http://icu-project.org/docs/papers/gb18030.html + // http://source.icu-project.org/repos/icu/data/trunk/charset/data/xml/gb-18030-2000.xml + // http://www.khngai.com/chinese/charmap/tblgbk.php?page=0 + + // == Korean =============================================================== + // EUC-KR, KS_C_5601 and KS X 1001 are exactly the same. + 'windows949': 'cp949', + '949': 'cp949', + 'cp949': { + type: '_dbcs', + table: function() { return require('./tables/cp949.json') }, + }, + + 'cseuckr': 'cp949', + 'csksc56011987': 'cp949', + 'euckr': 'cp949', + 'isoir149': 'cp949', + 'korean': 'cp949', + 'ksc56011987': 'cp949', + 'ksc56011989': 'cp949', + 'ksc5601': 'cp949', + + + // == Big5/Taiwan/Hong Kong ================================================ + // There are lots of tables for Big5 and cp950. Please see the following links for history: + // http://moztw.org/docs/big5/ http://www.haible.de/bruno/charsets/conversion-tables/Big5.html + // Variations, in roughly number of defined chars: + // * Windows CP 950: Microsoft variant of Big5. Canonical: http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT + // * Windows CP 951: Microsoft variant of Big5-HKSCS-2001. Seems to be never public. http://me.abelcheung.org/articles/research/what-is-cp951/ + // * Big5-2003 (Taiwan standard) almost superset of cp950. + // * Unicode-at-on (UAO) / Mozilla 1.8. Falling out of use on the Web. Not supported by other browsers. + // * Big5-HKSCS (-2001, -2004, -2008). Hong Kong standard. + // many unicode code points moved from PUA to Supplementary plane (U+2XXXX) over the years. + // Plus, it has 4 combining sequences. + // Seems that Mozilla refused to support it for 10 yrs. https://bugzilla.mozilla.org/show_bug.cgi?id=162431 https://bugzilla.mozilla.org/show_bug.cgi?id=310299 + // because big5-hkscs is the only encoding to include astral characters in non-algorithmic way. + // Implementations are not consistent within browsers; sometimes labeled as just big5. + // MS Internet Explorer switches from big5 to big5-hkscs when a patch applied. + // Great discussion & recap of what's going on https://bugzilla.mozilla.org/show_bug.cgi?id=912470#c31 + // In the encoder, it might make sense to support encoding old PUA mappings to Big5 bytes seq-s. + // Official spec: http://www.ogcio.gov.hk/en/business/tech_promotion/ccli/terms/doc/2003cmp_2008.txt + // http://www.ogcio.gov.hk/tc/business/tech_promotion/ccli/terms/doc/hkscs-2008-big5-iso.txt + // + // Current understanding of how to deal with Big5(-HKSCS) is in the Encoding Standard, http://encoding.spec.whatwg.org/#big5-encoder + // Unicode mapping (http://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/OTHER/BIG5.TXT) is said to be wrong. + + 'windows950': 'cp950', + '950': 'cp950', + 'cp950': { + type: '_dbcs', + table: function() { return require('./tables/cp950.json') }, + }, + + // Big5 has many variations and is an extension of cp950. We use Encoding Standard's as a consensus. + 'big5': 'big5hkscs', + 'big5hkscs': { + type: '_dbcs', + table: function() { return require('./tables/cp950.json').concat(require('./tables/big5-added.json')) }, + }, + + 'cnbig5': 'big5hkscs', + 'csbig5': 'big5hkscs', + 'xxbig5': 'big5hkscs', + +}; \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/index.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/index.js new file mode 100644 index 0000000..2cda918 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/index.js @@ -0,0 +1,20 @@ + +// Update this array if you add/rename/remove files in this directory. +// We support Browserify by skipping automatic module discovery and requiring modules directly. +var modules = [ + require("./internal"), + require("./utf16"), + require("./utf7"), + require("./sbcs-codec"), + require("./sbcs-data"), + require("./sbcs-data-generated"), + require("./dbcs-codec"), + require("./dbcs-data"), +]; + +// Put all encoding/alias/codec definitions to single object and export it. +for (var i = 0; i < modules.length; i++) { + var module = modules[i]; + for (var enc in module) + exports[enc] = module[enc]; +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/internal.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/internal.js new file mode 100644 index 0000000..396f580 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/internal.js @@ -0,0 +1,81 @@ + +// Export Node.js internal encodings. + +var utf16lebom = new Buffer([0xFF, 0xFE]); + +module.exports = { + // Encodings + utf8: { type: "_internal", enc: "utf8" }, + cesu8: { type: "_internal", enc: "utf8" }, + unicode11utf8: { type: "_internal", enc: "utf8" }, + ucs2: { type: "_internal", enc: "ucs2", bom: utf16lebom }, + utf16le:{ type: "_internal", enc: "ucs2", bom: utf16lebom }, + binary: { type: "_internal", enc: "binary" }, + base64: { type: "_internal", enc: "base64" }, + hex: { type: "_internal", enc: "hex" }, + + // Codec. + _internal: function(options) { + if (!options || !options.enc) + throw new Error("Internal codec is called without encoding type.") + + return { + encoder: options.enc == "base64" ? encoderBase64 : encoderInternal, + decoder: decoderInternal, + + enc: options.enc, + bom: options.bom, + }; + }, +}; + +// We use node.js internal decoder. It's signature is the same as ours. +var StringDecoder = require('string_decoder').StringDecoder; + +if (!StringDecoder.prototype.end) // Node v0.8 doesn't have this method. + StringDecoder.prototype.end = function() {}; + +function decoderInternal() { + return new StringDecoder(this.enc); +} + +// Encoder is mostly trivial + +function encoderInternal() { + return { + write: encodeInternal, + end: function() {}, + + enc: this.enc, + } +} + +function encodeInternal(str) { + return new Buffer(str, this.enc); +} + + +// Except base64 encoder, which must keep its state. + +function encoderBase64() { + return { + write: encodeBase64Write, + end: encodeBase64End, + + prevStr: '', + }; +} + +function encodeBase64Write(str) { + str = this.prevStr + str; + var completeQuads = str.length - (str.length % 4); + this.prevStr = str.slice(completeQuads); + str = str.slice(0, completeQuads); + + return new Buffer(str, "base64"); +} + +function encodeBase64End() { + return new Buffer(this.prevStr, "base64"); +} + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-codec.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-codec.js new file mode 100644 index 0000000..c79defb --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-codec.js @@ -0,0 +1,76 @@ + +// Single-byte codec. Needs a 'chars' string parameter that contains 256 or 128 chars that +// correspond to encoded bytes (if 128 - then lower half is ASCII). + +exports._sbcs = function(options) { + if (!options) + throw new Error("SBCS codec is called without the data.") + + // Prepare char buffer for decoding. + if (!options.chars || (options.chars.length !== 128 && options.chars.length !== 256)) + throw new Error("Encoding '"+options.type+"' has incorrect 'chars' (must be of len 128 or 256)"); + + if (options.chars.length === 128) { + var asciiString = ""; + for (var i = 0; i < 128; i++) + asciiString += String.fromCharCode(i); + options.chars = asciiString + options.chars; + } + + var decodeBuf = new Buffer(options.chars, 'ucs2'); + + // Encoding buffer. + var encodeBuf = new Buffer(65536); + encodeBuf.fill(options.iconv.defaultCharSingleByte.charCodeAt(0)); + + for (var i = 0; i < options.chars.length; i++) + encodeBuf[options.chars.charCodeAt(i)] = i; + + return { + encoder: encoderSBCS, + decoder: decoderSBCS, + + encodeBuf: encodeBuf, + decodeBuf: decodeBuf, + }; +} + +function encoderSBCS(options) { + return { + write: encoderSBCSWrite, + end: function() {}, + + encodeBuf: this.encodeBuf, + }; +} + +function encoderSBCSWrite(str) { + var buf = new Buffer(str.length); + for (var i = 0; i < str.length; i++) + buf[i] = this.encodeBuf[str.charCodeAt(i)]; + + return buf; +} + + +function decoderSBCS(options) { + return { + write: decoderSBCSWrite, + end: function() {}, + + decodeBuf: this.decodeBuf, + }; +} + +function decoderSBCSWrite(buf) { + // Strings are immutable in JS -> we use ucs2 buffer to speed up computations. + var decodeBuf = this.decodeBuf; + var newBuf = new Buffer(buf.length*2); + var idx1 = 0, idx2 = 0; + for (var i = 0, _len = buf.length; i < _len; i++) { + idx1 = buf[i]*2; idx2 = i*2; + newBuf[idx2] = decodeBuf[idx1]; + newBuf[idx2+1] = decodeBuf[idx1+1]; + } + return newBuf.toString('ucs2'); +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data-generated.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data-generated.js new file mode 100644 index 0000000..3808260 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data-generated.js @@ -0,0 +1,450 @@ + +// Generated data for sbcs codec. Don't edit manually. Regenerate using generation/gen-sbcs.js script. +module.exports = { + "437": "cp437", + "737": "cp737", + "775": "cp775", + "850": "cp850", + "852": "cp852", + "855": "cp855", + "856": "cp856", + "857": "cp857", + "858": "cp858", + "860": "cp860", + "861": "cp861", + "862": "cp862", + "863": "cp863", + "864": "cp864", + "865": "cp865", + "866": "cp866", + "869": "cp869", + "874": "windows874", + "922": "cp922", + "1046": "cp1046", + "1124": "cp1124", + "1125": "cp1125", + "1129": "cp1129", + "1133": "cp1133", + "1161": "cp1161", + "1162": "cp1162", + "1163": "cp1163", + "1250": "windows1250", + "1251": "windows1251", + "1252": "windows1252", + "1253": "windows1253", + "1254": "windows1254", + "1255": "windows1255", + "1256": "windows1256", + "1257": "windows1257", + "1258": "windows1258", + "28591": "iso88591", + "28592": "iso88592", + "28593": "iso88593", + "28594": "iso88594", + "28595": "iso88595", + "28596": "iso88596", + "28597": "iso88597", + "28598": "iso88598", + "28599": "iso88599", + "28600": "iso885910", + "28601": "iso885911", + "28603": "iso885913", + "28604": "iso885914", + "28605": "iso885915", + "28606": "iso885916", + "windows874": { + "type": "_sbcs", + "chars": "€����…�����������‘’“”•–—�������� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����" + }, + "win874": "windows874", + "cp874": "windows874", + "windows1250": { + "type": "_sbcs", + "chars": "€�‚�„…†‡�‰Š‹ŚŤŽŹ�‘’“”•–—�™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙" + }, + "win1250": "windows1250", + "cp1250": "windows1250", + "windows1251": { + "type": "_sbcs", + "chars": "ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—�™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя" + }, + "win1251": "windows1251", + "cp1251": "windows1251", + "windows1252": { + "type": "_sbcs", + "chars": "€�‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "win1252": "windows1252", + "cp1252": "windows1252", + "windows1253": { + "type": "_sbcs", + "chars": "€�‚ƒ„…†‡�‰�‹�����‘’“”•–—�™�›���� ΅Ά£¤¥¦§¨©�«¬­®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�" + }, + "win1253": "windows1253", + "cp1253": "windows1253", + "windows1254": { + "type": "_sbcs", + "chars": "€�‚ƒ„…†‡ˆ‰Š‹Œ����‘’“”•–—˜™š›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ" + }, + "win1254": "windows1254", + "cp1254": "windows1254", + "windows1255": { + "type": "_sbcs", + "chars": "€�‚ƒ„…†‡ˆ‰�‹�����‘’“”•–—˜™�›���� ¡¢£₪¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾¿ְֱֲֳִֵֶַָֹ�ֻּֽ־ֿ׀ׁׂ׃װױײ׳״�������אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�" + }, + "win1255": "windows1255", + "cp1255": "windows1255", + "windows1256": { + "type": "_sbcs", + "chars": "€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œ‌‍ں ،¢£¤¥¦§¨©ھ«¬­®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîïًٌٍَôُِ÷ّùْûü‎‏ے" + }, + "win1256": "windows1256", + "cp1256": "windows1256", + "windows1257": { + "type": "_sbcs", + "chars": "€�‚�„…†‡�‰�‹�¨ˇ¸�‘’“”•–—�™�›�¯˛� �¢£¤�¦§Ø©Ŗ«¬­®Æ°±²³´µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž˙" + }, + "win1257": "windows1257", + "cp1257": "windows1257", + "windows1258": { + "type": "_sbcs", + "chars": "€�‚ƒ„…†‡ˆ‰�‹Œ����‘’“”•–—˜™�›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖרÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ" + }, + "win1258": "windows1258", + "cp1258": "windows1258", + "iso88591": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "cp28591": "iso88591", + "iso88592": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ą˘Ł¤ĽŚ§¨ŠŞŤŹ­ŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙" + }, + "cp28592": "iso88592", + "iso88593": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ħ˘£¤�Ĥ§¨İŞĞĴ­�ݰħ²³´µĥ·¸ışğĵ½�żÀÁÂ�ÄĊĈÇÈÉÊËÌÍÎÏ�ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ�äċĉçèéêëìíîï�ñòóôġö÷ĝùúûüŭŝ˙" + }, + "cp28593": "iso88593", + "iso88594": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĸŖ¤Ĩϧ¨ŠĒĢŦ­Ž¯°ą˛ŗ´ĩšēģŧŊžŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖרŲÚÛÜŨŪßāáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙" + }, + "cp28594": "iso88594", + "iso88595": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂЃЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ" + }, + "cp28595": "iso88595", + "iso88596": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ���¤�������،­�������������؛���؟�ءآأؤإئابةتثجحخدذرزسشصضطظعغ�����ـفقكلمنهوىيًٌٍَُِّْ�������������" + }, + "cp28596": "iso88596", + "iso88597": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­�―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�" + }, + "cp28597": "iso88597", + "iso88598": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �¢£¤¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾��������������������������������‗אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�" + }, + "cp28598": "iso88598", + "iso88599": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ" + }, + "cp28599": "iso88599", + "iso885910": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĒĢĪĨͧĻĐŠŦŽ­ŪŊ°ąēģīĩķ·ļđšŧž―ūŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞßāáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ" + }, + "cp28600": "iso885910", + "iso885911": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����" + }, + "cp28601": "iso885911", + "iso885913": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’" + }, + "cp28603": "iso885913", + "iso885914": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ­®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶßàáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ" + }, + "cp28604": "iso885914", + "iso885915": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥Š§š©ª«¬­®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "cp28605": "iso885915", + "iso885916": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄąŁ€„Чš©Ș«Ź­źŻ°±ČłŽ”¶·žčș»ŒœŸżÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚßàáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ" + }, + "cp28606": "iso885916", + "cp437": { + "type": "_sbcs", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm437": "cp437", + "csibm437": "cp437", + "cp737": { + "type": "_sbcs", + "chars": "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρσςτυφχψ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ωάέήϊίόύϋώΆΈΉΊΌΎΏ±≥≤ΪΫ÷≈°∙·√ⁿ²■ " + }, + "ibm737": "cp737", + "csibm737": "cp737", + "cp775": { + "type": "_sbcs", + "chars": "ĆüéāäģåćłēŖŗīŹÄÅÉæÆōöĢ¢ŚśÖÜø£Ø×¤ĀĪóŻżź”¦©®¬½¼Ł«»░▒▓│┤ĄČĘĖ╣║╗╝ĮŠ┐└┴┬├─┼ŲŪ╚╔╩╦╠═╬Žąčęėįšųūž┘┌█▄▌▐▀ÓßŌŃõÕµńĶķĻļņĒŅ’­±“¾¶§÷„°∙·¹³²■ " + }, + "ibm775": "cp775", + "csibm775": "cp775", + "cp850": { + "type": "_sbcs", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø×ƒáíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈıÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ " + }, + "ibm850": "cp850", + "csibm850": "cp850", + "cp852": { + "type": "_sbcs", + "chars": "ÇüéâäůćçłëŐőîŹÄĆÉĹĺôöĽľŚśÖÜŤťŁ×čáíóúĄąŽžĘ꬟Ⱥ«»░▒▓│┤ÁÂĚŞ╣║╗╝Żż┐└┴┬├─┼Ăă╚╔╩╦╠═╬¤đĐĎËďŇÍÎě┘┌█▄ŢŮ▀ÓßÔŃńňŠšŔÚŕŰýÝţ´­˝˛ˇ˘§÷¸°¨˙űŘř■ " + }, + "ibm852": "cp852", + "csibm852": "cp852", + "cp855": { + "type": "_sbcs", + "chars": "ђЂѓЃёЁєЄѕЅіІїЇјЈљЉњЊћЋќЌўЎџЏюЮъЪаАбБцЦдДеЕфФгГ«»░▒▓│┤хХиИ╣║╗╝йЙ┐└┴┬├─┼кК╚╔╩╦╠═╬¤лЛмМнНоОп┘┌█▄Пя▀ЯрРсСтТуУжЖвВьЬ№­ыЫзЗшШэЭщЩчЧ§■ " + }, + "ibm855": "cp855", + "csibm855": "cp855", + "cp856": { + "type": "_sbcs", + "chars": "אבגדהוזחטיךכלםמןנסעףפץצקרשת�£�×����������®¬½¼�«»░▒▓│┤���©╣║╗╝¢¥┐└┴┬├─┼��╚╔╩╦╠═╬¤���������┘┌█▄¦�▀������µ�������¯´­±‗¾¶§÷¸°¨·¹³²■ " + }, + "ibm856": "cp856", + "csibm856": "cp856", + "cp857": { + "type": "_sbcs", + "chars": "ÇüéâäàåçêëèïîıÄÅÉæÆôöòûùİÖÜø£ØŞşáíóúñÑĞ𿮬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ºªÊËÈ�ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµ�×ÚÛÙìÿ¯´­±�¾¶§÷¸°¨·¹³²■ " + }, + "ibm857": "cp857", + "csibm857": "cp857", + "cp858": { + "type": "_sbcs", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø×ƒáíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈ€ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ " + }, + "ibm858": "cp858", + "csibm858": "cp858", + "cp860": { + "type": "_sbcs", + "chars": "ÇüéâãàÁçêÊèÍÔìÃÂÉÀÈôõòÚùÌÕÜ¢£Ù₧ÓáíóúñѪº¿Ò¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm860": "cp860", + "csibm860": "cp860", + "cp861": { + "type": "_sbcs", + "chars": "ÇüéâäàåçêëèÐðÞÄÅÉæÆôöþûÝýÖÜø£Ø₧ƒáíóúÁÍÓÚ¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm861": "cp861", + "csibm861": "cp861", + "cp862": { + "type": "_sbcs", + "chars": "אבגדהוזחטיךכלםמןנסעףפץצקרשת¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm862": "cp862", + "csibm862": "cp862", + "cp863": { + "type": "_sbcs", + "chars": "ÇüéâÂà¶çêëèïî‗À§ÉÈÊôËÏûù¤ÔÜ¢£ÙÛƒ¦´óú¨¸³¯Î⌐¬½¼¾«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm863": "cp863", + "csibm863": "cp863", + "cp864": { + "type": "_sbcs", + "chars": "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$٪&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~°·∙√▒─│┼┤┬├┴┐┌└┘β∞φ±½¼≈«»ﻷﻸ��ﻻﻼ� ­ﺂ£¤ﺄ��ﺎﺏﺕﺙ،ﺝﺡﺥ٠١٢٣٤٥٦٧٨٩ﻑ؛ﺱﺵﺹ؟¢ﺀﺁﺃﺅﻊﺋﺍﺑﺓﺗﺛﺟﺣﺧﺩﺫﺭﺯﺳﺷﺻﺿﻁﻅﻋﻏ¦¬÷×ﻉـﻓﻗﻛﻟﻣﻧﻫﻭﻯﻳﺽﻌﻎﻍﻡﹽّﻥﻩﻬﻰﻲﻐﻕﻵﻶﻝﻙﻱ■�" + }, + "ibm864": "cp864", + "csibm864": "cp864", + "cp865": { + "type": "_sbcs", + "chars": "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø₧ƒáíóúñѪº¿⌐¬½¼¡«¤░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " + }, + "ibm865": "cp865", + "csibm865": "cp865", + "cp866": { + "type": "_sbcs", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ " + }, + "ibm866": "cp866", + "csibm866": "cp866", + "cp869": { + "type": "_sbcs", + "chars": "������Ά�·¬¦‘’Έ―ΉΊΪΌ��ΎΫ©Ώ²³ά£έήίϊΐόύΑΒΓΔΕΖΗ½ΘΙ«»░▒▓│┤ΚΛΜΝ╣║╗╝ΞΟ┐└┴┬├─┼ΠΡ╚╔╩╦╠═╬ΣΤΥΦΧΨΩαβγ┘┌█▄δε▀ζηθικλμνξοπρσςτ΄­±υφχ§ψ΅°¨ωϋΰώ■ " + }, + "ibm869": "cp869", + "csibm869": "cp869", + "cp922": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®‾°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŠÑÒÓÔÕÖרÙÚÛÜÝŽßàáâãäåæçèéêëìíîïšñòóôõö÷øùúûüýžÿ" + }, + "ibm922": "cp922", + "csibm922": "cp922", + "cp1046": { + "type": "_sbcs", + "chars": "ﺈ×÷ﹱˆ■│─┐┌└┘ﹹﹻﹽﹿﹷﺊﻰﻳﻲﻎﻏﻐﻶﻸﻺﻼ ¤ﺋﺑﺗﺛﺟﺣ،­ﺧﺳ٠١٢٣٤٥٦٧٨٩ﺷ؛ﺻﺿﻊ؟ﻋءآأؤإئابةتثجحخدذرزسشصضطﻇعغﻌﺂﺄﺎﻓـفقكلمنهوىيًٌٍَُِّْﻗﻛﻟﻵﻷﻹﻻﻣﻧﻬﻩ�" + }, + "ibm1046": "cp1046", + "csibm1046": "cp1046", + "cp1124": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂҐЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђґєѕіїјљњћќ§ўџ" + }, + "ibm1124": "cp1124", + "csibm1124": "cp1124", + "cp1125": { + "type": "_sbcs", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёҐґЄєІіЇї·√№¤■ " + }, + "ibm1125": "cp1125", + "csibm1125": "cp1125", + "cp1129": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§œ©ª«¬­®¯°±²³Ÿµ¶·Œ¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖרÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ" + }, + "ibm1129": "cp1129", + "csibm1129": "cp1129", + "cp1133": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ກຂຄງຈສຊຍດຕຖທນບປຜຝພຟມຢຣລວຫອຮ���ຯະາຳິີຶືຸູຼັົຽ���ເແໂໃໄ່້໊໋໌ໍໆ�ໜໝ₭����������������໐໑໒໓໔໕໖໗໘໙��¢¬¦�" + }, + "ibm1133": "cp1133", + "csibm1133": "cp1133", + "cp1161": { + "type": "_sbcs", + "chars": "��������������������������������่กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู้๊๋€฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛¢¬¦ " + }, + "ibm1161": "cp1161", + "csibm1161": "cp1161", + "cp1162": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����" + }, + "ibm1162": "cp1162", + "csibm1162": "cp1162", + "cp1163": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥¦§œ©ª«¬­®¯°±²³Ÿµ¶·Œ¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖרÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ" + }, + "ibm1163": "cp1163", + "csibm1163": "cp1163", + "maccroatian": { + "type": "_sbcs", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈ƫȅ ÀÃÕŒœĐ—“”‘’÷◊�©⁄¤‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ" + }, + "maccyrillic": { + "type": "_sbcs", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°¢£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµ∂ЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤" + }, + "macgreek": { + "type": "_sbcs", + "chars": "Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦­ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ�" + }, + "maciceland": { + "type": "_sbcs", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüݰ¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macroman": { + "type": "_sbcs", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macromania": { + "type": "_sbcs", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂŞ∞±≤≥¥µ∂∑∏π∫ªºΩăş¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›Ţţ‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macthai": { + "type": "_sbcs", + "chars": "«»…“”�•‘’� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู​–—฿เแโใไๅๆ็่้๊๋์ํ™๏๐๑๒๓๔๕๖๗๘๙®©����" + }, + "macturkish": { + "type": "_sbcs", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙ�ˆ˜¯˘˙˚¸˝˛ˇ" + }, + "macukraine": { + "type": "_sbcs", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤" + }, + "koi8r": { + "type": "_sbcs", + "chars": "─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ" + }, + "koi8u": { + "type": "_sbcs", + "chars": "─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґ╝╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪Ґ╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ" + }, + "koi8ru": { + "type": "_sbcs", + "chars": "─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ" + }, + "koi8t": { + "type": "_sbcs", + "chars": "қғ‚Ғ„…†‡�‰ҳ‹ҲҷҶ�Қ‘’“”•–—�™�›�����ӯӮё¤ӣ¦§���«¬­®�°±²Ё�Ӣ¶·�№�»���©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ" + }, + "armscii8": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �և։)(»«—.՝,-֊…՜՛՞ԱաԲբԳգԴդԵեԶզԷէԸըԹթԺժԻիԼլԽխԾծԿկՀհՁձՂղՃճՄմՅյՆնՇշՈոՉչՊպՋջՌռՍսՎվՏտՐրՑցՒւՓփՔքՕօՖֆ՚�" + }, + "rk1048": { + "type": "_sbcs", + "chars": "ЂЃ‚ѓ„…†‡€‰Љ‹ЊҚҺЏђ‘’“”•–—�™љ›њқһџ ҰұӘ¤Ө¦§Ё©Ғ«¬­®Ү°±Ііөµ¶·ё№ғ»әҢңүАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя" + }, + "tcvn": { + "type": "_sbcs", + "chars": "\u0000ÚỤ\u0003ỪỬỮ\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010ỨỰỲỶỸÝỴ\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÀẢÃÁẠẶẬÈẺẼÉẸỆÌỈĨÍỊÒỎÕÓỌỘỜỞỠỚỢÙỦŨ ĂÂÊÔƠƯĐăâêôơưđẶ̀̀̉̃́àảãáạẲằẳẵắẴẮẦẨẪẤỀặầẩẫấậèỂẻẽéẹềểễếệìỉỄẾỒĩíịòỔỏõóọồổỗốộờởỡớợùỖủũúụừửữứựỳỷỹýỵỐ" + }, + "georgianacademy": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰჱჲჳჴჵჶçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "georgianps": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზჱთიკლმნჲოპჟრსტჳუფქღყშჩცძწჭხჴჯჰჵæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" + }, + "pt154": { + "type": "_sbcs", + "chars": "ҖҒӮғ„…ҶҮҲүҠӢҢҚҺҸҗ‘’“”•–—ҳҷҡӣңқһҹ ЎўЈӨҘҰ§Ё©Ә«¬ӯ®Ҝ°ұІіҙө¶·ё№ә»јҪҫҝАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя" + }, + "viscii": { + "type": "_sbcs", + "chars": "\u0000\u0001Ẳ\u0003\u0004ẴẪ\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013Ỷ\u0015\u0016\u0017\u0018Ỹ\u001a\u001b\u001c\u001dỴ\u001f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ẠẮẰẶẤẦẨẬẼẸẾỀỂỄỆỐỒỔỖỘỢỚỜỞỊỎỌỈỦŨỤỲÕắằặấầẩậẽẹếềểễệốồổỗỠƠộờởịỰỨỪỬơớƯÀÁÂÃẢĂẳẵÈÉÊẺÌÍĨỳĐứÒÓÔạỷừửÙÚỹỵÝỡưàáâãảăữẫèéêẻìíĩỉđựòóôõỏọụùúũủýợỮ" + }, + "iso646cn": { + "type": "_sbcs", + "chars": "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#¥%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}‾��������������������������������������������������������������������������������������������������������������������������������" + }, + "iso646jp": { + "type": "_sbcs", + "chars": "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_`abcdefghijklmnopqrstuvwxyz{|}‾��������������������������������������������������������������������������������������������������������������������������������" + }, + "hproman8": { + "type": "_sbcs", + "chars": "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ÀÂÈÊËÎÏ´ˋˆ¨˜ÙÛ₤¯Ýý°ÇçÑñ¡¿¤£¥§ƒ¢âêôûáéóúàèòùäëöüÅîØÆåíøæÄìÖÜÉïßÔÁÃãÐðÍÌÓÒÕõŠšÚŸÿÞþ·µ¶¾—¼½ªº«■»±�" + }, + "macintosh": { + "type": "_sbcs", + "chars": "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ" + }, + "ascii": { + "type": "_sbcs", + "chars": "��������������������������������������������������������������������������������������������������������������������������������" + }, + "tis620": { + "type": "_sbcs", + "chars": "���������������������������������กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����" + } +} \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data.js new file mode 100644 index 0000000..74fb34b --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data.js @@ -0,0 +1,168 @@ + +// Manually added data to be used by sbcs codec in addition to generated one. + +module.exports = { + // Not supported by iconv, not sure why. + "10029": "maccenteuro", + "maccenteuro": { + "type": "_sbcs", + "chars": "ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ" + }, + + "808": "cp808", + "ibm808": "cp808", + "cp808": { + "type": "_sbcs", + "chars": "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№€■ " + }, + + // Aliases of generated encodings. + "ascii8bit": "ascii", + "usascii": "ascii", + "ansix3.4": "ascii", + "ansix3.41968": "ascii", + "ansix3.41986": "ascii", + "csascii": "ascii", + "cp367": "ascii", + "ibm367": "ascii", + "isoir6": "ascii", + "iso646us": "ascii", + "iso646.irv": "ascii", + "us": "ascii", + + "latin1": "iso88591", + "latin2": "iso88592", + "latin3": "iso88593", + "latin4": "iso88594", + "latin5": "iso88599", + "latin6": "iso885910", + "latin7": "iso885913", + "latin8": "iso885914", + "latin9": "iso885915", + "latin10": "iso885916", + + "csisolatin1": "iso88591", + "csisolatin2": "iso88592", + "csisolatin3": "iso88593", + "csisolatin4": "iso88594", + "csisolatincyrillic": "iso88595", + "csisolatinarabic": "iso88596", + "csisolatingreek" : "iso88597", + "csisolatinhebrew": "iso88598", + "csisolatin5": "iso88599", + "csisolatin6": "iso885910", + + "l1": "iso88591", + "l2": "iso88592", + "l3": "iso88593", + "l4": "iso88594", + "l5": "iso88599", + "l6": "iso885910", + "l7": "iso885913", + "l8": "iso885914", + "l9": "iso885915", + "l10": "iso885916", + + "isoir14": "iso646jp", + "isoir57": "iso646cn", + "isoir100": "iso88591", + "isoir101": "iso88592", + "isoir109": "iso88593", + "isoir110": "iso88594", + "isoir144": "iso88595", + "isoir127": "iso88596", + "isoir126": "iso88597", + "isoir138": "iso88598", + "isoir148": "iso88599", + "isoir157": "iso885910", + "isoir166": "tis620", + "isoir179": "iso885913", + "isoir199": "iso885914", + "isoir203": "iso885915", + "isoir226": "iso885916", + + "cp819": "iso88591", + "ibm819": "iso88591", + + "cyrillic": "iso88595", + + "arabic": "iso88596", + "arabic8": "iso88596", + "ecma114": "iso88596", + "asmo708": "iso88596", + + "greek" : "iso88597", + "greek8" : "iso88597", + "ecma118" : "iso88597", + "elot928" : "iso88597", + + "hebrew": "iso88598", + "hebrew8": "iso88598", + + "turkish": "iso88599", + "turkish8": "iso88599", + + "thai": "iso885911", + "thai8": "iso885911", + + "celtic": "iso885914", + "celtic8": "iso885914", + "isoceltic": "iso885914", + + "tis6200": "tis620", + "tis620.25291": "tis620", + "tis620.25330": "tis620", + + "10000": "macroman", + "10006": "macgreek", + "10007": "maccyrillic", + "10079": "maciceland", + "10081": "macturkish", + + "cspc8codepage437": "cp437", + "cspc775baltic": "cp775", + "cspc850multilingual": "cp850", + "cspcp852": "cp852", + "cspc862latinhebrew": "cp862", + "cpgr": "cp869", + + "msee": "cp1250", + "mscyrl": "cp1251", + "msansi": "cp1252", + "msgreek": "cp1253", + "msturk": "cp1254", + "mshebr": "cp1255", + "msarab": "cp1256", + "winbaltrim": "cp1257", + + "cp20866": "koi8r", + "20866": "koi8r", + "ibm878": "koi8r", + "cskoi8r": "koi8r", + + "cp21866": "koi8u", + "21866": "koi8u", + "ibm1168": "koi8u", + + "strk10482002": "rk1048", + + "tcvn5712": "tcvn", + "tcvn57121": "tcvn", + + "gb198880": "iso646cn", + "cn": "iso646cn", + + "csiso14jisc6220ro": "iso646jp", + "jisc62201969ro": "iso646jp", + "jp": "iso646jp", + + "cshproman8": "hproman8", + "r8": "hproman8", + "roman8": "hproman8", + "xroman8": "hproman8", + "ibm1051": "hproman8", + + "mac": "macintosh", + "csmacintosh": "macintosh", +}; + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/big5-added.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/big5-added.json new file mode 100644 index 0000000..3c3d3c2 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/big5-added.json @@ -0,0 +1,122 @@ +[ +["8740","䏰䰲䘃䖦䕸𧉧䵷䖳𧲱䳢𧳅㮕䜶䝄䱇䱀𤊿𣘗𧍒𦺋𧃒䱗𪍑䝏䗚䲅𧱬䴇䪤䚡𦬣爥𥩔𡩣𣸆𣽡晍囻"], +["8767","綕夝𨮹㷴霴𧯯寛𡵞媤㘥𩺰嫑宷峼杮薓𩥅瑡璝㡵𡵓𣚞𦀡㻬"], +["87a1","𥣞㫵竼龗𤅡𨤍𣇪𠪊𣉞䌊蒄龖鐯䤰蘓墖靊鈘秐稲晠権袝瑌篅枂稬剏遆㓦珄𥶹瓆鿇垳䤯呌䄱𣚎堘穲𧭥讏䚮𦺈䆁𥶙箮𢒼鿈𢓁𢓉𢓌鿉蔄𣖻䂴鿊䓡𪷿拁灮鿋"], +["8840","㇀",4,"𠄌㇅𠃑𠃍㇆㇇𠃋𡿨㇈𠃊㇉㇊㇋㇌𠄎㇍㇎ĀÁǍÀĒÉĚÈŌÓǑÒ࿿Ê̄Ế࿿Ê̌ỀÊāáǎàɑēéěèīíǐìōóǒòūúǔùǖǘǚ"], +["88a1","ǜü࿿ê̄ế࿿ê̌ềêɡ⏚⏛"], +["8940","𪎩𡅅"], +["8943","攊"], +["8946","丽滝鵎釟"], +["894c","𧜵撑会伨侨兖兴农凤务动医华发变团声处备夲头学实実岚庆总斉柾栄桥济炼电纤纬纺织经统缆缷艺苏药视设询车轧轮"], +["89a1","琑糼緍楆竉刧"], +["89ab","醌碸酞肼"], +["89b0","贋胶𠧧"], +["89b5","肟黇䳍鷉鸌䰾𩷶𧀎鸊𪄳㗁"], +["89c1","溚舾甙"], +["89c5","䤑马骏龙禇𨑬𡷊𠗐𢫦两亁亀亇亿仫伷㑌侽㹈倃傈㑽㒓㒥円夅凛凼刅争剹劐匧㗇厩㕑厰㕓参吣㕭㕲㚁咓咣咴咹哐哯唘唣唨㖘唿㖥㖿嗗㗅"], +["8a40","𧶄唥"], +["8a43","𠱂𠴕𥄫喐𢳆㧬𠍁蹆𤶸𩓥䁓𨂾睺𢰸㨴䟕𨅝𦧲𤷪擝𠵼𠾴𠳕𡃴撍蹾𠺖𠰋𠽤𢲩𨉖𤓓"], +["8a64","𠵆𩩍𨃩䟴𤺧𢳂骲㩧𩗴㿭㔆𥋇𩟔𧣈𢵄鵮頕"], +["8a76","䏙𦂥撴哣𢵌𢯊𡁷㧻𡁯"], +["8aa1","𦛚𦜖𧦠擪𥁒𠱃蹨𢆡𨭌𠜱"], +["8aac","䠋𠆩㿺塳𢶍"], +["8ab2","𤗈𠓼𦂗𠽌𠶖啹䂻䎺"], +["8abb","䪴𢩦𡂝膪飵𠶜捹㧾𢝵跀嚡摼㹃"], +["8ac9","𪘁𠸉𢫏𢳉"], +["8ace","𡃈𣧂㦒㨆𨊛㕸𥹉𢃇噒𠼱𢲲𩜠㒼氽𤸻"], +["8adf","𧕴𢺋𢈈𪙛𨳍𠹺𠰴𦠜羓𡃏𢠃𢤹㗻𥇣𠺌𠾍𠺪㾓𠼰𠵇𡅏𠹌"], +["8af6","𠺫𠮩𠵈𡃀𡄽㿹𢚖搲𠾭"], +["8b40","𣏴𧘹𢯎𠵾𠵿𢱑𢱕㨘𠺘𡃇𠼮𪘲𦭐𨳒𨶙𨳊閪哌苄喹"], +["8b55","𩻃鰦骶𧝞𢷮煀腭胬尜𦕲脴㞗卟𨂽醶𠻺𠸏𠹷𠻻㗝𤷫㘉𠳖嚯𢞵𡃉𠸐𠹸𡁸𡅈𨈇𡑕𠹹𤹐𢶤婔𡀝𡀞𡃵𡃶垜𠸑"], +["8ba1","𧚔𨋍𠾵𠹻𥅾㜃𠾶𡆀𥋘𪊽𤧚𡠺𤅷𨉼墙剨㘚𥜽箲孨䠀䬬鼧䧧鰟鮍𥭴𣄽嗻㗲嚉丨夂𡯁屮靑𠂆乛亻㔾尣彑忄㣺扌攵歺氵氺灬爫丬犭𤣩罒礻糹罓𦉪㓁"], +["8bde","𦍋耂肀𦘒𦥑卝衤见𧢲讠贝钅镸长门𨸏韦页风飞饣𩠐鱼鸟黄歯龜丷𠂇阝户钢"], +["8c40","倻淾𩱳龦㷉袏𤅎灷峵䬠𥇍㕙𥴰愢𨨲辧釶熑朙玺𣊁𪄇㲋𡦀䬐磤琂冮𨜏䀉橣𪊺䈣蘏𠩯稪𩥇𨫪靕灍匤𢁾鏴盙𨧣龧矝亣俰傼丯众龨吴綋墒壐𡶶庒庙忂𢜒斋"], +["8ca1","𣏹椙橃𣱣泿"], +["8ca7","爀𤔅玌㻛𤨓嬕璹讃𥲤𥚕窓篬糃繬苸薗龩袐龪躹龫迏蕟駠鈡龬𨶹𡐿䁱䊢娚"], +["8cc9","顨杫䉶圽"], +["8cce","藖𤥻芿𧄍䲁𦵴嵻𦬕𦾾龭龮宖龯曧繛湗秊㶈䓃𣉖𢞖䎚䔶"], +["8ce6","峕𣬚諹屸㴒𣕑嵸龲煗䕘𤃬𡸣䱷㥸㑊𠆤𦱁諌侴𠈹妿腬顖𩣺弻"], +["8d40","𠮟"], +["8d42","𢇁𨥭䄂䚻𩁹㼇龳𪆵䃸㟖䛷𦱆䅼𨚲𧏿䕭㣔𥒚䕡䔛䶉䱻䵶䗪㿈𤬏㙡䓞䒽䇭崾嵈嵖㷼㠏嶤嶹㠠㠸幂庽弥徃㤈㤔㤿㥍惗愽峥㦉憷憹懏㦸戬抐拥挘㧸嚱"], +["8da1","㨃揢揻搇摚㩋擀崕嘡龟㪗斆㪽旿晓㫲暒㬢朖㭂枤栀㭘桊梄㭲㭱㭻椉楃牜楤榟榅㮼槖㯝橥橴橱檂㯬檙㯲檫檵櫔櫶殁毁毪汵沪㳋洂洆洦涁㳯涤涱渕渘温溆𨧀溻滢滚齿滨滩漤漴㵆𣽁澁澾㵪㵵熷岙㶊瀬㶑灐灔灯灿炉𠌥䏁㗱𠻘"], +["8e40","𣻗垾𦻓焾𥟠㙎榢𨯩孴穉𥣡𩓙穥穽𥦬窻窰竂竃燑𦒍䇊竚竝竪䇯咲𥰁笋筕笩𥌎𥳾箢筯莜𥮴𦱿篐萡箒箸𥴠㶭𥱥蒒篺簆簵𥳁籄粃𤢂粦晽𤕸糉糇糦籴糳糵糎"], +["8ea1","繧䔝𦹄絝𦻖璍綉綫焵綳緒𤁗𦀩緤㴓緵𡟹緥𨍭縝𦄡𦅚繮纒䌫鑬縧罀罁罇礶𦋐駡羗𦍑羣𡙡𠁨䕜𣝦䔃𨌺翺𦒉者耈耝耨耯𪂇𦳃耻耼聡𢜔䦉𦘦𣷣𦛨朥肧𨩈脇脚墰𢛶汿𦒘𤾸擧𡒊舘𡡞橓𤩥𤪕䑺舩𠬍𦩒𣵾俹𡓽蓢荢𦬊𤦧𣔰𡝳𣷸芪椛芳䇛"], +["8f40","蕋苐茚𠸖𡞴㛁𣅽𣕚艻苢茘𣺋𦶣𦬅𦮗𣗎㶿茝嗬莅䔋𦶥莬菁菓㑾𦻔橗蕚㒖𦹂𢻯葘𥯤葱㷓䓤檧葊𣲵祘蒨𦮖𦹷𦹃蓞萏莑䒠蒓蓤𥲑䉀𥳀䕃蔴嫲𦺙䔧蕳䔖枿蘖"], +["8fa1","𨘥𨘻藁𧂈蘂𡖂𧃍䕫䕪蘨㙈𡢢号𧎚虾蝱𪃸蟮𢰧螱蟚蠏噡虬桖䘏衅衆𧗠𣶹𧗤衞袜䙛袴袵揁装睷𧜏覇覊覦覩覧覼𨨥觧𧤤𧪽誜瞓釾誐𧩙竩𧬺𣾏䜓𧬸煼謌謟𥐰𥕥謿譌譍誩𤩺讐讛誯𡛟䘕衏貛𧵔𧶏貫㜥𧵓賖𧶘𧶽贒贃𡤐賛灜贑𤳉㻐起"], +["9040","趩𨀂𡀔𤦊㭼𨆼𧄌竧躭躶軃鋔輙輭𨍥𨐒辥錃𪊟𠩐辳䤪𨧞𨔽𣶻廸𣉢迹𪀔𨚼𨔁𢌥㦀𦻗逷𨔼𧪾遡𨕬𨘋邨𨜓郄𨛦邮都酧㫰醩釄粬𨤳𡺉鈎沟鉁鉢𥖹銹𨫆𣲛𨬌𥗛"], +["90a1","𠴱錬鍫𨫡𨯫炏嫃𨫢𨫥䥥鉄𨯬𨰹𨯿鍳鑛躼閅閦鐦閠濶䊹𢙺𨛘𡉼𣸮䧟氜陻隖䅬隣𦻕懚隶磵𨫠隽双䦡𦲸𠉴𦐐𩂯𩃥𤫑𡤕𣌊霱虂霶䨏䔽䖅𤫩灵孁霛靜𩇕靗孊𩇫靟鐥僐𣂷𣂼鞉鞟鞱鞾韀韒韠𥑬韮琜𩐳響韵𩐝𧥺䫑頴頳顋顦㬎𧅵㵑𠘰𤅜"], +["9140","𥜆飊颷飈飇䫿𦴧𡛓喰飡飦飬鍸餹𤨩䭲𩡗𩤅駵騌騻騐驘𥜥㛄𩂱𩯕髠髢𩬅髴䰎鬔鬭𨘀倴鬴𦦨㣃𣁽魐魀𩴾婅𡡣鮎𤉋鰂鯿鰌𩹨鷔𩾷𪆒𪆫𪃡𪄣𪇟鵾鶃𪄴鸎梈"], +["91a1","鷄𢅛𪆓𪈠𡤻𪈳鴹𪂹𪊴麐麕麞麢䴴麪麯𤍤黁㭠㧥㴝伲㞾𨰫鼂鼈䮖鐤𦶢鼗鼖鼹嚟嚊齅馸𩂋韲葿齢齩竜龎爖䮾𤥵𤦻煷𤧸𤍈𤩑玞𨯚𡣺禟𨥾𨸶鍩鏳𨩄鋬鎁鏋𨥬𤒹爗㻫睲穃烐𤑳𤏸煾𡟯炣𡢾𣖙㻇𡢅𥐯𡟸㜢𡛻𡠹㛡𡝴𡣑𥽋㜣𡛀坛𤨥𡏾𡊨"], +["9240","𡏆𡒶蔃𣚦蔃葕𤦔𧅥𣸱𥕜𣻻𧁒䓴𣛮𩦝𦼦柹㜳㰕㷧塬𡤢栐䁗𣜿𤃡𤂋𤄏𦰡哋嚞𦚱嚒𠿟𠮨𠸍鏆𨬓鎜仸儫㠙𤐶亼𠑥𠍿佋侊𥙑婨𠆫𠏋㦙𠌊𠐔㐵伩𠋀𨺳𠉵諚𠈌亘"], +["92a1","働儍侢伃𤨎𣺊佂倮偬傁俌俥偘僼兙兛兝兞湶𣖕𣸹𣺿浲𡢄𣺉冨凃𠗠䓝𠒣𠒒𠒑赺𨪜𠜎剙劤𠡳勡鍮䙺熌𤎌𠰠𤦬𡃤槑𠸝瑹㻞璙琔瑖玘䮎𤪼𤂍叐㖄爏𤃉喴𠍅响𠯆圝鉝雴鍦埝垍坿㘾壋媙𨩆𡛺𡝯𡜐娬妸銏婾嫏娒𥥆𡧳𡡡𤊕㛵洅瑃娡𥺃"], +["9340","媁𨯗𠐓鏠璌𡌃焅䥲鐈𨧻鎽㞠尞岞幞幈𡦖𡥼𣫮廍孏𡤃𡤄㜁𡢠㛝𡛾㛓脪𨩇𡶺𣑲𨦨弌弎𡤧𡞫婫𡜻孄蘔𧗽衠恾𢡠𢘫忛㺸𢖯𢖾𩂈𦽳懀𠀾𠁆𢘛憙憘恵𢲛𢴇𤛔𩅍"], +["93a1","摱𤙥𢭪㨩𢬢𣑐𩣪𢹸挷𪑛撶挱揑𤧣𢵧护𢲡搻敫楲㯴𣂎𣊭𤦉𣊫唍𣋠𡣙𩐿曎𣊉𣆳㫠䆐𥖄𨬢𥖏𡛼𥕛𥐥磮𣄃𡠪𣈴㑤𣈏𣆂𤋉暎𦴤晫䮓昰𧡰𡷫晣𣋒𣋡昞𥡲㣑𣠺𣞼㮙𣞢𣏾瓐㮖枏𤘪梶栞㯄檾㡣𣟕𤒇樳橒櫉欅𡤒攑梘橌㯗橺歗𣿀𣲚鎠鋲𨯪𨫋"], +["9440","銉𨀞𨧜鑧涥漋𤧬浧𣽿㶏渄𤀼娽渊塇洤硂焻𤌚𤉶烱牐犇犔𤞏𤜥兹𤪤𠗫瑺𣻸𣙟𤩊𤤗𥿡㼆㺱𤫟𨰣𣼵悧㻳瓌琼鎇琷䒟𦷪䕑疃㽣𤳙𤴆㽘畕癳𪗆㬙瑨𨫌𤦫𤦎㫻"], +["94a1","㷍𤩎㻿𤧅𤣳釺圲鍂𨫣𡡤僟𥈡𥇧睸𣈲眎眏睻𤚗𣞁㩞𤣰琸璛㺿𤪺𤫇䃈𤪖𦆮錇𥖁砞碍碈磒珐祙𧝁𥛣䄎禛蒖禥樭𣻺稺秴䅮𡛦䄲鈵秱𠵌𤦌𠊙𣶺𡝮㖗啫㕰㚪𠇔𠰍竢婙𢛵𥪯𥪜娍𠉛磰娪𥯆竾䇹籝籭䈑𥮳𥺼𥺦糍𤧹𡞰粎籼粮檲緜縇緓罎𦉡"], +["9540","𦅜𧭈綗𥺂䉪𦭵𠤖柖𠁎𣗏埄𦐒𦏸𤥢翝笧𠠬𥫩𥵃笌𥸎駦虅驣樜𣐿㧢𤧷𦖭騟𦖠蒀𧄧𦳑䓪脷䐂胆脉腂𦞴飃𦩂艢艥𦩑葓𦶧蘐𧈛媆䅿𡡀嬫𡢡嫤𡣘蚠蜨𣶏蠭𧐢娂"], +["95a1","衮佅袇袿裦襥襍𥚃襔𧞅𧞄𨯵𨯙𨮜𨧹㺭蒣䛵䛏㟲訽訜𩑈彍鈫𤊄旔焩烄𡡅鵭貟賩𧷜妚矃姰䍮㛔踪躧𤰉輰轊䋴汘澻𢌡䢛潹溋𡟚鯩㚵𤤯邻邗啱䤆醻鐄𨩋䁢𨫼鐧𨰝𨰻蓥訫閙閧閗閖𨴴瑅㻂𤣿𤩂𤏪㻧𣈥随𨻧𨹦𨹥㻌𤧭𤩸𣿮琒瑫㻼靁𩂰"], +["9640","桇䨝𩂓𥟟靝鍨𨦉𨰦𨬯𦎾銺嬑譩䤼珹𤈛鞛靱餸𠼦巁𨯅𤪲頟𩓚鋶𩗗釥䓀𨭐𤩧𨭤飜𨩅㼀鈪䤥萔餻饍𧬆㷽馛䭯馪驜𨭥𥣈檏騡嫾騯𩣱䮐𩥈馼䮽䮗鍽塲𡌂堢𤦸"], +["96a1","𡓨硄𢜟𣶸棅㵽鑘㤧慐𢞁𢥫愇鱏鱓鱻鰵鰐魿鯏𩸭鮟𪇵𪃾鴡䲮𤄄鸘䲰鴌𪆴𪃭𪃳𩤯鶥蒽𦸒𦿟𦮂藼䔳𦶤𦺄𦷰萠藮𦸀𣟗𦁤秢𣖜𣙀䤭𤧞㵢鏛銾鍈𠊿碹鉷鑍俤㑀遤𥕝砽硔碶硋𡝗𣇉𤥁㚚佲濚濙瀞瀞吔𤆵垻壳垊鴖埗焴㒯𤆬燫𦱀𤾗嬨𡞵𨩉"], +["9740","愌嫎娋䊼𤒈㜬䭻𨧼鎻鎸𡣖𠼝葲𦳀𡐓𤋺𢰦𤏁妔𣶷𦝁綨𦅛𦂤𤦹𤦋𨧺鋥珢㻩璴𨭣𡢟㻡𤪳櫘珳珻㻖𤨾𤪔𡟙𤩦𠎧𡐤𤧥瑈𤤖炥𤥶銄珦鍟𠓾錱𨫎𨨖鎆𨯧𥗕䤵𨪂煫"], +["97a1","𤥃𠳿嚤𠘚𠯫𠲸唂秄𡟺緾𡛂𤩐𡡒䔮鐁㜊𨫀𤦭妰𡢿𡢃𧒄媡㛢𣵛㚰鉟婹𨪁𡡢鍴㳍𠪴䪖㦊僴㵩㵌𡎜煵䋻𨈘渏𩃤䓫浗𧹏灧沯㳖𣿭𣸭渂漌㵯𠏵畑㚼㓈䚀㻚䡱姄鉮䤾轁𨰜𦯀堒埈㛖𡑒烾𤍢𤩱𢿣𡊰𢎽梹楧𡎘𣓥𧯴𣛟𨪃𣟖𣏺𤲟樚𣚭𦲷萾䓟䓎"], +["9840","𦴦𦵑𦲂𦿞漗𧄉茽𡜺菭𦲀𧁓𡟛妉媂𡞳婡婱𡤅𤇼㜭姯𡜼㛇熎鎐暚𤊥婮娫𤊓樫𣻹𧜶𤑛𤋊焝𤉙𨧡侰𦴨峂𤓎𧹍𤎽樌𤉖𡌄炦焳𤏩㶥泟勇𤩏繥姫崯㷳彜𤩝𡟟綤萦"], +["98a1","咅𣫺𣌀𠈔坾𠣕𠘙㿥𡾞𪊶瀃𩅛嵰玏糓𨩙𩐠俈翧狍猐𧫴猸猹𥛶獁獈㺩𧬘遬燵𤣲珡臶㻊県㻑沢国琙琞琟㻢㻰㻴㻺瓓㼎㽓畂畭畲疍㽼痈痜㿀癍㿗癴㿜発𤽜熈嘣覀塩䀝睃䀹条䁅㗛瞘䁪䁯属瞾矋売砘点砜䂨砹硇硑硦葈𥔵礳栃礲䄃"], +["9940","䄉禑禙辻稆込䅧窑䆲窼艹䇄竏竛䇏両筢筬筻簒簛䉠䉺类粜䊌粸䊔糭输烀𠳏総緔緐緽羮羴犟䎗耠耥笹耮耱联㷌垴炠肷胩䏭脌猪脎脒畠脔䐁㬹腖腙腚"], +["99a1","䐓堺腼膄䐥膓䐭膥埯臁臤艔䒏芦艶苊苘苿䒰荗险榊萅烵葤惣蒈䔄蒾蓡蓸蔐蔸蕒䔻蕯蕰藠䕷虲蚒蚲蛯际螋䘆䘗袮裿褤襇覑𧥧訩訸誔誴豑賔賲贜䞘塟跃䟭仮踺嗘坔蹱嗵躰䠷軎転軤軭軲辷迁迊迌逳駄䢭飠鈓䤞鈨鉘鉫銱銮銿"], +["9a40","鋣鋫鋳鋴鋽鍃鎄鎭䥅䥑麿鐗匁鐝鐭鐾䥪鑔鑹锭関䦧间阳䧥枠䨤靀䨵鞲韂噔䫤惨颹䬙飱塄餎餙冴餜餷饂饝饢䭰駅䮝騼鬏窃魩鮁鯝鯱鯴䱭鰠㝯𡯂鵉鰺"], +["9aa1","黾噐鶓鶽鷀鷼银辶鹻麬麱麽黆铜黢黱黸竈齄𠂔𠊷𠎠椚铃妬𠓗塀铁㞹𠗕𠘕𠙶𡚺块煳𠫂𠫍𠮿呪吆𠯋咞𠯻𠰻𠱓𠱥𠱼惧𠲍噺𠲵𠳝𠳭𠵯𠶲𠷈楕鰯螥𠸄𠸎𠻗𠾐𠼭𠹳尠𠾼帋𡁜𡁏𡁶朞𡁻𡂈𡂖㙇𡂿𡃓𡄯𡄻卤蒭𡋣𡍵𡌶讁𡕷𡘙𡟃𡟇乸炻𡠭𡥪"], +["9b40","𡨭𡩅𡰪𡱰𡲬𡻈拃𡻕𡼕熘桕𢁅槩㛈𢉼𢏗𢏺𢜪𢡱𢥏苽𢥧𢦓𢫕覥𢫨辠𢬎鞸𢬿顇骽𢱌"], +["9b62","𢲈𢲷𥯨𢴈𢴒𢶷𢶕𢹂𢽴𢿌𣀳𣁦𣌟𣏞徱晈暿𧩹𣕧𣗳爁𤦺矗𣘚𣜖纇𠍆墵朎"], +["9ba1","椘𣪧𧙗𥿢𣸑𣺹𧗾𢂚䣐䪸𤄙𨪚𤋮𤌍𤀻𤌴𤎖𤩅𠗊凒𠘑妟𡺨㮾𣳿𤐄𤓖垈𤙴㦛𤜯𨗨𩧉㝢𢇃譞𨭎駖𤠒𤣻𤨕爉𤫀𠱸奥𤺥𤾆𠝹軚𥀬劏圿煱𥊙𥐙𣽊𤪧喼𥑆𥑮𦭒釔㑳𥔿𧘲𥕞䜘𥕢𥕦𥟇𤤿𥡝偦㓻𣏌惞𥤃䝼𨥈𥪮𥮉𥰆𡶐垡煑澶𦄂𧰒遖𦆲𤾚譢𦐂𦑊"], +["9c40","嵛𦯷輶𦒄𡤜諪𤧶𦒈𣿯𦔒䯀𦖿𦚵𢜛鑥𥟡憕娧晉侻嚹𤔡𦛼乪𤤴陖涏𦲽㘘襷𦞙𦡮𦐑𦡞營𦣇筂𩃀𠨑𦤦鄄𦤹穅鷰𦧺騦𦨭㙟𦑩𠀡禃𦨴𦭛崬𣔙菏𦮝䛐𦲤画补𦶮墶"], +["9ca1","㜜𢖍𧁋𧇍㱔𧊀𧊅銁𢅺𧊋錰𧋦𤧐氹钟𧑐𠻸蠧裵𢤦𨑳𡞱溸𤨪𡠠㦤㚹尐秣䔿暶𩲭𩢤襃𧟌𧡘囖䃟𡘊㦡𣜯𨃨𡏅熭荦𧧝𩆨婧䲷𧂯𨦫𧧽𧨊𧬋𧵦𤅺筃祾𨀉澵𪋟樃𨌘厢𦸇鎿栶靝𨅯𨀣𦦵𡏭𣈯𨁈嶅𨰰𨂃圕頣𨥉嶫𤦈斾槕叒𤪥𣾁㰑朶𨂐𨃴𨄮𡾡𨅏"], +["9d40","𨆉𨆯𨈚𨌆𨌯𨎊㗊𨑨𨚪䣺揦𨥖砈鉕𨦸䏲𨧧䏟𨧨𨭆𨯔姸𨰉輋𨿅𩃬筑𩄐𩄼㷷𩅞𤫊运犏嚋𩓧𩗩𩖰𩖸𩜲𩣑𩥉𩥪𩧃𩨨𩬎𩵚𩶛纟𩻸𩼣䲤镇𪊓熢𪋿䶑递𪗋䶜𠲜达嗁"], +["9da1","辺𢒰边𤪓䔉繿潖檱仪㓤𨬬𧢝㜺躀𡟵𨀤𨭬𨮙𧨾𦚯㷫𧙕𣲷𥘵𥥖亚𥺁𦉘嚿𠹭踎孭𣺈𤲞揞拐𡟶𡡻攰嘭𥱊吚𥌑㷆𩶘䱽嘢嘞罉𥻘奵𣵀蝰东𠿪𠵉𣚺脗鵞贘瘻鱅癎瞹鍅吲腈苷嘥脲萘肽嗪祢噃吖𠺝㗎嘅嗱曱𨋢㘭甴嗰喺咗啲𠱁𠲖廐𥅈𠹶𢱢"], +["9e40","𠺢麫絚嗞𡁵抝靭咔賍燶酶揼掹揾啩𢭃鱲𢺳冚㓟𠶧冧呍唞唓癦踭𦢊疱肶蠄螆裇膶萜𡃁䓬猄𤜆宐茋𦢓噻𢛴𧴯𤆣𧵳𦻐𧊶酰𡇙鈈𣳼𪚩𠺬𠻹牦𡲢䝎𤿂𧿹𠿫䃺"], +["9ea1","鱝攟𢶠䣳𤟠𩵼𠿬𠸊恢𧖣𠿭"], +["9ead","𦁈𡆇熣纎鵐业丄㕷嬍沲卧㚬㧜卽㚥𤘘墚𤭮舭呋垪𥪕𠥹"], +["9ec5","㩒𢑥獴𩺬䴉鯭𣳾𩼰䱛𤾩𩖞𩿞葜𣶶𧊲𦞳𣜠挮紥𣻷𣸬㨪逈勌㹴㙺䗩𠒎癀嫰𠺶硺𧼮墧䂿噼鮋嵴癔𪐴麅䳡痹㟻愙𣃚𤏲"], +["9ef5","噝𡊩垧𤥣𩸆刴𧂮㖭汊鵼"], +["9f40","籖鬹埞𡝬屓擓𩓐𦌵𧅤蚭𠴨𦴢𤫢𠵱"], +["9f4f","凾𡼏嶎霃𡷑麁遌笟鬂峑箣扨挵髿篏鬪籾鬮籂粆鰕篼鬉鼗鰛𤤾齚啳寃俽麘俲剠㸆勑坧偖妷帒韈鶫轜呩鞴饀鞺匬愰"], +["9fa1","椬叚鰊鴂䰻陁榀傦畆𡝭駚剳"], +["9fae","酙隁酜"], +["9fb2","酑𨺗捿𦴣櫊嘑醎畺抅𠏼獏籰𥰡𣳽"], +["9fc1","𤤙盖鮝个𠳔莾衂"], +["9fc9","届槀僭坺刟巵从氱𠇲伹咜哚劚趂㗾弌㗳"], +["9fdb","歒酼龥鮗頮颴骺麨麄煺笔"], +["9fe7","毺蠘罸"], +["9feb","嘠𪙊蹷齓"], +["9ff0","跔蹏鸜踁抂𨍽踨蹵竓𤩷稾磘泪詧瘇"], +["a040","𨩚鼦泎蟖痃𪊲硓咢贌狢獱謭猂瓱賫𤪻蘯徺袠䒷"], +["a055","𡠻𦸅"], +["a058","詾𢔛"], +["a05b","惽癧髗鵄鍮鮏蟵"], +["a063","蠏賷猬霡鮰㗖犲䰇籑饊𦅙慙䰄麖慽"], +["a073","坟慯抦戹拎㩜懢厪𣏵捤栂㗒"], +["a0a1","嵗𨯂迚𨸹"], +["a0a6","僙𡵆礆匲阸𠼻䁥"], +["a0ae","矾"], +["a0b0","糂𥼚糚稭聦聣絍甅瓲覔舚朌聢𧒆聛瓰脃眤覉𦟌畓𦻑螩蟎臈螌詉貭譃眫瓸蓚㘵榲趦"], +["a0d4","覩瑨涹蟁𤀑瓧㷛煶悤憜㳑煢恷"], +["a0e2","罱𨬭牐惩䭾删㰘𣳇𥻗𧙖𥔱𡥄𡋾𩤃𦷜𧂭峁𦆭𨨏𣙷𠃮𦡆𤼎䕢嬟𦍌齐麦𦉫"], +["a3c0","␀",31,"␡"], +["c6a1","①",9,"⑴",9,"ⅰ",9,"丶丿亅亠冂冖冫勹匸卩厶夊宀巛⼳广廴彐彡攴无疒癶辵隶¨ˆヽヾゝゞ〃仝々〆〇ー[]✽ぁ",23], +["c740","す",58,"ァアィイ"], +["c7a1","ゥ",81,"А",5,"ЁЖ",4], +["c840","Л",26,"ёж",25,"⇧↸↹㇏𠃌乚𠂊刂䒑"], +["c8a1","龰冈龱𧘇"], +["c8cd","¬¦'"㈱№℡゛゜⺀⺄⺆⺇⺈⺊⺌⺍⺕⺜⺝⺥⺧⺪⺬⺮⺶⺼⺾⻆⻊⻌⻍⻏⻖⻗⻞⻣"], +["c8f5","ʃɐɛɔɵœøŋʊɪ"], +["f9fe","■"], +["fa40","𠕇鋛𠗟𣿅蕌䊵珯况㙉𤥂𨧤鍄𡧛苮𣳈砼杄拟𤤳𨦪𠊠𦮳𡌅侫𢓭倈𦴩𧪄𣘀𤪱𢔓倩𠍾徤𠎀𠍇滛𠐟偽儁㑺儎顬㝃萖𤦤𠒇兠𣎴兪𠯿𢃼𠋥𢔰𠖎𣈳𡦃宂蝽𠖳𣲙冲冸"], +["faa1","鴴凉减凑㳜凓𤪦决凢卂凭菍椾𣜭彻刋刦刼劵剗劔効勅簕蕂勠蘍𦬓包𨫞啉滙𣾀𠥔𣿬匳卄𠯢泋𡜦栛珕恊㺪㣌𡛨燝䒢卭却𨚫卾卿𡖖𡘓矦厓𨪛厠厫厮玧𥝲㽙玜叁叅汉义埾叙㪫𠮏叠𣿫𢶣叶𠱷吓灹唫晗浛呭𦭓𠵴啝咏咤䞦𡜍𠻝㶴𠵍"], +["fb40","𨦼𢚘啇䳭启琗喆喩嘅𡣗𤀺䕒𤐵暳𡂴嘷曍𣊊暤暭噍噏磱囱鞇叾圀囯园𨭦㘣𡉏坆𤆥汮炋坂㚱𦱾埦𡐖堃𡑔𤍣堦𤯵塜墪㕡壠壜𡈼壻寿坃𪅐𤉸鏓㖡够梦㛃湙"], +["fba1","𡘾娤啓𡚒蔅姉𠵎𦲁𦴪𡟜姙𡟻𡞲𦶦浱𡠨𡛕姹𦹅媫婣㛦𤦩婷㜈媖瑥嫓𦾡𢕔㶅𡤑㜲𡚸広勐孶斈孼𧨎䀄䡝𠈄寕慠𡨴𥧌𠖥寳宝䴐尅𡭄尓珎尔𡲥𦬨屉䣝岅峩峯嶋𡷹𡸷崐崘嵆𡺤岺巗苼㠭𤤁𢁉𢅳芇㠶㯂帮檊幵幺𤒼𠳓厦亷廐厨𡝱帉廴𨒂"], +["fc40","廹廻㢠廼栾鐛弍𠇁弢㫞䢮𡌺强𦢈𢏐彘𢑱彣鞽𦹮彲鍀𨨶徧嶶㵟𥉐𡽪𧃸𢙨釖𠊞𨨩怱暅𡡷㥣㷇㘹垐𢞴祱㹀悞悤悳𤦂𤦏𧩓璤僡媠慤萤慂慈𦻒憁凴𠙖憇宪𣾷"], +["fca1","𢡟懓𨮝𩥝懐㤲𢦀𢣁怣慜攞掋𠄘担𡝰拕𢸍捬𤧟㨗搸揸𡎎𡟼撐澊𢸶頔𤂌𥜝擡擥鑻㩦携㩗敍漖𤨨𤨣斅敭敟𣁾斵𤥀䬷旑䃘𡠩无旣忟𣐀昘𣇷𣇸晄𣆤𣆥晋𠹵晧𥇦晳晴𡸽𣈱𨗴𣇈𥌓矅𢣷馤朂𤎜𤨡㬫槺𣟂杞杧杢𤇍𩃭柗䓩栢湐鈼栁𣏦𦶠桝"], +["fd40","𣑯槡樋𨫟楳棃𣗍椁椀㴲㨁𣘼㮀枬楡𨩊䋼椶榘㮡𠏉荣傐槹𣙙𢄪橅𣜃檝㯳枱櫈𩆜㰍欝𠤣惞欵歴𢟍溵𣫛𠎵𡥘㝀吡𣭚毡𣻼毜氷𢒋𤣱𦭑汚舦汹𣶼䓅𣶽𤆤𤤌𤤀"], +["fda1","𣳉㛥㳫𠴲鮃𣇹𢒑羏样𦴥𦶡𦷫涖浜湼漄𤥿𤂅𦹲蔳𦽴凇沜渝萮𨬡港𣸯瑓𣾂秌湏媑𣁋濸㜍澝𣸰滺𡒗𤀽䕕鏰潄潜㵎潴𩅰㴻澟𤅄濓𤂑𤅕𤀹𣿰𣾴𤄿凟𤅖𤅗𤅀𦇝灋灾炧炁烌烕烖烟䄄㷨熴熖𤉷焫煅媈煊煮岜𤍥煏鍢𤋁焬𤑚𤨧𤨢熺𨯨炽爎"], +["fe40","鑂爕夑鑃爤鍁𥘅爮牀𤥴梽牕牗㹕𣁄栍漽犂猪猫𤠣𨠫䣭𨠄猨献珏玪𠰺𦨮珉瑉𤇢𡛧𤨤昣㛅𤦷𤦍𤧻珷琕椃𤨦琹𠗃㻗瑜𢢭瑠𨺲瑇珤瑶莹瑬㜰瑴鏱樬璂䥓𤪌"], +["fea1","𤅟𤩹𨮏孆𨰃𡢞瓈𡦈甎瓩甞𨻙𡩋寗𨺬鎅畍畊畧畮𤾂㼄𤴓疎瑝疞疴瘂瘬癑癏癯癶𦏵皐臯㟸𦤑𦤎皡皥皷盌𦾟葢𥂝𥅽𡸜眞眦着撯𥈠睘𣊬瞯𨥤𨥨𡛁矴砉𡍶𤨒棊碯磇磓隥礮𥗠磗礴碱𧘌辸袄𨬫𦂃𢘜禆褀椂禀𥡗禝𧬹礼禩渪𧄦㺨秆𩄍秔"] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp936.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp936.json new file mode 100644 index 0000000..49ddb9a --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp936.json @@ -0,0 +1,264 @@ +[ +["0","\u0000",127,"€"], +["8140","丂丄丅丆丏丒丗丟丠両丣並丩丮丯丱丳丵丷丼乀乁乂乄乆乊乑乕乗乚乛乢乣乤乥乧乨乪",5,"乲乴",9,"乿",6,"亇亊"], +["8180","亐亖亗亙亜亝亞亣亪亯亰亱亴亶亷亸亹亼亽亾仈仌仏仐仒仚仛仜仠仢仦仧仩仭仮仯仱仴仸仹仺仼仾伀伂",6,"伋伌伒",4,"伜伝伡伣伨伩伬伭伮伱伳伵伷伹伻伾",4,"佄佅佇",5,"佒佔佖佡佢佦佨佪佫佭佮佱佲併佷佸佹佺佽侀侁侂侅來侇侊侌侎侐侒侓侕侖侘侙侚侜侞侟価侢"], +["8240","侤侫侭侰",4,"侶",8,"俀俁係俆俇俈俉俋俌俍俒",4,"俙俛俠俢俤俥俧俫俬俰俲俴俵俶俷俹俻俼俽俿",11], +["8280","個倎倐們倓倕倖倗倛倝倞倠倢倣値倧倫倯",10,"倻倽倿偀偁偂偄偅偆偉偊偋偍偐",4,"偖偗偘偙偛偝",7,"偦",5,"偭",8,"偸偹偺偼偽傁傂傃傄傆傇傉傊傋傌傎",20,"傤傦傪傫傭",4,"傳",6,"傼"], +["8340","傽",17,"僐",5,"僗僘僙僛",10,"僨僩僪僫僯僰僱僲僴僶",4,"僼",9,"儈"], +["8380","儉儊儌",5,"儓",13,"儢",28,"兂兇兊兌兎兏児兒兓兗兘兙兛兝",4,"兣兤兦內兩兪兯兲兺兾兿冃冄円冇冊冋冎冏冐冑冓冔冘冚冝冞冟冡冣冦",4,"冭冮冴冸冹冺冾冿凁凂凃凅凈凊凍凎凐凒",5], +["8440","凘凙凚凜凞凟凢凣凥",5,"凬凮凱凲凴凷凾刄刅刉刋刌刏刐刓刔刕刜刞刟刡刢刣別刦刧刪刬刯刱刲刴刵刼刾剄",5,"剋剎剏剒剓剕剗剘"], +["8480","剙剚剛剝剟剠剢剣剤剦剨剫剬剭剮剰剱剳",9,"剾劀劃",4,"劉",6,"劑劒劔",6,"劜劤劥劦劧劮劯劰労",9,"勀勁勂勄勅勆勈勊勌勍勎勏勑勓勔動勗務",5,"勠勡勢勣勥",10,"勱",7,"勻勼勽匁匂匃匄匇匉匊匋匌匎"], +["8540","匑匒匓匔匘匛匜匞匟匢匤匥匧匨匩匫匬匭匯",9,"匼匽區卂卄卆卋卌卍卐協単卙卛卝卥卨卪卬卭卲卶卹卻卼卽卾厀厁厃厇厈厊厎厏"], +["8580","厐",4,"厖厗厙厛厜厞厠厡厤厧厪厫厬厭厯",6,"厷厸厹厺厼厽厾叀參",4,"収叏叐叒叓叕叚叜叝叞叡叢叧叴叺叾叿吀吂吅吇吋吔吘吙吚吜吢吤吥吪吰吳吶吷吺吽吿呁呂呄呅呇呉呌呍呎呏呑呚呝",4,"呣呥呧呩",7,"呴呹呺呾呿咁咃咅咇咈咉咊咍咑咓咗咘咜咞咟咠咡"], +["8640","咢咥咮咰咲咵咶咷咹咺咼咾哃哅哊哋哖哘哛哠",4,"哫哬哯哰哱哴",5,"哻哾唀唂唃唄唅唈唊",4,"唒唓唕",5,"唜唝唞唟唡唥唦"], +["8680","唨唩唫唭唲唴唵唶唸唹唺唻唽啀啂啅啇啈啋",4,"啑啒啓啔啗",4,"啝啞啟啠啢啣啨啩啫啯",5,"啹啺啽啿喅喆喌喍喎喐喒喓喕喖喗喚喛喞喠",6,"喨",8,"喲喴営喸喺喼喿",4,"嗆嗇嗈嗊嗋嗎嗏嗐嗕嗗",4,"嗞嗠嗢嗧嗩嗭嗮嗰嗱嗴嗶嗸",4,"嗿嘂嘃嘄嘅"], +["8740","嘆嘇嘊嘋嘍嘐",7,"嘙嘚嘜嘝嘠嘡嘢嘥嘦嘨嘩嘪嘫嘮嘯嘰嘳嘵嘷嘸嘺嘼嘽嘾噀",11,"噏",4,"噕噖噚噛噝",4], +["8780","噣噥噦噧噭噮噯噰噲噳噴噵噷噸噹噺噽",7,"嚇",6,"嚐嚑嚒嚔",14,"嚤",10,"嚰",6,"嚸嚹嚺嚻嚽",12,"囋",8,"囕囖囘囙囜団囥",5,"囬囮囯囲図囶囷囸囻囼圀圁圂圅圇國",6], +["8840","園",9,"圝圞圠圡圢圤圥圦圧圫圱圲圴",4,"圼圽圿坁坃坄坅坆坈坉坋坒",4,"坘坙坢坣坥坧坬坮坰坱坲坴坵坸坹坺坽坾坿垀"], +["8880","垁垇垈垉垊垍",4,"垔",6,"垜垝垞垟垥垨垪垬垯垰垱垳垵垶垷垹",8,"埄",6,"埌埍埐埑埓埖埗埛埜埞埡埢埣埥",7,"埮埰埱埲埳埵埶執埻埼埾埿堁堃堄堅堈堉堊堌堎堏堐堒堓堔堖堗堘堚堛堜堝堟堢堣堥",4,"堫",4,"報堲堳場堶",7], +["8940","堾",5,"塅",6,"塎塏塐塒塓塕塖塗塙",4,"塟",5,"塦",4,"塭",16,"塿墂墄墆墇墈墊墋墌"], +["8980","墍",4,"墔",4,"墛墜墝墠",7,"墪",17,"墽墾墿壀壂壃壄壆",10,"壒壓壔壖",13,"壥",5,"壭壯壱売壴壵壷壸壺",7,"夃夅夆夈",4,"夎夐夑夒夓夗夘夛夝夞夠夡夢夣夦夨夬夰夲夳夵夶夻"], +["8a40","夽夾夿奀奃奅奆奊奌奍奐奒奓奙奛",4,"奡奣奤奦",12,"奵奷奺奻奼奾奿妀妅妉妋妌妎妏妐妑妔妕妘妚妛妜妝妟妠妡妢妦"], +["8a80","妧妬妭妰妱妳",5,"妺妼妽妿",6,"姇姈姉姌姍姎姏姕姖姙姛姞",4,"姤姦姧姩姪姫姭",11,"姺姼姽姾娀娂娊娋娍娎娏娐娒娔娕娖娗娙娚娛娝娞娡娢娤娦娧娨娪",6,"娳娵娷",4,"娽娾娿婁",4,"婇婈婋",9,"婖婗婘婙婛",5], +["8b40","婡婣婤婥婦婨婩婫",8,"婸婹婻婼婽婾媀",17,"媓",6,"媜",13,"媫媬"], +["8b80","媭",4,"媴媶媷媹",4,"媿嫀嫃",5,"嫊嫋嫍",4,"嫓嫕嫗嫙嫚嫛嫝嫞嫟嫢嫤嫥嫧嫨嫪嫬",4,"嫲",22,"嬊",11,"嬘",25,"嬳嬵嬶嬸",7,"孁",6], +["8c40","孈",7,"孒孖孞孠孡孧孨孫孭孮孯孲孴孶孷學孹孻孼孾孿宂宆宊宍宎宐宑宒宔宖実宧宨宩宬宭宮宯宱宲宷宺宻宼寀寁寃寈寉寊寋寍寎寏"], +["8c80","寑寔",8,"寠寢寣實寧審",4,"寯寱",6,"寽対尀専尃尅將專尋尌對導尐尒尓尗尙尛尞尟尠尡尣尦尨尩尪尫尭尮尯尰尲尳尵尶尷屃屄屆屇屌屍屒屓屔屖屗屘屚屛屜屝屟屢層屧",6,"屰屲",6,"屻屼屽屾岀岃",4,"岉岊岋岎岏岒岓岕岝",4,"岤",4], +["8d40","岪岮岯岰岲岴岶岹岺岻岼岾峀峂峃峅",5,"峌",5,"峓",5,"峚",6,"峢峣峧峩峫峬峮峯峱",9,"峼",4], +["8d80","崁崄崅崈",5,"崏",4,"崕崗崘崙崚崜崝崟",4,"崥崨崪崫崬崯",4,"崵",7,"崿",7,"嵈嵉嵍",10,"嵙嵚嵜嵞",10,"嵪嵭嵮嵰嵱嵲嵳嵵",12,"嶃",21,"嶚嶛嶜嶞嶟嶠"], +["8e40","嶡",21,"嶸",12,"巆",6,"巎",12,"巜巟巠巣巤巪巬巭"], +["8e80","巰巵巶巸",4,"巿帀帄帇帉帊帋帍帎帒帓帗帞",7,"帨",4,"帯帰帲",4,"帹帺帾帿幀幁幃幆",5,"幍",6,"幖",4,"幜幝幟幠幣",14,"幵幷幹幾庁庂広庅庈庉庌庍庎庒庘庛庝庡庢庣庤庨",4,"庮",4,"庴庺庻庼庽庿",6], +["8f40","廆廇廈廋",5,"廔廕廗廘廙廚廜",11,"廩廫",8,"廵廸廹廻廼廽弅弆弇弉弌弍弎弐弒弔弖弙弚弜弝弞弡弢弣弤"], +["8f80","弨弫弬弮弰弲",6,"弻弽弾弿彁",14,"彑彔彙彚彛彜彞彟彠彣彥彧彨彫彮彯彲彴彵彶彸彺彽彾彿徃徆徍徎徏徑従徔徖徚徛徝從徟徠徢",5,"復徫徬徯",5,"徶徸徹徺徻徾",4,"忇忈忊忋忎忓忔忕忚忛応忞忟忢忣忥忦忨忩忬忯忰忲忳忴忶忷忹忺忼怇"], +["9040","怈怉怋怌怐怑怓怗怘怚怞怟怢怣怤怬怭怮怰",4,"怶",4,"怽怾恀恄",6,"恌恎恏恑恓恔恖恗恘恛恜恞恟恠恡恥恦恮恱恲恴恵恷恾悀"], +["9080","悁悂悅悆悇悈悊悋悎悏悐悑悓悕悗悘悙悜悞悡悢悤悥悧悩悪悮悰悳悵悶悷悹悺悽",7,"惇惈惉惌",4,"惒惓惔惖惗惙惛惞惡",4,"惪惱惲惵惷惸惻",4,"愂愃愄愅愇愊愋愌愐",4,"愖愗愘愙愛愜愝愞愡愢愥愨愩愪愬",18,"慀",6], +["9140","慇慉態慍慏慐慒慓慔慖",6,"慞慟慠慡慣慤慥慦慩",6,"慱慲慳慴慶慸",18,"憌憍憏",4,"憕"], +["9180","憖",6,"憞",8,"憪憫憭",9,"憸",5,"憿懀懁懃",4,"應懌",4,"懓懕",16,"懧",13,"懶",8,"戀",5,"戇戉戓戔戙戜戝戞戠戣戦戧戨戩戫戭戯戰戱戲戵戶戸",4,"扂扄扅扆扊"], +["9240","扏扐払扖扗扙扚扜",6,"扤扥扨扱扲扴扵扷扸扺扻扽抁抂抃抅抆抇抈抋",5,"抔抙抜抝択抣抦抧抩抪抭抮抯抰抲抳抴抶抷抸抺抾拀拁"], +["9280","拃拋拏拑拕拝拞拠拡拤拪拫拰拲拵拸拹拺拻挀挃挄挅挆挊挋挌挍挏挐挒挓挔挕挗挘挙挜挦挧挩挬挭挮挰挱挳",5,"挻挼挾挿捀捁捄捇捈捊捑捒捓捔捖",7,"捠捤捥捦捨捪捫捬捯捰捲捳捴捵捸捹捼捽捾捿掁掃掄掅掆掋掍掑掓掔掕掗掙",6,"採掤掦掫掯掱掲掵掶掹掻掽掿揀"], +["9340","揁揂揃揅揇揈揊揋揌揑揓揔揕揗",6,"揟揢揤",4,"揫揬揮揯揰揱揳揵揷揹揺揻揼揾搃搄搆",4,"損搎搑搒搕",5,"搝搟搢搣搤"], +["9380","搥搧搨搩搫搮",5,"搵",4,"搻搼搾摀摂摃摉摋",6,"摓摕摖摗摙",4,"摟",7,"摨摪摫摬摮",9,"摻",6,"撃撆撈",8,"撓撔撗撘撚撛撜撝撟",4,"撥撦撧撨撪撫撯撱撲撳撴撶撹撻撽撾撿擁擃擄擆",6,"擏擑擓擔擕擖擙據"], +["9440","擛擜擝擟擠擡擣擥擧",24,"攁",7,"攊",7,"攓",4,"攙",8], +["9480","攢攣攤攦",4,"攬攭攰攱攲攳攷攺攼攽敀",4,"敆敇敊敋敍敎敐敒敓敔敗敘敚敜敟敠敡敤敥敧敨敩敪敭敮敯敱敳敵敶數",14,"斈斉斊斍斎斏斒斔斕斖斘斚斝斞斠斢斣斦斨斪斬斮斱",7,"斺斻斾斿旀旂旇旈旉旊旍旐旑旓旔旕旘",7,"旡旣旤旪旫"], +["9540","旲旳旴旵旸旹旻",4,"昁昄昅昇昈昉昋昍昐昑昒昖昗昘昚昛昜昞昡昢昣昤昦昩昪昫昬昮昰昲昳昷",4,"昽昿晀時晄",6,"晍晎晐晑晘"], +["9580","晙晛晜晝晞晠晢晣晥晧晩",4,"晱晲晳晵晸晹晻晼晽晿暀暁暃暅暆暈暉暊暋暍暎暏暐暒暓暔暕暘",4,"暞",8,"暩",4,"暯",4,"暵暶暷暸暺暻暼暽暿",25,"曚曞",7,"曧曨曪",5,"曱曵曶書曺曻曽朁朂會"], +["9640","朄朅朆朇朌朎朏朑朒朓朖朘朙朚朜朞朠",5,"朧朩朮朰朲朳朶朷朸朹朻朼朾朿杁杄杅杇杊杋杍杒杔杕杗",4,"杝杢杣杤杦杧杫杬杮東杴杶"], +["9680","杸杹杺杻杽枀枂枃枅枆枈枊枌枍枎枏枑枒枓枔枖枙枛枟枠枡枤枦枩枬枮枱枲枴枹",7,"柂柅",9,"柕柖柗柛柟柡柣柤柦柧柨柪柫柭柮柲柵",7,"柾栁栂栃栄栆栍栐栒栔栕栘",4,"栞栟栠栢",6,"栫",6,"栴栵栶栺栻栿桇桋桍桏桒桖",5], +["9740","桜桝桞桟桪桬",7,"桵桸",8,"梂梄梇",7,"梐梑梒梔梕梖梘",9,"梣梤梥梩梪梫梬梮梱梲梴梶梷梸"], +["9780","梹",6,"棁棃",5,"棊棌棎棏棐棑棓棔棖棗棙棛",4,"棡棢棤",9,"棯棲棳棴棶棷棸棻棽棾棿椀椂椃椄椆",4,"椌椏椑椓",11,"椡椢椣椥",7,"椮椯椱椲椳椵椶椷椸椺椻椼椾楀楁楃",16,"楕楖楘楙楛楜楟"], +["9840","楡楢楤楥楧楨楩楪楬業楯楰楲",4,"楺楻楽楾楿榁榃榅榊榋榌榎",5,"榖榗榙榚榝",9,"榩榪榬榮榯榰榲榳榵榶榸榹榺榼榽"], +["9880","榾榿槀槂",7,"構槍槏槑槒槓槕",5,"槜槝槞槡",11,"槮槯槰槱槳",9,"槾樀",9,"樋",11,"標",5,"樠樢",5,"権樫樬樭樮樰樲樳樴樶",6,"樿",4,"橅橆橈",7,"橑",6,"橚"], +["9940","橜",4,"橢橣橤橦",10,"橲",6,"橺橻橽橾橿檁檂檃檅",8,"檏檒",4,"檘",7,"檡",5], +["9980","檧檨檪檭",114,"欥欦欨",6], +["9a40","欯欰欱欳欴欵欶欸欻欼欽欿歀歁歂歄歅歈歊歋歍",11,"歚",7,"歨歩歫",13,"歺歽歾歿殀殅殈"], +["9a80","殌殎殏殐殑殔殕殗殘殙殜",4,"殢",7,"殫",7,"殶殸",6,"毀毃毄毆",4,"毌毎毐毑毘毚毜",4,"毢",7,"毬毭毮毰毱毲毴毶毷毸毺毻毼毾",6,"氈",4,"氎氒気氜氝氞氠氣氥氫氬氭氱氳氶氷氹氺氻氼氾氿汃汄汅汈汋",4,"汑汒汓汖汘"], +["9b40","汙汚汢汣汥汦汧汫",4,"汱汳汵汷汸決汻汼汿沀沄沇沊沋沍沎沑沒沕沖沗沘沚沜沝沞沠沢沨沬沯沰沴沵沶沷沺泀況泂泃泆泇泈泋泍泎泏泑泒泘"], +["9b80","泙泚泜泝泟泤泦泧泩泬泭泲泴泹泿洀洂洃洅洆洈洉洊洍洏洐洑洓洔洕洖洘洜洝洟",5,"洦洨洩洬洭洯洰洴洶洷洸洺洿浀浂浄浉浌浐浕浖浗浘浛浝浟浡浢浤浥浧浨浫浬浭浰浱浲浳浵浶浹浺浻浽",4,"涃涄涆涇涊涋涍涏涐涒涖",4,"涜涢涥涬涭涰涱涳涴涶涷涹",5,"淁淂淃淈淉淊"], +["9c40","淍淎淏淐淒淓淔淕淗淚淛淜淟淢淣淥淧淨淩淪淭淯淰淲淴淵淶淸淺淽",7,"渆渇済渉渋渏渒渓渕渘渙減渜渞渟渢渦渧渨渪測渮渰渱渳渵"], +["9c80","渶渷渹渻",7,"湅",7,"湏湐湑湒湕湗湙湚湜湝湞湠",10,"湬湭湯",14,"満溁溂溄溇溈溊",4,"溑",6,"溙溚溛溝溞溠溡溣溤溦溨溩溫溬溭溮溰溳溵溸溹溼溾溿滀滃滄滅滆滈滉滊滌滍滎滐滒滖滘滙滛滜滝滣滧滪",5], +["9d40","滰滱滲滳滵滶滷滸滺",7,"漃漄漅漇漈漊",4,"漐漑漒漖",9,"漡漢漣漥漦漧漨漬漮漰漲漴漵漷",6,"漿潀潁潂"], +["9d80","潃潄潅潈潉潊潌潎",9,"潙潚潛潝潟潠潡潣潤潥潧",5,"潯潰潱潳潵潶潷潹潻潽",6,"澅澆澇澊澋澏",12,"澝澞澟澠澢",4,"澨",10,"澴澵澷澸澺",5,"濁濃",5,"濊",6,"濓",10,"濟濢濣濤濥"], +["9e40","濦",7,"濰",32,"瀒",7,"瀜",6,"瀤",6], +["9e80","瀫",9,"瀶瀷瀸瀺",17,"灍灎灐",13,"灟",11,"灮灱灲灳灴灷灹灺灻災炁炂炃炄炆炇炈炋炌炍炏炐炑炓炗炘炚炛炞",12,"炰炲炴炵炶為炾炿烄烅烆烇烉烋",12,"烚"], +["9f40","烜烝烞烠烡烢烣烥烪烮烰",6,"烸烺烻烼烾",10,"焋",4,"焑焒焔焗焛",10,"焧",7,"焲焳焴"], +["9f80","焵焷",13,"煆煇煈煉煋煍煏",12,"煝煟",4,"煥煩",4,"煯煰煱煴煵煶煷煹煻煼煾",5,"熅",4,"熋熌熍熎熐熑熒熓熕熖熗熚",4,"熡",6,"熩熪熫熭",5,"熴熶熷熸熺",8,"燄",9,"燏",4], +["a040","燖",9,"燡燢燣燤燦燨",5,"燯",9,"燺",11,"爇",19], +["a080","爛爜爞",9,"爩爫爭爮爯爲爳爴爺爼爾牀",6,"牉牊牋牎牏牐牑牓牔牕牗牘牚牜牞牠牣牤牥牨牪牫牬牭牰牱牳牴牶牷牸牻牼牽犂犃犅",4,"犌犎犐犑犓",11,"犠",11,"犮犱犲犳犵犺",6,"狅狆狇狉狊狋狌狏狑狓狔狕狖狘狚狛"], +["a1a1"," 、。·ˉˇ¨〃々—~‖…‘’“”〔〕〈",7,"〖〗【】±×÷∶∧∨∑∏∪∩∈∷√⊥∥∠⌒⊙∫∮≡≌≈∽∝≠≮≯≤≥∞∵∴♂♀°′″℃$¤¢£‰§№☆★○●◎◇◆□■△▲※→←↑↓〓"], +["a2a1","ⅰ",9], +["a2b1","⒈",19,"⑴",19,"①",9], +["a2e5","㈠",9], +["a2f1","Ⅰ",11], +["a3a1","!"#¥%",88," ̄"], +["a4a1","ぁ",82], +["a5a1","ァ",85], +["a6a1","Α",16,"Σ",6], +["a6c1","α",16,"σ",6], +["a6e0","︵︶︹︺︿﹀︽︾﹁﹂﹃﹄"], +["a6ee","︻︼︷︸︱"], +["a6f4","︳︴"], +["a7a1","А",5,"ЁЖ",25], +["a7d1","а",5,"ёж",25], +["a840","ˊˋ˙–―‥‵℅℉↖↗↘↙∕∟∣≒≦≧⊿═",35,"▁",6], +["a880","█",7,"▓▔▕▼▽◢◣◤◥☉⊕〒〝〞"], +["a8a1","āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜüêɑ"], +["a8bd","ńň"], +["a8c0","ɡ"], +["a8c5","ㄅ",36], +["a940","〡",8,"㊣㎎㎏㎜㎝㎞㎡㏄㏎㏑㏒㏕︰¬¦"], +["a959","℡㈱"], +["a95c","‐"], +["a960","ー゛゜ヽヾ〆ゝゞ﹉",9,"﹔﹕﹖﹗﹙",8], +["a980","﹢",4,"﹨﹩﹪﹫"], +["a996","〇"], +["a9a4","─",75], +["aa40","狜狝狟狢",5,"狪狫狵狶狹狽狾狿猀猂猄",5,"猋猌猍猏猐猑猒猔猘猙猚猟猠猣猤猦猧猨猭猯猰猲猳猵猶猺猻猼猽獀",8], +["aa80","獉獊獋獌獎獏獑獓獔獕獖獘",7,"獡",10,"獮獰獱"], +["ab40","獲",11,"獿",4,"玅玆玈玊玌玍玏玐玒玓玔玕玗玘玙玚玜玝玞玠玡玣",5,"玪玬玭玱玴玵玶玸玹玼玽玾玿珁珃",4], +["ab80","珋珌珎珒",6,"珚珛珜珝珟珡珢珣珤珦珨珪珫珬珮珯珰珱珳",4], +["ac40","珸",10,"琄琇琈琋琌琍琎琑",8,"琜",5,"琣琤琧琩琫琭琯琱琲琷",4,"琽琾琿瑀瑂",11], +["ac80","瑎",6,"瑖瑘瑝瑠",12,"瑮瑯瑱",4,"瑸瑹瑺"], +["ad40","瑻瑼瑽瑿璂璄璅璆璈璉璊璌璍璏璑",10,"璝璟",7,"璪",15,"璻",12], +["ad80","瓈",9,"瓓",8,"瓝瓟瓡瓥瓧",6,"瓰瓱瓲"], +["ae40","瓳瓵瓸",6,"甀甁甂甃甅",7,"甎甐甒甔甕甖甗甛甝甞甠",4,"甦甧甪甮甴甶甹甼甽甿畁畂畃畄畆畇畉畊畍畐畑畒畓畕畖畗畘"], +["ae80","畝",7,"畧畨畩畫",6,"畳畵當畷畺",4,"疀疁疂疄疅疇"], +["af40","疈疉疊疌疍疎疐疓疕疘疛疜疞疢疦",4,"疭疶疷疺疻疿痀痁痆痋痌痎痏痐痑痓痗痙痚痜痝痟痠痡痥痩痬痭痮痯痲痳痵痶痷痸痺痻痽痾瘂瘄瘆瘇"], +["af80","瘈瘉瘋瘍瘎瘏瘑瘒瘓瘔瘖瘚瘜瘝瘞瘡瘣瘧瘨瘬瘮瘯瘱瘲瘶瘷瘹瘺瘻瘽癁療癄"], +["b040","癅",6,"癎",5,"癕癗",4,"癝癟癠癡癢癤",6,"癬癭癮癰",7,"癹発發癿皀皁皃皅皉皊皌皍皏皐皒皔皕皗皘皚皛"], +["b080","皜",7,"皥",8,"皯皰皳皵",9,"盀盁盃啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥"], +["b140","盄盇盉盋盌盓盕盙盚盜盝盞盠",4,"盦",7,"盰盳盵盶盷盺盻盽盿眀眂眃眅眆眊県眎",10,"眛眜眝眞眡眣眤眥眧眪眫"], +["b180","眬眮眰",4,"眹眻眽眾眿睂睄睅睆睈",7,"睒",7,"睜薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳"], +["b240","睝睞睟睠睤睧睩睪睭",11,"睺睻睼瞁瞂瞃瞆",5,"瞏瞐瞓",11,"瞡瞣瞤瞦瞨瞫瞭瞮瞯瞱瞲瞴瞶",4], +["b280","瞼瞾矀",12,"矎",8,"矘矙矚矝",4,"矤病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖"], +["b340","矦矨矪矯矰矱矲矴矵矷矹矺矻矼砃",5,"砊砋砎砏砐砓砕砙砛砞砠砡砢砤砨砪砫砮砯砱砲砳砵砶砽砿硁硂硃硄硆硈硉硊硋硍硏硑硓硔硘硙硚"], +["b380","硛硜硞",11,"硯",7,"硸硹硺硻硽",6,"场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚"], +["b440","碄碅碆碈碊碋碏碐碒碔碕碖碙碝碞碠碢碤碦碨",7,"碵碶碷碸確碻碼碽碿磀磂磃磄磆磇磈磌磍磎磏磑磒磓磖磗磘磚",9], +["b480","磤磥磦磧磩磪磫磭",4,"磳磵磶磸磹磻",5,"礂礃礄礆",6,"础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮"], +["b540","礍",5,"礔",9,"礟",4,"礥",14,"礵",4,"礽礿祂祃祄祅祇祊",8,"祔祕祘祙祡祣"], +["b580","祤祦祩祪祫祬祮祰",6,"祹祻",4,"禂禃禆禇禈禉禋禌禍禎禐禑禒怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠"], +["b640","禓",6,"禛",11,"禨",10,"禴",4,"禼禿秂秄秅秇秈秊秌秎秏秐秓秔秖秗秙",5,"秠秡秢秥秨秪"], +["b680","秬秮秱",6,"秹秺秼秾秿稁稄稅稇稈稉稊稌稏",4,"稕稖稘稙稛稜丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二"], +["b740","稝稟稡稢稤",14,"稴稵稶稸稺稾穀",5,"穇",9,"穒",4,"穘",16], +["b780","穩",6,"穱穲穳穵穻穼穽穾窂窅窇窉窊窋窌窎窏窐窓窔窙窚窛窞窡窢贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服"], +["b840","窣窤窧窩窪窫窮",4,"窴",10,"竀",10,"竌",9,"竗竘竚竛竜竝竡竢竤竧",5,"竮竰竱竲竳"], +["b880","竴",4,"竻竼竾笀笁笂笅笇笉笌笍笎笐笒笓笖笗笘笚笜笝笟笡笢笣笧笩笭浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹"], +["b940","笯笰笲笴笵笶笷笹笻笽笿",5,"筆筈筊筍筎筓筕筗筙筜筞筟筡筣",10,"筯筰筳筴筶筸筺筼筽筿箁箂箃箄箆",6,"箎箏"], +["b980","箑箒箓箖箘箙箚箛箞箟箠箣箤箥箮箯箰箲箳箵箶箷箹",7,"篂篃範埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈"], +["ba40","篅篈築篊篋篍篎篏篐篒篔",4,"篛篜篞篟篠篢篣篤篧篨篩篫篬篭篯篰篲",4,"篸篹篺篻篽篿",7,"簈簉簊簍簎簐",5,"簗簘簙"], +["ba80","簚",4,"簠",5,"簨簩簫",12,"簹",5,"籂骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖"], +["bb40","籃",9,"籎",36,"籵",5,"籾",9], +["bb80","粈粊",6,"粓粔粖粙粚粛粠粡粣粦粧粨粩粫粬粭粯粰粴",4,"粺粻弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕"], +["bc40","粿糀糂糃糄糆糉糋糎",6,"糘糚糛糝糞糡",6,"糩",5,"糰",7,"糹糺糼",13,"紋",5], +["bc80","紑",14,"紡紣紤紥紦紨紩紪紬紭紮細",6,"肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际妓继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件"], +["bd40","紷",54,"絯",7], +["bd80","絸",32,"健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸"], +["be40","継",12,"綧",6,"綯",42], +["be80","線",32,"尽劲荆兢茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵觉决诀绝均菌钧军君峻"], +["bf40","緻",62], +["bf80","縺縼",4,"繂",4,"繈",21,"俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀"], +["c040","繞",35,"纃",23,"纜纝纞"], +["c080","纮纴纻纼绖绤绬绹缊缐缞缷缹缻",6,"罃罆",9,"罒罓馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐"], +["c140","罖罙罛罜罝罞罠罣",4,"罫罬罭罯罰罳罵罶罷罸罺罻罼罽罿羀羂",7,"羋羍羏",4,"羕",4,"羛羜羠羢羣羥羦羨",6,"羱"], +["c180","羳",4,"羺羻羾翀翂翃翄翆翇翈翉翋翍翏",4,"翖翗翙",5,"翢翣痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿"], +["c240","翤翧翨翪翫翬翭翯翲翴",6,"翽翾翿耂耇耈耉耊耎耏耑耓耚耛耝耞耟耡耣耤耫",5,"耲耴耹耺耼耾聀聁聄聅聇聈聉聎聏聐聑聓聕聖聗"], +["c280","聙聛",13,"聫",5,"聲",11,"隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫"], +["c340","聾肁肂肅肈肊肍",5,"肔肕肗肙肞肣肦肧肨肬肰肳肵肶肸肹肻胅胇",4,"胏",6,"胘胟胠胢胣胦胮胵胷胹胻胾胿脀脁脃脄脅脇脈脋"], +["c380","脌脕脗脙脛脜脝脟",12,"脭脮脰脳脴脵脷脹",4,"脿谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸"], +["c440","腀",5,"腇腉腍腎腏腒腖腗腘腛",4,"腡腢腣腤腦腨腪腫腬腯腲腳腵腶腷腸膁膃",4,"膉膋膌膍膎膐膒",5,"膙膚膞",4,"膤膥"], +["c480","膧膩膫",7,"膴",5,"膼膽膾膿臄臅臇臈臉臋臍",6,"摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁"], +["c540","臔",14,"臤臥臦臨臩臫臮",4,"臵",5,"臽臿舃與",4,"舎舏舑舓舕",5,"舝舠舤舥舦舧舩舮舲舺舼舽舿"], +["c580","艀艁艂艃艅艆艈艊艌艍艎艐",7,"艙艛艜艝艞艠",7,"艩拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗"], +["c640","艪艫艬艭艱艵艶艷艸艻艼芀芁芃芅芆芇芉芌芐芓芔芕芖芚芛芞芠芢芣芧芲芵芶芺芻芼芿苀苂苃苅苆苉苐苖苙苚苝苢苧苨苩苪苬苭苮苰苲苳苵苶苸"], +["c680","苺苼",4,"茊茋茍茐茒茓茖茘茙茝",9,"茩茪茮茰茲茷茻茽啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐"], +["c740","茾茿荁荂荄荅荈荊",4,"荓荕",4,"荝荢荰",6,"荹荺荾",6,"莇莈莊莋莌莍莏莐莑莔莕莖莗莙莚莝莟莡",6,"莬莭莮"], +["c780","莯莵莻莾莿菂菃菄菆菈菉菋菍菎菐菑菒菓菕菗菙菚菛菞菢菣菤菦菧菨菫菬菭恰洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠"], +["c840","菮華菳",4,"菺菻菼菾菿萀萂萅萇萈萉萊萐萒",5,"萙萚萛萞",5,"萩",7,"萲",5,"萹萺萻萾",7,"葇葈葉"], +["c880","葊",6,"葒",4,"葘葝葞葟葠葢葤",4,"葪葮葯葰葲葴葷葹葻葼取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁"], +["c940","葽",4,"蒃蒄蒅蒆蒊蒍蒏",7,"蒘蒚蒛蒝蒞蒟蒠蒢",12,"蒰蒱蒳蒵蒶蒷蒻蒼蒾蓀蓂蓃蓅蓆蓇蓈蓋蓌蓎蓏蓒蓔蓕蓗"], +["c980","蓘",4,"蓞蓡蓢蓤蓧",4,"蓭蓮蓯蓱",10,"蓽蓾蔀蔁蔂伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳"], +["ca40","蔃",8,"蔍蔎蔏蔐蔒蔔蔕蔖蔘蔙蔛蔜蔝蔞蔠蔢",8,"蔭",9,"蔾",4,"蕄蕅蕆蕇蕋",10], +["ca80","蕗蕘蕚蕛蕜蕝蕟",4,"蕥蕦蕧蕩",8,"蕳蕵蕶蕷蕸蕼蕽蕿薀薁省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱"], +["cb40","薂薃薆薈",6,"薐",10,"薝",6,"薥薦薧薩薫薬薭薱",5,"薸薺",6,"藂",6,"藊",4,"藑藒"], +["cb80","藔藖",5,"藝",6,"藥藦藧藨藪",14,"恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔"], +["cc40","藹藺藼藽藾蘀",4,"蘆",10,"蘒蘓蘔蘕蘗",15,"蘨蘪",13,"蘹蘺蘻蘽蘾蘿虀"], +["cc80","虁",11,"虒虓處",4,"虛虜虝號虠虡虣",7,"獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃"], +["cd40","虭虯虰虲",6,"蚃",6,"蚎",4,"蚔蚖",5,"蚞",4,"蚥蚦蚫蚭蚮蚲蚳蚷蚸蚹蚻",4,"蛁蛂蛃蛅蛈蛌蛍蛒蛓蛕蛖蛗蛚蛜"], +["cd80","蛝蛠蛡蛢蛣蛥蛦蛧蛨蛪蛫蛬蛯蛵蛶蛷蛺蛻蛼蛽蛿蜁蜄蜅蜆蜋蜌蜎蜏蜐蜑蜔蜖汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威"], +["ce40","蜙蜛蜝蜟蜠蜤蜦蜧蜨蜪蜫蜬蜭蜯蜰蜲蜳蜵蜶蜸蜹蜺蜼蜽蝀",6,"蝊蝋蝍蝏蝐蝑蝒蝔蝕蝖蝘蝚",5,"蝡蝢蝦",7,"蝯蝱蝲蝳蝵"], +["ce80","蝷蝸蝹蝺蝿螀螁螄螆螇螉螊螌螎",4,"螔螕螖螘",6,"螠",4,"巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺"], +["cf40","螥螦螧螩螪螮螰螱螲螴螶螷螸螹螻螼螾螿蟁",4,"蟇蟈蟉蟌",4,"蟔",6,"蟜蟝蟞蟟蟡蟢蟣蟤蟦蟧蟨蟩蟫蟬蟭蟯",9], +["cf80","蟺蟻蟼蟽蟿蠀蠁蠂蠄",5,"蠋",7,"蠔蠗蠘蠙蠚蠜",4,"蠣稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓"], +["d040","蠤",13,"蠳",5,"蠺蠻蠽蠾蠿衁衂衃衆",5,"衎",5,"衕衖衘衚",6,"衦衧衪衭衯衱衳衴衵衶衸衹衺"], +["d080","衻衼袀袃袆袇袉袊袌袎袏袐袑袓袔袕袗",4,"袝",4,"袣袥",5,"小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄"], +["d140","袬袮袯袰袲",4,"袸袹袺袻袽袾袿裀裃裄裇裈裊裋裌裍裏裐裑裓裖裗裚",4,"裠裡裦裧裩",6,"裲裵裶裷裺裻製裿褀褁褃",5], +["d180","褉褋",4,"褑褔",4,"褜",4,"褢褣褤褦褧褨褩褬褭褮褯褱褲褳褵褷选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶"], +["d240","褸",8,"襂襃襅",24,"襠",5,"襧",19,"襼"], +["d280","襽襾覀覂覄覅覇",26,"摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐"], +["d340","覢",30,"觃觍觓觔觕觗觘觙觛觝觟觠觡觢觤觧觨觩觪觬觭觮觰觱觲觴",6], +["d380","觻",4,"訁",5,"計",21,"印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉"], +["d440","訞",31,"訿",8,"詉",21], +["d480","詟",25,"詺",6,"浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧"], +["d540","誁",7,"誋",7,"誔",46], +["d580","諃",32,"铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政"], +["d640","諤",34,"謈",27], +["d680","謤謥謧",30,"帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑"], +["d740","譆",31,"譧",4,"譭",25], +["d780","讇",24,"讬讱讻诇诐诪谉谞住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座"], +["d840","谸",8,"豂豃豄豅豈豊豋豍",7,"豖豗豘豙豛",5,"豣",6,"豬",6,"豴豵豶豷豻",6,"貃貄貆貇"], +["d880","貈貋貍",6,"貕貖貗貙",20,"亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛啬嘏仄厍厝厣厥厮靥赝匚叵匦匮匾赜卦卣刂刈刎刭刳刿剀剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞伛仳伢佤仵伥伧伉伫佞佧攸佚佝"], +["d940","貮",62], +["d980","賭",32,"佟佗伲伽佶佴侑侉侃侏佾佻侪佼侬侔俦俨俪俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨偾偃偕偈偎偬偻傥傧傩傺僖儆僭僬僦僮儇儋仝氽佘佥俎龠汆籴兮巽黉馘冁夔勹匍訇匐凫夙兕亠兖亳衮袤亵脔裒禀嬴蠃羸冫冱冽冼"], +["da40","贎",14,"贠赑赒赗赟赥赨赩赪赬赮赯赱赲赸",8,"趂趃趆趇趈趉趌",4,"趒趓趕",9,"趠趡"], +["da80","趢趤",12,"趲趶趷趹趻趽跀跁跂跅跇跈跉跊跍跐跒跓跔凇冖冢冥讠讦讧讪讴讵讷诂诃诋诏诎诒诓诔诖诘诙诜诟诠诤诨诩诮诰诳诶诹诼诿谀谂谄谇谌谏谑谒谔谕谖谙谛谘谝谟谠谡谥谧谪谫谮谯谲谳谵谶卩卺阝阢阡阱阪阽阼陂陉陔陟陧陬陲陴隈隍隗隰邗邛邝邙邬邡邴邳邶邺"], +["db40","跕跘跙跜跠跡跢跥跦跧跩跭跮跰跱跲跴跶跼跾",6,"踆踇踈踋踍踎踐踑踒踓踕",7,"踠踡踤",4,"踫踭踰踲踳踴踶踷踸踻踼踾"], +["db80","踿蹃蹅蹆蹌",4,"蹓",5,"蹚",11,"蹧蹨蹪蹫蹮蹱邸邰郏郅邾郐郄郇郓郦郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆刍奂劢劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巯坌垩垡塾墼壅壑圩圬圪圳圹圮圯坜圻坂坩垅坫垆坼坻坨坭坶坳垭垤垌垲埏垧垴垓垠埕埘埚埙埒垸埴埯埸埤埝"], +["dc40","蹳蹵蹷",4,"蹽蹾躀躂躃躄躆躈",6,"躑躒躓躕",6,"躝躟",11,"躭躮躰躱躳",6,"躻",7], +["dc80","軃",10,"軏",21,"堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑芗芙芫芸芾芰苈苊苣芘芷芮苋苌苁芩芴芡芪芟苄苎芤苡茉苷苤茏茇苜苴苒苘茌苻苓茑茚茆茔茕苠苕茜荑荛荜茈莒茼茴茱莛荞茯荏荇荃荟荀茗荠茭茺茳荦荥"], +["dd40","軥",62], +["dd80","輤",32,"荨茛荩荬荪荭荮莰荸莳莴莠莪莓莜莅荼莶莩荽莸荻莘莞莨莺莼菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀萦菰菡葜葑葚葙葳蒇蒈葺蒉葸萼葆葩葶蒌蒎萱葭蓁蓍蓐蓦蒽蓓蓊蒿蒺蓠蒡蒹蒴蒗蓥蓣蔌甍蔸蓰蔹蔟蔺"], +["de40","轅",32,"轪辀辌辒辝辠辡辢辤辥辦辧辪辬辭辮辯農辳辴辵辷辸辺辻込辿迀迃迆"], +["de80","迉",4,"迏迒迖迗迚迠迡迣迧迬迯迱迲迴迵迶迺迻迼迾迿逇逈逌逎逓逕逘蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蕲蕻薤薨薇薏蕹薮薜薅薹薷薰藓藁藜藿蘧蘅蘩蘖蘼廾弈夼奁耷奕奚奘匏尢尥尬尴扌扪抟抻拊拚拗拮挢拶挹捋捃掭揶捱捺掎掴捭掬掊捩掮掼揲揸揠揿揄揞揎摒揆掾摅摁搋搛搠搌搦搡摞撄摭撖"], +["df40","這逜連逤逥逧",5,"逰",4,"逷逹逺逽逿遀遃遅遆遈",4,"過達違遖遙遚遜",5,"遤遦遧適遪遫遬遯",4,"遶",6,"遾邁"], +["df80","還邅邆邇邉邊邌",4,"邒邔邖邘邚邜邞邟邠邤邥邧邨邩邫邭邲邷邼邽邿郀摺撷撸撙撺擀擐擗擤擢攉攥攮弋忒甙弑卟叱叽叩叨叻吒吖吆呋呒呓呔呖呃吡呗呙吣吲咂咔呷呱呤咚咛咄呶呦咝哐咭哂咴哒咧咦哓哔呲咣哕咻咿哌哙哚哜咩咪咤哝哏哞唛哧唠哽唔哳唢唣唏唑唧唪啧喏喵啉啭啁啕唿啐唼"], +["e040","郂郃郆郈郉郋郌郍郒郔郕郖郘郙郚郞郟郠郣郤郥郩郪郬郮郰郱郲郳郵郶郷郹郺郻郼郿鄀鄁鄃鄅",19,"鄚鄛鄜"], +["e080","鄝鄟鄠鄡鄤",10,"鄰鄲",6,"鄺",8,"酄唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟喽喾喔喙嗪嗷嗉嘟嗑嗫嗬嗔嗦嗝嗄嗯嗥嗲嗳嗌嗍嗨嗵嗤辔嘞嘈嘌嘁嘤嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙噜噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡囵囫囹囿圄圊圉圜帏帙帔帑帱帻帼"], +["e140","酅酇酈酑酓酔酕酖酘酙酛酜酟酠酦酧酨酫酭酳酺酻酼醀",4,"醆醈醊醎醏醓",6,"醜",5,"醤",5,"醫醬醰醱醲醳醶醷醸醹醻"], +["e180","醼",10,"釈釋釐釒",9,"針",8,"帷幄幔幛幞幡岌屺岍岐岖岈岘岙岑岚岜岵岢岽岬岫岱岣峁岷峄峒峤峋峥崂崃崧崦崮崤崞崆崛嵘崾崴崽嵬嵛嵯嵝嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巅彳彷徂徇徉後徕徙徜徨徭徵徼衢彡犭犰犴犷犸狃狁狎狍狒狨狯狩狲狴狷猁狳猃狺"], +["e240","釦",62], +["e280","鈥",32,"狻猗猓猡猊猞猝猕猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂饣饧",5,"饴饷饽馀馄馇馊馍馐馑馓馔馕庀庑庋庖庥庠庹庵庾庳赓廒廑廛廨廪膺忄忉忖忏怃忮怄忡忤忾怅怆忪忭忸怙怵怦怛怏怍怩怫怊怿怡恸恹恻恺恂"], +["e340","鉆",45,"鉵",16], +["e380","銆",7,"銏",24,"恪恽悖悚悭悝悃悒悌悛惬悻悱惝惘惆惚悴愠愦愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳闩闫闱闳闵闶闼闾阃阄阆阈阊阋阌阍阏阒阕阖阗阙阚丬爿戕氵汔汜汊沣沅沐沔沌汨汩汴汶沆沩泐泔沭泷泸泱泗沲泠泖泺泫泮沱泓泯泾"], +["e440","銨",5,"銯",24,"鋉",31], +["e480","鋩",32,"洹洧洌浃浈洇洄洙洎洫浍洮洵洚浏浒浔洳涑浯涞涠浞涓涔浜浠浼浣渚淇淅淞渎涿淠渑淦淝淙渖涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄滟溱溘滠漭滢溥溧溽溻溷滗溴滏溏滂溟潢潆潇漤漕滹漯漶潋潴漪漉漩澉澍澌潸潲潼潺濑"], +["e540","錊",51,"錿",10], +["e580","鍊",31,"鍫濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灏灞宀宄宕宓宥宸甯骞搴寤寮褰寰蹇謇辶迓迕迥迮迤迩迦迳迨逅逄逋逦逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屦羼弪弩弭艴弼鬻屮妁妃妍妩妪妣"], +["e640","鍬",34,"鎐",27], +["e680","鎬",29,"鏋鏌鏍妗姊妫妞妤姒妲妯姗妾娅娆姝娈姣姘姹娌娉娲娴娑娣娓婀婧婊婕娼婢婵胬媪媛婷婺媾嫫媲嫒嫔媸嫠嫣嫱嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢驵驷驸驺驿驽骀骁骅骈骊骐骒骓骖骘骛骜骝骟骠骢骣骥骧纟纡纣纥纨纩"], +["e740","鏎",7,"鏗",54], +["e780","鐎",32,"纭纰纾绀绁绂绉绋绌绐绔绗绛绠绡绨绫绮绯绱绲缍绶绺绻绾缁缂缃缇缈缋缌缏缑缒缗缙缜缛缟缡",6,"缪缫缬缭缯",4,"缵幺畿巛甾邕玎玑玮玢玟珏珂珑玷玳珀珉珈珥珙顼琊珩珧珞玺珲琏琪瑛琦琥琨琰琮琬"], +["e840","鐯",14,"鐿",43,"鑬鑭鑮鑯"], +["e880","鑰",20,"钑钖钘铇铏铓铔铚铦铻锜锠琛琚瑁瑜瑗瑕瑙瑷瑭瑾璜璎璀璁璇璋璞璨璩璐璧瓒璺韪韫韬杌杓杞杈杩枥枇杪杳枘枧杵枨枞枭枋杷杼柰栉柘栊柩枰栌柙枵柚枳柝栀柃枸柢栎柁柽栲栳桠桡桎桢桄桤梃栝桕桦桁桧桀栾桊桉栩梵梏桴桷梓桫棂楮棼椟椠棹"], +["e940","锧锳锽镃镈镋镕镚镠镮镴镵長",7,"門",42], +["e980","閫",32,"椤棰椋椁楗棣椐楱椹楠楂楝榄楫榀榘楸椴槌榇榈槎榉楦楣楹榛榧榻榫榭槔榱槁槊槟榕槠榍槿樯槭樗樘橥槲橄樾檠橐橛樵檎橹樽樨橘橼檑檐檩檗檫猷獒殁殂殇殄殒殓殍殚殛殡殪轫轭轱轲轳轵轶轸轷轹轺轼轾辁辂辄辇辋"], +["ea40","闌",27,"闬闿阇阓阘阛阞阠阣",6,"阫阬阭阯阰阷阸阹阺阾陁陃陊陎陏陑陒陓陖陗"], +["ea80","陘陙陚陜陝陞陠陣陥陦陫陭",4,"陳陸",12,"隇隉隊辍辎辏辘辚軎戋戗戛戟戢戡戥戤戬臧瓯瓴瓿甏甑甓攴旮旯旰昊昙杲昃昕昀炅曷昝昴昱昶昵耆晟晔晁晏晖晡晗晷暄暌暧暝暾曛曜曦曩贲贳贶贻贽赀赅赆赈赉赇赍赕赙觇觊觋觌觎觏觐觑牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰"], +["eb40","隌階隑隒隓隕隖隚際隝",9,"隨",7,"隱隲隴隵隷隸隺隻隿雂雃雈雊雋雐雑雓雔雖",9,"雡",6,"雫"], +["eb80","雬雭雮雰雱雲雴雵雸雺電雼雽雿霂霃霅霊霋霌霐霑霒霔霕霗",4,"霝霟霠搿擘耄毪毳毽毵毹氅氇氆氍氕氘氙氚氡氩氤氪氲攵敕敫牍牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷胧胨胩胪胛胂胄胙胍胗朐胝胫胱胴胭脍脎胲胼朕脒豚脶脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂膑滕膣膪臌朦臊膻"], +["ec40","霡",8,"霫霬霮霯霱霳",4,"霺霻霼霽霿",18,"靔靕靗靘靚靜靝靟靣靤靦靧靨靪",7], +["ec80","靲靵靷",4,"靽",7,"鞆",4,"鞌鞎鞏鞐鞓鞕鞖鞗鞙",4,"臁膦欤欷欹歃歆歙飑飒飓飕飙飚殳彀毂觳斐齑斓於旆旄旃旌旎旒旖炀炜炖炝炻烀炷炫炱烨烊焐焓焖焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬焘煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚祢祗祠祯祧祺禅禊禚禧禳忑忐"], +["ed40","鞞鞟鞡鞢鞤",6,"鞬鞮鞰鞱鞳鞵",46], +["ed80","韤韥韨韮",4,"韴韷",23,"怼恝恚恧恁恙恣悫愆愍慝憩憝懋懑戆肀聿沓泶淼矶矸砀砉砗砘砑斫砭砜砝砹砺砻砟砼砥砬砣砩硎硭硖硗砦硐硇硌硪碛碓碚碇碜碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龛黹黻黼盱眄眍盹眇眈眚眢眙眭眦眵眸睐睑睇睃睚睨"], +["ee40","頏",62], +["ee80","顎",32,"睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨罴罱罹羁罾盍盥蠲钅钆钇钋钊钌钍钏钐钔钗钕钚钛钜钣钤钫钪钭钬钯钰钲钴钶",4,"钼钽钿铄铈",6,"铐铑铒铕铖铗铙铘铛铞铟铠铢铤铥铧铨铪"], +["ef40","顯",5,"颋颎颒颕颙颣風",37,"飏飐飔飖飗飛飜飝飠",4], +["ef80","飥飦飩",30,"铩铫铮铯铳铴铵铷铹铼铽铿锃锂锆锇锉锊锍锎锏锒",4,"锘锛锝锞锟锢锪锫锩锬锱锲锴锶锷锸锼锾锿镂锵镄镅镆镉镌镎镏镒镓镔镖镗镘镙镛镞镟镝镡镢镤",8,"镯镱镲镳锺矧矬雉秕秭秣秫稆嵇稃稂稞稔"], +["f040","餈",4,"餎餏餑",28,"餯",26], +["f080","饊",9,"饖",12,"饤饦饳饸饹饻饾馂馃馉稹稷穑黏馥穰皈皎皓皙皤瓞瓠甬鸠鸢鸨",4,"鸲鸱鸶鸸鸷鸹鸺鸾鹁鹂鹄鹆鹇鹈鹉鹋鹌鹎鹑鹕鹗鹚鹛鹜鹞鹣鹦",6,"鹱鹭鹳疒疔疖疠疝疬疣疳疴疸痄疱疰痃痂痖痍痣痨痦痤痫痧瘃痱痼痿瘐瘀瘅瘌瘗瘊瘥瘘瘕瘙"], +["f140","馌馎馚",10,"馦馧馩",47], +["f180","駙",32,"瘛瘼瘢瘠癀瘭瘰瘿瘵癃瘾瘳癍癞癔癜癖癫癯翊竦穸穹窀窆窈窕窦窠窬窨窭窳衤衩衲衽衿袂袢裆袷袼裉裢裎裣裥裱褚裼裨裾裰褡褙褓褛褊褴褫褶襁襦襻疋胥皲皴矜耒耔耖耜耠耢耥耦耧耩耨耱耋耵聃聆聍聒聩聱覃顸颀颃"], +["f240","駺",62], +["f280","騹",32,"颉颌颍颏颔颚颛颞颟颡颢颥颦虍虔虬虮虿虺虼虻蚨蚍蚋蚬蚝蚧蚣蚪蚓蚩蚶蛄蚵蛎蚰蚺蚱蚯蛉蛏蚴蛩蛱蛲蛭蛳蛐蜓蛞蛴蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蝈蜴蜱蜩蜷蜿螂蜢蝽蝾蝻蝠蝰蝌蝮螋蝓蝣蝼蝤蝙蝥螓螯螨蟒"], +["f340","驚",17,"驲骃骉骍骎骔骕骙骦骩",6,"骲骳骴骵骹骻骽骾骿髃髄髆",4,"髍髎髏髐髒體髕髖髗髙髚髛髜"], +["f380","髝髞髠髢髣髤髥髧髨髩髪髬髮髰",8,"髺髼",6,"鬄鬅鬆蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罂罄罅舐竺竽笈笃笄笕笊笫笏筇笸笪笙笮笱笠笥笤笳笾笞筘筚筅筵筌筝筠筮筻筢筲筱箐箦箧箸箬箝箨箅箪箜箢箫箴篑篁篌篝篚篥篦篪簌篾篼簏簖簋"], +["f440","鬇鬉",5,"鬐鬑鬒鬔",10,"鬠鬡鬢鬤",10,"鬰鬱鬳",7,"鬽鬾鬿魀魆魊魋魌魎魐魒魓魕",5], +["f480","魛",32,"簟簪簦簸籁籀臾舁舂舄臬衄舡舢舣舭舯舨舫舸舻舳舴舾艄艉艋艏艚艟艨衾袅袈裘裟襞羝羟羧羯羰羲籼敉粑粝粜粞粢粲粼粽糁糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸絷綦綮繇纛麸麴赳趄趔趑趱赧赭豇豉酊酐酎酏酤"], +["f540","魼",62], +["f580","鮻",32,"酢酡酰酩酯酽酾酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹾趸跫踅蹙蹩趵趿趼趺跄跖跗跚跞跎跏跛跆跬跷跸跣跹跻跤踉跽踔踝踟踬踮踣踯踺蹀踹踵踽踱蹉蹁蹂蹑蹒蹊蹰蹶蹼蹯蹴躅躏躔躐躜躞豸貂貊貅貘貔斛觖觞觚觜"], +["f640","鯜",62], +["f680","鰛",32,"觥觫觯訾謦靓雩雳雯霆霁霈霏霎霪霭霰霾龀龃龅",5,"龌黾鼋鼍隹隼隽雎雒瞿雠銎銮鋈錾鍪鏊鎏鐾鑫鱿鲂鲅鲆鲇鲈稣鲋鲎鲐鲑鲒鲔鲕鲚鲛鲞",5,"鲥",4,"鲫鲭鲮鲰",7,"鲺鲻鲼鲽鳄鳅鳆鳇鳊鳋"], +["f740","鰼",62], +["f780","鱻鱽鱾鲀鲃鲄鲉鲊鲌鲏鲓鲖鲗鲘鲙鲝鲪鲬鲯鲹鲾",4,"鳈鳉鳑鳒鳚鳛鳠鳡鳌",4,"鳓鳔鳕鳗鳘鳙鳜鳝鳟鳢靼鞅鞑鞒鞔鞯鞫鞣鞲鞴骱骰骷鹘骶骺骼髁髀髅髂髋髌髑魅魃魇魉魈魍魑飨餍餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬓鬟鬣麽麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黩黧黥黪黯鼢鼬鼯鼹鼷鼽鼾齄"], +["f840","鳣",62], +["f880","鴢",32], +["f940","鵃",62], +["f980","鶂",32], +["fa40","鶣",62], +["fa80","鷢",32], +["fb40","鸃",27,"鸤鸧鸮鸰鸴鸻鸼鹀鹍鹐鹒鹓鹔鹖鹙鹝鹟鹠鹡鹢鹥鹮鹯鹲鹴",9,"麀"], +["fb80","麁麃麄麅麆麉麊麌",5,"麔",8,"麞麠",5,"麧麨麩麪"], +["fc40","麫",8,"麵麶麷麹麺麼麿",4,"黅黆黇黈黊黋黌黐黒黓黕黖黗黙黚點黡黣黤黦黨黫黬黭黮黰",8,"黺黽黿",6], +["fc80","鼆",4,"鼌鼏鼑鼒鼔鼕鼖鼘鼚",5,"鼡鼣",8,"鼭鼮鼰鼱"], +["fd40","鼲",4,"鼸鼺鼼鼿",4,"齅",10,"齒",38], +["fd80","齹",5,"龁龂龍",11,"龜龝龞龡",4,"郎凉秊裏隣"], +["fe40","兀嗀﨎﨏﨑﨓﨔礼﨟蘒﨡﨣﨤﨧﨨﨩"] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp949.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp949.json new file mode 100644 index 0000000..2022a00 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp949.json @@ -0,0 +1,273 @@ +[ +["0","\u0000",127], +["8141","갂갃갅갆갋",4,"갘갞갟갡갢갣갥",6,"갮갲갳갴"], +["8161","갵갶갷갺갻갽갾갿걁",9,"걌걎",5,"걕"], +["8181","걖걗걙걚걛걝",18,"걲걳걵걶걹걻",4,"겂겇겈겍겎겏겑겒겓겕",6,"겞겢",5,"겫겭겮겱",6,"겺겾겿곀곂곃곅곆곇곉곊곋곍",7,"곖곘",7,"곢곣곥곦곩곫곭곮곲곴곷",4,"곾곿괁괂괃괅괇",4,"괎괐괒괓"], +["8241","괔괕괖괗괙괚괛괝괞괟괡",7,"괪괫괮",5], +["8261","괶괷괹괺괻괽",6,"굆굈굊",5,"굑굒굓굕굖굗"], +["8281","굙",7,"굢굤",7,"굮굯굱굲굷굸굹굺굾궀궃",4,"궊궋궍궎궏궑",10,"궞",5,"궥",17,"궸",7,"귂귃귅귆귇귉",6,"귒귔",7,"귝귞귟귡귢귣귥",18], +["8341","귺귻귽귾긂",5,"긊긌긎",5,"긕",7], +["8361","긝",18,"긲긳긵긶긹긻긼"], +["8381","긽긾긿깂깄깇깈깉깋깏깑깒깓깕깗",4,"깞깢깣깤깦깧깪깫깭깮깯깱",6,"깺깾",5,"꺆",5,"꺍",46,"꺿껁껂껃껅",6,"껎껒",5,"껚껛껝",8], +["8441","껦껧껩껪껬껮",5,"껵껶껷껹껺껻껽",8], +["8461","꼆꼉꼊꼋꼌꼎꼏꼑",18], +["8481","꼤",7,"꼮꼯꼱꼳꼵",6,"꼾꽀꽄꽅꽆꽇꽊",5,"꽑",10,"꽞",5,"꽦",18,"꽺",5,"꾁꾂꾃꾅꾆꾇꾉",6,"꾒꾓꾔꾖",5,"꾝",26,"꾺꾻꾽꾾"], +["8541","꾿꿁",5,"꿊꿌꿏",4,"꿕",6,"꿝",4], +["8561","꿢",5,"꿪",5,"꿲꿳꿵꿶꿷꿹",6,"뀂뀃"], +["8581","뀅",6,"뀍뀎뀏뀑뀒뀓뀕",6,"뀞",9,"뀩",26,"끆끇끉끋끍끏끐끑끒끖끘끚끛끜끞",29,"끾끿낁낂낃낅",6,"낎낐낒",5,"낛낝낞낣낤"], +["8641","낥낦낧낪낰낲낶낷낹낺낻낽",6,"냆냊",5,"냒"], +["8661","냓냕냖냗냙",6,"냡냢냣냤냦",10], +["8681","냱",22,"넊넍넎넏넑넔넕넖넗넚넞",4,"넦넧넩넪넫넭",6,"넶넺",5,"녂녃녅녆녇녉",6,"녒녓녖녗녙녚녛녝녞녟녡",22,"녺녻녽녾녿놁놃",4,"놊놌놎놏놐놑놕놖놗놙놚놛놝"], +["8741","놞",9,"놩",15], +["8761","놹",18,"뇍뇎뇏뇑뇒뇓뇕"], +["8781","뇖",5,"뇞뇠",7,"뇪뇫뇭뇮뇯뇱",7,"뇺뇼뇾",5,"눆눇눉눊눍",6,"눖눘눚",5,"눡",18,"눵",6,"눽",26,"뉙뉚뉛뉝뉞뉟뉡",6,"뉪",4], +["8841","뉯",4,"뉶",5,"뉽",6,"늆늇늈늊",4], +["8861","늏늒늓늕늖늗늛",4,"늢늤늧늨늩늫늭늮늯늱늲늳늵늶늷"], +["8881","늸",15,"닊닋닍닎닏닑닓",4,"닚닜닞닟닠닡닣닧닩닪닰닱닲닶닼닽닾댂댃댅댆댇댉",6,"댒댖",5,"댝",54,"덗덙덚덝덠덡덢덣"], +["8941","덦덨덪덬덭덯덲덳덵덶덷덹",6,"뎂뎆",5,"뎍"], +["8961","뎎뎏뎑뎒뎓뎕",10,"뎢",5,"뎩뎪뎫뎭"], +["8981","뎮",21,"돆돇돉돊돍돏돑돒돓돖돘돚돜돞돟돡돢돣돥돦돧돩",18,"돽",18,"됑",6,"됙됚됛됝됞됟됡",6,"됪됬",7,"됵",15], +["8a41","둅",10,"둒둓둕둖둗둙",6,"둢둤둦"], +["8a61","둧",4,"둭",18,"뒁뒂"], +["8a81","뒃",4,"뒉",19,"뒞",5,"뒥뒦뒧뒩뒪뒫뒭",7,"뒶뒸뒺",5,"듁듂듃듅듆듇듉",6,"듑듒듓듔듖",5,"듞듟듡듢듥듧",4,"듮듰듲",5,"듹",26,"딖딗딙딚딝"], +["8b41","딞",5,"딦딫",4,"딲딳딵딶딷딹",6,"땂땆"], +["8b61","땇땈땉땊땎땏땑땒땓땕",6,"땞땢",8], +["8b81","땫",52,"떢떣떥떦떧떩떬떭떮떯떲떶",4,"떾떿뗁뗂뗃뗅",6,"뗎뗒",5,"뗙",18,"뗭",18], +["8c41","똀",15,"똒똓똕똖똗똙",4], +["8c61","똞",6,"똦",5,"똭",6,"똵",5], +["8c81","똻",12,"뙉",26,"뙥뙦뙧뙩",50,"뚞뚟뚡뚢뚣뚥",5,"뚭뚮뚯뚰뚲",16], +["8d41","뛃",16,"뛕",8], +["8d61","뛞",17,"뛱뛲뛳뛵뛶뛷뛹뛺"], +["8d81","뛻",4,"뜂뜃뜄뜆",33,"뜪뜫뜭뜮뜱",6,"뜺뜼",7,"띅띆띇띉띊띋띍",6,"띖",9,"띡띢띣띥띦띧띩",6,"띲띴띶",5,"띾띿랁랂랃랅",6,"랎랓랔랕랚랛랝랞"], +["8e41","랟랡",6,"랪랮",5,"랶랷랹",8], +["8e61","럂",4,"럈럊",19], +["8e81","럞",13,"럮럯럱럲럳럵",6,"럾렂",4,"렊렋렍렎렏렑",6,"렚렜렞",5,"렦렧렩렪렫렭",6,"렶렺",5,"롁롂롃롅",11,"롒롔",7,"롞롟롡롢롣롥",6,"롮롰롲",5,"롹롺롻롽",7], +["8f41","뢅",7,"뢎",17], +["8f61","뢠",7,"뢩",6,"뢱뢲뢳뢵뢶뢷뢹",4], +["8f81","뢾뢿룂룄룆",5,"룍룎룏룑룒룓룕",7,"룞룠룢",5,"룪룫룭룮룯룱",6,"룺룼룾",5,"뤅",18,"뤙",6,"뤡",26,"뤾뤿륁륂륃륅",6,"륍륎륐륒",5], +["9041","륚륛륝륞륟륡",6,"륪륬륮",5,"륶륷륹륺륻륽"], +["9061","륾",5,"릆릈릋릌릏",15], +["9081","릟",12,"릮릯릱릲릳릵",6,"릾맀맂",5,"맊맋맍맓",4,"맚맜맟맠맢맦맧맩맪맫맭",6,"맶맻",4,"먂",5,"먉",11,"먖",33,"먺먻먽먾먿멁멃멄멅멆"], +["9141","멇멊멌멏멐멑멒멖멗멙멚멛멝",6,"멦멪",5], +["9161","멲멳멵멶멷멹",9,"몆몈몉몊몋몍",5], +["9181","몓",20,"몪몭몮몯몱몳",4,"몺몼몾",5,"뫅뫆뫇뫉",14,"뫚",33,"뫽뫾뫿묁묂묃묅",7,"묎묐묒",5,"묙묚묛묝묞묟묡",6], +["9241","묨묪묬",7,"묷묹묺묿",4,"뭆뭈뭊뭋뭌뭎뭑뭒"], +["9261","뭓뭕뭖뭗뭙",7,"뭢뭤",7,"뭭",4], +["9281","뭲",21,"뮉뮊뮋뮍뮎뮏뮑",18,"뮥뮦뮧뮩뮪뮫뮭",6,"뮵뮶뮸",7,"믁믂믃믅믆믇믉",6,"믑믒믔",35,"믺믻믽믾밁"], +["9341","밃",4,"밊밎밐밒밓밙밚밠밡밢밣밦밨밪밫밬밮밯밲밳밵"], +["9361","밶밷밹",6,"뱂뱆뱇뱈뱊뱋뱎뱏뱑",8], +["9381","뱚뱛뱜뱞",37,"벆벇벉벊벍벏",4,"벖벘벛",4,"벢벣벥벦벩",6,"벲벶",5,"벾벿볁볂볃볅",7,"볎볒볓볔볖볗볙볚볛볝",22,"볷볹볺볻볽"], +["9441","볾",5,"봆봈봊",5,"봑봒봓봕",8], +["9461","봞",5,"봥",6,"봭",12], +["9481","봺",5,"뵁",6,"뵊뵋뵍뵎뵏뵑",6,"뵚",9,"뵥뵦뵧뵩",22,"붂붃붅붆붋",4,"붒붔붖붗붘붛붝",6,"붥",10,"붱",6,"붹",24], +["9541","뷒뷓뷖뷗뷙뷚뷛뷝",11,"뷪",5,"뷱"], +["9561","뷲뷳뷵뷶뷷뷹",6,"븁븂븄븆",5,"븎븏븑븒븓"], +["9581","븕",6,"븞븠",35,"빆빇빉빊빋빍빏",4,"빖빘빜빝빞빟빢빣빥빦빧빩빫",4,"빲빶",4,"빾빿뺁뺂뺃뺅",6,"뺎뺒",5,"뺚",13,"뺩",14], +["9641","뺸",23,"뻒뻓"], +["9661","뻕뻖뻙",6,"뻡뻢뻦",5,"뻭",8], +["9681","뻶",10,"뼂",5,"뼊",13,"뼚뼞",33,"뽂뽃뽅뽆뽇뽉",6,"뽒뽓뽔뽖",44], +["9741","뾃",16,"뾕",8], +["9761","뾞",17,"뾱",7], +["9781","뾹",11,"뿆",5,"뿎뿏뿑뿒뿓뿕",6,"뿝뿞뿠뿢",89,"쀽쀾쀿"], +["9841","쁀",16,"쁒",5,"쁙쁚쁛"], +["9861","쁝쁞쁟쁡",6,"쁪",15], +["9881","쁺",21,"삒삓삕삖삗삙",6,"삢삤삦",5,"삮삱삲삷",4,"삾샂샃샄샆샇샊샋샍샎샏샑",6,"샚샞",5,"샦샧샩샪샫샭",6,"샶샸샺",5,"섁섂섃섅섆섇섉",6,"섑섒섓섔섖",5,"섡섢섥섨섩섪섫섮"], +["9941","섲섳섴섵섷섺섻섽섾섿셁",6,"셊셎",5,"셖셗"], +["9961","셙셚셛셝",6,"셦셪",5,"셱셲셳셵셶셷셹셺셻"], +["9981","셼",8,"솆",5,"솏솑솒솓솕솗",4,"솞솠솢솣솤솦솧솪솫솭솮솯솱",11,"솾",5,"쇅쇆쇇쇉쇊쇋쇍",6,"쇕쇖쇙",6,"쇡쇢쇣쇥쇦쇧쇩",6,"쇲쇴",7,"쇾쇿숁숂숃숅",6,"숎숐숒",5,"숚숛숝숞숡숢숣"], +["9a41","숤숥숦숧숪숬숮숰숳숵",16], +["9a61","쉆쉇쉉",6,"쉒쉓쉕쉖쉗쉙",6,"쉡쉢쉣쉤쉦"], +["9a81","쉧",4,"쉮쉯쉱쉲쉳쉵",6,"쉾슀슂",5,"슊",5,"슑",6,"슙슚슜슞",5,"슦슧슩슪슫슮",5,"슶슸슺",33,"싞싟싡싢싥",5,"싮싰싲싳싴싵싷싺싽싾싿쌁",6,"쌊쌋쌎쌏"], +["9b41","쌐쌑쌒쌖쌗쌙쌚쌛쌝",6,"쌦쌧쌪",8], +["9b61","쌳",17,"썆",7], +["9b81","썎",25,"썪썫썭썮썯썱썳",4,"썺썻썾",5,"쎅쎆쎇쎉쎊쎋쎍",50,"쏁",22,"쏚"], +["9c41","쏛쏝쏞쏡쏣",4,"쏪쏫쏬쏮",5,"쏶쏷쏹",5], +["9c61","쏿",8,"쐉",6,"쐑",9], +["9c81","쐛",8,"쐥",6,"쐭쐮쐯쐱쐲쐳쐵",6,"쐾",9,"쑉",26,"쑦쑧쑩쑪쑫쑭",6,"쑶쑷쑸쑺",5,"쒁",18,"쒕",6,"쒝",12], +["9d41","쒪",13,"쒹쒺쒻쒽",8], +["9d61","쓆",25], +["9d81","쓠",8,"쓪",5,"쓲쓳쓵쓶쓷쓹쓻쓼쓽쓾씂",9,"씍씎씏씑씒씓씕",6,"씝",10,"씪씫씭씮씯씱",6,"씺씼씾",5,"앆앇앋앏앐앑앒앖앚앛앜앟앢앣앥앦앧앩",6,"앲앶",5,"앾앿얁얂얃얅얆얈얉얊얋얎얐얒얓얔"], +["9e41","얖얙얚얛얝얞얟얡",7,"얪",9,"얶"], +["9e61","얷얺얿",4,"엋엍엏엒엓엕엖엗엙",6,"엢엤엦엧"], +["9e81","엨엩엪엫엯엱엲엳엵엸엹엺엻옂옃옄옉옊옋옍옎옏옑",6,"옚옝",6,"옦옧옩옪옫옯옱옲옶옸옺옼옽옾옿왂왃왅왆왇왉",6,"왒왖",5,"왞왟왡",10,"왭왮왰왲",5,"왺왻왽왾왿욁",6,"욊욌욎",5,"욖욗욙욚욛욝",6,"욦"], +["9f41","욨욪",5,"욲욳욵욶욷욻",4,"웂웄웆",5,"웎"], +["9f61","웏웑웒웓웕",6,"웞웟웢",5,"웪웫웭웮웯웱웲"], +["9f81","웳",4,"웺웻웼웾",5,"윆윇윉윊윋윍",6,"윖윘윚",5,"윢윣윥윦윧윩",6,"윲윴윶윸윹윺윻윾윿읁읂읃읅",4,"읋읎읐읙읚읛읝읞읟읡",6,"읩읪읬",7,"읶읷읹읺읻읿잀잁잂잆잋잌잍잏잒잓잕잙잛",4,"잢잧",4,"잮잯잱잲잳잵잶잷"], +["a041","잸잹잺잻잾쟂",5,"쟊쟋쟍쟏쟑",6,"쟙쟚쟛쟜"], +["a061","쟞",5,"쟥쟦쟧쟩쟪쟫쟭",13], +["a081","쟻",4,"젂젃젅젆젇젉젋",4,"젒젔젗",4,"젞젟젡젢젣젥",6,"젮젰젲",5,"젹젺젻젽젾젿졁",6,"졊졋졎",5,"졕",26,"졲졳졵졶졷졹졻",4,"좂좄좈좉좊좎",5,"좕",7,"좞좠좢좣좤"], +["a141","좥좦좧좩",18,"좾좿죀죁"], +["a161","죂죃죅죆죇죉죊죋죍",6,"죖죘죚",5,"죢죣죥"], +["a181","죦",14,"죶",5,"죾죿줁줂줃줇",4,"줎 、。·‥…¨〃­―∥\∼‘’“”〔〕〈",9,"±×÷≠≤≥∞∴°′″℃Å¢£¥♂♀∠⊥⌒∂∇≡≒§※☆★○●◎◇◆□■△▲▽▼→←↑↓↔〓≪≫√∽∝∵∫∬∈∋⊆⊇⊂⊃∪∩∧∨¬"], +["a241","줐줒",5,"줙",18], +["a261","줭",6,"줵",18], +["a281","쥈",7,"쥒쥓쥕쥖쥗쥙",6,"쥢쥤",7,"쥭쥮쥯⇒⇔∀∃´~ˇ˘˝˚˙¸˛¡¿ː∮∑∏¤℉‰◁◀▷▶♤♠♡♥♧♣⊙◈▣◐◑▒▤▥▨▧▦▩♨☏☎☜☞¶†‡↕↗↙↖↘♭♩♪♬㉿㈜№㏇™㏂㏘℡€®"], +["a341","쥱쥲쥳쥵",6,"쥽",10,"즊즋즍즎즏"], +["a361","즑",6,"즚즜즞",16], +["a381","즯",16,"짂짃짅짆짉짋",4,"짒짔짗짘짛!",58,"₩]",32," ̄"], +["a441","짞짟짡짣짥짦짨짩짪짫짮짲",5,"짺짻짽짾짿쨁쨂쨃쨄"], +["a461","쨅쨆쨇쨊쨎",5,"쨕쨖쨗쨙",12], +["a481","쨦쨧쨨쨪",28,"ㄱ",93], +["a541","쩇",4,"쩎쩏쩑쩒쩓쩕",6,"쩞쩢",5,"쩩쩪"], +["a561","쩫",17,"쩾",5,"쪅쪆"], +["a581","쪇",16,"쪙",14,"ⅰ",9], +["a5b0","Ⅰ",9], +["a5c1","Α",16,"Σ",6], +["a5e1","α",16,"σ",6], +["a641","쪨",19,"쪾쪿쫁쫂쫃쫅"], +["a661","쫆",5,"쫎쫐쫒쫔쫕쫖쫗쫚",5,"쫡",6], +["a681","쫨쫩쫪쫫쫭",6,"쫵",18,"쬉쬊─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂┒┑┚┙┖┕┎┍┞┟┡┢┦┧┩┪┭┮┱┲┵┶┹┺┽┾╀╁╃",7], +["a741","쬋",4,"쬑쬒쬓쬕쬖쬗쬙",6,"쬢",7], +["a761","쬪",22,"쭂쭃쭄"], +["a781","쭅쭆쭇쭊쭋쭍쭎쭏쭑",6,"쭚쭛쭜쭞",5,"쭥",7,"㎕㎖㎗ℓ㎘㏄㎣㎤㎥㎦㎙",9,"㏊㎍㎎㎏㏏㎈㎉㏈㎧㎨㎰",9,"㎀",4,"㎺",5,"㎐",4,"Ω㏀㏁㎊㎋㎌㏖㏅㎭㎮㎯㏛㎩㎪㎫㎬㏝㏐㏓㏃㏉㏜㏆"], +["a841","쭭",10,"쭺",14], +["a861","쮉",18,"쮝",6], +["a881","쮤",19,"쮹",11,"ÆÐªĦ"], +["a8a6","IJ"], +["a8a8","ĿŁØŒºÞŦŊ"], +["a8b1","㉠",27,"ⓐ",25,"①",14,"½⅓⅔¼¾⅛⅜⅝⅞"], +["a941","쯅",14,"쯕",10], +["a961","쯠쯡쯢쯣쯥쯦쯨쯪",18], +["a981","쯽",14,"찎찏찑찒찓찕",6,"찞찟찠찣찤æđðħıijĸŀłøœßþŧŋʼn㈀",27,"⒜",25,"⑴",14,"¹²³⁴ⁿ₁₂₃₄"], +["aa41","찥찦찪찫찭찯찱",6,"찺찿",4,"챆챇챉챊챋챍챎"], +["aa61","챏",4,"챖챚",5,"챡챢챣챥챧챩",6,"챱챲"], +["aa81","챳챴챶",29,"ぁ",82], +["ab41","첔첕첖첗첚첛첝첞첟첡",6,"첪첮",5,"첶첷첹"], +["ab61","첺첻첽",6,"쳆쳈쳊",5,"쳑쳒쳓쳕",5], +["ab81","쳛",8,"쳥",6,"쳭쳮쳯쳱",12,"ァ",85], +["ac41","쳾쳿촀촂",5,"촊촋촍촎촏촑",6,"촚촜촞촟촠"], +["ac61","촡촢촣촥촦촧촩촪촫촭",11,"촺",4], +["ac81","촿",28,"쵝쵞쵟А",5,"ЁЖ",25], +["acd1","а",5,"ёж",25], +["ad41","쵡쵢쵣쵥",6,"쵮쵰쵲",5,"쵹",7], +["ad61","춁",6,"춉",10,"춖춗춙춚춛춝춞춟"], +["ad81","춠춡춢춣춦춨춪",5,"춱",18,"췅"], +["ae41","췆",5,"췍췎췏췑",16], +["ae61","췢",5,"췩췪췫췭췮췯췱",6,"췺췼췾",4], +["ae81","츃츅츆츇츉츊츋츍",6,"츕츖츗츘츚",5,"츢츣츥츦츧츩츪츫"], +["af41","츬츭츮츯츲츴츶",19], +["af61","칊",13,"칚칛칝칞칢",5,"칪칬"], +["af81","칮",5,"칶칷칹칺칻칽",6,"캆캈캊",5,"캒캓캕캖캗캙"], +["b041","캚",5,"캢캦",5,"캮",12], +["b061","캻",5,"컂",19], +["b081","컖",13,"컦컧컩컪컭",6,"컶컺",5,"가각간갇갈갉갊감",7,"같",4,"갠갤갬갭갯갰갱갸갹갼걀걋걍걔걘걜거걱건걷걸걺검겁것겄겅겆겉겊겋게겐겔겜겝겟겠겡겨격겪견겯결겸겹겻겼경곁계곈곌곕곗고곡곤곧골곪곬곯곰곱곳공곶과곽관괄괆"], +["b141","켂켃켅켆켇켉",6,"켒켔켖",5,"켝켞켟켡켢켣"], +["b161","켥",6,"켮켲",5,"켹",11], +["b181","콅",14,"콖콗콙콚콛콝",6,"콦콨콪콫콬괌괍괏광괘괜괠괩괬괭괴괵괸괼굄굅굇굉교굔굘굡굣구국군굳굴굵굶굻굼굽굿궁궂궈궉권궐궜궝궤궷귀귁귄귈귐귑귓규균귤그극근귿글긁금급긋긍긔기긱긴긷길긺김깁깃깅깆깊까깍깎깐깔깖깜깝깟깠깡깥깨깩깬깰깸"], +["b241","콭콮콯콲콳콵콶콷콹",6,"쾁쾂쾃쾄쾆",5,"쾍"], +["b261","쾎",18,"쾢",5,"쾩"], +["b281","쾪",5,"쾱",18,"쿅",6,"깹깻깼깽꺄꺅꺌꺼꺽꺾껀껄껌껍껏껐껑께껙껜껨껫껭껴껸껼꼇꼈꼍꼐꼬꼭꼰꼲꼴꼼꼽꼿꽁꽂꽃꽈꽉꽐꽜꽝꽤꽥꽹꾀꾄꾈꾐꾑꾕꾜꾸꾹꾼꿀꿇꿈꿉꿋꿍꿎꿔꿜꿨꿩꿰꿱꿴꿸뀀뀁뀄뀌뀐뀔뀜뀝뀨끄끅끈끊끌끎끓끔끕끗끙"], +["b341","쿌",19,"쿢쿣쿥쿦쿧쿩"], +["b361","쿪",5,"쿲쿴쿶",5,"쿽쿾쿿퀁퀂퀃퀅",5], +["b381","퀋",5,"퀒",5,"퀙",19,"끝끼끽낀낄낌낍낏낑나낙낚난낟날낡낢남납낫",4,"낱낳내낵낸낼냄냅냇냈냉냐냑냔냘냠냥너넉넋넌널넒넓넘넙넛넜넝넣네넥넨넬넴넵넷넸넹녀녁년녈념녑녔녕녘녜녠노녹논놀놂놈놉놋농높놓놔놘놜놨뇌뇐뇔뇜뇝"], +["b441","퀮",5,"퀶퀷퀹퀺퀻퀽",6,"큆큈큊",5], +["b461","큑큒큓큕큖큗큙",6,"큡",10,"큮큯"], +["b481","큱큲큳큵",6,"큾큿킀킂",18,"뇟뇨뇩뇬뇰뇹뇻뇽누눅눈눋눌눔눕눗눙눠눴눼뉘뉜뉠뉨뉩뉴뉵뉼늄늅늉느늑는늘늙늚늠늡늣능늦늪늬늰늴니닉닌닐닒님닙닛닝닢다닥닦단닫",4,"닳담답닷",4,"닿대댁댄댈댐댑댓댔댕댜더덕덖던덛덜덞덟덤덥"], +["b541","킕",14,"킦킧킩킪킫킭",5], +["b561","킳킶킸킺",5,"탂탃탅탆탇탊",5,"탒탖",4], +["b581","탛탞탟탡탢탣탥",6,"탮탲",5,"탹",11,"덧덩덫덮데덱덴델뎀뎁뎃뎄뎅뎌뎐뎔뎠뎡뎨뎬도독돈돋돌돎돐돔돕돗동돛돝돠돤돨돼됐되된될됨됩됫됴두둑둔둘둠둡둣둥둬뒀뒈뒝뒤뒨뒬뒵뒷뒹듀듄듈듐듕드득든듣들듦듬듭듯등듸디딕딘딛딜딤딥딧딨딩딪따딱딴딸"], +["b641","턅",7,"턎",17], +["b661","턠",15,"턲턳턵턶턷턹턻턼턽턾"], +["b681","턿텂텆",5,"텎텏텑텒텓텕",6,"텞텠텢",5,"텩텪텫텭땀땁땃땄땅땋때땍땐땔땜땝땟땠땡떠떡떤떨떪떫떰떱떳떴떵떻떼떽뗀뗄뗌뗍뗏뗐뗑뗘뗬또똑똔똘똥똬똴뙈뙤뙨뚜뚝뚠뚤뚫뚬뚱뛔뛰뛴뛸뜀뜁뜅뜨뜩뜬뜯뜰뜸뜹뜻띄띈띌띔띕띠띤띨띰띱띳띵라락란랄람랍랏랐랑랒랖랗"], +["b741","텮",13,"텽",6,"톅톆톇톉톊"], +["b761","톋",20,"톢톣톥톦톧"], +["b781","톩",6,"톲톴톶톷톸톹톻톽톾톿퇁",14,"래랙랜랠램랩랫랬랭랴략랸럇량러럭런럴럼럽럿렀렁렇레렉렌렐렘렙렛렝려력련렬렴렵렷렸령례롄롑롓로록론롤롬롭롯롱롸롼뢍뢨뢰뢴뢸룀룁룃룅료룐룔룝룟룡루룩룬룰룸룹룻룽뤄뤘뤠뤼뤽륀륄륌륏륑류륙륜률륨륩"], +["b841","퇐",7,"퇙",17], +["b861","퇫",8,"퇵퇶퇷퇹",13], +["b881","툈툊",5,"툑",24,"륫륭르륵른를름릅릇릉릊릍릎리릭린릴림립릿링마막만많",4,"맘맙맛망맞맡맣매맥맨맬맴맵맷맸맹맺먀먁먈먕머먹먼멀멂멈멉멋멍멎멓메멕멘멜멤멥멧멨멩며멱면멸몃몄명몇몌모목몫몬몰몲몸몹못몽뫄뫈뫘뫙뫼"], +["b941","툪툫툮툯툱툲툳툵",6,"툾퉀퉂",5,"퉉퉊퉋퉌"], +["b961","퉍",14,"퉝",6,"퉥퉦퉧퉨"], +["b981","퉩",22,"튂튃튅튆튇튉튊튋튌묀묄묍묏묑묘묜묠묩묫무묵묶문묻물묽묾뭄뭅뭇뭉뭍뭏뭐뭔뭘뭡뭣뭬뮈뮌뮐뮤뮨뮬뮴뮷므믄믈믐믓미믹민믿밀밂밈밉밋밌밍및밑바",4,"받",4,"밤밥밧방밭배백밴밸뱀뱁뱃뱄뱅뱉뱌뱍뱐뱝버벅번벋벌벎범법벗"], +["ba41","튍튎튏튒튓튔튖",5,"튝튞튟튡튢튣튥",6,"튭"], +["ba61","튮튯튰튲",5,"튺튻튽튾틁틃",4,"틊틌",5], +["ba81","틒틓틕틖틗틙틚틛틝",6,"틦",9,"틲틳틵틶틷틹틺벙벚베벡벤벧벨벰벱벳벴벵벼벽변별볍볏볐병볕볘볜보복볶본볼봄봅봇봉봐봔봤봬뵀뵈뵉뵌뵐뵘뵙뵤뵨부북분붇불붉붊붐붑붓붕붙붚붜붤붰붸뷔뷕뷘뷜뷩뷰뷴뷸븀븃븅브븍븐블븜븝븟비빅빈빌빎빔빕빗빙빚빛빠빡빤"], +["bb41","틻",4,"팂팄팆",5,"팏팑팒팓팕팗",4,"팞팢팣"], +["bb61","팤팦팧팪팫팭팮팯팱",6,"팺팾",5,"퍆퍇퍈퍉"], +["bb81","퍊",31,"빨빪빰빱빳빴빵빻빼빽뺀뺄뺌뺍뺏뺐뺑뺘뺙뺨뻐뻑뻔뻗뻘뻠뻣뻤뻥뻬뼁뼈뼉뼘뼙뼛뼜뼝뽀뽁뽄뽈뽐뽑뽕뾔뾰뿅뿌뿍뿐뿔뿜뿟뿡쀼쁑쁘쁜쁠쁨쁩삐삑삔삘삠삡삣삥사삭삯산삳살삵삶삼삽삿샀상샅새색샌샐샘샙샛샜생샤"], +["bc41","퍪",17,"퍾퍿펁펂펃펅펆펇"], +["bc61","펈펉펊펋펎펒",5,"펚펛펝펞펟펡",6,"펪펬펮"], +["bc81","펯",4,"펵펶펷펹펺펻펽",6,"폆폇폊",5,"폑",5,"샥샨샬샴샵샷샹섀섄섈섐섕서",4,"섣설섦섧섬섭섯섰성섶세섹센셀셈셉셋셌셍셔셕션셜셤셥셧셨셩셰셴셸솅소속솎손솔솖솜솝솟송솥솨솩솬솰솽쇄쇈쇌쇔쇗쇘쇠쇤쇨쇰쇱쇳쇼쇽숀숄숌숍숏숑수숙순숟술숨숩숫숭"], +["bd41","폗폙",7,"폢폤",7,"폮폯폱폲폳폵폶폷"], +["bd61","폸폹폺폻폾퐀퐂",5,"퐉",13], +["bd81","퐗",5,"퐞",25,"숯숱숲숴쉈쉐쉑쉔쉘쉠쉥쉬쉭쉰쉴쉼쉽쉿슁슈슉슐슘슛슝스슥슨슬슭슴습슷승시식신싣실싫심십싯싱싶싸싹싻싼쌀쌈쌉쌌쌍쌓쌔쌕쌘쌜쌤쌥쌨쌩썅써썩썬썰썲썸썹썼썽쎄쎈쎌쏀쏘쏙쏜쏟쏠쏢쏨쏩쏭쏴쏵쏸쐈쐐쐤쐬쐰"], +["be41","퐸",7,"푁푂푃푅",14], +["be61","푔",7,"푝푞푟푡푢푣푥",7,"푮푰푱푲"], +["be81","푳",4,"푺푻푽푾풁풃",4,"풊풌풎",5,"풕",8,"쐴쐼쐽쑈쑤쑥쑨쑬쑴쑵쑹쒀쒔쒜쒸쒼쓩쓰쓱쓴쓸쓺쓿씀씁씌씐씔씜씨씩씬씰씸씹씻씽아악안앉않알앍앎앓암압앗았앙앝앞애액앤앨앰앱앳앴앵야약얀얄얇얌얍얏양얕얗얘얜얠얩어억언얹얻얼얽얾엄",6,"엌엎"], +["bf41","풞",10,"풪",14], +["bf61","풹",18,"퓍퓎퓏퓑퓒퓓퓕"], +["bf81","퓖",5,"퓝퓞퓠",7,"퓩퓪퓫퓭퓮퓯퓱",6,"퓹퓺퓼에엑엔엘엠엡엣엥여역엮연열엶엷염",5,"옅옆옇예옌옐옘옙옛옜오옥온올옭옮옰옳옴옵옷옹옻와왁완왈왐왑왓왔왕왜왝왠왬왯왱외왹왼욀욈욉욋욍요욕욘욜욤욥욧용우욱운울욹욺움웁웃웅워웍원월웜웝웠웡웨"], +["c041","퓾",5,"픅픆픇픉픊픋픍",6,"픖픘",5], +["c061","픞",25], +["c081","픸픹픺픻픾픿핁핂핃핅",6,"핎핐핒",5,"핚핛핝핞핟핡핢핣웩웬웰웸웹웽위윅윈윌윔윕윗윙유육윤율윰윱윳융윷으윽은을읊음읍읏응",7,"읜읠읨읫이익인일읽읾잃임입잇있잉잊잎자작잔잖잗잘잚잠잡잣잤장잦재잭잰잴잼잽잿쟀쟁쟈쟉쟌쟎쟐쟘쟝쟤쟨쟬저적전절젊"], +["c141","핤핦핧핪핬핮",5,"핶핷핹핺핻핽",6,"햆햊햋"], +["c161","햌햍햎햏햑",19,"햦햧"], +["c181","햨",31,"점접젓정젖제젝젠젤젬젭젯젱져젼졀졈졉졌졍졔조족존졸졺좀좁좃종좆좇좋좌좍좔좝좟좡좨좼좽죄죈죌죔죕죗죙죠죡죤죵주죽준줄줅줆줌줍줏중줘줬줴쥐쥑쥔쥘쥠쥡쥣쥬쥰쥴쥼즈즉즌즐즘즙즛증지직진짇질짊짐집짓"], +["c241","헊헋헍헎헏헑헓",4,"헚헜헞",5,"헦헧헩헪헫헭헮"], +["c261","헯",4,"헶헸헺",5,"혂혃혅혆혇혉",6,"혒"], +["c281","혖",5,"혝혞혟혡혢혣혥",7,"혮",9,"혺혻징짖짙짚짜짝짠짢짤짧짬짭짯짰짱째짹짼쨀쨈쨉쨋쨌쨍쨔쨘쨩쩌쩍쩐쩔쩜쩝쩟쩠쩡쩨쩽쪄쪘쪼쪽쫀쫄쫌쫍쫏쫑쫓쫘쫙쫠쫬쫴쬈쬐쬔쬘쬠쬡쭁쭈쭉쭌쭐쭘쭙쭝쭤쭸쭹쮜쮸쯔쯤쯧쯩찌찍찐찔찜찝찡찢찧차착찬찮찰참찹찻"], +["c341","혽혾혿홁홂홃홄홆홇홊홌홎홏홐홒홓홖홗홙홚홛홝",4], +["c361","홢",4,"홨홪",5,"홲홳홵",11], +["c381","횁횂횄횆",5,"횎횏횑횒횓횕",7,"횞횠횢",5,"횩횪찼창찾채책챈챌챔챕챗챘챙챠챤챦챨챰챵처척천철첨첩첫첬청체첵첸첼쳄쳅쳇쳉쳐쳔쳤쳬쳰촁초촉촌촐촘촙촛총촤촨촬촹최쵠쵤쵬쵭쵯쵱쵸춈추축춘출춤춥춧충춰췄췌췐취췬췰췸췹췻췽츄츈츌츔츙츠측츤츨츰츱츳층"], +["c441","횫횭횮횯횱",7,"횺횼",7,"훆훇훉훊훋"], +["c461","훍훎훏훐훒훓훕훖훘훚",5,"훡훢훣훥훦훧훩",4], +["c481","훮훯훱훲훳훴훶",5,"훾훿휁휂휃휅",11,"휒휓휔치칙친칟칠칡침칩칫칭카칵칸칼캄캅캇캉캐캑캔캘캠캡캣캤캥캬캭컁커컥컨컫컬컴컵컷컸컹케켁켄켈켐켑켓켕켜켠켤켬켭켯켰켱켸코콕콘콜콤콥콧콩콰콱콴콸쾀쾅쾌쾡쾨쾰쿄쿠쿡쿤쿨쿰쿱쿳쿵쿼퀀퀄퀑퀘퀭퀴퀵퀸퀼"], +["c541","휕휖휗휚휛휝휞휟휡",6,"휪휬휮",5,"휶휷휹"], +["c561","휺휻휽",6,"흅흆흈흊",5,"흒흓흕흚",4], +["c581","흟흢흤흦흧흨흪흫흭흮흯흱흲흳흵",6,"흾흿힀힂",5,"힊힋큄큅큇큉큐큔큘큠크큭큰클큼큽킁키킥킨킬킴킵킷킹타탁탄탈탉탐탑탓탔탕태택탠탤탬탭탯탰탱탸턍터턱턴털턺텀텁텃텄텅테텍텐텔템텝텟텡텨텬텼톄톈토톡톤톨톰톱톳통톺톼퇀퇘퇴퇸툇툉툐투툭툰툴툼툽툿퉁퉈퉜"], +["c641","힍힎힏힑",6,"힚힜힞",5], +["c6a1","퉤튀튁튄튈튐튑튕튜튠튤튬튱트특튼튿틀틂틈틉틋틔틘틜틤틥티틱틴틸팀팁팃팅파팍팎판팔팖팜팝팟팠팡팥패팩팬팰팸팹팻팼팽퍄퍅퍼퍽펀펄펌펍펏펐펑페펙펜펠펨펩펫펭펴편펼폄폅폈평폐폘폡폣포폭폰폴폼폽폿퐁"], +["c7a1","퐈퐝푀푄표푠푤푭푯푸푹푼푿풀풂품풉풋풍풔풩퓌퓐퓔퓜퓟퓨퓬퓰퓸퓻퓽프픈플픔픕픗피픽핀필핌핍핏핑하학한할핥함합핫항해핵핸핼햄햅햇했행햐향허헉헌헐헒험헙헛헝헤헥헨헬헴헵헷헹혀혁현혈혐협혓혔형혜혠"], +["c8a1","혤혭호혹혼홀홅홈홉홋홍홑화확환활홧황홰홱홴횃횅회획횐횔횝횟횡효횬횰횹횻후훅훈훌훑훔훗훙훠훤훨훰훵훼훽휀휄휑휘휙휜휠휨휩휫휭휴휵휸휼흄흇흉흐흑흔흖흗흘흙흠흡흣흥흩희흰흴흼흽힁히힉힌힐힘힙힛힝"], +["caa1","伽佳假價加可呵哥嘉嫁家暇架枷柯歌珂痂稼苛茄街袈訶賈跏軻迦駕刻却各恪慤殼珏脚覺角閣侃刊墾奸姦干幹懇揀杆柬桿澗癎看磵稈竿簡肝艮艱諫間乫喝曷渴碣竭葛褐蝎鞨勘坎堪嵌感憾戡敢柑橄減甘疳監瞰紺邯鑑鑒龕"], +["cba1","匣岬甲胛鉀閘剛堈姜岡崗康强彊慷江畺疆糠絳綱羌腔舡薑襁講鋼降鱇介价個凱塏愷愾慨改槪漑疥皆盖箇芥蓋豈鎧開喀客坑更粳羹醵倨去居巨拒据據擧渠炬祛距踞車遽鉅鋸乾件健巾建愆楗腱虔蹇鍵騫乞傑杰桀儉劍劒檢"], +["cca1","瞼鈐黔劫怯迲偈憩揭擊格檄激膈覡隔堅牽犬甄絹繭肩見譴遣鵑抉決潔結缺訣兼慊箝謙鉗鎌京俓倞傾儆勁勍卿坰境庚徑慶憬擎敬景暻更梗涇炅烱璟璥瓊痙硬磬竟競絅經耕耿脛莖警輕逕鏡頃頸驚鯨係啓堺契季屆悸戒桂械"], +["cda1","棨溪界癸磎稽系繫繼計誡谿階鷄古叩告呱固姑孤尻庫拷攷故敲暠枯槁沽痼皐睾稿羔考股膏苦苽菰藁蠱袴誥賈辜錮雇顧高鼓哭斛曲梏穀谷鵠困坤崑昆梱棍滾琨袞鯤汨滑骨供公共功孔工恐恭拱控攻珙空蚣貢鞏串寡戈果瓜"], +["cea1","科菓誇課跨過鍋顆廓槨藿郭串冠官寬慣棺款灌琯瓘管罐菅觀貫關館刮恝括适侊光匡壙廣曠洸炚狂珖筐胱鑛卦掛罫乖傀塊壞怪愧拐槐魁宏紘肱轟交僑咬喬嬌嶠巧攪敎校橋狡皎矯絞翹膠蕎蛟較轎郊餃驕鮫丘久九仇俱具勾"], +["cfa1","區口句咎嘔坵垢寇嶇廐懼拘救枸柩構歐毆毬求溝灸狗玖球瞿矩究絿耉臼舅舊苟衢謳購軀逑邱鉤銶駒驅鳩鷗龜國局菊鞠鞫麴君窘群裙軍郡堀屈掘窟宮弓穹窮芎躬倦券勸卷圈拳捲權淃眷厥獗蕨蹶闕机櫃潰詭軌饋句晷歸貴"], +["d0a1","鬼龜叫圭奎揆槻珪硅窺竅糾葵規赳逵閨勻均畇筠菌鈞龜橘克剋劇戟棘極隙僅劤勤懃斤根槿瑾筋芹菫覲謹近饉契今妗擒昑檎琴禁禽芩衾衿襟金錦伋及急扱汲級給亘兢矜肯企伎其冀嗜器圻基埼夔奇妓寄岐崎己幾忌技旗旣"], +["d1a1","朞期杞棋棄機欺氣汽沂淇玘琦琪璂璣畸畿碁磯祁祇祈祺箕紀綺羈耆耭肌記譏豈起錡錤飢饑騎騏驥麒緊佶吉拮桔金喫儺喇奈娜懦懶拏拿癩",5,"那樂",4,"諾酪駱亂卵暖欄煖爛蘭難鸞捏捺南嵐枏楠湳濫男藍襤拉"], +["d2a1","納臘蠟衲囊娘廊",4,"乃來內奈柰耐冷女年撚秊念恬拈捻寧寗努勞奴弩怒擄櫓爐瑙盧",5,"駑魯",10,"濃籠聾膿農惱牢磊腦賂雷尿壘",7,"嫩訥杻紐勒",5,"能菱陵尼泥匿溺多茶"], +["d3a1","丹亶但單團壇彖斷旦檀段湍短端簞緞蛋袒鄲鍛撻澾獺疸達啖坍憺擔曇淡湛潭澹痰聃膽蕁覃談譚錟沓畓答踏遝唐堂塘幢戇撞棠當糖螳黨代垈坮大對岱帶待戴擡玳臺袋貸隊黛宅德悳倒刀到圖堵塗導屠島嶋度徒悼挑掉搗桃"], +["d4a1","棹櫂淘渡滔濤燾盜睹禱稻萄覩賭跳蹈逃途道都鍍陶韜毒瀆牘犢獨督禿篤纛讀墩惇敦旽暾沌焞燉豚頓乭突仝冬凍動同憧東桐棟洞潼疼瞳童胴董銅兜斗杜枓痘竇荳讀豆逗頭屯臀芚遁遯鈍得嶝橙燈登等藤謄鄧騰喇懶拏癩羅"], +["d5a1","蘿螺裸邏樂洛烙珞絡落諾酪駱丹亂卵欄欒瀾爛蘭鸞剌辣嵐擥攬欖濫籃纜藍襤覽拉臘蠟廊朗浪狼琅瑯螂郞來崍徠萊冷掠略亮倆兩凉梁樑粮粱糧良諒輛量侶儷勵呂廬慮戾旅櫚濾礪藜蠣閭驢驪麗黎力曆歷瀝礫轢靂憐戀攣漣"], +["d6a1","煉璉練聯蓮輦連鍊冽列劣洌烈裂廉斂殮濂簾獵令伶囹寧岺嶺怜玲笭羚翎聆逞鈴零靈領齡例澧禮醴隷勞怒撈擄櫓潞瀘爐盧老蘆虜路輅露魯鷺鹵碌祿綠菉錄鹿麓論壟弄朧瀧瓏籠聾儡瀨牢磊賂賚賴雷了僚寮廖料燎療瞭聊蓼"], +["d7a1","遼鬧龍壘婁屢樓淚漏瘻累縷蔞褸鏤陋劉旒柳榴流溜瀏琉瑠留瘤硫謬類六戮陸侖倫崙淪綸輪律慄栗率隆勒肋凜凌楞稜綾菱陵俚利厘吏唎履悧李梨浬犁狸理璃異痢籬罹羸莉裏裡里釐離鯉吝潾燐璘藺躪隣鱗麟林淋琳臨霖砬"], +["d8a1","立笠粒摩瑪痲碼磨馬魔麻寞幕漠膜莫邈万卍娩巒彎慢挽晩曼滿漫灣瞞萬蔓蠻輓饅鰻唜抹末沫茉襪靺亡妄忘忙望網罔芒茫莽輞邙埋妹媒寐昧枚梅每煤罵買賣邁魅脈貊陌驀麥孟氓猛盲盟萌冪覓免冕勉棉沔眄眠綿緬面麵滅"], +["d9a1","蔑冥名命明暝椧溟皿瞑茗蓂螟酩銘鳴袂侮冒募姆帽慕摸摹暮某模母毛牟牡瑁眸矛耗芼茅謀謨貌木沐牧目睦穆鶩歿沒夢朦蒙卯墓妙廟描昴杳渺猫竗苗錨務巫憮懋戊拇撫无楙武毋無珷畝繆舞茂蕪誣貿霧鵡墨默們刎吻問文"], +["daa1","汶紊紋聞蚊門雯勿沕物味媚尾嵋彌微未梶楣渼湄眉米美薇謎迷靡黴岷悶愍憫敏旻旼民泯玟珉緡閔密蜜謐剝博拍搏撲朴樸泊珀璞箔粕縛膊舶薄迫雹駁伴半反叛拌搬攀斑槃泮潘班畔瘢盤盼磐磻礬絆般蟠返頒飯勃拔撥渤潑"], +["dba1","發跋醱鉢髮魃倣傍坊妨尨幇彷房放方旁昉枋榜滂磅紡肪膀舫芳蒡蚌訪謗邦防龐倍俳北培徘拜排杯湃焙盃背胚裴裵褙賠輩配陪伯佰帛柏栢白百魄幡樊煩燔番磻繁蕃藩飜伐筏罰閥凡帆梵氾汎泛犯範范法琺僻劈壁擘檗璧癖"], +["dca1","碧蘗闢霹便卞弁變辨辯邊別瞥鱉鼈丙倂兵屛幷昞昺柄棅炳甁病秉竝輧餠騈保堡報寶普步洑湺潽珤甫菩補褓譜輔伏僕匐卜宓復服福腹茯蔔複覆輹輻馥鰒本乶俸奉封峯峰捧棒烽熢琫縫蓬蜂逢鋒鳳不付俯傅剖副否咐埠夫婦"], +["dda1","孚孵富府復扶敷斧浮溥父符簿缶腐腑膚艀芙莩訃負賦賻赴趺部釜阜附駙鳧北分吩噴墳奔奮忿憤扮昐汾焚盆粉糞紛芬賁雰不佛弗彿拂崩朋棚硼繃鵬丕備匕匪卑妃婢庇悲憊扉批斐枇榧比毖毗毘沸泌琵痺砒碑秕秘粃緋翡肥"], +["dea1","脾臂菲蜚裨誹譬費鄙非飛鼻嚬嬪彬斌檳殯浜濱瀕牝玭貧賓頻憑氷聘騁乍事些仕伺似使俟僿史司唆嗣四士奢娑寫寺射巳師徙思捨斜斯柶査梭死沙泗渣瀉獅砂社祀祠私篩紗絲肆舍莎蓑蛇裟詐詞謝賜赦辭邪飼駟麝削數朔索"], +["dfa1","傘刪山散汕珊産疝算蒜酸霰乷撒殺煞薩三參杉森渗芟蔘衫揷澁鈒颯上傷像償商喪嘗孀尙峠常床庠廂想桑橡湘爽牀狀相祥箱翔裳觴詳象賞霜塞璽賽嗇塞穡索色牲生甥省笙墅壻嶼序庶徐恕抒捿敍暑曙書栖棲犀瑞筮絮緖署"], +["e0a1","胥舒薯西誓逝鋤黍鼠夕奭席惜昔晳析汐淅潟石碩蓆釋錫仙僊先善嬋宣扇敾旋渲煽琁瑄璇璿癬禪線繕羨腺膳船蘚蟬詵跣選銑鐥饍鮮卨屑楔泄洩渫舌薛褻設說雪齧剡暹殲纖蟾贍閃陝攝涉燮葉城姓宬性惺成星晟猩珹盛省筬"], +["e1a1","聖聲腥誠醒世勢歲洗稅笹細說貰召嘯塑宵小少巢所掃搔昭梳沼消溯瀟炤燒甦疏疎瘙笑篠簫素紹蔬蕭蘇訴逍遡邵銷韶騷俗屬束涑粟續謖贖速孫巽損蓀遜飡率宋悚松淞訟誦送頌刷殺灑碎鎖衰釗修受嗽囚垂壽嫂守岫峀帥愁"], +["e2a1","戍手授搜收數樹殊水洙漱燧狩獸琇璲瘦睡秀穗竪粹綏綬繡羞脩茱蒐蓚藪袖誰讐輸遂邃酬銖銹隋隧隨雖需須首髓鬚叔塾夙孰宿淑潚熟琡璹肅菽巡徇循恂旬栒楯橓殉洵淳珣盾瞬筍純脣舜荀蓴蕣詢諄醇錞順馴戌術述鉥崇崧"], +["e3a1","嵩瑟膝蝨濕拾習褶襲丞乘僧勝升承昇繩蠅陞侍匙嘶始媤尸屎屍市弑恃施是時枾柴猜矢示翅蒔蓍視試詩諡豕豺埴寔式息拭植殖湜熄篒蝕識軾食飾伸侁信呻娠宸愼新晨燼申神紳腎臣莘薪藎蜃訊身辛辰迅失室實悉審尋心沁"], +["e4a1","沈深瀋甚芯諶什十拾雙氏亞俄兒啞娥峨我牙芽莪蛾衙訝阿雅餓鴉鵝堊岳嶽幄惡愕握樂渥鄂鍔顎鰐齷安岸按晏案眼雁鞍顔鮟斡謁軋閼唵岩巖庵暗癌菴闇壓押狎鴨仰央怏昻殃秧鴦厓哀埃崖愛曖涯碍艾隘靄厄扼掖液縊腋額"], +["e5a1","櫻罌鶯鸚也倻冶夜惹揶椰爺耶若野弱掠略約若葯蒻藥躍亮佯兩凉壤孃恙揚攘敭暘梁楊樣洋瀁煬痒瘍禳穰糧羊良襄諒讓釀陽量養圄御於漁瘀禦語馭魚齬億憶抑檍臆偃堰彦焉言諺孼蘖俺儼嚴奄掩淹嶪業円予余勵呂女如廬"], +["e6a1","旅歟汝濾璵礖礪與艅茹輿轝閭餘驪麗黎亦力域役易曆歷疫繹譯轢逆驛嚥堧姸娟宴年延憐戀捐挻撚椽沇沿涎涓淵演漣烟然煙煉燃燕璉硏硯秊筵緣練縯聯衍軟輦蓮連鉛鍊鳶列劣咽悅涅烈熱裂說閱厭廉念捻染殮炎焰琰艶苒"], +["e7a1","簾閻髥鹽曄獵燁葉令囹塋寧嶺嶸影怜映暎楹榮永泳渶潁濚瀛瀯煐營獰玲瑛瑩瓔盈穎纓羚聆英詠迎鈴鍈零霙靈領乂倪例刈叡曳汭濊猊睿穢芮藝蘂禮裔詣譽豫醴銳隸霓預五伍俉傲午吾吳嗚塢墺奧娛寤悟惡懊敖旿晤梧汚澳"], +["e8a1","烏熬獒筽蜈誤鰲鼇屋沃獄玉鈺溫瑥瘟穩縕蘊兀壅擁瓮甕癰翁邕雍饔渦瓦窩窪臥蛙蝸訛婉完宛梡椀浣玩琓琬碗緩翫脘腕莞豌阮頑曰往旺枉汪王倭娃歪矮外嵬巍猥畏了僚僥凹堯夭妖姚寥寮尿嶢拗搖撓擾料曜樂橈燎燿瑤療"], +["e9a1","窈窯繇繞耀腰蓼蟯要謠遙遼邀饒慾欲浴縟褥辱俑傭冗勇埇墉容庸慂榕涌湧溶熔瑢用甬聳茸蓉踊鎔鏞龍于佑偶優又友右宇寓尤愚憂旴牛玗瑀盂祐禑禹紆羽芋藕虞迂遇郵釪隅雨雩勖彧旭昱栯煜稶郁頊云暈橒殞澐熉耘芸蕓"], +["eaa1","運隕雲韻蔚鬱亐熊雄元原員圓園垣媛嫄寃怨愿援沅洹湲源爰猿瑗苑袁轅遠阮院願鴛月越鉞位偉僞危圍委威尉慰暐渭爲瑋緯胃萎葦蔿蝟衛褘謂違韋魏乳侑儒兪劉唯喩孺宥幼幽庾悠惟愈愉揄攸有杻柔柚柳楡楢油洧流游溜"], +["eba1","濡猶猷琉瑜由留癒硫紐維臾萸裕誘諛諭踰蹂遊逾遺酉釉鍮類六堉戮毓肉育陸倫允奫尹崙淪潤玧胤贇輪鈗閏律慄栗率聿戎瀜絨融隆垠恩慇殷誾銀隱乙吟淫蔭陰音飮揖泣邑凝應膺鷹依倚儀宜意懿擬椅毅疑矣義艤薏蟻衣誼"], +["eca1","議醫二以伊利吏夷姨履已弛彛怡易李梨泥爾珥理異痍痢移罹而耳肄苡荑裏裡貽貳邇里離飴餌匿溺瀷益翊翌翼謚人仁刃印吝咽因姻寅引忍湮燐璘絪茵藺蚓認隣靭靷鱗麟一佚佾壹日溢逸鎰馹任壬妊姙恁林淋稔臨荏賃入卄"], +["eda1","立笠粒仍剩孕芿仔刺咨姉姿子字孜恣慈滋炙煮玆瓷疵磁紫者自茨蔗藉諮資雌作勺嚼斫昨灼炸爵綽芍酌雀鵲孱棧殘潺盞岑暫潛箴簪蠶雜丈仗匠場墻壯奬將帳庄張掌暲杖樟檣欌漿牆狀獐璋章粧腸臟臧莊葬蔣薔藏裝贓醬長"], +["eea1","障再哉在宰才材栽梓渽滓災縡裁財載齋齎爭箏諍錚佇低儲咀姐底抵杵楮樗沮渚狙猪疽箸紵苧菹著藷詛貯躇這邸雎齟勣吊嫡寂摘敵滴狄炙的積笛籍績翟荻謫賊赤跡蹟迪迹適鏑佃佺傳全典前剪塡塼奠專展廛悛戰栓殿氈澱"], +["efa1","煎琠田甸畑癲筌箋箭篆纏詮輾轉鈿銓錢鐫電顚顫餞切截折浙癤竊節絶占岾店漸点粘霑鮎點接摺蝶丁井亭停偵呈姃定幀庭廷征情挺政整旌晶晸柾楨檉正汀淀淨渟湞瀞炡玎珽町睛碇禎程穽精綎艇訂諪貞鄭酊釘鉦鋌錠霆靖"], +["f0a1","靜頂鼎制劑啼堤帝弟悌提梯濟祭第臍薺製諸蹄醍除際霽題齊俎兆凋助嘲弔彫措操早晁曺曹朝條棗槽漕潮照燥爪璪眺祖祚租稠窕粗糟組繰肇藻蚤詔調趙躁造遭釣阻雕鳥族簇足鏃存尊卒拙猝倧宗從悰慫棕淙琮種終綜縱腫"], +["f1a1","踪踵鍾鐘佐坐左座挫罪主住侏做姝胄呪周嗾奏宙州廚晝朱柱株注洲湊澍炷珠疇籌紂紬綢舟蛛註誅走躊輳週酎酒鑄駐竹粥俊儁准埈寯峻晙樽浚準濬焌畯竣蠢逡遵雋駿茁中仲衆重卽櫛楫汁葺增憎曾拯烝甑症繒蒸證贈之只"], +["f2a1","咫地址志持指摯支旨智枝枳止池沚漬知砥祉祗紙肢脂至芝芷蜘誌識贄趾遲直稙稷織職唇嗔塵振搢晉晋桭榛殄津溱珍瑨璡畛疹盡眞瞋秦縉縝臻蔯袗診賑軫辰進鎭陣陳震侄叱姪嫉帙桎瓆疾秩窒膣蛭質跌迭斟朕什執潗緝輯"], +["f3a1","鏶集徵懲澄且侘借叉嗟嵯差次此磋箚茶蹉車遮捉搾着窄錯鑿齪撰澯燦璨瓚竄簒纂粲纘讚贊鑽餐饌刹察擦札紮僭參塹慘慙懺斬站讒讖倉倡創唱娼廠彰愴敞昌昶暢槍滄漲猖瘡窓脹艙菖蒼債埰寀寨彩採砦綵菜蔡采釵冊柵策"], +["f4a1","責凄妻悽處倜刺剔尺慽戚拓擲斥滌瘠脊蹠陟隻仟千喘天川擅泉淺玔穿舛薦賤踐遷釧闡阡韆凸哲喆徹撤澈綴輟轍鐵僉尖沾添甛瞻簽籤詹諂堞妾帖捷牒疊睫諜貼輒廳晴淸聽菁請靑鯖切剃替涕滯締諦逮遞體初剿哨憔抄招梢"], +["f5a1","椒楚樵炒焦硝礁礎秒稍肖艸苕草蕉貂超酢醋醮促囑燭矗蜀觸寸忖村邨叢塚寵悤憁摠總聰蔥銃撮催崔最墜抽推椎楸樞湫皺秋芻萩諏趨追鄒酋醜錐錘鎚雛騶鰍丑畜祝竺筑築縮蓄蹙蹴軸逐春椿瑃出朮黜充忠沖蟲衝衷悴膵萃"], +["f6a1","贅取吹嘴娶就炊翠聚脆臭趣醉驟鷲側仄厠惻測層侈値嗤峙幟恥梔治淄熾痔痴癡稚穉緇緻置致蚩輜雉馳齒則勅飭親七柒漆侵寢枕沈浸琛砧針鍼蟄秤稱快他咤唾墮妥惰打拖朶楕舵陀馱駝倬卓啄坼度托拓擢晫柝濁濯琢琸託"], +["f7a1","鐸呑嘆坦彈憚歎灘炭綻誕奪脫探眈耽貪塔搭榻宕帑湯糖蕩兌台太怠態殆汰泰笞胎苔跆邰颱宅擇澤撑攄兎吐土討慟桶洞痛筒統通堆槌腿褪退頹偸套妬投透鬪慝特闖坡婆巴把播擺杷波派爬琶破罷芭跛頗判坂板版瓣販辦鈑"], +["f8a1","阪八叭捌佩唄悖敗沛浿牌狽稗覇貝彭澎烹膨愎便偏扁片篇編翩遍鞭騙貶坪平枰萍評吠嬖幣廢弊斃肺蔽閉陛佈包匍匏咆哺圃布怖抛抱捕暴泡浦疱砲胞脯苞葡蒲袍褒逋鋪飽鮑幅暴曝瀑爆輻俵剽彪慓杓標漂瓢票表豹飇飄驃"], +["f9a1","品稟楓諷豊風馮彼披疲皮被避陂匹弼必泌珌畢疋筆苾馝乏逼下何厦夏廈昰河瑕荷蝦賀遐霞鰕壑學虐謔鶴寒恨悍旱汗漢澣瀚罕翰閑閒限韓割轄函含咸啣喊檻涵緘艦銜陷鹹合哈盒蛤閤闔陜亢伉姮嫦巷恒抗杭桁沆港缸肛航"], +["faa1","行降項亥偕咳垓奚孩害懈楷海瀣蟹解該諧邂駭骸劾核倖幸杏荇行享向嚮珦鄕響餉饗香噓墟虛許憲櫶獻軒歇險驗奕爀赫革俔峴弦懸晛泫炫玄玹現眩睍絃絢縣舷衒見賢鉉顯孑穴血頁嫌俠協夾峽挾浹狹脅脇莢鋏頰亨兄刑型"], +["fba1","形泂滎瀅灐炯熒珩瑩荊螢衡逈邢鎣馨兮彗惠慧暳蕙蹊醯鞋乎互呼壕壺好岵弧戶扈昊晧毫浩淏湖滸澔濠濩灝狐琥瑚瓠皓祜糊縞胡芦葫蒿虎號蝴護豪鎬頀顥惑或酷婚昏混渾琿魂忽惚笏哄弘汞泓洪烘紅虹訌鴻化和嬅樺火畵"], +["fca1","禍禾花華話譁貨靴廓擴攫確碻穫丸喚奐宦幻患換歡晥桓渙煥環紈還驩鰥活滑猾豁闊凰幌徨恍惶愰慌晃晄榥況湟滉潢煌璜皇篁簧荒蝗遑隍黃匯回廻徊恢悔懷晦會檜淮澮灰獪繪膾茴蛔誨賄劃獲宖橫鐄哮嚆孝效斅曉梟涍淆"], +["fda1","爻肴酵驍侯候厚后吼喉嗅帿後朽煦珝逅勛勳塤壎焄熏燻薰訓暈薨喧暄煊萱卉喙毁彙徽揮暉煇諱輝麾休携烋畦虧恤譎鷸兇凶匈洶胸黑昕欣炘痕吃屹紇訖欠欽歆吸恰洽翕興僖凞喜噫囍姬嬉希憙憘戱晞曦熙熹熺犧禧稀羲詰"] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp950.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp950.json new file mode 100644 index 0000000..d8bc871 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp950.json @@ -0,0 +1,177 @@ +[ +["0","\u0000",127], +["a140"," ,、。.‧;:?!︰…‥﹐﹑﹒·﹔﹕﹖﹗|–︱—︳╴︴﹏()︵︶{}︷︸〔〕︹︺【】︻︼《》︽︾〈〉︿﹀「」﹁﹂『』﹃﹄﹙﹚"], +["a1a1","﹛﹜﹝﹞‘’“”〝〞‵′#&*※§〃○●△▲◎☆★◇◆□■▽▼㊣℅¯ ̄_ˍ﹉﹊﹍﹎﹋﹌﹟﹠﹡+-×÷±√<>=≦≧≠∞≒≡﹢",4,"~∩∪⊥∠∟⊿㏒㏑∫∮∵∴♀♂⊕⊙↑↓←→↖↗↙↘∥∣/"], +["a240","\∕﹨$¥〒¢£%@℃℉﹩﹪﹫㏕㎜㎝㎞㏎㎡㎎㎏㏄°兙兛兞兝兡兣嗧瓩糎▁",7,"▏▎▍▌▋▊▉┼┴┬┤├▔─│▕┌┐└┘╭"], +["a2a1","╮╰╯═╞╪╡◢◣◥◤╱╲╳0",9,"Ⅰ",9,"〡",8,"十卄卅A",25,"a",21], +["a340","wxyzΑ",16,"Σ",6,"α",16,"σ",6,"ㄅ",10], +["a3a1","ㄐ",25,"˙ˉˊˇˋ"], +["a3e1","€"], +["a440","一乙丁七乃九了二人儿入八几刀刁力匕十卜又三下丈上丫丸凡久么也乞于亡兀刃勺千叉口土士夕大女子孑孓寸小尢尸山川工己已巳巾干廾弋弓才"], +["a4a1","丑丐不中丰丹之尹予云井互五亢仁什仃仆仇仍今介仄元允內六兮公冗凶分切刈勻勾勿化匹午升卅卞厄友及反壬天夫太夭孔少尤尺屯巴幻廿弔引心戈戶手扎支文斗斤方日曰月木欠止歹毋比毛氏水火爪父爻片牙牛犬王丙"], +["a540","世丕且丘主乍乏乎以付仔仕他仗代令仙仞充兄冉冊冬凹出凸刊加功包匆北匝仟半卉卡占卯卮去可古右召叮叩叨叼司叵叫另只史叱台句叭叻四囚外"], +["a5a1","央失奴奶孕它尼巨巧左市布平幼弁弘弗必戊打扔扒扑斥旦朮本未末札正母民氐永汁汀氾犯玄玉瓜瓦甘生用甩田由甲申疋白皮皿目矛矢石示禾穴立丞丟乒乓乩亙交亦亥仿伉伙伊伕伍伐休伏仲件任仰仳份企伋光兇兆先全"], +["a640","共再冰列刑划刎刖劣匈匡匠印危吉吏同吊吐吁吋各向名合吃后吆吒因回囝圳地在圭圬圯圩夙多夷夸妄奸妃好她如妁字存宇守宅安寺尖屹州帆并年"], +["a6a1","式弛忙忖戎戌戍成扣扛托收早旨旬旭曲曳有朽朴朱朵次此死氖汝汗汙江池汐汕污汛汍汎灰牟牝百竹米糸缶羊羽老考而耒耳聿肉肋肌臣自至臼舌舛舟艮色艾虫血行衣西阡串亨位住佇佗佞伴佛何估佐佑伽伺伸佃佔似但佣"], +["a740","作你伯低伶余佝佈佚兌克免兵冶冷別判利刪刨劫助努劬匣即卵吝吭吞吾否呎吧呆呃吳呈呂君吩告吹吻吸吮吵吶吠吼呀吱含吟听囪困囤囫坊坑址坍"], +["a7a1","均坎圾坐坏圻壯夾妝妒妨妞妣妙妖妍妤妓妊妥孝孜孚孛完宋宏尬局屁尿尾岐岑岔岌巫希序庇床廷弄弟彤形彷役忘忌志忍忱快忸忪戒我抄抗抖技扶抉扭把扼找批扳抒扯折扮投抓抑抆改攻攸旱更束李杏材村杜杖杞杉杆杠"], +["a840","杓杗步每求汞沙沁沈沉沅沛汪決沐汰沌汨沖沒汽沃汲汾汴沆汶沍沔沘沂灶灼災灸牢牡牠狄狂玖甬甫男甸皂盯矣私秀禿究系罕肖肓肝肘肛肚育良芒"], +["a8a1","芋芍見角言谷豆豕貝赤走足身車辛辰迂迆迅迄巡邑邢邪邦那酉釆里防阮阱阪阬並乖乳事些亞享京佯依侍佳使佬供例來侃佰併侈佩佻侖佾侏侑佺兔兒兕兩具其典冽函刻券刷刺到刮制剁劾劻卒協卓卑卦卷卸卹取叔受味呵"], +["a940","咖呸咕咀呻呷咄咒咆呼咐呱呶和咚呢周咋命咎固垃坷坪坩坡坦坤坼夜奉奇奈奄奔妾妻委妹妮姑姆姐姍始姓姊妯妳姒姅孟孤季宗定官宜宙宛尚屈居"], +["a9a1","屆岷岡岸岩岫岱岳帘帚帖帕帛帑幸庚店府底庖延弦弧弩往征彿彼忝忠忽念忿怏怔怯怵怖怪怕怡性怩怫怛或戕房戾所承拉拌拄抿拂抹拒招披拓拔拋拈抨抽押拐拙拇拍抵拚抱拘拖拗拆抬拎放斧於旺昔易昌昆昂明昀昏昕昊"], +["aa40","昇服朋杭枋枕東果杳杷枇枝林杯杰板枉松析杵枚枓杼杪杲欣武歧歿氓氛泣注泳沱泌泥河沽沾沼波沫法泓沸泄油況沮泗泅泱沿治泡泛泊沬泯泜泖泠"], +["aaa1","炕炎炒炊炙爬爭爸版牧物狀狎狙狗狐玩玨玟玫玥甽疝疙疚的盂盲直知矽社祀祁秉秈空穹竺糾罔羌羋者肺肥肢肱股肫肩肴肪肯臥臾舍芳芝芙芭芽芟芹花芬芥芯芸芣芰芾芷虎虱初表軋迎返近邵邸邱邶采金長門阜陀阿阻附"], +["ab40","陂隹雨青非亟亭亮信侵侯便俠俑俏保促侶俘俟俊俗侮俐俄係俚俎俞侷兗冒冑冠剎剃削前剌剋則勇勉勃勁匍南卻厚叛咬哀咨哎哉咸咦咳哇哂咽咪品"], +["aba1","哄哈咯咫咱咻咩咧咿囿垂型垠垣垢城垮垓奕契奏奎奐姜姘姿姣姨娃姥姪姚姦威姻孩宣宦室客宥封屎屏屍屋峙峒巷帝帥帟幽庠度建弈弭彥很待徊律徇後徉怒思怠急怎怨恍恰恨恢恆恃恬恫恪恤扁拜挖按拼拭持拮拽指拱拷"], +["ac40","拯括拾拴挑挂政故斫施既春昭映昧是星昨昱昤曷柿染柱柔某柬架枯柵柩柯柄柑枴柚查枸柏柞柳枰柙柢柝柒歪殃殆段毒毗氟泉洋洲洪流津洌洱洞洗"], +["aca1","活洽派洶洛泵洹洧洸洩洮洵洎洫炫為炳炬炯炭炸炮炤爰牲牯牴狩狠狡玷珊玻玲珍珀玳甚甭畏界畎畋疫疤疥疢疣癸皆皇皈盈盆盃盅省盹相眉看盾盼眇矜砂研砌砍祆祉祈祇禹禺科秒秋穿突竿竽籽紂紅紀紉紇約紆缸美羿耄"], +["ad40","耐耍耑耶胖胥胚胃胄背胡胛胎胞胤胝致舢苧范茅苣苛苦茄若茂茉苒苗英茁苜苔苑苞苓苟苯茆虐虹虻虺衍衫要觔計訂訃貞負赴赳趴軍軌述迦迢迪迥"], +["ada1","迭迫迤迨郊郎郁郃酋酊重閂限陋陌降面革韋韭音頁風飛食首香乘亳倌倍倣俯倦倥俸倩倖倆值借倚倒們俺倀倔倨俱倡個候倘俳修倭倪俾倫倉兼冤冥冢凍凌准凋剖剜剔剛剝匪卿原厝叟哨唐唁唷哼哥哲唆哺唔哩哭員唉哮哪"], +["ae40","哦唧唇哽唏圃圄埂埔埋埃堉夏套奘奚娑娘娜娟娛娓姬娠娣娩娥娌娉孫屘宰害家宴宮宵容宸射屑展屐峭峽峻峪峨峰島崁峴差席師庫庭座弱徒徑徐恙"], +["aea1","恣恥恐恕恭恩息悄悟悚悍悔悌悅悖扇拳挈拿捎挾振捕捂捆捏捉挺捐挽挪挫挨捍捌效敉料旁旅時晉晏晃晒晌晅晁書朔朕朗校核案框桓根桂桔栩梳栗桌桑栽柴桐桀格桃株桅栓栘桁殊殉殷氣氧氨氦氤泰浪涕消涇浦浸海浙涓"], +["af40","浬涉浮浚浴浩涌涊浹涅浥涔烊烘烤烙烈烏爹特狼狹狽狸狷玆班琉珮珠珪珞畔畝畜畚留疾病症疲疳疽疼疹痂疸皋皰益盍盎眩真眠眨矩砰砧砸砝破砷"], +["afa1","砥砭砠砟砲祕祐祠祟祖神祝祗祚秤秣秧租秦秩秘窄窈站笆笑粉紡紗紋紊素索純紐紕級紜納紙紛缺罟羔翅翁耆耘耕耙耗耽耿胱脂胰脅胭胴脆胸胳脈能脊胼胯臭臬舀舐航舫舨般芻茫荒荔荊茸荐草茵茴荏茲茹茶茗荀茱茨荃"], +["b040","虔蚊蚪蚓蚤蚩蚌蚣蚜衰衷袁袂衽衹記訐討訌訕訊託訓訖訏訑豈豺豹財貢起躬軒軔軏辱送逆迷退迺迴逃追逅迸邕郡郝郢酒配酌釘針釗釜釙閃院陣陡"], +["b0a1","陛陝除陘陞隻飢馬骨高鬥鬲鬼乾偺偽停假偃偌做偉健偶偎偕偵側偷偏倏偯偭兜冕凰剪副勒務勘動匐匏匙匿區匾參曼商啪啦啄啞啡啃啊唱啖問啕唯啤唸售啜唬啣唳啁啗圈國圉域堅堊堆埠埤基堂堵執培夠奢娶婁婉婦婪婀"], +["b140","娼婢婚婆婊孰寇寅寄寂宿密尉專將屠屜屝崇崆崎崛崖崢崑崩崔崙崤崧崗巢常帶帳帷康庸庶庵庾張強彗彬彩彫得徙從徘御徠徜恿患悉悠您惋悴惦悽"], +["b1a1","情悻悵惜悼惘惕惆惟悸惚惇戚戛扈掠控捲掖探接捷捧掘措捱掩掉掃掛捫推掄授掙採掬排掏掀捻捩捨捺敝敖救教敗啟敏敘敕敔斜斛斬族旋旌旎晝晚晤晨晦晞曹勗望梁梯梢梓梵桿桶梱梧梗械梃棄梭梆梅梔條梨梟梡梂欲殺"], +["b240","毫毬氫涎涼淳淙液淡淌淤添淺清淇淋涯淑涮淞淹涸混淵淅淒渚涵淚淫淘淪深淮淨淆淄涪淬涿淦烹焉焊烽烯爽牽犁猜猛猖猓猙率琅琊球理現琍瓠瓶"], +["b2a1","瓷甜產略畦畢異疏痔痕疵痊痍皎盔盒盛眷眾眼眶眸眺硫硃硎祥票祭移窒窕笠笨笛第符笙笞笮粒粗粕絆絃統紮紹紼絀細紳組累終紲紱缽羞羚翌翎習耜聊聆脯脖脣脫脩脰脤舂舵舷舶船莎莞莘荸莢莖莽莫莒莊莓莉莠荷荻荼"], +["b340","莆莧處彪蛇蛀蚶蛄蚵蛆蛋蚱蚯蛉術袞袈被袒袖袍袋覓規訪訝訣訥許設訟訛訢豉豚販責貫貨貪貧赧赦趾趺軛軟這逍通逗連速逝逐逕逞造透逢逖逛途"], +["b3a1","部郭都酗野釵釦釣釧釭釩閉陪陵陳陸陰陴陶陷陬雀雪雩章竟頂頃魚鳥鹵鹿麥麻傢傍傅備傑傀傖傘傚最凱割剴創剩勞勝勛博厥啻喀喧啼喊喝喘喂喜喪喔喇喋喃喳單喟唾喲喚喻喬喱啾喉喫喙圍堯堪場堤堰報堡堝堠壹壺奠"], +["b440","婷媚婿媒媛媧孳孱寒富寓寐尊尋就嵌嵐崴嵇巽幅帽幀幃幾廊廁廂廄弼彭復循徨惑惡悲悶惠愜愣惺愕惰惻惴慨惱愎惶愉愀愒戟扉掣掌描揀揩揉揆揍"], +["b4a1","插揣提握揖揭揮捶援揪換摒揚揹敞敦敢散斑斐斯普晰晴晶景暑智晾晷曾替期朝棺棕棠棘棗椅棟棵森棧棹棒棲棣棋棍植椒椎棉棚楮棻款欺欽殘殖殼毯氮氯氬港游湔渡渲湧湊渠渥渣減湛湘渤湖湮渭渦湯渴湍渺測湃渝渾滋"], +["b540","溉渙湎湣湄湲湩湟焙焚焦焰無然煮焜牌犄犀猶猥猴猩琺琪琳琢琥琵琶琴琯琛琦琨甥甦畫番痢痛痣痙痘痞痠登發皖皓皴盜睏短硝硬硯稍稈程稅稀窘"], +["b5a1","窗窖童竣等策筆筐筒答筍筋筏筑粟粥絞結絨絕紫絮絲絡給絢絰絳善翔翕耋聒肅腕腔腋腑腎脹腆脾腌腓腴舒舜菩萃菸萍菠菅萋菁華菱菴著萊菰萌菌菽菲菊萸萎萄菜萇菔菟虛蛟蛙蛭蛔蛛蛤蛐蛞街裁裂袱覃視註詠評詞証詁"], +["b640","詔詛詐詆訴診訶詖象貂貯貼貳貽賁費賀貴買貶貿貸越超趁跎距跋跚跑跌跛跆軻軸軼辜逮逵週逸進逶鄂郵鄉郾酣酥量鈔鈕鈣鈉鈞鈍鈐鈇鈑閔閏開閑"], +["b6a1","間閒閎隊階隋陽隅隆隍陲隄雁雅雄集雇雯雲韌項順須飧飪飯飩飲飭馮馭黃黍黑亂傭債傲傳僅傾催傷傻傯僇剿剷剽募勦勤勢勣匯嗟嗨嗓嗦嗎嗜嗇嗑嗣嗤嗯嗚嗡嗅嗆嗥嗉園圓塞塑塘塗塚塔填塌塭塊塢塒塋奧嫁嫉嫌媾媽媼"], +["b740","媳嫂媲嵩嵯幌幹廉廈弒彙徬微愚意慈感想愛惹愁愈慎慌慄慍愾愴愧愍愆愷戡戢搓搾搞搪搭搽搬搏搜搔損搶搖搗搆敬斟新暗暉暇暈暖暄暘暍會榔業"], +["b7a1","楚楷楠楔極椰概楊楨楫楞楓楹榆楝楣楛歇歲毀殿毓毽溢溯滓溶滂源溝滇滅溥溘溼溺溫滑準溜滄滔溪溧溴煎煙煩煤煉照煜煬煦煌煥煞煆煨煖爺牒猷獅猿猾瑯瑚瑕瑟瑞瑁琿瑙瑛瑜當畸瘀痰瘁痲痱痺痿痴痳盞盟睛睫睦睞督"], +["b840","睹睪睬睜睥睨睢矮碎碰碗碘碌碉硼碑碓硿祺祿禁萬禽稜稚稠稔稟稞窟窠筷節筠筮筧粱粳粵經絹綑綁綏絛置罩罪署義羨群聖聘肆肄腱腰腸腥腮腳腫"], +["b8a1","腹腺腦舅艇蒂葷落萱葵葦葫葉葬葛萼萵葡董葩葭葆虞虜號蛹蜓蜈蜇蜀蛾蛻蜂蜃蜆蜊衙裟裔裙補裘裝裡裊裕裒覜解詫該詳試詩詰誇詼詣誠話誅詭詢詮詬詹詻訾詨豢貊貉賊資賈賄貲賃賂賅跡跟跨路跳跺跪跤跦躲較載軾輊"], +["b940","辟農運遊道遂達逼違遐遇遏過遍遑逾遁鄒鄗酬酪酩釉鈷鉗鈸鈽鉀鈾鉛鉋鉤鉑鈴鉉鉍鉅鈹鈿鉚閘隘隔隕雍雋雉雊雷電雹零靖靴靶預頑頓頊頒頌飼飴"], +["b9a1","飽飾馳馱馴髡鳩麂鼎鼓鼠僧僮僥僖僭僚僕像僑僱僎僩兢凳劃劂匱厭嗾嘀嘛嘗嗽嘔嘆嘉嘍嘎嗷嘖嘟嘈嘐嗶團圖塵塾境墓墊塹墅塽壽夥夢夤奪奩嫡嫦嫩嫗嫖嫘嫣孵寞寧寡寥實寨寢寤察對屢嶄嶇幛幣幕幗幔廓廖弊彆彰徹慇"], +["ba40","愿態慷慢慣慟慚慘慵截撇摘摔撤摸摟摺摑摧搴摭摻敲斡旗旖暢暨暝榜榨榕槁榮槓構榛榷榻榫榴槐槍榭槌榦槃榣歉歌氳漳演滾漓滴漩漾漠漬漏漂漢"], +["baa1","滿滯漆漱漸漲漣漕漫漯澈漪滬漁滲滌滷熔熙煽熊熄熒爾犒犖獄獐瑤瑣瑪瑰瑭甄疑瘧瘍瘋瘉瘓盡監瞄睽睿睡磁碟碧碳碩碣禎福禍種稱窪窩竭端管箕箋筵算箝箔箏箸箇箄粹粽精綻綰綜綽綾綠緊綴網綱綺綢綿綵綸維緒緇綬"], +["bb40","罰翠翡翟聞聚肇腐膀膏膈膊腿膂臧臺與舔舞艋蓉蒿蓆蓄蒙蒞蒲蒜蓋蒸蓀蓓蒐蒼蓑蓊蜿蜜蜻蜢蜥蜴蜘蝕蜷蜩裳褂裴裹裸製裨褚裯誦誌語誣認誡誓誤"], +["bba1","說誥誨誘誑誚誧豪貍貌賓賑賒赫趙趕跼輔輒輕輓辣遠遘遜遣遙遞遢遝遛鄙鄘鄞酵酸酷酴鉸銀銅銘銖鉻銓銜銨鉼銑閡閨閩閣閥閤隙障際雌雒需靼鞅韶頗領颯颱餃餅餌餉駁骯骰髦魁魂鳴鳶鳳麼鼻齊億儀僻僵價儂儈儉儅凜"], +["bc40","劇劈劉劍劊勰厲嘮嘻嘹嘲嘿嘴嘩噓噎噗噴嘶嘯嘰墀墟增墳墜墮墩墦奭嬉嫻嬋嫵嬌嬈寮寬審寫層履嶝嶔幢幟幡廢廚廟廝廣廠彈影德徵慶慧慮慝慕憂"], +["bca1","慼慰慫慾憧憐憫憎憬憚憤憔憮戮摩摯摹撞撲撈撐撰撥撓撕撩撒撮播撫撚撬撙撢撳敵敷數暮暫暴暱樣樟槨樁樞標槽模樓樊槳樂樅槭樑歐歎殤毅毆漿潼澄潑潦潔澆潭潛潸潮澎潺潰潤澗潘滕潯潠潟熟熬熱熨牖犛獎獗瑩璋璃"], +["bd40","瑾璀畿瘠瘩瘟瘤瘦瘡瘢皚皺盤瞎瞇瞌瞑瞋磋磅確磊碾磕碼磐稿稼穀稽稷稻窯窮箭箱範箴篆篇篁箠篌糊締練緯緻緘緬緝編緣線緞緩綞緙緲緹罵罷羯"], +["bda1","翩耦膛膜膝膠膚膘蔗蔽蔚蓮蔬蔭蔓蔑蔣蔡蔔蓬蔥蓿蔆螂蝴蝶蝠蝦蝸蝨蝙蝗蝌蝓衛衝褐複褒褓褕褊誼諒談諄誕請諸課諉諂調誰論諍誶誹諛豌豎豬賠賞賦賤賬賭賢賣賜質賡赭趟趣踫踐踝踢踏踩踟踡踞躺輝輛輟輩輦輪輜輞"], +["be40","輥適遮遨遭遷鄰鄭鄧鄱醇醉醋醃鋅銻銷鋪銬鋤鋁銳銼鋒鋇鋰銲閭閱霄霆震霉靠鞍鞋鞏頡頫頜颳養餓餒餘駝駐駟駛駑駕駒駙骷髮髯鬧魅魄魷魯鴆鴉"], +["bea1","鴃麩麾黎墨齒儒儘儔儐儕冀冪凝劑劓勳噙噫噹噩噤噸噪器噥噱噯噬噢噶壁墾壇壅奮嬝嬴學寰導彊憲憑憩憊懍憶憾懊懈戰擅擁擋撻撼據擄擇擂操撿擒擔撾整曆曉暹曄曇暸樽樸樺橙橫橘樹橄橢橡橋橇樵機橈歙歷氅濂澱澡"], +["bf40","濃澤濁澧澳激澹澶澦澠澴熾燉燐燒燈燕熹燎燙燜燃燄獨璜璣璘璟璞瓢甌甍瘴瘸瘺盧盥瞠瞞瞟瞥磨磚磬磧禦積穎穆穌穋窺篙簑築篤篛篡篩篦糕糖縊"], +["bfa1","縑縈縛縣縞縝縉縐罹羲翰翱翮耨膳膩膨臻興艘艙蕊蕙蕈蕨蕩蕃蕉蕭蕪蕞螃螟螞螢融衡褪褲褥褫褡親覦諦諺諫諱謀諜諧諮諾謁謂諷諭諳諶諼豫豭貓賴蹄踱踴蹂踹踵輻輯輸輳辨辦遵遴選遲遼遺鄴醒錠錶鋸錳錯錢鋼錫錄錚"], +["c040","錐錦錡錕錮錙閻隧隨險雕霎霑霖霍霓霏靛靜靦鞘頰頸頻頷頭頹頤餐館餞餛餡餚駭駢駱骸骼髻髭鬨鮑鴕鴣鴦鴨鴒鴛默黔龍龜優償儡儲勵嚎嚀嚐嚅嚇"], +["c0a1","嚏壕壓壑壎嬰嬪嬤孺尷屨嶼嶺嶽嶸幫彌徽應懂懇懦懋戲戴擎擊擘擠擰擦擬擱擢擭斂斃曙曖檀檔檄檢檜櫛檣橾檗檐檠歜殮毚氈濘濱濟濠濛濤濫濯澀濬濡濩濕濮濰燧營燮燦燥燭燬燴燠爵牆獰獲璩環璦璨癆療癌盪瞳瞪瞰瞬"], +["c140","瞧瞭矯磷磺磴磯礁禧禪穗窿簇簍篾篷簌篠糠糜糞糢糟糙糝縮績繆縷縲繃縫總縱繅繁縴縹繈縵縿縯罄翳翼聱聲聰聯聳臆臃膺臂臀膿膽臉膾臨舉艱薪"], +["c1a1","薄蕾薜薑薔薯薛薇薨薊虧蟀蟑螳蟒蟆螫螻螺蟈蟋褻褶襄褸褽覬謎謗謙講謊謠謝謄謐豁谿豳賺賽購賸賻趨蹉蹋蹈蹊轄輾轂轅輿避遽還邁邂邀鄹醣醞醜鍍鎂錨鍵鍊鍥鍋錘鍾鍬鍛鍰鍚鍔闊闋闌闈闆隱隸雖霜霞鞠韓顆颶餵騁"], +["c240","駿鮮鮫鮪鮭鴻鴿麋黏點黜黝黛鼾齋叢嚕嚮壙壘嬸彝懣戳擴擲擾攆擺擻擷斷曜朦檳檬櫃檻檸櫂檮檯歟歸殯瀉瀋濾瀆濺瀑瀏燻燼燾燸獷獵璧璿甕癖癘"], +["c2a1","癒瞽瞿瞻瞼礎禮穡穢穠竄竅簫簧簪簞簣簡糧織繕繞繚繡繒繙罈翹翻職聶臍臏舊藏薩藍藐藉薰薺薹薦蟯蟬蟲蟠覆覲觴謨謹謬謫豐贅蹙蹣蹦蹤蹟蹕軀轉轍邇邃邈醫醬釐鎔鎊鎖鎢鎳鎮鎬鎰鎘鎚鎗闔闖闐闕離雜雙雛雞霤鞣鞦"], +["c340","鞭韹額顏題顎顓颺餾餿餽餮馥騎髁鬃鬆魏魎魍鯊鯉鯽鯈鯀鵑鵝鵠黠鼕鼬儳嚥壞壟壢寵龐廬懲懷懶懵攀攏曠曝櫥櫝櫚櫓瀛瀟瀨瀚瀝瀕瀘爆爍牘犢獸"], +["c3a1","獺璽瓊瓣疇疆癟癡矇礙禱穫穩簾簿簸簽簷籀繫繭繹繩繪羅繳羶羹羸臘藩藝藪藕藤藥藷蟻蠅蠍蟹蟾襠襟襖襞譁譜識證譚譎譏譆譙贈贊蹼蹲躇蹶蹬蹺蹴轔轎辭邊邋醱醮鏡鏑鏟鏃鏈鏜鏝鏖鏢鏍鏘鏤鏗鏨關隴難霪霧靡韜韻類"], +["c440","願顛颼饅饉騖騙鬍鯨鯧鯖鯛鶉鵡鵲鵪鵬麒麗麓麴勸嚨嚷嚶嚴嚼壤孀孃孽寶巉懸懺攘攔攙曦朧櫬瀾瀰瀲爐獻瓏癢癥礦礪礬礫竇競籌籃籍糯糰辮繽繼"], +["c4a1","纂罌耀臚艦藻藹蘑藺蘆蘋蘇蘊蠔蠕襤覺觸議譬警譯譟譫贏贍躉躁躅躂醴釋鐘鐃鏽闡霰飄饒饑馨騫騰騷騵鰓鰍鹹麵黨鼯齟齣齡儷儸囁囀囂夔屬巍懼懾攝攜斕曩櫻欄櫺殲灌爛犧瓖瓔癩矓籐纏續羼蘗蘭蘚蠣蠢蠡蠟襪襬覽譴"], +["c540","護譽贓躊躍躋轟辯醺鐮鐳鐵鐺鐸鐲鐫闢霸霹露響顧顥饗驅驃驀騾髏魔魑鰭鰥鶯鶴鷂鶸麝黯鼙齜齦齧儼儻囈囊囉孿巔巒彎懿攤權歡灑灘玀瓤疊癮癬"], +["c5a1","禳籠籟聾聽臟襲襯觼讀贖贗躑躓轡酈鑄鑑鑒霽霾韃韁顫饕驕驍髒鬚鱉鰱鰾鰻鷓鷗鼴齬齪龔囌巖戀攣攫攪曬欐瓚竊籤籣籥纓纖纔臢蘸蘿蠱變邐邏鑣鑠鑤靨顯饜驚驛驗髓體髑鱔鱗鱖鷥麟黴囑壩攬灞癱癲矗罐羈蠶蠹衢讓讒"], +["c640","讖艷贛釀鑪靂靈靄韆顰驟鬢魘鱟鷹鷺鹼鹽鼇齷齲廳欖灣籬籮蠻觀躡釁鑲鑰顱饞髖鬣黌灤矚讚鑷韉驢驥纜讜躪釅鑽鑾鑼鱷鱸黷豔鑿鸚爨驪鬱鸛鸞籲"], +["c940","乂乜凵匚厂万丌乇亍囗兀屮彳丏冇与丮亓仂仉仈冘勼卬厹圠夃夬尐巿旡殳毌气爿丱丼仨仜仩仡仝仚刌匜卌圢圣夗夯宁宄尒尻屴屳帄庀庂忉戉扐氕"], +["c9a1","氶汃氿氻犮犰玊禸肊阞伎优伬仵伔仱伀价伈伝伂伅伢伓伄仴伒冱刓刉刐劦匢匟卍厊吇囡囟圮圪圴夼妀奼妅奻奾奷奿孖尕尥屼屺屻屾巟幵庄异弚彴忕忔忏扜扞扤扡扦扢扙扠扚扥旯旮朾朹朸朻机朿朼朳氘汆汒汜汏汊汔汋"], +["ca40","汌灱牞犴犵玎甪癿穵网艸艼芀艽艿虍襾邙邗邘邛邔阢阤阠阣佖伻佢佉体佤伾佧佒佟佁佘伭伳伿佡冏冹刜刞刡劭劮匉卣卲厎厏吰吷吪呔呅吙吜吥吘"], +["caa1","吽呏呁吨吤呇囮囧囥坁坅坌坉坋坒夆奀妦妘妠妗妎妢妐妏妧妡宎宒尨尪岍岏岈岋岉岒岊岆岓岕巠帊帎庋庉庌庈庍弅弝彸彶忒忑忐忭忨忮忳忡忤忣忺忯忷忻怀忴戺抃抌抎抏抔抇扱扻扺扰抁抈扷扽扲扴攷旰旴旳旲旵杅杇"], +["cb40","杙杕杌杈杝杍杚杋毐氙氚汸汧汫沄沋沏汱汯汩沚汭沇沕沜汦汳汥汻沎灴灺牣犿犽狃狆狁犺狅玕玗玓玔玒町甹疔疕皁礽耴肕肙肐肒肜芐芏芅芎芑芓"], +["cba1","芊芃芄豸迉辿邟邡邥邞邧邠阰阨阯阭丳侘佼侅佽侀侇佶佴侉侄佷佌侗佪侚佹侁佸侐侜侔侞侒侂侕佫佮冞冼冾刵刲刳剆刱劼匊匋匼厒厔咇呿咁咑咂咈呫呺呾呥呬呴呦咍呯呡呠咘呣呧呤囷囹坯坲坭坫坱坰坶垀坵坻坳坴坢"], +["cc40","坨坽夌奅妵妺姏姎妲姌姁妶妼姃姖妱妽姀姈妴姇孢孥宓宕屄屇岮岤岠岵岯岨岬岟岣岭岢岪岧岝岥岶岰岦帗帔帙弨弢弣弤彔徂彾彽忞忥怭怦怙怲怋"], +["cca1","怴怊怗怳怚怞怬怢怍怐怮怓怑怌怉怜戔戽抭抴拑抾抪抶拊抮抳抯抻抩抰抸攽斨斻昉旼昄昒昈旻昃昋昍昅旽昑昐曶朊枅杬枎枒杶杻枘枆构杴枍枌杺枟枑枙枃杽极杸杹枔欥殀歾毞氝沓泬泫泮泙沶泔沭泧沷泐泂沺泃泆泭泲"], +["cd40","泒泝沴沊沝沀泞泀洰泍泇沰泹泏泩泑炔炘炅炓炆炄炑炖炂炚炃牪狖狋狘狉狜狒狔狚狌狑玤玡玭玦玢玠玬玝瓝瓨甿畀甾疌疘皯盳盱盰盵矸矼矹矻矺"], +["cda1","矷祂礿秅穸穻竻籵糽耵肏肮肣肸肵肭舠芠苀芫芚芘芛芵芧芮芼芞芺芴芨芡芩苂芤苃芶芢虰虯虭虮豖迒迋迓迍迖迕迗邲邴邯邳邰阹阽阼阺陃俍俅俓侲俉俋俁俔俜俙侻侳俛俇俖侺俀侹俬剄剉勀勂匽卼厗厖厙厘咺咡咭咥哏"], +["ce40","哃茍咷咮哖咶哅哆咠呰咼咢咾呲哞咰垵垞垟垤垌垗垝垛垔垘垏垙垥垚垕壴复奓姡姞姮娀姱姝姺姽姼姶姤姲姷姛姩姳姵姠姾姴姭宨屌峐峘峌峗峋峛"], +["cea1","峞峚峉峇峊峖峓峔峏峈峆峎峟峸巹帡帢帣帠帤庰庤庢庛庣庥弇弮彖徆怷怹恔恲恞恅恓恇恉恛恌恀恂恟怤恄恘恦恮扂扃拏挍挋拵挎挃拫拹挏挌拸拶挀挓挔拺挕拻拰敁敃斪斿昶昡昲昵昜昦昢昳昫昺昝昴昹昮朏朐柁柲柈枺"], +["cf40","柜枻柸柘柀枷柅柫柤柟枵柍枳柷柶柮柣柂枹柎柧柰枲柼柆柭柌枮柦柛柺柉柊柃柪柋欨殂殄殶毖毘毠氠氡洨洴洭洟洼洿洒洊泚洳洄洙洺洚洑洀洝浂"], +["cfa1","洁洘洷洃洏浀洇洠洬洈洢洉洐炷炟炾炱炰炡炴炵炩牁牉牊牬牰牳牮狊狤狨狫狟狪狦狣玅珌珂珈珅玹玶玵玴珫玿珇玾珃珆玸珋瓬瓮甮畇畈疧疪癹盄眈眃眄眅眊盷盻盺矧矨砆砑砒砅砐砏砎砉砃砓祊祌祋祅祄秕种秏秖秎窀"], +["d040","穾竑笀笁籺籸籹籿粀粁紃紈紁罘羑羍羾耇耎耏耔耷胘胇胠胑胈胂胐胅胣胙胜胊胕胉胏胗胦胍臿舡芔苙苾苹茇苨茀苕茺苫苖苴苬苡苲苵茌苻苶苰苪"], +["d0a1","苤苠苺苳苭虷虴虼虳衁衎衧衪衩觓訄訇赲迣迡迮迠郱邽邿郕郅邾郇郋郈釔釓陔陏陑陓陊陎倞倅倇倓倢倰倛俵俴倳倷倬俶俷倗倜倠倧倵倯倱倎党冔冓凊凄凅凈凎剡剚剒剞剟剕剢勍匎厞唦哢唗唒哧哳哤唚哿唄唈哫唑唅哱"], +["d140","唊哻哷哸哠唎唃唋圁圂埌堲埕埒垺埆垽垼垸垶垿埇埐垹埁夎奊娙娖娭娮娕娏娗娊娞娳孬宧宭宬尃屖屔峬峿峮峱峷崀峹帩帨庨庮庪庬弳弰彧恝恚恧"], +["d1a1","恁悢悈悀悒悁悝悃悕悛悗悇悜悎戙扆拲挐捖挬捄捅挶捃揤挹捋捊挼挩捁挴捘捔捙挭捇挳捚捑挸捗捀捈敊敆旆旃旄旂晊晟晇晑朒朓栟栚桉栲栳栻桋桏栖栱栜栵栫栭栯桎桄栴栝栒栔栦栨栮桍栺栥栠欬欯欭欱欴歭肂殈毦毤"], +["d240","毨毣毢毧氥浺浣浤浶洍浡涒浘浢浭浯涑涍淯浿涆浞浧浠涗浰浼浟涂涘洯浨涋浾涀涄洖涃浻浽浵涐烜烓烑烝烋缹烢烗烒烞烠烔烍烅烆烇烚烎烡牂牸"], +["d2a1","牷牶猀狺狴狾狶狳狻猁珓珙珥珖玼珧珣珩珜珒珛珔珝珚珗珘珨瓞瓟瓴瓵甡畛畟疰痁疻痄痀疿疶疺皊盉眝眛眐眓眒眣眑眕眙眚眢眧砣砬砢砵砯砨砮砫砡砩砳砪砱祔祛祏祜祓祒祑秫秬秠秮秭秪秜秞秝窆窉窅窋窌窊窇竘笐"], +["d340","笄笓笅笏笈笊笎笉笒粄粑粊粌粈粍粅紞紝紑紎紘紖紓紟紒紏紌罜罡罞罠罝罛羖羒翃翂翀耖耾耹胺胲胹胵脁胻脀舁舯舥茳茭荄茙荑茥荖茿荁茦茜茢"], +["d3a1","荂荎茛茪茈茼荍茖茤茠茷茯茩荇荅荌荓茞茬荋茧荈虓虒蚢蚨蚖蚍蚑蚞蚇蚗蚆蚋蚚蚅蚥蚙蚡蚧蚕蚘蚎蚝蚐蚔衃衄衭衵衶衲袀衱衿衯袃衾衴衼訒豇豗豻貤貣赶赸趵趷趶軑軓迾迵适迿迻逄迼迶郖郠郙郚郣郟郥郘郛郗郜郤酐"], +["d440","酎酏釕釢釚陜陟隼飣髟鬯乿偰偪偡偞偠偓偋偝偲偈偍偁偛偊偢倕偅偟偩偫偣偤偆偀偮偳偗偑凐剫剭剬剮勖勓匭厜啵啶唼啍啐唴唪啑啢唶唵唰啒啅"], +["d4a1","唌唲啥啎唹啈唭唻啀啋圊圇埻堔埢埶埜埴堀埭埽堈埸堋埳埏堇埮埣埲埥埬埡堎埼堐埧堁堌埱埩埰堍堄奜婠婘婕婧婞娸娵婭婐婟婥婬婓婤婗婃婝婒婄婛婈媎娾婍娹婌婰婩婇婑婖婂婜孲孮寁寀屙崞崋崝崚崠崌崨崍崦崥崏"], +["d540","崰崒崣崟崮帾帴庱庴庹庲庳弶弸徛徖徟悊悐悆悾悰悺惓惔惏惤惙惝惈悱惛悷惊悿惃惍惀挲捥掊掂捽掽掞掭掝掗掫掎捯掇掐据掯捵掜捭掮捼掤挻掟"], +["d5a1","捸掅掁掑掍捰敓旍晥晡晛晙晜晢朘桹梇梐梜桭桮梮梫楖桯梣梬梩桵桴梲梏桷梒桼桫桲梪梀桱桾梛梖梋梠梉梤桸桻梑梌梊桽欶欳欷欸殑殏殍殎殌氪淀涫涴涳湴涬淩淢涷淶淔渀淈淠淟淖涾淥淜淝淛淴淊涽淭淰涺淕淂淏淉"], +["d640","淐淲淓淽淗淍淣涻烺焍烷焗烴焌烰焄烳焐烼烿焆焓焀烸烶焋焂焎牾牻牼牿猝猗猇猑猘猊猈狿猏猞玈珶珸珵琄琁珽琇琀珺珼珿琌琋珴琈畤畣痎痒痏"], +["d6a1","痋痌痑痐皏皉盓眹眯眭眱眲眴眳眽眥眻眵硈硒硉硍硊硌砦硅硐祤祧祩祪祣祫祡离秺秸秶秷窏窔窐笵筇笴笥笰笢笤笳笘笪笝笱笫笭笯笲笸笚笣粔粘粖粣紵紽紸紶紺絅紬紩絁絇紾紿絊紻紨罣羕羜羝羛翊翋翍翐翑翇翏翉耟"], +["d740","耞耛聇聃聈脘脥脙脛脭脟脬脞脡脕脧脝脢舑舸舳舺舴舲艴莐莣莨莍荺荳莤荴莏莁莕莙荵莔莩荽莃莌莝莛莪莋荾莥莯莈莗莰荿莦莇莮荶莚虙虖蚿蚷"], +["d7a1","蛂蛁蛅蚺蚰蛈蚹蚳蚸蛌蚴蚻蚼蛃蚽蚾衒袉袕袨袢袪袚袑袡袟袘袧袙袛袗袤袬袌袓袎覂觖觙觕訰訧訬訞谹谻豜豝豽貥赽赻赹趼跂趹趿跁軘軞軝軜軗軠軡逤逋逑逜逌逡郯郪郰郴郲郳郔郫郬郩酖酘酚酓酕釬釴釱釳釸釤釹釪"], +["d840","釫釷釨釮镺閆閈陼陭陫陱陯隿靪頄飥馗傛傕傔傞傋傣傃傌傎傝偨傜傒傂傇兟凔匒匑厤厧喑喨喥喭啷噅喢喓喈喏喵喁喣喒喤啽喌喦啿喕喡喎圌堩堷"], +["d8a1","堙堞堧堣堨埵塈堥堜堛堳堿堶堮堹堸堭堬堻奡媯媔媟婺媢媞婸媦婼媥媬媕媮娷媄媊媗媃媋媩婻婽媌媜媏媓媝寪寍寋寔寑寊寎尌尰崷嵃嵫嵁嵋崿崵嵑嵎嵕崳崺嵒崽崱嵙嵂崹嵉崸崼崲崶嵀嵅幄幁彘徦徥徫惉悹惌惢惎惄愔"], +["d940","惲愊愖愅惵愓惸惼惾惁愃愘愝愐惿愄愋扊掔掱掰揎揥揨揯揃撝揳揊揠揶揕揲揵摡揟掾揝揜揄揘揓揂揇揌揋揈揰揗揙攲敧敪敤敜敨敥斌斝斞斮旐旒"], +["d9a1","晼晬晻暀晱晹晪晲朁椌棓椄棜椪棬棪棱椏棖棷棫棤棶椓椐棳棡椇棌椈楰梴椑棯棆椔棸棐棽棼棨椋椊椗棎棈棝棞棦棴棑椆棔棩椕椥棇欹欻欿欼殔殗殙殕殽毰毲毳氰淼湆湇渟湉溈渼渽湅湢渫渿湁湝湳渜渳湋湀湑渻渃渮湞"], +["da40","湨湜湡渱渨湠湱湫渹渢渰湓湥渧湸湤湷湕湹湒湦渵渶湚焠焞焯烻焮焱焣焥焢焲焟焨焺焛牋牚犈犉犆犅犋猒猋猰猢猱猳猧猲猭猦猣猵猌琮琬琰琫琖"], +["daa1","琚琡琭琱琤琣琝琩琠琲瓻甯畯畬痧痚痡痦痝痟痤痗皕皒盚睆睇睄睍睅睊睎睋睌矞矬硠硤硥硜硭硱硪确硰硩硨硞硢祴祳祲祰稂稊稃稌稄窙竦竤筊笻筄筈筌筎筀筘筅粢粞粨粡絘絯絣絓絖絧絪絏絭絜絫絒絔絩絑絟絎缾缿罥"], +["db40","罦羢羠羡翗聑聏聐胾胔腃腊腒腏腇脽腍脺臦臮臷臸臹舄舼舽舿艵茻菏菹萣菀菨萒菧菤菼菶萐菆菈菫菣莿萁菝菥菘菿菡菋菎菖菵菉萉萏菞萑萆菂菳"], +["dba1","菕菺菇菑菪萓菃菬菮菄菻菗菢萛菛菾蛘蛢蛦蛓蛣蛚蛪蛝蛫蛜蛬蛩蛗蛨蛑衈衖衕袺裗袹袸裀袾袶袼袷袽袲褁裉覕覘覗觝觚觛詎詍訹詙詀詗詘詄詅詒詈詑詊詌詏豟貁貀貺貾貰貹貵趄趀趉跘跓跍跇跖跜跏跕跙跈跗跅軯軷軺"], +["dc40","軹軦軮軥軵軧軨軶軫軱軬軴軩逭逴逯鄆鄬鄄郿郼鄈郹郻鄁鄀鄇鄅鄃酡酤酟酢酠鈁鈊鈥鈃鈚鈦鈏鈌鈀鈒釿釽鈆鈄鈧鈂鈜鈤鈙鈗鈅鈖镻閍閌閐隇陾隈"], +["dca1","隉隃隀雂雈雃雱雰靬靰靮頇颩飫鳦黹亃亄亶傽傿僆傮僄僊傴僈僂傰僁傺傱僋僉傶傸凗剺剸剻剼嗃嗛嗌嗐嗋嗊嗝嗀嗔嗄嗩喿嗒喍嗏嗕嗢嗖嗈嗲嗍嗙嗂圔塓塨塤塏塍塉塯塕塎塝塙塥塛堽塣塱壼嫇嫄嫋媺媸媱媵媰媿嫈媻嫆"], +["dd40","媷嫀嫊媴媶嫍媹媐寖寘寙尟尳嵱嵣嵊嵥嵲嵬嵞嵨嵧嵢巰幏幎幊幍幋廅廌廆廋廇彀徯徭惷慉慊愫慅愶愲愮慆愯慏愩慀戠酨戣戥戤揅揱揫搐搒搉搠搤"], +["dda1","搳摃搟搕搘搹搷搢搣搌搦搰搨摁搵搯搊搚摀搥搧搋揧搛搮搡搎敯斒旓暆暌暕暐暋暊暙暔晸朠楦楟椸楎楢楱椿楅楪椹楂楗楙楺楈楉椵楬椳椽楥棰楸椴楩楀楯楄楶楘楁楴楌椻楋椷楜楏楑椲楒椯楻椼歆歅歃歂歈歁殛嗀毻毼"], +["de40","毹毷毸溛滖滈溏滀溟溓溔溠溱溹滆滒溽滁溞滉溷溰滍溦滏溲溾滃滜滘溙溒溎溍溤溡溿溳滐滊溗溮溣煇煔煒煣煠煁煝煢煲煸煪煡煂煘煃煋煰煟煐煓"], +["dea1","煄煍煚牏犍犌犑犐犎猼獂猻猺獀獊獉瑄瑊瑋瑒瑑瑗瑀瑏瑐瑎瑂瑆瑍瑔瓡瓿瓾瓽甝畹畷榃痯瘏瘃痷痾痼痹痸瘐痻痶痭痵痽皙皵盝睕睟睠睒睖睚睩睧睔睙睭矠碇碚碔碏碄碕碅碆碡碃硹碙碀碖硻祼禂祽祹稑稘稙稒稗稕稢稓"], +["df40","稛稐窣窢窞竫筦筤筭筴筩筲筥筳筱筰筡筸筶筣粲粴粯綈綆綀綍絿綅絺綎絻綃絼綌綔綄絽綒罭罫罧罨罬羦羥羧翛翜耡腤腠腷腜腩腛腢腲朡腞腶腧腯"], +["dfa1","腄腡舝艉艄艀艂艅蓱萿葖葶葹蒏蒍葥葑葀蒆葧萰葍葽葚葙葴葳葝蔇葞萷萺萴葺葃葸萲葅萩菙葋萯葂萭葟葰萹葎葌葒葯蓅蒎萻葇萶萳葨葾葄萫葠葔葮葐蜋蜄蛷蜌蛺蛖蛵蝍蛸蜎蜉蜁蛶蜍蜅裖裋裍裎裞裛裚裌裐覅覛觟觥觤"], +["e040","觡觠觢觜触詶誆詿詡訿詷誂誄詵誃誁詴詺谼豋豊豥豤豦貆貄貅賌赨赩趑趌趎趏趍趓趔趐趒跰跠跬跱跮跐跩跣跢跧跲跫跴輆軿輁輀輅輇輈輂輋遒逿"], +["e0a1","遄遉逽鄐鄍鄏鄑鄖鄔鄋鄎酮酯鉈鉒鈰鈺鉦鈳鉥鉞銃鈮鉊鉆鉭鉬鉏鉠鉧鉯鈶鉡鉰鈱鉔鉣鉐鉲鉎鉓鉌鉖鈲閟閜閞閛隒隓隑隗雎雺雽雸雵靳靷靸靲頏頍頎颬飶飹馯馲馰馵骭骫魛鳪鳭鳧麀黽僦僔僗僨僳僛僪僝僤僓僬僰僯僣僠"], +["e140","凘劀劁勩勫匰厬嘧嘕嘌嘒嗼嘏嘜嘁嘓嘂嗺嘝嘄嗿嗹墉塼墐墘墆墁塿塴墋塺墇墑墎塶墂墈塻墔墏壾奫嫜嫮嫥嫕嫪嫚嫭嫫嫳嫢嫠嫛嫬嫞嫝嫙嫨嫟孷寠"], +["e1a1","寣屣嶂嶀嵽嶆嵺嶁嵷嶊嶉嶈嵾嵼嶍嵹嵿幘幙幓廘廑廗廎廜廕廙廒廔彄彃彯徶愬愨慁慞慱慳慒慓慲慬憀慴慔慺慛慥愻慪慡慖戩戧戫搫摍摛摝摴摶摲摳摽摵摦撦摎撂摞摜摋摓摠摐摿搿摬摫摙摥摷敳斠暡暠暟朅朄朢榱榶槉"], +["e240","榠槎榖榰榬榼榑榙榎榧榍榩榾榯榿槄榽榤槔榹槊榚槏榳榓榪榡榞槙榗榐槂榵榥槆歊歍歋殞殟殠毃毄毾滎滵滱漃漥滸漷滻漮漉潎漙漚漧漘漻漒滭漊"], +["e2a1","漶潳滹滮漭潀漰漼漵滫漇漎潃漅滽滶漹漜滼漺漟漍漞漈漡熇熐熉熀熅熂熏煻熆熁熗牄牓犗犕犓獃獍獑獌瑢瑳瑱瑵瑲瑧瑮甀甂甃畽疐瘖瘈瘌瘕瘑瘊瘔皸瞁睼瞅瞂睮瞀睯睾瞃碲碪碴碭碨硾碫碞碥碠碬碢碤禘禊禋禖禕禔禓"], +["e340","禗禈禒禐稫穊稰稯稨稦窨窫窬竮箈箜箊箑箐箖箍箌箛箎箅箘劄箙箤箂粻粿粼粺綧綷緂綣綪緁緀緅綝緎緄緆緋緌綯綹綖綼綟綦綮綩綡緉罳翢翣翥翞"], +["e3a1","耤聝聜膉膆膃膇膍膌膋舕蒗蒤蒡蒟蒺蓎蓂蒬蒮蒫蒹蒴蓁蓍蒪蒚蒱蓐蒝蒧蒻蒢蒔蓇蓌蒛蒩蒯蒨蓖蒘蒶蓏蒠蓗蓔蓒蓛蒰蒑虡蜳蜣蜨蝫蝀蜮蜞蜡蜙蜛蝃蜬蝁蜾蝆蜠蜲蜪蜭蜼蜒蜺蜱蜵蝂蜦蜧蜸蜤蜚蜰蜑裷裧裱裲裺裾裮裼裶裻"], +["e440","裰裬裫覝覡覟覞觩觫觨誫誙誋誒誏誖谽豨豩賕賏賗趖踉踂跿踍跽踊踃踇踆踅跾踀踄輐輑輎輍鄣鄜鄠鄢鄟鄝鄚鄤鄡鄛酺酲酹酳銥銤鉶銛鉺銠銔銪銍"], +["e4a1","銦銚銫鉹銗鉿銣鋮銎銂銕銢鉽銈銡銊銆銌銙銧鉾銇銩銝銋鈭隞隡雿靘靽靺靾鞃鞀鞂靻鞄鞁靿韎韍頖颭颮餂餀餇馝馜駃馹馻馺駂馽駇骱髣髧鬾鬿魠魡魟鳱鳲鳵麧僿儃儰僸儆儇僶僾儋儌僽儊劋劌勱勯噈噂噌嘵噁噊噉噆噘"], +["e540","噚噀嘳嘽嘬嘾嘸嘪嘺圚墫墝墱墠墣墯墬墥墡壿嫿嫴嫽嫷嫶嬃嫸嬂嫹嬁嬇嬅嬏屧嶙嶗嶟嶒嶢嶓嶕嶠嶜嶡嶚嶞幩幝幠幜緳廛廞廡彉徲憋憃慹憱憰憢憉"], +["e5a1","憛憓憯憭憟憒憪憡憍慦憳戭摮摰撖撠撅撗撜撏撋撊撌撣撟摨撱撘敶敺敹敻斲斳暵暰暩暲暷暪暯樀樆樗槥槸樕槱槤樠槿槬槢樛樝槾樧槲槮樔槷槧橀樈槦槻樍槼槫樉樄樘樥樏槶樦樇槴樖歑殥殣殢殦氁氀毿氂潁漦潾澇濆澒"], +["e640","澍澉澌潢潏澅潚澖潶潬澂潕潲潒潐潗澔澓潝漀潡潫潽潧澐潓澋潩潿澕潣潷潪潻熲熯熛熰熠熚熩熵熝熥熞熤熡熪熜熧熳犘犚獘獒獞獟獠獝獛獡獚獙"], +["e6a1","獢璇璉璊璆璁瑽璅璈瑼瑹甈甇畾瘥瘞瘙瘝瘜瘣瘚瘨瘛皜皝皞皛瞍瞏瞉瞈磍碻磏磌磑磎磔磈磃磄磉禚禡禠禜禢禛歶稹窲窴窳箷篋箾箬篎箯箹篊箵糅糈糌糋緷緛緪緧緗緡縃緺緦緶緱緰緮緟罶羬羰羭翭翫翪翬翦翨聤聧膣膟"], +["e740","膞膕膢膙膗舖艏艓艒艐艎艑蔤蔻蔏蔀蔩蔎蔉蔍蔟蔊蔧蔜蓻蔫蓺蔈蔌蓴蔪蓲蔕蓷蓫蓳蓼蔒蓪蓩蔖蓾蔨蔝蔮蔂蓽蔞蓶蔱蔦蓧蓨蓰蓯蓹蔘蔠蔰蔋蔙蔯虢"], +["e7a1","蝖蝣蝤蝷蟡蝳蝘蝔蝛蝒蝡蝚蝑蝞蝭蝪蝐蝎蝟蝝蝯蝬蝺蝮蝜蝥蝏蝻蝵蝢蝧蝩衚褅褌褔褋褗褘褙褆褖褑褎褉覢覤覣觭觰觬諏諆誸諓諑諔諕誻諗誾諀諅諘諃誺誽諙谾豍貏賥賟賙賨賚賝賧趠趜趡趛踠踣踥踤踮踕踛踖踑踙踦踧"], +["e840","踔踒踘踓踜踗踚輬輤輘輚輠輣輖輗遳遰遯遧遫鄯鄫鄩鄪鄲鄦鄮醅醆醊醁醂醄醀鋐鋃鋄鋀鋙銶鋏鋱鋟鋘鋩鋗鋝鋌鋯鋂鋨鋊鋈鋎鋦鋍鋕鋉鋠鋞鋧鋑鋓"], +["e8a1","銵鋡鋆銴镼閬閫閮閰隤隢雓霅霈霂靚鞊鞎鞈韐韏頞頝頦頩頨頠頛頧颲餈飺餑餔餖餗餕駜駍駏駓駔駎駉駖駘駋駗駌骳髬髫髳髲髱魆魃魧魴魱魦魶魵魰魨魤魬鳼鳺鳽鳿鳷鴇鴀鳹鳻鴈鴅鴄麃黓鼏鼐儜儓儗儚儑凞匴叡噰噠噮"], +["e940","噳噦噣噭噲噞噷圜圛壈墽壉墿墺壂墼壆嬗嬙嬛嬡嬔嬓嬐嬖嬨嬚嬠嬞寯嶬嶱嶩嶧嶵嶰嶮嶪嶨嶲嶭嶯嶴幧幨幦幯廩廧廦廨廥彋徼憝憨憖懅憴懆懁懌憺"], +["e9a1","憿憸憌擗擖擐擏擉撽撉擃擛擳擙攳敿敼斢曈暾曀曊曋曏暽暻暺曌朣樴橦橉橧樲橨樾橝橭橶橛橑樨橚樻樿橁橪橤橐橏橔橯橩橠樼橞橖橕橍橎橆歕歔歖殧殪殫毈毇氄氃氆澭濋澣濇澼濎濈潞濄澽澞濊澨瀄澥澮澺澬澪濏澿澸"], +["ea40","澢濉澫濍澯澲澰燅燂熿熸燖燀燁燋燔燊燇燏熽燘熼燆燚燛犝犞獩獦獧獬獥獫獪瑿璚璠璔璒璕璡甋疀瘯瘭瘱瘽瘳瘼瘵瘲瘰皻盦瞚瞝瞡瞜瞛瞢瞣瞕瞙"], +["eaa1","瞗磝磩磥磪磞磣磛磡磢磭磟磠禤穄穈穇窶窸窵窱窷篞篣篧篝篕篥篚篨篹篔篪篢篜篫篘篟糒糔糗糐糑縒縡縗縌縟縠縓縎縜縕縚縢縋縏縖縍縔縥縤罃罻罼罺羱翯耪耩聬膱膦膮膹膵膫膰膬膴膲膷膧臲艕艖艗蕖蕅蕫蕍蕓蕡蕘"], +["eb40","蕀蕆蕤蕁蕢蕄蕑蕇蕣蔾蕛蕱蕎蕮蕵蕕蕧蕠薌蕦蕝蕔蕥蕬虣虥虤螛螏螗螓螒螈螁螖螘蝹螇螣螅螐螑螝螄螔螜螚螉褞褦褰褭褮褧褱褢褩褣褯褬褟觱諠"], +["eba1","諢諲諴諵諝謔諤諟諰諈諞諡諨諿諯諻貑貒貐賵賮賱賰賳赬赮趥趧踳踾踸蹀蹅踶踼踽蹁踰踿躽輶輮輵輲輹輷輴遶遹遻邆郺鄳鄵鄶醓醐醑醍醏錧錞錈錟錆錏鍺錸錼錛錣錒錁鍆錭錎錍鋋錝鋺錥錓鋹鋷錴錂錤鋿錩錹錵錪錔錌"], +["ec40","錋鋾錉錀鋻錖閼闍閾閹閺閶閿閵閽隩雔霋霒霐鞙鞗鞔韰韸頵頯頲餤餟餧餩馞駮駬駥駤駰駣駪駩駧骹骿骴骻髶髺髹髷鬳鮀鮅鮇魼魾魻鮂鮓鮒鮐魺鮕"], +["eca1","魽鮈鴥鴗鴠鴞鴔鴩鴝鴘鴢鴐鴙鴟麈麆麇麮麭黕黖黺鼒鼽儦儥儢儤儠儩勴嚓嚌嚍嚆嚄嚃噾嚂噿嚁壖壔壏壒嬭嬥嬲嬣嬬嬧嬦嬯嬮孻寱寲嶷幬幪徾徻懃憵憼懧懠懥懤懨懞擯擩擣擫擤擨斁斀斶旚曒檍檖檁檥檉檟檛檡檞檇檓檎"], +["ed40","檕檃檨檤檑橿檦檚檅檌檒歛殭氉濌澩濴濔濣濜濭濧濦濞濲濝濢濨燡燱燨燲燤燰燢獳獮獯璗璲璫璐璪璭璱璥璯甐甑甒甏疄癃癈癉癇皤盩瞵瞫瞲瞷瞶"], +["eda1","瞴瞱瞨矰磳磽礂磻磼磲礅磹磾礄禫禨穜穛穖穘穔穚窾竀竁簅簏篲簀篿篻簎篴簋篳簂簉簃簁篸篽簆篰篱簐簊糨縭縼繂縳顈縸縪繉繀繇縩繌縰縻縶繄縺罅罿罾罽翴翲耬膻臄臌臊臅臇膼臩艛艚艜薃薀薏薧薕薠薋薣蕻薤薚薞"], +["ee40","蕷蕼薉薡蕺蕸蕗薎薖薆薍薙薝薁薢薂薈薅蕹蕶薘薐薟虨螾螪螭蟅螰螬螹螵螼螮蟉蟃蟂蟌螷螯蟄蟊螴螶螿螸螽蟞螲褵褳褼褾襁襒褷襂覭覯覮觲觳謞"], +["eea1","謘謖謑謅謋謢謏謒謕謇謍謈謆謜謓謚豏豰豲豱豯貕貔賹赯蹎蹍蹓蹐蹌蹇轃轀邅遾鄸醚醢醛醙醟醡醝醠鎡鎃鎯鍤鍖鍇鍼鍘鍜鍶鍉鍐鍑鍠鍭鎏鍌鍪鍹鍗鍕鍒鍏鍱鍷鍻鍡鍞鍣鍧鎀鍎鍙闇闀闉闃闅閷隮隰隬霠霟霘霝霙鞚鞡鞜"], +["ef40","鞞鞝韕韔韱顁顄顊顉顅顃餥餫餬餪餳餲餯餭餱餰馘馣馡騂駺駴駷駹駸駶駻駽駾駼騃骾髾髽鬁髼魈鮚鮨鮞鮛鮦鮡鮥鮤鮆鮢鮠鮯鴳鵁鵧鴶鴮鴯鴱鴸鴰"], +["efa1","鵅鵂鵃鴾鴷鵀鴽翵鴭麊麉麍麰黈黚黻黿鼤鼣鼢齔龠儱儭儮嚘嚜嚗嚚嚝嚙奰嬼屩屪巀幭幮懘懟懭懮懱懪懰懫懖懩擿攄擽擸攁攃擼斔旛曚曛曘櫅檹檽櫡櫆檺檶檷櫇檴檭歞毉氋瀇瀌瀍瀁瀅瀔瀎濿瀀濻瀦濼濷瀊爁燿燹爃燽獶"], +["f040","璸瓀璵瓁璾璶璻瓂甔甓癜癤癙癐癓癗癚皦皽盬矂瞺磿礌礓礔礉礐礒礑禭禬穟簜簩簙簠簟簭簝簦簨簢簥簰繜繐繖繣繘繢繟繑繠繗繓羵羳翷翸聵臑臒"], +["f0a1","臐艟艞薴藆藀藃藂薳薵薽藇藄薿藋藎藈藅薱薶藒蘤薸薷薾虩蟧蟦蟢蟛蟫蟪蟥蟟蟳蟤蟔蟜蟓蟭蟘蟣螤蟗蟙蠁蟴蟨蟝襓襋襏襌襆襐襑襉謪謧謣謳謰謵譇謯謼謾謱謥謷謦謶謮謤謻謽謺豂豵貙貘貗賾贄贂贀蹜蹢蹠蹗蹖蹞蹥蹧"], +["f140","蹛蹚蹡蹝蹩蹔轆轇轈轋鄨鄺鄻鄾醨醥醧醯醪鎵鎌鎒鎷鎛鎝鎉鎧鎎鎪鎞鎦鎕鎈鎙鎟鎍鎱鎑鎲鎤鎨鎴鎣鎥闒闓闑隳雗雚巂雟雘雝霣霢霥鞬鞮鞨鞫鞤鞪"], +["f1a1","鞢鞥韗韙韖韘韺顐顑顒颸饁餼餺騏騋騉騍騄騑騊騅騇騆髀髜鬈鬄鬅鬩鬵魊魌魋鯇鯆鯃鮿鯁鮵鮸鯓鮶鯄鮹鮽鵜鵓鵏鵊鵛鵋鵙鵖鵌鵗鵒鵔鵟鵘鵚麎麌黟鼁鼀鼖鼥鼫鼪鼩鼨齌齕儴儵劖勷厴嚫嚭嚦嚧嚪嚬壚壝壛夒嬽嬾嬿巃幰"], +["f240","徿懻攇攐攍攉攌攎斄旞旝曞櫧櫠櫌櫑櫙櫋櫟櫜櫐櫫櫏櫍櫞歠殰氌瀙瀧瀠瀖瀫瀡瀢瀣瀩瀗瀤瀜瀪爌爊爇爂爅犥犦犤犣犡瓋瓅璷瓃甖癠矉矊矄矱礝礛"], +["f2a1","礡礜礗礞禰穧穨簳簼簹簬簻糬糪繶繵繸繰繷繯繺繲繴繨罋罊羃羆羷翽翾聸臗臕艤艡艣藫藱藭藙藡藨藚藗藬藲藸藘藟藣藜藑藰藦藯藞藢蠀蟺蠃蟶蟷蠉蠌蠋蠆蟼蠈蟿蠊蠂襢襚襛襗襡襜襘襝襙覈覷覶觶譐譈譊譀譓譖譔譋譕"], +["f340","譑譂譒譗豃豷豶貚贆贇贉趬趪趭趫蹭蹸蹳蹪蹯蹻軂轒轑轏轐轓辴酀鄿醰醭鏞鏇鏏鏂鏚鏐鏹鏬鏌鏙鎩鏦鏊鏔鏮鏣鏕鏄鏎鏀鏒鏧镽闚闛雡霩霫霬霨霦"], +["f3a1","鞳鞷鞶韝韞韟顜顙顝顗颿颽颻颾饈饇饃馦馧騚騕騥騝騤騛騢騠騧騣騞騜騔髂鬋鬊鬎鬌鬷鯪鯫鯠鯞鯤鯦鯢鯰鯔鯗鯬鯜鯙鯥鯕鯡鯚鵷鶁鶊鶄鶈鵱鶀鵸鶆鶋鶌鵽鵫鵴鵵鵰鵩鶅鵳鵻鶂鵯鵹鵿鶇鵨麔麑黀黼鼭齀齁齍齖齗齘匷嚲"], +["f440","嚵嚳壣孅巆巇廮廯忀忁懹攗攖攕攓旟曨曣曤櫳櫰櫪櫨櫹櫱櫮櫯瀼瀵瀯瀷瀴瀱灂瀸瀿瀺瀹灀瀻瀳灁爓爔犨獽獼璺皫皪皾盭矌矎矏矍矲礥礣礧礨礤礩"], +["f4a1","禲穮穬穭竷籉籈籊籇籅糮繻繾纁纀羺翿聹臛臙舋艨艩蘢藿蘁藾蘛蘀藶蘄蘉蘅蘌藽蠙蠐蠑蠗蠓蠖襣襦覹觷譠譪譝譨譣譥譧譭趮躆躈躄轙轖轗轕轘轚邍酃酁醷醵醲醳鐋鐓鏻鐠鐏鐔鏾鐕鐐鐨鐙鐍鏵鐀鏷鐇鐎鐖鐒鏺鐉鏸鐊鏿"], +["f540","鏼鐌鏶鐑鐆闞闠闟霮霯鞹鞻韽韾顠顢顣顟飁飂饐饎饙饌饋饓騲騴騱騬騪騶騩騮騸騭髇髊髆鬐鬒鬑鰋鰈鯷鰅鰒鯸鱀鰇鰎鰆鰗鰔鰉鶟鶙鶤鶝鶒鶘鶐鶛"], +["f5a1","鶠鶔鶜鶪鶗鶡鶚鶢鶨鶞鶣鶿鶩鶖鶦鶧麙麛麚黥黤黧黦鼰鼮齛齠齞齝齙龑儺儹劘劗囃嚽嚾孈孇巋巏廱懽攛欂櫼欃櫸欀灃灄灊灈灉灅灆爝爚爙獾甗癪矐礭礱礯籔籓糲纊纇纈纋纆纍罍羻耰臝蘘蘪蘦蘟蘣蘜蘙蘧蘮蘡蘠蘩蘞蘥"], +["f640","蠩蠝蠛蠠蠤蠜蠫衊襭襩襮襫觺譹譸譅譺譻贐贔趯躎躌轞轛轝酆酄酅醹鐿鐻鐶鐩鐽鐼鐰鐹鐪鐷鐬鑀鐱闥闤闣霵霺鞿韡顤飉飆飀饘饖騹騽驆驄驂驁騺"], +["f6a1","騿髍鬕鬗鬘鬖鬺魒鰫鰝鰜鰬鰣鰨鰩鰤鰡鶷鶶鶼鷁鷇鷊鷏鶾鷅鷃鶻鶵鷎鶹鶺鶬鷈鶱鶭鷌鶳鷍鶲鹺麜黫黮黭鼛鼘鼚鼱齎齥齤龒亹囆囅囋奱孋孌巕巑廲攡攠攦攢欋欈欉氍灕灖灗灒爞爟犩獿瓘瓕瓙瓗癭皭礵禴穰穱籗籜籙籛籚"], +["f740","糴糱纑罏羇臞艫蘴蘵蘳蘬蘲蘶蠬蠨蠦蠪蠥襱覿覾觻譾讄讂讆讅譿贕躕躔躚躒躐躖躗轠轢酇鑌鑐鑊鑋鑏鑇鑅鑈鑉鑆霿韣顪顩飋饔饛驎驓驔驌驏驈驊"], +["f7a1","驉驒驐髐鬙鬫鬻魖魕鱆鱈鰿鱄鰹鰳鱁鰼鰷鰴鰲鰽鰶鷛鷒鷞鷚鷋鷐鷜鷑鷟鷩鷙鷘鷖鷵鷕鷝麶黰鼵鼳鼲齂齫龕龢儽劙壨壧奲孍巘蠯彏戁戃戄攩攥斖曫欑欒欏毊灛灚爢玂玁玃癰矔籧籦纕艬蘺虀蘹蘼蘱蘻蘾蠰蠲蠮蠳襶襴襳觾"], +["f840","讌讎讋讈豅贙躘轤轣醼鑢鑕鑝鑗鑞韄韅頀驖驙鬞鬟鬠鱒鱘鱐鱊鱍鱋鱕鱙鱌鱎鷻鷷鷯鷣鷫鷸鷤鷶鷡鷮鷦鷲鷰鷢鷬鷴鷳鷨鷭黂黐黲黳鼆鼜鼸鼷鼶齃齏"], +["f8a1","齱齰齮齯囓囍孎屭攭曭曮欓灟灡灝灠爣瓛瓥矕礸禷禶籪纗羉艭虃蠸蠷蠵衋讔讕躞躟躠躝醾醽釂鑫鑨鑩雥靆靃靇韇韥驞髕魙鱣鱧鱦鱢鱞鱠鸂鷾鸇鸃鸆鸅鸀鸁鸉鷿鷽鸄麠鼞齆齴齵齶囔攮斸欘欙欗欚灢爦犪矘矙礹籩籫糶纚"], +["f940","纘纛纙臠臡虆虇虈襹襺襼襻觿讘讙躥躤躣鑮鑭鑯鑱鑳靉顲饟鱨鱮鱭鸋鸍鸐鸏鸒鸑麡黵鼉齇齸齻齺齹圞灦籯蠼趲躦釃鑴鑸鑶鑵驠鱴鱳鱱鱵鸔鸓黶鼊"], +["f9a1","龤灨灥糷虪蠾蠽蠿讞貜躩軉靋顳顴飌饡馫驤驦驧鬤鸕鸗齈戇欞爧虌躨钂钀钁驩驨鬮鸙爩虋讟钃鱹麷癵驫鱺鸝灩灪麤齾齉龘碁銹裏墻恒粧嫺╔╦╗╠╬╣╚╩╝╒╤╕╞╪╡╘╧╛╓╥╖╟╫╢╙╨╜║═╭╮╰╯▓"] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/eucjp.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/eucjp.json new file mode 100644 index 0000000..4fa61ca --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/eucjp.json @@ -0,0 +1,182 @@ +[ +["0","\u0000",127], +["8ea1","。",62], +["a1a1"," 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈",9,"+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇"], +["a2a1","◆□■△▲▽▼※〒→←↑↓〓"], +["a2ba","∈∋⊆⊇⊂⊃∪∩"], +["a2ca","∧∨¬⇒⇔∀∃"], +["a2dc","∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬"], +["a2f2","ʼn♯♭♪†‡¶"], +["a2fe","◯"], +["a3b0","0",9], +["a3c1","A",25], +["a3e1","a",25], +["a4a1","ぁ",82], +["a5a1","ァ",85], +["a6a1","Α",16,"Σ",6], +["a6c1","α",16,"σ",6], +["a7a1","А",5,"ЁЖ",25], +["a7d1","а",5,"ёж",25], +["a8a1","─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂"], +["ada1","①",19,"Ⅰ",9], +["adc0","㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡"], +["addf","㍻〝〟№㏍℡㊤",4,"㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪"], +["b0a1","亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭"], +["b1a1","院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応"], +["b2a1","押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改"], +["b3a1","魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱"], +["b4a1","粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄"], +["b5a1","機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京"], +["b6a1","供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈"], +["b7a1","掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲"], +["b8a1","検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向"], +["b9a1","后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込"], +["baa1","此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷"], +["bba1","察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時"], +["bca1","次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"], +["bda1","宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償"], +["bea1","勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾"], +["bfa1","拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾"], +["c0a1","澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線"], +["c1a1","繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎"], +["c2a1","臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只"], +["c3a1","叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵"], +["c4a1","帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓"], +["c5a1","邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到"], +["c6a1","董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入"], +["c7a1","如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦"], +["c8a1","函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美"], +["c9a1","鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服"], +["caa1","福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋"], +["cba1","法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満"], +["cca1","漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒"], +["cda1","諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃"], +["cea1","痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯"], +["cfa1","蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕"], +["d0a1","弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲"], +["d1a1","僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨"], +["d2a1","辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨"], +["d3a1","咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉"], +["d4a1","圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩"], +["d5a1","奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓"], +["d6a1","屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏"], +["d7a1","廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚"], +["d8a1","悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛"], +["d9a1","戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼"], +["daa1","據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼"], +["dba1","曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍"], +["dca1","棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣"], +["dda1","檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾"], +["dea1","沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌"], +["dfa1","漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼"], +["e0a1","燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱"], +["e1a1","瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰"], +["e2a1","癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬"], +["e3a1","磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐"], +["e4a1","筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆"], +["e5a1","紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺"], +["e6a1","罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋"], +["e7a1","隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙"], +["e8a1","茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈"], +["e9a1","蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙"], +["eaa1","蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞"], +["eba1","襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫"], +["eca1","譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊"], +["eda1","蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸"], +["eea1","遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮"], +["efa1","錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞"], +["f0a1","陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰"], +["f1a1","顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷"], +["f2a1","髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈"], +["f3a1","鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠"], +["f4a1","堯槇遙瑤凜熙"], +["f9a1","纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德"], +["faa1","忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱"], +["fba1","犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚"], +["fca1","釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"], +["fcf1","ⅰ",9,"¬¦'""], +["8fa2af","˘ˇ¸˙˝¯˛˚~΄΅"], +["8fa2c2","¡¦¿"], +["8fa2eb","ºª©®™¤№"], +["8fa6e1","ΆΈΉΊΪ"], +["8fa6e7","Ό"], +["8fa6e9","ΎΫ"], +["8fa6ec","Ώ"], +["8fa6f1","άέήίϊΐόςύϋΰώ"], +["8fa7c2","Ђ",10,"ЎЏ"], +["8fa7f2","ђ",10,"ўџ"], +["8fa9a1","ÆĐ"], +["8fa9a4","Ħ"], +["8fa9a6","IJ"], +["8fa9a8","ŁĿ"], +["8fa9ab","ŊØŒ"], +["8fa9af","ŦÞ"], +["8fa9c1","æđðħıijĸłŀʼnŋøœßŧþ"], +["8faaa1","ÁÀÄÂĂǍĀĄÅÃĆĈČÇĊĎÉÈËÊĚĖĒĘ"], +["8faaba","ĜĞĢĠĤÍÌÏÎǏİĪĮĨĴĶĹĽĻŃŇŅÑÓÒÖÔǑŐŌÕŔŘŖŚŜŠŞŤŢÚÙÜÛŬǓŰŪŲŮŨǗǛǙǕŴÝŸŶŹŽŻ"], +["8faba1","áàäâăǎāąåãćĉčçċďéèëêěėēęǵĝğ"], +["8fabbd","ġĥíìïîǐ"], +["8fabc5","īįĩĵķĺľļńňņñóòöôǒőōõŕřŗśŝšşťţúùüûŭǔűūųůũǘǜǚǖŵýÿŷźžż"], +["8fb0a1","丂丄丅丌丒丟丣两丨丫丮丯丰丵乀乁乄乇乑乚乜乣乨乩乴乵乹乿亍亖亗亝亯亹仃仐仚仛仠仡仢仨仯仱仳仵份仾仿伀伂伃伈伋伌伒伕伖众伙伮伱你伳伵伷伹伻伾佀佂佈佉佋佌佒佔佖佘佟佣佪佬佮佱佷佸佹佺佽佾侁侂侄"], +["8fb1a1","侅侉侊侌侎侐侒侓侔侗侙侚侞侟侲侷侹侻侼侽侾俀俁俅俆俈俉俋俌俍俏俒俜俠俢俰俲俼俽俿倀倁倄倇倊倌倎倐倓倗倘倛倜倝倞倢倧倮倰倲倳倵偀偁偂偅偆偊偌偎偑偒偓偗偙偟偠偢偣偦偧偪偭偰偱倻傁傃傄傆傊傎傏傐"], +["8fb2a1","傒傓傔傖傛傜傞",4,"傪傯傰傹傺傽僀僃僄僇僌僎僐僓僔僘僜僝僟僢僤僦僨僩僯僱僶僺僾儃儆儇儈儋儌儍儎僲儐儗儙儛儜儝儞儣儧儨儬儭儯儱儳儴儵儸儹兂兊兏兓兕兗兘兟兤兦兾冃冄冋冎冘冝冡冣冭冸冺冼冾冿凂"], +["8fb3a1","凈减凑凒凓凕凘凞凢凥凮凲凳凴凷刁刂刅划刓刕刖刘刢刨刱刲刵刼剅剉剕剗剘剚剜剟剠剡剦剮剷剸剹劀劂劅劊劌劓劕劖劗劘劚劜劤劥劦劧劯劰劶劷劸劺劻劽勀勄勆勈勌勏勑勔勖勛勜勡勥勨勩勪勬勰勱勴勶勷匀匃匊匋"], +["8fb4a1","匌匑匓匘匛匜匞匟匥匧匨匩匫匬匭匰匲匵匼匽匾卂卌卋卙卛卡卣卥卬卭卲卹卾厃厇厈厎厓厔厙厝厡厤厪厫厯厲厴厵厷厸厺厽叀叅叏叒叓叕叚叝叞叠另叧叵吂吓吚吡吧吨吪启吱吴吵呃呄呇呍呏呞呢呤呦呧呩呫呭呮呴呿"], +["8fb5a1","咁咃咅咈咉咍咑咕咖咜咟咡咦咧咩咪咭咮咱咷咹咺咻咿哆哊响哎哠哪哬哯哶哼哾哿唀唁唅唈唉唌唍唎唕唪唫唲唵唶唻唼唽啁啇啉啊啍啐啑啘啚啛啞啠啡啤啦啿喁喂喆喈喎喏喑喒喓喔喗喣喤喭喲喿嗁嗃嗆嗉嗋嗌嗎嗑嗒"], +["8fb6a1","嗓嗗嗘嗛嗞嗢嗩嗶嗿嘅嘈嘊嘍",5,"嘙嘬嘰嘳嘵嘷嘹嘻嘼嘽嘿噀噁噃噄噆噉噋噍噏噔噞噠噡噢噣噦噩噭噯噱噲噵嚄嚅嚈嚋嚌嚕嚙嚚嚝嚞嚟嚦嚧嚨嚩嚫嚬嚭嚱嚳嚷嚾囅囉囊囋囏囐囌囍囙囜囝囟囡囤",4,"囱囫园"], +["8fb7a1","囶囷圁圂圇圊圌圑圕圚圛圝圠圢圣圤圥圩圪圬圮圯圳圴圽圾圿坅坆坌坍坒坢坥坧坨坫坭",4,"坳坴坵坷坹坺坻坼坾垁垃垌垔垗垙垚垜垝垞垟垡垕垧垨垩垬垸垽埇埈埌埏埕埝埞埤埦埧埩埭埰埵埶埸埽埾埿堃堄堈堉埡"], +["8fb8a1","堌堍堛堞堟堠堦堧堭堲堹堿塉塌塍塏塐塕塟塡塤塧塨塸塼塿墀墁墇墈墉墊墌墍墏墐墔墖墝墠墡墢墦墩墱墲壄墼壂壈壍壎壐壒壔壖壚壝壡壢壩壳夅夆夋夌夒夓夔虁夝夡夣夤夨夯夰夳夵夶夿奃奆奒奓奙奛奝奞奟奡奣奫奭"], +["8fb9a1","奯奲奵奶她奻奼妋妌妎妒妕妗妟妤妧妭妮妯妰妳妷妺妼姁姃姄姈姊姍姒姝姞姟姣姤姧姮姯姱姲姴姷娀娄娌娍娎娒娓娞娣娤娧娨娪娭娰婄婅婇婈婌婐婕婞婣婥婧婭婷婺婻婾媋媐媓媖媙媜媞媟媠媢媧媬媱媲媳媵媸媺媻媿"], +["8fbaa1","嫄嫆嫈嫏嫚嫜嫠嫥嫪嫮嫵嫶嫽嬀嬁嬈嬗嬴嬙嬛嬝嬡嬥嬭嬸孁孋孌孒孖孞孨孮孯孼孽孾孿宁宄宆宊宎宐宑宓宔宖宨宩宬宭宯宱宲宷宺宼寀寁寍寏寖",4,"寠寯寱寴寽尌尗尞尟尣尦尩尫尬尮尰尲尵尶屙屚屜屢屣屧屨屩"], +["8fbba1","屭屰屴屵屺屻屼屽岇岈岊岏岒岝岟岠岢岣岦岪岲岴岵岺峉峋峒峝峗峮峱峲峴崁崆崍崒崫崣崤崦崧崱崴崹崽崿嵂嵃嵆嵈嵕嵑嵙嵊嵟嵠嵡嵢嵤嵪嵭嵰嵹嵺嵾嵿嶁嶃嶈嶊嶒嶓嶔嶕嶙嶛嶟嶠嶧嶫嶰嶴嶸嶹巃巇巋巐巎巘巙巠巤"], +["8fbca1","巩巸巹帀帇帍帒帔帕帘帟帠帮帨帲帵帾幋幐幉幑幖幘幛幜幞幨幪",4,"幰庀庋庎庢庤庥庨庪庬庱庳庽庾庿廆廌廋廎廑廒廔廕廜廞廥廫异弆弇弈弎弙弜弝弡弢弣弤弨弫弬弮弰弴弶弻弽弿彀彄彅彇彍彐彔彘彛彠彣彤彧"], +["8fbda1","彯彲彴彵彸彺彽彾徉徍徏徖徜徝徢徧徫徤徬徯徰徱徸忄忇忈忉忋忐",4,"忞忡忢忨忩忪忬忭忮忯忲忳忶忺忼怇怊怍怓怔怗怘怚怟怤怭怳怵恀恇恈恉恌恑恔恖恗恝恡恧恱恾恿悂悆悈悊悎悑悓悕悘悝悞悢悤悥您悰悱悷"], +["8fbea1","悻悾惂惄惈惉惊惋惎惏惔惕惙惛惝惞惢惥惲惵惸惼惽愂愇愊愌愐",4,"愖愗愙愜愞愢愪愫愰愱愵愶愷愹慁慅慆慉慞慠慬慲慸慻慼慿憀憁憃憄憋憍憒憓憗憘憜憝憟憠憥憨憪憭憸憹憼懀懁懂懎懏懕懜懝懞懟懡懢懧懩懥"], +["8fbfa1","懬懭懯戁戃戄戇戓戕戜戠戢戣戧戩戫戹戽扂扃扄扆扌扐扑扒扔扖扚扜扤扭扯扳扺扽抍抎抏抐抦抨抳抶抷抺抾抿拄拎拕拖拚拪拲拴拼拽挃挄挊挋挍挐挓挖挘挩挪挭挵挶挹挼捁捂捃捄捆捊捋捎捒捓捔捘捛捥捦捬捭捱捴捵"], +["8fc0a1","捸捼捽捿掂掄掇掊掐掔掕掙掚掞掤掦掭掮掯掽揁揅揈揎揑揓揔揕揜揠揥揪揬揲揳揵揸揹搉搊搐搒搔搘搞搠搢搤搥搩搪搯搰搵搽搿摋摏摑摒摓摔摚摛摜摝摟摠摡摣摭摳摴摻摽撅撇撏撐撑撘撙撛撝撟撡撣撦撨撬撳撽撾撿"], +["8fc1a1","擄擉擊擋擌擎擐擑擕擗擤擥擩擪擭擰擵擷擻擿攁攄攈攉攊攏攓攔攖攙攛攞攟攢攦攩攮攱攺攼攽敃敇敉敐敒敔敟敠敧敫敺敽斁斅斊斒斕斘斝斠斣斦斮斲斳斴斿旂旈旉旎旐旔旖旘旟旰旲旴旵旹旾旿昀昄昈昉昍昑昒昕昖昝"], +["8fc2a1","昞昡昢昣昤昦昩昪昫昬昮昰昱昳昹昷晀晅晆晊晌晑晎晗晘晙晛晜晠晡曻晪晫晬晾晳晵晿晷晸晹晻暀晼暋暌暍暐暒暙暚暛暜暟暠暤暭暱暲暵暻暿曀曂曃曈曌曎曏曔曛曟曨曫曬曮曺朅朇朎朓朙朜朠朢朳朾杅杇杈杌杔杕杝"], +["8fc3a1","杦杬杮杴杶杻极构枎枏枑枓枖枘枙枛枰枱枲枵枻枼枽柹柀柂柃柅柈柉柒柗柙柜柡柦柰柲柶柷桒栔栙栝栟栨栧栬栭栯栰栱栳栻栿桄桅桊桌桕桗桘桛桫桮",4,"桵桹桺桻桼梂梄梆梈梖梘梚梜梡梣梥梩梪梮梲梻棅棈棌棏"], +["8fc4a1","棐棑棓棖棙棜棝棥棨棪棫棬棭棰棱棵棶棻棼棽椆椉椊椐椑椓椖椗椱椳椵椸椻楂楅楉楎楗楛楣楤楥楦楨楩楬楰楱楲楺楻楿榀榍榒榖榘榡榥榦榨榫榭榯榷榸榺榼槅槈槑槖槗槢槥槮槯槱槳槵槾樀樁樃樏樑樕樚樝樠樤樨樰樲"], +["8fc5a1","樴樷樻樾樿橅橆橉橊橎橐橑橒橕橖橛橤橧橪橱橳橾檁檃檆檇檉檋檑檛檝檞檟檥檫檯檰檱檴檽檾檿櫆櫉櫈櫌櫐櫔櫕櫖櫜櫝櫤櫧櫬櫰櫱櫲櫼櫽欂欃欆欇欉欏欐欑欗欛欞欤欨欫欬欯欵欶欻欿歆歊歍歒歖歘歝歠歧歫歮歰歵歽"], +["8fc6a1","歾殂殅殗殛殟殠殢殣殨殩殬殭殮殰殸殹殽殾毃毄毉毌毖毚毡毣毦毧毮毱毷毹毿氂氄氅氉氍氎氐氒氙氟氦氧氨氬氮氳氵氶氺氻氿汊汋汍汏汒汔汙汛汜汫汭汯汴汶汸汹汻沅沆沇沉沔沕沗沘沜沟沰沲沴泂泆泍泏泐泑泒泔泖"], +["8fc7a1","泚泜泠泧泩泫泬泮泲泴洄洇洊洎洏洑洓洚洦洧洨汧洮洯洱洹洼洿浗浞浟浡浥浧浯浰浼涂涇涑涒涔涖涗涘涪涬涴涷涹涽涿淄淈淊淎淏淖淛淝淟淠淢淥淩淯淰淴淶淼渀渄渞渢渧渲渶渹渻渼湄湅湈湉湋湏湑湒湓湔湗湜湝湞"], +["8fc8a1","湢湣湨湳湻湽溍溓溙溠溧溭溮溱溳溻溿滀滁滃滇滈滊滍滎滏滫滭滮滹滻滽漄漈漊漌漍漖漘漚漛漦漩漪漯漰漳漶漻漼漭潏潑潒潓潗潙潚潝潞潡潢潨潬潽潾澃澇澈澋澌澍澐澒澓澔澖澚澟澠澥澦澧澨澮澯澰澵澶澼濅濇濈濊"], +["8fc9a1","濚濞濨濩濰濵濹濼濽瀀瀅瀆瀇瀍瀗瀠瀣瀯瀴瀷瀹瀼灃灄灈灉灊灋灔灕灝灞灎灤灥灬灮灵灶灾炁炅炆炔",4,"炛炤炫炰炱炴炷烊烑烓烔烕烖烘烜烤烺焃",4,"焋焌焏焞焠焫焭焯焰焱焸煁煅煆煇煊煋煐煒煗煚煜煞煠"], +["8fcaa1","煨煹熀熅熇熌熒熚熛熠熢熯熰熲熳熺熿燀燁燄燋燌燓燖燙燚燜燸燾爀爇爈爉爓爗爚爝爟爤爫爯爴爸爹牁牂牃牅牎牏牐牓牕牖牚牜牞牠牣牨牫牮牯牱牷牸牻牼牿犄犉犍犎犓犛犨犭犮犱犴犾狁狇狉狌狕狖狘狟狥狳狴狺狻"], +["8fcba1","狾猂猄猅猇猋猍猒猓猘猙猞猢猤猧猨猬猱猲猵猺猻猽獃獍獐獒獖獘獝獞獟獠獦獧獩獫獬獮獯獱獷獹獼玀玁玃玅玆玎玐玓玕玗玘玜玞玟玠玢玥玦玪玫玭玵玷玹玼玽玿珅珆珉珋珌珏珒珓珖珙珝珡珣珦珧珩珴珵珷珹珺珻珽"], +["8fcca1","珿琀琁琄琇琊琑琚琛琤琦琨",9,"琹瑀瑃瑄瑆瑇瑋瑍瑑瑒瑗瑝瑢瑦瑧瑨瑫瑭瑮瑱瑲璀璁璅璆璇璉璏璐璑璒璘璙璚璜璟璠璡璣璦璨璩璪璫璮璯璱璲璵璹璻璿瓈瓉瓌瓐瓓瓘瓚瓛瓞瓟瓤瓨瓪瓫瓯瓴瓺瓻瓼瓿甆"], +["8fcda1","甒甖甗甠甡甤甧甩甪甯甶甹甽甾甿畀畃畇畈畎畐畒畗畞畟畡畯畱畹",5,"疁疅疐疒疓疕疙疜疢疤疴疺疿痀痁痄痆痌痎痏痗痜痟痠痡痤痧痬痮痯痱痹瘀瘂瘃瘄瘇瘈瘊瘌瘏瘒瘓瘕瘖瘙瘛瘜瘝瘞瘣瘥瘦瘩瘭瘲瘳瘵瘸瘹"], +["8fcea1","瘺瘼癊癀癁癃癄癅癉癋癕癙癟癤癥癭癮癯癱癴皁皅皌皍皕皛皜皝皟皠皢",6,"皪皭皽盁盅盉盋盌盎盔盙盠盦盨盬盰盱盶盹盼眀眆眊眎眒眔眕眗眙眚眜眢眨眭眮眯眴眵眶眹眽眾睂睅睆睊睍睎睏睒睖睗睜睞睟睠睢"], +["8fcfa1","睤睧睪睬睰睲睳睴睺睽瞀瞄瞌瞍瞔瞕瞖瞚瞟瞢瞧瞪瞮瞯瞱瞵瞾矃矉矑矒矕矙矞矟矠矤矦矪矬矰矱矴矸矻砅砆砉砍砎砑砝砡砢砣砭砮砰砵砷硃硄硇硈硌硎硒硜硞硠硡硣硤硨硪确硺硾碊碏碔碘碡碝碞碟碤碨碬碭碰碱碲碳"], +["8fd0a1","碻碽碿磇磈磉磌磎磒磓磕磖磤磛磟磠磡磦磪磲磳礀磶磷磺磻磿礆礌礐礚礜礞礟礠礥礧礩礭礱礴礵礻礽礿祄祅祆祊祋祏祑祔祘祛祜祧祩祫祲祹祻祼祾禋禌禑禓禔禕禖禘禛禜禡禨禩禫禯禱禴禸离秂秄秇秈秊秏秔秖秚秝秞"], +["8fd1a1","秠秢秥秪秫秭秱秸秼稂稃稇稉稊稌稑稕稛稞稡稧稫稭稯稰稴稵稸稹稺穄穅穇穈穌穕穖穙穜穝穟穠穥穧穪穭穵穸穾窀窂窅窆窊窋窐窑窔窞窠窣窬窳窵窹窻窼竆竉竌竎竑竛竨竩竫竬竱竴竻竽竾笇笔笟笣笧笩笪笫笭笮笯笰"], +["8fd2a1","笱笴笽笿筀筁筇筎筕筠筤筦筩筪筭筯筲筳筷箄箉箎箐箑箖箛箞箠箥箬箯箰箲箵箶箺箻箼箽篂篅篈篊篔篖篗篙篚篛篨篪篲篴篵篸篹篺篼篾簁簂簃簄簆簉簋簌簎簏簙簛簠簥簦簨簬簱簳簴簶簹簺籆籊籕籑籒籓籙",5], +["8fd3a1","籡籣籧籩籭籮籰籲籹籼籽粆粇粏粔粞粠粦粰粶粷粺粻粼粿糄糇糈糉糍糏糓糔糕糗糙糚糝糦糩糫糵紃紇紈紉紏紑紒紓紖紝紞紣紦紪紭紱紼紽紾絀絁絇絈絍絑絓絗絙絚絜絝絥絧絪絰絸絺絻絿綁綂綃綅綆綈綋綌綍綑綖綗綝"], +["8fd4a1","綞綦綧綪綳綶綷綹緂",4,"緌緍緎緗緙縀緢緥緦緪緫緭緱緵緶緹緺縈縐縑縕縗縜縝縠縧縨縬縭縯縳縶縿繄繅繇繎繐繒繘繟繡繢繥繫繮繯繳繸繾纁纆纇纊纍纑纕纘纚纝纞缼缻缽缾缿罃罄罇罏罒罓罛罜罝罡罣罤罥罦罭"], +["8fd5a1","罱罽罾罿羀羋羍羏羐羑羖羗羜羡羢羦羪羭羴羼羿翀翃翈翎翏翛翟翣翥翨翬翮翯翲翺翽翾翿耇耈耊耍耎耏耑耓耔耖耝耞耟耠耤耦耬耮耰耴耵耷耹耺耼耾聀聄聠聤聦聭聱聵肁肈肎肜肞肦肧肫肸肹胈胍胏胒胔胕胗胘胠胭胮"], +["8fd6a1","胰胲胳胶胹胺胾脃脋脖脗脘脜脞脠脤脧脬脰脵脺脼腅腇腊腌腒腗腠腡腧腨腩腭腯腷膁膐膄膅膆膋膎膖膘膛膞膢膮膲膴膻臋臃臅臊臎臏臕臗臛臝臞臡臤臫臬臰臱臲臵臶臸臹臽臿舀舃舏舓舔舙舚舝舡舢舨舲舴舺艃艄艅艆"], +["8fd7a1","艋艎艏艑艖艜艠艣艧艭艴艻艽艿芀芁芃芄芇芉芊芎芑芔芖芘芚芛芠芡芣芤芧芨芩芪芮芰芲芴芷芺芼芾芿苆苐苕苚苠苢苤苨苪苭苯苶苷苽苾茀茁茇茈茊茋荔茛茝茞茟茡茢茬茭茮茰茳茷茺茼茽荂荃荄荇荍荎荑荕荖荗荰荸"], +["8fd8a1","荽荿莀莂莄莆莍莒莔莕莘莙莛莜莝莦莧莩莬莾莿菀菇菉菏菐菑菔菝荓菨菪菶菸菹菼萁萆萊萏萑萕萙莭萯萹葅葇葈葊葍葏葑葒葖葘葙葚葜葠葤葥葧葪葰葳葴葶葸葼葽蒁蒅蒒蒓蒕蒞蒦蒨蒩蒪蒯蒱蒴蒺蒽蒾蓀蓂蓇蓈蓌蓏蓓"], +["8fd9a1","蓜蓧蓪蓯蓰蓱蓲蓷蔲蓺蓻蓽蔂蔃蔇蔌蔎蔐蔜蔞蔢蔣蔤蔥蔧蔪蔫蔯蔳蔴蔶蔿蕆蕏",4,"蕖蕙蕜",6,"蕤蕫蕯蕹蕺蕻蕽蕿薁薅薆薉薋薌薏薓薘薝薟薠薢薥薧薴薶薷薸薼薽薾薿藂藇藊藋藎薭藘藚藟藠藦藨藭藳藶藼"], +["8fdaa1","藿蘀蘄蘅蘍蘎蘐蘑蘒蘘蘙蘛蘞蘡蘧蘩蘶蘸蘺蘼蘽虀虂虆虒虓虖虗虘虙虝虠",4,"虩虬虯虵虶虷虺蚍蚑蚖蚘蚚蚜蚡蚦蚧蚨蚭蚱蚳蚴蚵蚷蚸蚹蚿蛀蛁蛃蛅蛑蛒蛕蛗蛚蛜蛠蛣蛥蛧蚈蛺蛼蛽蜄蜅蜇蜋蜎蜏蜐蜓蜔蜙蜞蜟蜡蜣"], +["8fdba1","蜨蜮蜯蜱蜲蜹蜺蜼蜽蜾蝀蝃蝅蝍蝘蝝蝡蝤蝥蝯蝱蝲蝻螃",6,"螋螌螐螓螕螗螘螙螞螠螣螧螬螭螮螱螵螾螿蟁蟈蟉蟊蟎蟕蟖蟙蟚蟜蟟蟢蟣蟤蟪蟫蟭蟱蟳蟸蟺蟿蠁蠃蠆蠉蠊蠋蠐蠙蠒蠓蠔蠘蠚蠛蠜蠞蠟蠨蠭蠮蠰蠲蠵"], +["8fdca1","蠺蠼衁衃衅衈衉衊衋衎衑衕衖衘衚衜衟衠衤衩衱衹衻袀袘袚袛袜袟袠袨袪袺袽袾裀裊",4,"裑裒裓裛裞裧裯裰裱裵裷褁褆褍褎褏褕褖褘褙褚褜褠褦褧褨褰褱褲褵褹褺褾襀襂襅襆襉襏襒襗襚襛襜襡襢襣襫襮襰襳襵襺"], +["8fdda1","襻襼襽覉覍覐覔覕覛覜覟覠覥覰覴覵覶覷覼觔",4,"觥觩觫觭觱觳觶觹觽觿訄訅訇訏訑訒訔訕訞訠訢訤訦訫訬訯訵訷訽訾詀詃詅詇詉詍詎詓詖詗詘詜詝詡詥詧詵詶詷詹詺詻詾詿誀誃誆誋誏誐誒誖誗誙誟誧誩誮誯誳"], +["8fdea1","誶誷誻誾諃諆諈諉諊諑諓諔諕諗諝諟諬諰諴諵諶諼諿謅謆謋謑謜謞謟謊謭謰謷謼譂",4,"譈譒譓譔譙譍譞譣譭譶譸譹譼譾讁讄讅讋讍讏讔讕讜讞讟谸谹谽谾豅豇豉豋豏豑豓豔豗豘豛豝豙豣豤豦豨豩豭豳豵豶豻豾貆"], +["8fdfa1","貇貋貐貒貓貙貛貜貤貹貺賅賆賉賋賏賖賕賙賝賡賨賬賯賰賲賵賷賸賾賿贁贃贉贒贗贛赥赩赬赮赿趂趄趈趍趐趑趕趞趟趠趦趫趬趯趲趵趷趹趻跀跅跆跇跈跊跎跑跔跕跗跙跤跥跧跬跰趼跱跲跴跽踁踄踅踆踋踑踔踖踠踡踢"], +["8fe0a1","踣踦踧踱踳踶踷踸踹踽蹀蹁蹋蹍蹎蹏蹔蹛蹜蹝蹞蹡蹢蹩蹬蹭蹯蹰蹱蹹蹺蹻躂躃躉躐躒躕躚躛躝躞躢躧躩躭躮躳躵躺躻軀軁軃軄軇軏軑軔軜軨軮軰軱軷軹軺軭輀輂輇輈輏輐輖輗輘輞輠輡輣輥輧輨輬輭輮輴輵輶輷輺轀轁"], +["8fe1a1","轃轇轏轑",4,"轘轝轞轥辝辠辡辤辥辦辵辶辸达迀迁迆迊迋迍运迒迓迕迠迣迤迨迮迱迵迶迻迾适逄逈逌逘逛逨逩逯逪逬逭逳逴逷逿遃遄遌遛遝遢遦遧遬遰遴遹邅邈邋邌邎邐邕邗邘邙邛邠邡邢邥邰邲邳邴邶邽郌邾郃"], +["8fe2a1","郄郅郇郈郕郗郘郙郜郝郟郥郒郶郫郯郰郴郾郿鄀鄄鄅鄆鄈鄍鄐鄔鄖鄗鄘鄚鄜鄞鄠鄥鄢鄣鄧鄩鄮鄯鄱鄴鄶鄷鄹鄺鄼鄽酃酇酈酏酓酗酙酚酛酡酤酧酭酴酹酺酻醁醃醅醆醊醎醑醓醔醕醘醞醡醦醨醬醭醮醰醱醲醳醶醻醼醽醿"], +["8fe3a1","釂釃釅釓釔釗釙釚釞釤釥釩釪釬",5,"釷釹釻釽鈀鈁鈄鈅鈆鈇鈉鈊鈌鈐鈒鈓鈖鈘鈜鈝鈣鈤鈥鈦鈨鈮鈯鈰鈳鈵鈶鈸鈹鈺鈼鈾鉀鉂鉃鉆鉇鉊鉍鉎鉏鉑鉘鉙鉜鉝鉠鉡鉥鉧鉨鉩鉮鉯鉰鉵",4,"鉻鉼鉽鉿銈銉銊銍銎銒銗"], +["8fe4a1","銙銟銠銤銥銧銨銫銯銲銶銸銺銻銼銽銿",4,"鋅鋆鋇鋈鋋鋌鋍鋎鋐鋓鋕鋗鋘鋙鋜鋝鋟鋠鋡鋣鋥鋧鋨鋬鋮鋰鋹鋻鋿錀錂錈錍錑錔錕錜錝錞錟錡錤錥錧錩錪錳錴錶錷鍇鍈鍉鍐鍑鍒鍕鍗鍘鍚鍞鍤鍥鍧鍩鍪鍭鍯鍰鍱鍳鍴鍶"], +["8fe5a1","鍺鍽鍿鎀鎁鎂鎈鎊鎋鎍鎏鎒鎕鎘鎛鎞鎡鎣鎤鎦鎨鎫鎴鎵鎶鎺鎩鏁鏄鏅鏆鏇鏉",4,"鏓鏙鏜鏞鏟鏢鏦鏧鏹鏷鏸鏺鏻鏽鐁鐂鐄鐈鐉鐍鐎鐏鐕鐖鐗鐟鐮鐯鐱鐲鐳鐴鐻鐿鐽鑃鑅鑈鑊鑌鑕鑙鑜鑟鑡鑣鑨鑫鑭鑮鑯鑱鑲钄钃镸镹"], +["8fe6a1","镾閄閈閌閍閎閝閞閟閡閦閩閫閬閴閶閺閽閿闆闈闉闋闐闑闒闓闙闚闝闞闟闠闤闦阝阞阢阤阥阦阬阱阳阷阸阹阺阼阽陁陒陔陖陗陘陡陮陴陻陼陾陿隁隂隃隄隉隑隖隚隝隟隤隥隦隩隮隯隳隺雊雒嶲雘雚雝雞雟雩雯雱雺霂"], +["8fe7a1","霃霅霉霚霛霝霡霢霣霨霱霳靁靃靊靎靏靕靗靘靚靛靣靧靪靮靳靶靷靸靻靽靿鞀鞉鞕鞖鞗鞙鞚鞞鞟鞢鞬鞮鞱鞲鞵鞶鞸鞹鞺鞼鞾鞿韁韄韅韇韉韊韌韍韎韐韑韔韗韘韙韝韞韠韛韡韤韯韱韴韷韸韺頇頊頙頍頎頔頖頜頞頠頣頦"], +["8fe8a1","頫頮頯頰頲頳頵頥頾顄顇顊顑顒顓顖顗顙顚顢顣顥顦顪顬颫颭颮颰颴颷颸颺颻颿飂飅飈飌飡飣飥飦飧飪飳飶餂餇餈餑餕餖餗餚餛餜餟餢餦餧餫餱",4,"餹餺餻餼饀饁饆饇饈饍饎饔饘饙饛饜饞饟饠馛馝馟馦馰馱馲馵"], +["8fe9a1","馹馺馽馿駃駉駓駔駙駚駜駞駧駪駫駬駰駴駵駹駽駾騂騃騄騋騌騐騑騖騞騠騢騣騤騧騭騮騳騵騶騸驇驁驄驊驋驌驎驑驔驖驝骪骬骮骯骲骴骵骶骹骻骾骿髁髃髆髈髎髐髒髕髖髗髛髜髠髤髥髧髩髬髲髳髵髹髺髽髿",4], +["8feaa1","鬄鬅鬈鬉鬋鬌鬍鬎鬐鬒鬖鬙鬛鬜鬠鬦鬫鬭鬳鬴鬵鬷鬹鬺鬽魈魋魌魕魖魗魛魞魡魣魥魦魨魪",4,"魳魵魷魸魹魿鮀鮄鮅鮆鮇鮉鮊鮋鮍鮏鮐鮔鮚鮝鮞鮦鮧鮩鮬鮰鮱鮲鮷鮸鮻鮼鮾鮿鯁鯇鯈鯎鯐鯗鯘鯝鯟鯥鯧鯪鯫鯯鯳鯷鯸"], +["8feba1","鯹鯺鯽鯿鰀鰂鰋鰏鰑鰖鰘鰙鰚鰜鰞鰢鰣鰦",4,"鰱鰵鰶鰷鰽鱁鱃鱄鱅鱉鱊鱎鱏鱐鱓鱔鱖鱘鱛鱝鱞鱟鱣鱩鱪鱜鱫鱨鱮鱰鱲鱵鱷鱻鳦鳲鳷鳹鴋鴂鴑鴗鴘鴜鴝鴞鴯鴰鴲鴳鴴鴺鴼鵅鴽鵂鵃鵇鵊鵓鵔鵟鵣鵢鵥鵩鵪鵫鵰鵶鵷鵻"], +["8feca1","鵼鵾鶃鶄鶆鶊鶍鶎鶒鶓鶕鶖鶗鶘鶡鶪鶬鶮鶱鶵鶹鶼鶿鷃鷇鷉鷊鷔鷕鷖鷗鷚鷞鷟鷠鷥鷧鷩鷫鷮鷰鷳鷴鷾鸊鸂鸇鸎鸐鸑鸒鸕鸖鸙鸜鸝鹺鹻鹼麀麂麃麄麅麇麎麏麖麘麛麞麤麨麬麮麯麰麳麴麵黆黈黋黕黟黤黧黬黭黮黰黱黲黵"], +["8feda1","黸黿鼂鼃鼉鼏鼐鼑鼒鼔鼖鼗鼙鼚鼛鼟鼢鼦鼪鼫鼯鼱鼲鼴鼷鼹鼺鼼鼽鼿齁齃",4,"齓齕齖齗齘齚齝齞齨齩齭",4,"齳齵齺齽龏龐龑龒龔龖龗龞龡龢龣龥"] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json new file mode 100644 index 0000000..85c6934 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json @@ -0,0 +1 @@ +{"uChars":[128,165,169,178,184,216,226,235,238,244,248,251,253,258,276,284,300,325,329,334,364,463,465,467,469,471,473,475,477,506,594,610,712,716,730,930,938,962,970,1026,1104,1106,8209,8215,8218,8222,8231,8241,8244,8246,8252,8365,8452,8454,8458,8471,8482,8556,8570,8596,8602,8713,8720,8722,8726,8731,8737,8740,8742,8748,8751,8760,8766,8777,8781,8787,8802,8808,8816,8854,8858,8870,8896,8979,9322,9372,9548,9588,9616,9622,9634,9652,9662,9672,9676,9680,9702,9735,9738,9793,9795,11906,11909,11913,11917,11928,11944,11947,11951,11956,11960,11964,11979,12284,12292,12312,12319,12330,12351,12436,12447,12535,12543,12586,12842,12850,12964,13200,13215,13218,13253,13263,13267,13270,13384,13428,13727,13839,13851,14617,14703,14801,14816,14964,15183,15471,15585,16471,16736,17208,17325,17330,17374,17623,17997,18018,18212,18218,18301,18318,18760,18811,18814,18820,18823,18844,18848,18872,19576,19620,19738,19887,40870,59244,59336,59367,59413,59417,59423,59431,59437,59443,59452,59460,59478,59493,63789,63866,63894,63976,63986,64016,64018,64021,64025,64034,64037,64042,65074,65093,65107,65112,65127,65132,65375,65510,65536],"gbChars":[0,36,38,45,50,81,89,95,96,100,103,104,105,109,126,133,148,172,175,179,208,306,307,308,309,310,311,312,313,341,428,443,544,545,558,741,742,749,750,805,819,820,7922,7924,7925,7927,7934,7943,7944,7945,7950,8062,8148,8149,8152,8164,8174,8236,8240,8262,8264,8374,8380,8381,8384,8388,8390,8392,8393,8394,8396,8401,8406,8416,8419,8424,8437,8439,8445,8482,8485,8496,8521,8603,8936,8946,9046,9050,9063,9066,9076,9092,9100,9108,9111,9113,9131,9162,9164,9218,9219,11329,11331,11334,11336,11346,11361,11363,11366,11370,11372,11375,11389,11682,11686,11687,11692,11694,11714,11716,11723,11725,11730,11736,11982,11989,12102,12336,12348,12350,12384,12393,12395,12397,12510,12553,12851,12962,12973,13738,13823,13919,13933,14080,14298,14585,14698,15583,15847,16318,16434,16438,16481,16729,17102,17122,17315,17320,17402,17418,17859,17909,17911,17915,17916,17936,17939,17961,18664,18703,18814,18962,19043,33469,33470,33471,33484,33485,33490,33497,33501,33505,33513,33520,33536,33550,37845,37921,37948,38029,38038,38064,38065,38066,38069,38075,38076,38078,39108,39109,39113,39114,39115,39116,39265,39394,189000]} \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gbk-added.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gbk-added.json new file mode 100644 index 0000000..8abfa9f --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gbk-added.json @@ -0,0 +1,55 @@ +[ +["a140","",62], +["a180","",32], +["a240","",62], +["a280","",32], +["a2ab","",5], +["a2e3","€"], +["a2ef",""], +["a2fd",""], +["a340","",62], +["a380","",31," "], +["a440","",62], +["a480","",32], +["a4f4","",10], +["a540","",62], +["a580","",32], +["a5f7","",7], +["a640","",62], +["a680","",32], +["a6b9","",7], +["a6d9","",6], +["a6ec",""], +["a6f3",""], +["a6f6","",8], +["a740","",62], +["a780","",32], +["a7c2","",14], +["a7f2","",12], +["a896","",10], +["a8bc",""], +["a8bf","ǹ"], +["a8c1",""], +["a8ea","",20], +["a958",""], +["a95b",""], +["a95d",""], +["a989","〾⿰",11], +["a997","",12], +["a9f0","",14], +["aaa1","",93], +["aba1","",93], +["aca1","",93], +["ada1","",93], +["aea1","",93], +["afa1","",93], +["d7fa","",4], +["f8a1","",93], +["f9a1","",93], +["faa1","",93], +["fba1","",93], +["fca1","",93], +["fda1","",93], +["fe50","⺁⺄㑳㑇⺈⺋㖞㘚㘎⺌⺗㥮㤘㧏㧟㩳㧐㭎㱮㳠⺧⺪䁖䅟⺮䌷⺳⺶⺷䎱䎬⺻䏝䓖䙡䙌"], +["fe80","䜣䜩䝼䞍⻊䥇䥺䥽䦂䦃䦅䦆䦟䦛䦷䦶䲣䲟䲠䲡䱷䲢䴓",6,"䶮",93] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/shiftjis.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/shiftjis.json new file mode 100644 index 0000000..5a3a43c --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables/shiftjis.json @@ -0,0 +1,125 @@ +[ +["0","\u0000",128], +["a1","。",62], +["8140"," 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈",9,"+-±×"], +["8180","÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓"], +["81b8","∈∋⊆⊇⊂⊃∪∩"], +["81c8","∧∨¬⇒⇔∀∃"], +["81da","∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬"], +["81f0","ʼn♯♭♪†‡¶"], +["81fc","◯"], +["824f","0",9], +["8260","A",25], +["8281","a",25], +["829f","ぁ",82], +["8340","ァ",62], +["8380","ム",22], +["839f","Α",16,"Σ",6], +["83bf","α",16,"σ",6], +["8440","А",5,"ЁЖ",25], +["8470","а",5,"ёж",7], +["8480","о",17], +["849f","─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂"], +["8740","①",19,"Ⅰ",9], +["875f","㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡"], +["877e","㍻"], +["8780","〝〟№㏍℡㊤",4,"㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪"], +["889f","亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭"], +["8940","院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円"], +["8980","園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改"], +["8a40","魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫"], +["8a80","橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄"], +["8b40","機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救"], +["8b80","朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈"], +["8c40","掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨"], +["8c80","劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向"], +["8d40","后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降"], +["8d80","項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷"], +["8e40","察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止"], +["8e80","死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"], +["8f40","宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳"], +["8f80","準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾"], +["9040","拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨"], +["9080","逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線"], +["9140","繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻"], +["9180","操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只"], +["9240","叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄"], +["9280","逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓"], +["9340","邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬"], +["9380","凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入"], +["9440","如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅"], +["9480","楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美"], +["9540","鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷"], +["9580","斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋"], +["9640","法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆"], +["9680","摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒"], +["9740","諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲"], +["9780","沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯"], +["9840","蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕"], +["989f","弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲"], +["9940","僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭"], +["9980","凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨"], +["9a40","咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸"], +["9a80","噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩"], +["9b40","奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀"], +["9b80","它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏"], +["9c40","廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠"], +["9c80","怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛"], +["9d40","戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫"], +["9d80","捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼"], +["9e40","曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎"], +["9e80","梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣"], +["9f40","檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯"], +["9f80","麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌"], +["e040","漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝"], +["e080","烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱"], +["e140","瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿"], +["e180","痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬"], +["e240","磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰"], +["e280","窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆"], +["e340","紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷"], +["e380","縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋"], +["e440","隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤"], +["e480","艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈"], +["e540","蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬"], +["e580","蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞"], +["e640","襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧"], +["e680","諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊"], +["e740","蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜"], +["e780","轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮"], +["e840","錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙"], +["e880","閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰"], +["e940","顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃"], +["e980","騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈"], +["ea40","鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯"], +["ea80","黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠堯槇遙瑤凜熙"], +["ed40","纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏"], +["ed80","塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱"], +["ee40","犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙"], +["ee80","蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"], +["eeef","ⅰ",9,"¬¦'""], +["f040","",62], +["f080","",124], +["f140","",62], +["f180","",124], +["f240","",62], +["f280","",124], +["f340","",62], +["f380","",124], +["f440","",62], +["f480","",124], +["f540","",62], +["f580","",124], +["f640","",62], +["f680","",124], +["f740","",62], +["f780","",124], +["f840","",62], +["f880","",124], +["f940",""], +["fa40","ⅰ",9,"Ⅰ",9,"¬¦'"㈱№℡∵纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊"], +["fa80","兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯"], +["fb40","涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神"], +["fb80","祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙"], +["fc40","髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"] +] diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf16.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf16.js new file mode 100644 index 0000000..4cd425d --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf16.js @@ -0,0 +1,202 @@ + + +// == UTF16-BE codec. ========================================================== + +exports.utf16be = function(options) { + return { + encoder: utf16beEncoder, + decoder: utf16beDecoder, + + bom: new Buffer([0xFE, 0xFF]), + }; +}; + + +// -- Encoding + +function utf16beEncoder(options) { + return { + write: utf16beEncoderWrite, + end: function() {}, + } +} + +function utf16beEncoderWrite(str) { + var buf = new Buffer(str, 'ucs2'); + for (var i = 0; i < buf.length; i += 2) { + var tmp = buf[i]; buf[i] = buf[i+1]; buf[i+1] = tmp; + } + return buf; +} + + +// -- Decoding + +function utf16beDecoder(options) { + return { + write: utf16beDecoderWrite, + end: function() {}, + + overflowByte: -1, + }; +} + +function utf16beDecoderWrite(buf) { + if (buf.length == 0) + return ''; + + var buf2 = new Buffer(buf.length + 1), + i = 0, j = 0; + + if (this.overflowByte !== -1) { + buf2[0] = buf[0]; + buf2[1] = this.overflowByte; + i = 1; j = 2; + } + + for (; i < buf.length-1; i += 2, j+= 2) { + buf2[j] = buf[i+1]; + buf2[j+1] = buf[i]; + } + + this.overflowByte = (i == buf.length-1) ? buf[buf.length-1] : -1; + + return buf2.slice(0, j).toString('ucs2'); +} + + +// == UTF-16 codec ============================================================= +// Decoder chooses automatically from UTF-16LE and UTF-16BE using BOM and space-based heuristic. +// Defaults to UTF-16BE, according to RFC 2781, although it is against some industry practices, see +// http://en.wikipedia.org/wiki/UTF-16 and http://encoding.spec.whatwg.org/#utf-16le +// Decoder default can be changed: iconv.decode(buf, 'utf16', {default: 'utf-16le'}); + +// Encoder prepends BOM and uses UTF-16BE. +// Endianness can also be changed: iconv.encode(str, 'utf16', {use: 'utf-16le'}); + +exports.utf16 = function(options) { + return { + encoder: utf16Encoder, + decoder: utf16Decoder, + + getCodec: options.iconv.getCodec, + }; +}; + +// -- Encoding + +function utf16Encoder(options) { + options = options || {}; + var codec = this.getCodec(options.use || 'utf-16be'); + if (!codec.bom) + throw new Error("iconv-lite: in UTF-16 encoder, 'use' parameter should be either UTF-16BE or UTF16-LE."); + + return { + write: utf16EncoderWrite, + end: utf16EncoderEnd, + + bom: codec.bom, + internalEncoder: codec.encoder(options), + }; +} + +function utf16EncoderWrite(str) { + var buf = this.internalEncoder.write(str); + + if (this.bom) { + buf = Buffer.concat([this.bom, buf]); + this.bom = null; + } + + return buf; +} + +function utf16EncoderEnd() { + return this.internalEncoder.end(); +} + + +// -- Decoding + +function utf16Decoder(options) { + return { + write: utf16DecoderWrite, + end: utf16DecoderEnd, + + internalDecoder: null, + initialBytes: [], + initialBytesLen: 0, + + options: options || {}, + getCodec: this.getCodec, + }; +} + +function utf16DecoderWrite(buf) { + if (this.internalDecoder) + return this.internalDecoder.write(buf); + + // Codec is not chosen yet. Accumulate initial bytes. + this.initialBytes.push(buf); + this.initialBytesLen += buf.length; + + if (this.initialBytesLen < 16) // We need > 2 bytes to use space heuristic (see below) + return ''; + + // We have enough bytes -> decide endianness. + return utf16DecoderDecideEndianness.call(this); +} + +function utf16DecoderEnd() { + if (this.internalDecoder) + return this.internalDecoder.end(); + + var res = utf16DecoderDecideEndianness.call(this); + var trail; + + if (this.internalDecoder) + trail = this.internalDecoder.end(); + + return (trail && trail.length > 0) ? (res + trail) : res; +} + +function utf16DecoderDecideEndianness() { + var buf = Buffer.concat(this.initialBytes); + this.initialBytes.length = this.initialBytesLen = 0; + + if (buf.length < 2) + return ''; // Not a valid UTF-16 sequence anyway. + + // Default encoding. + var enc = this.options.default || 'utf-16be'; + + // Check BOM. + if (buf[0] == 0xFE && buf[1] == 0xFF) { // UTF-16BE BOM + enc = 'utf-16be'; buf = buf.slice(2); + } + else if (buf[0] == 0xFF && buf[1] == 0xFE) { // UTF-16LE BOM + enc = 'utf-16le'; buf = buf.slice(2); + } + else { + // No BOM found. Try to deduce encoding from initial content. + // Most of the time, the content has spaces (U+0020), but the opposite (U+2000) is very uncommon. + // So, we count spaces as if it was LE or BE, and decide from that. + var spaces = [0, 0], // Counts of space chars in both positions + _len = Math.min(buf.length - (buf.length % 2), 64); // Len is always even. + + for (var i = 0; i < _len; i += 2) { + if (buf[i] == 0x00 && buf[i+1] == 0x20) spaces[0]++; + if (buf[i] == 0x20 && buf[i+1] == 0x00) spaces[1]++; + } + + if (spaces[0] > 0 && spaces[1] == 0) + enc = 'utf-16be'; + else if (spaces[0] == 0 && spaces[1] > 0) + enc = 'utf-16le'; + } + + this.internalDecoder = this.getCodec(enc).decoder(this.options); + return this.internalDecoder.write(buf); +} + + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf7.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf7.js new file mode 100644 index 0000000..740f766 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/utf7.js @@ -0,0 +1,284 @@ + +// UTF-7 codec, according to https://tools.ietf.org/html/rfc2152 +// Below is UTF-7-IMAP codec, according to http://tools.ietf.org/html/rfc3501#section-5.1.3 + +exports.utf7 = function(options) { + return { + encoder: function utf7Encoder() { + return { + write: utf7EncoderWrite, + end: function() {}, + + iconv: options.iconv, + }; + }, + decoder: function utf7Decoder() { + return { + write: utf7DecoderWrite, + end: utf7DecoderEnd, + + iconv: options.iconv, + inBase64: false, + base64Accum: '', + }; + }, + }; +}; + + +var nonDirectChars = /[^A-Za-z0-9'\(\),-\.\/:\? \n\r\t]+/g; + +function utf7EncoderWrite(str) { + // Naive implementation. + // Non-direct chars are encoded as "+-"; single "+" char is encoded as "+-". + return new Buffer(str.replace(nonDirectChars, function(chunk) { + return "+" + (chunk === '+' ? '' : + this.iconv.encode(chunk, 'utf16-be').toString('base64').replace(/=+$/, '')) + + "-"; + }.bind(this))); +} + + +var base64Regex = /[A-Za-z0-9\/+]/; +var base64Chars = []; +for (var i = 0; i < 256; i++) + base64Chars[i] = base64Regex.test(String.fromCharCode(i)); + +var plusChar = '+'.charCodeAt(0), + minusChar = '-'.charCodeAt(0), + andChar = '&'.charCodeAt(0); + +function utf7DecoderWrite(buf) { + var res = "", lastI = 0, + inBase64 = this.inBase64, + base64Accum = this.base64Accum; + + // The decoder is more involved as we must handle chunks in stream. + + for (var i = 0; i < buf.length; i++) { + if (!inBase64) { // We're in direct mode. + // Write direct chars until '+' + if (buf[i] == plusChar) { + res += this.iconv.decode(buf.slice(lastI, i), "ascii"); // Write direct chars. + lastI = i+1; + inBase64 = true; + } + } else { // We decode base64. + if (!base64Chars[buf[i]]) { // Base64 ended. + if (i == lastI && buf[i] == minusChar) {// "+-" -> "+" + res += "+"; + } else { + var b64str = base64Accum + buf.slice(lastI, i).toString(); + res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be"); + } + + if (buf[i] != minusChar) // Minus is absorbed after base64. + i--; + + lastI = i+1; + inBase64 = false; + base64Accum = ''; + } + } + } + + if (!inBase64) { + res += this.iconv.decode(buf.slice(lastI), "ascii"); // Write direct chars. + } else { + var b64str = base64Accum + buf.slice(lastI).toString(); + + var canBeDecoded = b64str.length - (b64str.length % 8); // Minimal chunk: 2 quads -> 2x3 bytes -> 3 chars. + base64Accum = b64str.slice(canBeDecoded); // The rest will be decoded in future. + b64str = b64str.slice(0, canBeDecoded); + + res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be"); + } + + this.inBase64 = inBase64; + this.base64Accum = base64Accum; + + return res; +} + +function utf7DecoderEnd() { + var res = ""; + if (this.inBase64 && this.base64Accum.length > 0) + res = this.iconv.decode(new Buffer(this.base64Accum, 'base64'), "utf16-be"); + + this.inBase64 = false; + this.base64Accum = ''; + return res; +} + + +// UTF-7-IMAP codec. +// RFC3501 Sec. 5.1.3 Modified UTF-7 (http://tools.ietf.org/html/rfc3501#section-5.1.3) +// Differences: +// * Base64 part is started by "&" instead of "+" +// * Direct characters are 0x20-0x7E, except "&" (0x26) +// * In Base64, "," is used instead of "/" +// * Base64 must not be used to represent direct characters. +// * No implicit shift back from Base64 (should always end with '-') +// * String must end in non-shifted position. +// * "-&" while in base64 is not allowed. + + +exports.utf7imap = function(options) { + return { + encoder: function utf7ImapEncoder() { + return { + write: utf7ImapEncoderWrite, + end: utf7ImapEncoderEnd, + + iconv: options.iconv, + inBase64: false, + base64Accum: new Buffer(6), + base64AccumIdx: 0, + }; + }, + decoder: function utf7ImapDecoder() { + return { + write: utf7ImapDecoderWrite, + end: utf7ImapDecoderEnd, + + iconv: options.iconv, + inBase64: false, + base64Accum: '', + }; + }, + }; +}; + + +function utf7ImapEncoderWrite(str) { + var inBase64 = this.inBase64, + base64Accum = this.base64Accum, + base64AccumIdx = this.base64AccumIdx, + buf = new Buffer(str.length*5 + 10), bufIdx = 0; + + for (var i = 0; i < str.length; i++) { + var uChar = str.charCodeAt(i); + if (0x20 <= uChar && uChar <= 0x7E) { // Direct character or '&'. + if (inBase64) { + if (base64AccumIdx > 0) { + bufIdx += buf.write(base64Accum.slice(0, base64AccumIdx).toString('base64').replace(/\//g, ',').replace(/=+$/, ''), bufIdx); + base64AccumIdx = 0; + } + + buf[bufIdx++] = minusChar; // Write '-', then go to direct mode. + inBase64 = false; + } + + if (!inBase64) { + buf[bufIdx++] = uChar; // Write direct character + + if (uChar === andChar) // Ampersand -> '&-' + buf[bufIdx++] = minusChar; + } + + } else { // Non-direct character + if (!inBase64) { + buf[bufIdx++] = andChar; // Write '&', then go to base64 mode. + inBase64 = true; + } + if (inBase64) { + base64Accum[base64AccumIdx++] = uChar >> 8; + base64Accum[base64AccumIdx++] = uChar & 0xFF; + + if (base64AccumIdx == base64Accum.length) { + bufIdx += buf.write(base64Accum.toString('base64').replace(/\//g, ','), bufIdx); + base64AccumIdx = 0; + } + } + } + } + + this.inBase64 = inBase64; + this.base64AccumIdx = base64AccumIdx; + + return buf.slice(0, bufIdx); +} + +function utf7ImapEncoderEnd() { + var buf = new Buffer(10), bufIdx = 0; + if (this.inBase64) { + if (this.base64AccumIdx > 0) { + bufIdx += buf.write(this.base64Accum.slice(0, this.base64AccumIdx).toString('base64').replace(/\//g, ',').replace(/=+$/, ''), bufIdx); + this.base64AccumIdx = 0; + } + + buf[bufIdx++] = minusChar; // Write '-', then go to direct mode. + this.inBase64 = false; + } + + return buf.slice(0, bufIdx); +} + + +var base64IMAPChars = base64Chars.slice(); +base64IMAPChars[','.charCodeAt(0)] = true; + +function utf7ImapDecoderWrite(buf) { + var res = "", lastI = 0, + inBase64 = this.inBase64, + base64Accum = this.base64Accum; + + // The decoder is more involved as we must handle chunks in stream. + // It is forgiving, closer to standard UTF-7 (for example, '-' is optional at the end). + + for (var i = 0; i < buf.length; i++) { + if (!inBase64) { // We're in direct mode. + // Write direct chars until '&' + if (buf[i] == andChar) { + res += this.iconv.decode(buf.slice(lastI, i), "ascii"); // Write direct chars. + lastI = i+1; + inBase64 = true; + } + } else { // We decode base64. + if (!base64IMAPChars[buf[i]]) { // Base64 ended. + if (i == lastI && buf[i] == minusChar) { // "&-" -> "&" + res += "&"; + } else { + var b64str = base64Accum + buf.slice(lastI, i).toString().replace(/,/g, '/'); + res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be"); + } + + if (buf[i] != minusChar) // Minus may be absorbed after base64. + i--; + + lastI = i+1; + inBase64 = false; + base64Accum = ''; + } + } + } + + if (!inBase64) { + res += this.iconv.decode(buf.slice(lastI), "ascii"); // Write direct chars. + } else { + var b64str = base64Accum + buf.slice(lastI).toString().replace(/,/g, '/'); + + var canBeDecoded = b64str.length - (b64str.length % 8); // Minimal chunk: 2 quads -> 2x3 bytes -> 3 chars. + base64Accum = b64str.slice(canBeDecoded); // The rest will be decoded in future. + b64str = b64str.slice(0, canBeDecoded); + + res += this.iconv.decode(new Buffer(b64str, 'base64'), "utf16-be"); + } + + this.inBase64 = inBase64; + this.base64Accum = base64Accum; + + return res; +} + +function utf7ImapDecoderEnd() { + var res = ""; + if (this.inBase64 && this.base64Accum.length > 0) + res = this.iconv.decode(new Buffer(this.base64Accum, 'base64'), "utf16-be"); + + this.inBase64 = false; + this.base64Accum = ''; + return res; +} + + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/extend-node.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/extend-node.js new file mode 100644 index 0000000..000cee2 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/extend-node.js @@ -0,0 +1,210 @@ + +// == Extend Node primitives to use iconv-lite ================================= + +module.exports = function (iconv) { + var original = undefined; // Place to keep original methods. + + iconv.extendNodeEncodings = function extendNodeEncodings() { + if (original) return; + original = {}; + + var nodeNativeEncodings = { + 'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true, + 'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true, + }; + + Buffer.isNativeEncoding = function(enc) { + return nodeNativeEncodings[enc && enc.toLowerCase()]; + } + + // -- SlowBuffer ----------------------------------------------------------- + var SlowBuffer = require('buffer').SlowBuffer; + + original.SlowBufferToString = SlowBuffer.prototype.toString; + SlowBuffer.prototype.toString = function(encoding, start, end) { + encoding = String(encoding || 'utf8').toLowerCase(); + start = +start || 0; + if (typeof end !== 'number') end = this.length; + + // Fastpath empty strings + if (+end == start) + return ''; + + // Use native conversion when possible + if (Buffer.isNativeEncoding(encoding)) + return original.SlowBufferToString.call(this, encoding, start, end); + + // Otherwise, use our decoding method. + if (typeof start == 'undefined') start = 0; + if (typeof end == 'undefined') end = this.length; + return iconv.decode(this.slice(start, end), encoding); + } + + original.SlowBufferWrite = SlowBuffer.prototype.write; + SlowBuffer.prototype.write = function(string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length; + length = undefined; + } + } else { // legacy + var swap = encoding; + encoding = offset; + offset = length; + length = swap; + } + + offset = +offset || 0; + var remaining = this.length - offset; + if (!length) { + length = remaining; + } else { + length = +length; + if (length > remaining) { + length = remaining; + } + } + encoding = String(encoding || 'utf8').toLowerCase(); + + // Use native conversion when possible + if (Buffer.isNativeEncoding(encoding)) + return original.SlowBufferWrite.call(this, string, offset, length, encoding); + + if (string.length > 0 && (length < 0 || offset < 0)) + throw new RangeError('attempt to write beyond buffer bounds'); + + // Otherwise, use our encoding method. + var buf = iconv.encode(string, encoding); + if (buf.length < length) length = buf.length; + buf.copy(this, offset, 0, length); + return length; + } + + // -- Buffer --------------------------------------------------------------- + + original.BufferIsEncoding = Buffer.isEncoding; + Buffer.isEncoding = function(encoding) { + return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding); + } + + original.BufferByteLength = Buffer.byteLength; + Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) { + encoding = String(encoding || 'utf8').toLowerCase(); + + // Use native conversion when possible + if (Buffer.isNativeEncoding(encoding)) + return original.BufferByteLength.call(this, str, encoding); + + // Slow, I know, but we don't have a better way yet. + return iconv.encode(str, encoding).length; + } + + original.BufferToString = Buffer.prototype.toString; + Buffer.prototype.toString = function(encoding, start, end) { + encoding = String(encoding || 'utf8').toLowerCase(); + + // Use native conversion when possible + if (Buffer.isNativeEncoding(encoding)) + return original.BufferToString.call(this, encoding, start, end); + + // Otherwise, use our decoding method. + if (typeof start == 'undefined') start = 0; + if (typeof end == 'undefined') end = this.length; + return iconv.decode(this.slice(start, end), encoding); + } + + original.BufferWrite = Buffer.prototype.write; + Buffer.prototype.write = function(string, offset, length, encoding) { + var _offset = offset, _length = length, _encoding = encoding; + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length; + length = undefined; + } + } else { // legacy + var swap = encoding; + encoding = offset; + offset = length; + length = swap; + } + + encoding = String(encoding || 'utf8').toLowerCase(); + + // Use native conversion when possible + if (Buffer.isNativeEncoding(encoding)) + return original.BufferWrite.call(this, string, _offset, _length, _encoding); + + offset = +offset || 0; + var remaining = this.length - offset; + if (!length) { + length = remaining; + } else { + length = +length; + if (length > remaining) { + length = remaining; + } + } + + if (string.length > 0 && (length < 0 || offset < 0)) + throw new RangeError('attempt to write beyond buffer bounds'); + + // Otherwise, use our encoding method. + var buf = iconv.encode(string, encoding); + if (buf.length < length) length = buf.length; + buf.copy(this, offset, 0, length); + return length; + + // TODO: Set _charsWritten. + } + + + // -- Readable ------------------------------------------------------------- + if (iconv.supportsStreams) { + var Readable = require('stream').Readable; + + original.ReadableSetEncoding = Readable.prototype.setEncoding; + Readable.prototype.setEncoding = function setEncoding(enc, options) { + // Try to use original function when possible. + if (Buffer.isNativeEncoding(enc)) + return original.ReadableSetEncoding.call(this, enc); + + // Try to use our own decoder, it has the same interface. + this._readableState.decoder = iconv.getCodec(enc).decoder(options); + this._readableState.encoding = enc; + } + + Readable.prototype.collect = iconv._collect; + } + } + + // Remove iconv-lite Node primitive extensions. + iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() { + if (!original) + throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.") + + delete Buffer.isNativeEncoding; + + var SlowBuffer = require('buffer').SlowBuffer; + + SlowBuffer.prototype.toString = original.SlowBufferToString; + SlowBuffer.prototype.write = original.SlowBufferWrite; + + Buffer.isEncoding = original.BufferIsEncoding; + Buffer.byteLength = original.BufferByteLength; + Buffer.prototype.toString = original.BufferToString; + Buffer.prototype.write = original.BufferWrite; + + if (iconv.supportsStreams) { + var Readable = require('stream').Readable; + + Readable.prototype.setEncoding = original.ReadableSetEncoding; + delete Readable.prototype.collect; + } + + original = undefined; + } +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/index.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/index.js new file mode 100644 index 0000000..0775589 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/index.js @@ -0,0 +1,122 @@ + +var iconv = module.exports; + +// All codecs and aliases are kept here, keyed by encoding name/alias. +// They are lazy loaded in `iconv.getCodec` from `encodings/index.js`. +iconv.encodings = null; + +// Characters emitted in case of error. +iconv.defaultCharUnicode = '�'; +iconv.defaultCharSingleByte = '?'; + +// Public API. +iconv.encode = function encode(str, encoding, options) { + str = "" + (str || ""); // Ensure string. + + var encoder = iconv.getCodec(encoding).encoder(options); + + var res = encoder.write(str); + var trail = encoder.end(); + + return (trail && trail.length > 0) ? Buffer.concat([res, trail]) : res; +} + +iconv.decode = function decode(buf, encoding, options) { + if (typeof buf === 'string') { + if (!iconv.skipDecodeWarning) { + console.error('Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding'); + iconv.skipDecodeWarning = true; + } + + buf = new Buffer("" + (buf || ""), "binary"); // Ensure buffer. + } + + var decoder = iconv.getCodec(encoding).decoder(options); + + var res = decoder.write(buf); + var trail = decoder.end(); + + return (trail && trail.length > 0) ? (res + trail) : res; +} + +iconv.encodingExists = function encodingExists(enc) { + try { + iconv.getCodec(enc); + return true; + } catch (e) { + return false; + } +} + +// Legacy aliases to convert functions +iconv.toEncoding = iconv.encode; +iconv.fromEncoding = iconv.decode; + +// Search for a codec in iconv.encodings. Cache codec data in iconv._codecDataCache. +iconv._codecDataCache = {}; +iconv.getCodec = function getCodec(encoding) { + if (!iconv.encodings) + iconv.encodings = require("../encodings"); // Lazy load all encoding definitions. + + // Canonicalize encoding name: strip all non-alphanumeric chars and appended year. + var enc = (''+encoding).toLowerCase().replace(/[^0-9a-z]|:\d{4}$/g, ""); + + // Traverse iconv.encodings to find actual codec. + var codecData, codecOptions; + while (true) { + codecData = iconv._codecDataCache[enc]; + if (codecData) + return codecData; + + var codec = iconv.encodings[enc]; + + switch (typeof codec) { + case "string": // Direct alias to other encoding. + enc = codec; + break; + + case "object": // Alias with options. Can be layered. + if (!codecOptions) { + codecOptions = codec; + codecOptions.encodingName = enc; + } + else { + for (var key in codec) + codecOptions[key] = codec[key]; + } + + enc = codec.type; + break; + + case "function": // Codec itself. + if (!codecOptions) + codecOptions = { encodingName: enc }; + codecOptions.iconv = iconv; + + // The codec function must load all tables and return object with .encoder and .decoder methods. + // It'll be called only once (for each different options object). + codecData = codec.call(iconv.encodings, codecOptions); + + iconv._codecDataCache[codecOptions.encodingName] = codecData; // Save it to be reused later. + return codecData; + + default: + throw new Error("Encoding not recognized: '" + encoding + "' (searched as: '"+enc+"')"); + } + } +} + +// Load extensions in Node. All of them are omitted in Browserify build via 'browser' field in package.json. +var nodeVer = typeof process !== 'undefined' && process.versions && process.versions.node; +if (nodeVer) { + + // Load streaming support in Node v0.10+ + var nodeVerArr = nodeVer.split(".").map(Number); + if (nodeVerArr[0] > 0 || nodeVerArr[1] >= 10) { + require("./streams")(iconv); + } + + // Load Node primitive extensions. + require("./extend-node")(iconv); +} + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/streams.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/streams.js new file mode 100644 index 0000000..0563731 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/lib/streams.js @@ -0,0 +1,118 @@ +var Transform = require("stream").Transform; + + +// == Exports ================================================================== +module.exports = function(iconv) { + + // Additional Public API. + iconv.encodeStream = function encodeStream(encoding, options) { + return new IconvLiteEncoderStream(iconv.getCodec(encoding).encoder(options), options); + } + + iconv.decodeStream = function decodeStream(encoding, options) { + return new IconvLiteDecoderStream(iconv.getCodec(encoding).decoder(options), options); + } + + iconv.supportsStreams = true; + + + // Not published yet. + iconv.IconvLiteEncoderStream = IconvLiteEncoderStream; + iconv.IconvLiteDecoderStream = IconvLiteDecoderStream; + iconv._collect = IconvLiteDecoderStream.prototype.collect; +}; + + +// == Encoder stream ======================================================= +function IconvLiteEncoderStream(conv, options) { + this.conv = conv; + options = options || {}; + options.decodeStrings = false; // We accept only strings, so we don't need to decode them. + Transform.call(this, options); +} + +IconvLiteEncoderStream.prototype = Object.create(Transform.prototype, { + constructor: { value: IconvLiteEncoderStream } +}); + +IconvLiteEncoderStream.prototype._transform = function(chunk, encoding, done) { + if (typeof chunk != 'string') + return done(new Error("Iconv encoding stream needs strings as its input.")); + try { + var res = this.conv.write(chunk); + if (res && res.length) this.push(res); + done(); + } + catch (e) { + done(e); + } +} + +IconvLiteEncoderStream.prototype._flush = function(done) { + try { + var res = this.conv.end(); + if (res && res.length) this.push(res); + done(); + } + catch (e) { + done(e); + } +} + +IconvLiteEncoderStream.prototype.collect = function(cb) { + var chunks = []; + this.on('error', cb); + this.on('data', function(chunk) { chunks.push(chunk); }); + this.on('end', function() { + cb(null, Buffer.concat(chunks)); + }); + return this; +} + + +// == Decoder stream ======================================================= +function IconvLiteDecoderStream(conv, options) { + this.conv = conv; + options = options || {}; + options.encoding = this.encoding = 'utf8'; // We output strings. + Transform.call(this, options); +} + +IconvLiteDecoderStream.prototype = Object.create(Transform.prototype, { + constructor: { value: IconvLiteDecoderStream } +}); + +IconvLiteDecoderStream.prototype._transform = function(chunk, encoding, done) { + if (!Buffer.isBuffer(chunk)) + return done(new Error("Iconv decoding stream needs buffers as its input.")); + try { + var res = this.conv.write(chunk); + if (res && res.length) this.push(res, this.encoding); + done(); + } + catch (e) { + done(e); + } +} + +IconvLiteDecoderStream.prototype._flush = function(done) { + try { + var res = this.conv.end(); + if (res && res.length) this.push(res, this.encoding); + done(); + } + catch (e) { + done(e); + } +} + +IconvLiteDecoderStream.prototype.collect = function(cb) { + var res = ''; + this.on('error', cb); + this.on('data', function(chunk) { res += chunk; }); + this.on('end', function() { + cb(null, res); + }); + return this; +} + diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/package.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/package.json new file mode 100644 index 0000000..3a89d53 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/package.json @@ -0,0 +1,95 @@ +{ + "name": "iconv-lite", + "description": "Convert character encodings in pure javascript.", + "version": "0.4.4", + "license": "MIT", + "keywords": [ + "iconv", + "convert", + "charset", + "icu" + ], + "author": { + "name": "Alexander Shtuchkin", + "email": "ashtuchkin@gmail.com" + }, + "contributors": [ + { + "name": "Jinwu Zhan", + "url": "https://github.com/jenkinv" + }, + { + "name": "Adamansky Anton", + "url": "https://github.com/adamansky" + }, + { + "name": "George Stagas", + "url": "https://github.com/stagas" + }, + { + "name": "Mike D Pilsbury", + "url": "https://github.com/pekim" + }, + { + "name": "Niggler", + "url": "https://github.com/Niggler" + }, + { + "name": "wychi", + "url": "https://github.com/wychi" + }, + { + "name": "David Kuo", + "url": "https://github.com/david50407" + }, + { + "name": "ChangZhuo Chen", + "url": "https://github.com/czchen" + }, + { + "name": "Lee Treveil", + "url": "https://github.com/leetreveil" + }, + { + "name": "Brian White", + "url": "https://github.com/mscdex" + }, + { + "name": "Mithgol", + "url": "https://github.com/Mithgol" + } + ], + "main": "./lib/index.js", + "homepage": "https://github.com/ashtuchkin/iconv-lite", + "bugs": "https://github.com/ashtuchkin/iconv-lite/issues", + "repository": { + "type": "git", + "url": "git://github.com/ashtuchkin/iconv-lite.git" + }, + "engines": { + "node": ">=0.8.0" + }, + "scripts": { + "test": "mocha --reporter spec --grep ." + }, + "browser": { + "./extend-node": false, + "./streams": false + }, + "devDependencies": { + "mocha": "*", + "request": "*", + "unorm": "*", + "errto": "*", + "async": "*", + "iconv": "~2.1.4" + }, + "readme": "## Pure JS character encoding conversion\n\n\n\n * Doesn't need native code compilation. Works on Windows and in sandboxed environments like [Cloud9](http://c9.io).\n * Used in popular projects like [Grunt](http://gruntjs.com/), [Nodemailer](http://www.nodemailer.com/), [Yeoman](http://yeoman.io/) and others.\n * Faster than [node-iconv](https://github.com/bnoordhuis/node-iconv) (see below for performance comparison).\n * Intuitive encode/decode API\n * Streaming support for Node v0.10+\n * Can extend Node.js primitives (buffers, streams) to support all iconv-lite encodings.\n * In-browser usage via [Browserify](https://github.com/substack/node-browserify) (~180k gzip compressed with Buffer shim included).\n * License: MIT.\n\n[![NPM Stats](https://nodei.co/npm/iconv-lite.png?downloads=true)](https://npmjs.org/packages/iconv-lite/)\n\n## Usage\n### Basic API\n```javascript\nvar iconv = require('iconv-lite');\n\n// Convert from an encoded buffer to js string.\nstr = iconv.decode(new Buffer([0x68, 0x65, 0x6c, 0x6c, 0x6f]), 'win1251');\n\n// Convert from js string to an encoded buffer.\nbuf = iconv.encode(\"Sample input string\", 'win1251');\n\n// Check if encoding is supported\niconv.encodingExists(\"us-ascii\")\n```\n\n### Streaming API (Node v0.10+)\n```javascript\n\n// Decode stream (from binary stream to js strings)\nhttp.createServer(function(req, res) {\n var converterStream = iconv.decodeStream('win1251');\n req.pipe(converterStream);\n\n converterStream.on('data', function(str) {\n console.log(str); // Do something with decoded strings, chunk-by-chunk.\n });\n});\n\n// Convert encoding streaming example\nfs.createReadStream('file-in-win1251.txt')\n .pipe(iconv.decodeStream('win1251'))\n .pipe(iconv.encodeStream('ucs2'))\n .pipe(fs.createWriteStream('file-in-ucs2.txt'));\n\n// Sugar: all encode/decode streams have .collect(cb) method to accumulate data.\nhttp.createServer(function(req, res) {\n req.pipe(iconv.decodeStream('win1251')).collect(function(err, body) {\n assert(typeof body == 'string');\n console.log(body); // full request body string\n });\n});\n```\n\n### Extend Node.js own encodings\n```javascript\n// After this call all Node basic primitives will understand iconv-lite encodings.\niconv.extendNodeEncodings();\n\n// Examples:\nbuf = new Buffer(str, 'win1251');\nbuf.write(str, 'gbk');\nstr = buf.toString('latin1');\nassert(Buffer.isEncoding('iso-8859-15'));\nBuffer.byteLength(str, 'us-ascii');\n\nhttp.createServer(function(req, res) {\n req.setEncoding('big5');\n req.collect(function(err, body) {\n console.log(body);\n });\n});\n\nfs.createReadStream(\"file.txt\", \"shift_jis\");\n\n// External modules are also supported (if they use Node primitives, which they probably do).\nrequest = require('request');\nrequest({\n url: \"http://github.com/\", \n encoding: \"cp932\"\n});\n\n// To remove extensions\niconv.undoExtendNodeEncodings();\n```\n\n## Supported encodings\n\n * All node.js native encodings: utf8, ucs2 / utf16-le, ascii, binary, base64, hex.\n * Additional unicode encodings: utf16, utf16-be, utf-7, utf-7-imap.\n * All widespread singlebyte encodings: Windows 125x family, ISO-8859 family, \n IBM/DOS codepages, Macintosh family, KOI8 family, all others supported by iconv library. \n Aliases like 'latin1', 'us-ascii' also supported.\n * All widespread multibyte encodings: CP932, CP936, CP949, CP950, GB2313, GBK, GB18030, Big5, Shift_JIS, EUC-JP.\n\nSee [all supported encodings on wiki](https://github.com/ashtuchkin/iconv-lite/wiki/Supported-Encodings).\n\nMost singlebyte encodings are generated automatically from [node-iconv](https://github.com/bnoordhuis/node-iconv). Thank you Ben Noordhuis and libiconv authors!\n\nMultibyte encodings are generated from [Unicode.org mappings](http://www.unicode.org/Public/MAPPINGS/) and [WHATWG Encoding Standard mappings](http://encoding.spec.whatwg.org/). Thank you, respective authors!\n\n\n## Encoding/decoding speed\n\nComparison with node-iconv module (1000x256kb, on MacBook Pro, Core i5/2.6 GHz, Node v0.10.26). \nNote: your results may vary, so please always check on your hardware.\n\n operation iconv@2.1.4 iconv-lite@0.4.0\n ----------------------------------------------------------\n encode('win1251') ~130 Mb/s ~380 Mb/s\n decode('win1251') ~127 Mb/s ~210 Mb/s\n\n\n## Notes\n\nWhen decoding, be sure to supply a Buffer to decode() method, otherwise [bad things usually happen](https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding). \nUntranslatable characters are set to � or ?. No transliteration is currently supported.\n\n## Testing\n\n```bash\n$ git clone git@github.com:ashtuchkin/iconv-lite.git\n$ cd iconv-lite\n$ npm install\n$ npm test\n \n$ # To view performance:\n$ node test/performance.js\n```\n\n## Adoption\n[![NPM](https://nodei.co/npm-dl/iconv-lite.png)](https://nodei.co/npm/iconv-lite/)\n\n", + "readmeFilename": "README.md", + "_id": "iconv-lite@0.4.4", + "dist": { + "shasum": "bbdfcbd1214400050e24f5ebbc26345c702186ac" + }, + "_from": "iconv-lite@~0.4.3", + "_resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz" +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/package.json b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/package.json new file mode 100644 index 0000000..2a0aaeb --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/package.json @@ -0,0 +1,31 @@ +{ + "name": "encoding", + "version": "0.1.8", + "description": "Convert encodings, uses iconv by default and fallbacks to iconv-lite if needed", + "main": "lib/encoding.js", + "scripts": { + "test": "nodeunit test" + }, + "repository": { + "type": "git", + "url": "https://github.com/andris9/encoding.git" + }, + "author": { + "name": "Andris Reinman" + }, + "license": "MIT", + "dependencies": { + "iconv-lite": "~0.4.3" + }, + "devDependencies": { + "nodeunit": "~0.8.1" + }, + "readme": "# Encoding\n\n**encoding** is a simple wrapper around [node-iconv](https://github.com/bnoordhuis/node-iconv) and [iconv-lite](https://github.com/ashtuchkin/iconv-lite/) to convert strings from one encoding to another. If node-iconv is not available for some reason,\niconv-lite will be used instead of it as a fallback.\n\n## Install\n\nInstall through npm\n\n npm install encoding\n\n## Usage\n\nRequire the module\n\n var encoding = require(\"encoding\");\n\nConvert with encoding.convert()\n\n var resultBuffer = encoding.convert(text, toCharset, fromCharset);\n\nWhere\n\n * **text** is either a Buffer or a String to be converted\n * **toCharset** is the characterset to convert the string\n * **fromCharset** (*optional*, defaults to UTF-8) is the source charset\n\nOutput of the conversion is always a Buffer object.\n\nExample\n\n var result = encoding.convert(\"ÕÄÖÜ\", \"Latin_1\");\n console.log(result); //\n\n## iconv support\n\nBy default only iconv-lite is bundled. If you need node-iconv support, you need to add it\nas an additional dependency for your project:\n\n ...,\n \"dependencies\":{\n \"encoding\": \"*\",\n \"iconv\": \"*\"\n },\n ...\n\n## License\n\n**MIT**", + "readmeFilename": "README.md", + "_id": "encoding@0.1.8", + "dist": { + "shasum": "dfe6b04ae615f11cf653132d7f9674327a2ebf3c" + }, + "_from": "encoding@~0.1", + "_resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.8.tgz" +} diff --git a/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/test/test.js b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/test/test.js new file mode 100644 index 0000000..0445e27 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/node_modules/encoding/test/test.js @@ -0,0 +1,48 @@ +'use strict'; + +var encoding = require('../lib/encoding'); + +exports['General tests'] = { + + 'From UTF-8 to Latin_1': function(test) { + var input = 'ÕÄÖÜ', + expected = new Buffer([0xd5, 0xc4, 0xd6, 0xdc]); + test.deepEqual(encoding.convert(input, 'latin1'), expected); + test.done(); + }, + + 'From Latin_1 to UTF-8': function(test) { + var input = new Buffer([0xd5, 0xc4, 0xd6, 0xdc]), + expected = 'ÕÄÖÜ'; + test.deepEqual(encoding.convert(input, 'utf-8', 'latin1').toString(), expected); + test.done(); + }, + + 'From UTF-8 to UTF-8': function(test) { + var input = 'ÕÄÖÜ', + expected = new Buffer('ÕÄÖÜ'); + test.deepEqual(encoding.convert(input, 'utf-8', 'utf-8'), expected); + test.done(); + }, + + 'From Latin_13 to Latin_15': function(test) { + var input = new Buffer([0xd5, 0xc4, 0xd6, 0xdc, 0xd0]), + expected = new Buffer([0xd5, 0xc4, 0xd6, 0xdc, 0xA6]); + test.deepEqual(encoding.convert(input, 'latin_15', 'latin13'), expected); + test.done(); + }, + + 'From Latin_13 to Latin_15 lite': function(test) { + var input = new Buffer([0xd5, 0xc4, 0xd6, 0xdc, 0xd0]), + expected = new Buffer([0xd5, 0xc4, 0xd6, 0xdc, 0xA6]); + test.deepEqual(encoding.convert(input, 'latin_15', 'latin13', true), expected); + test.done(); + }, + + 'From ISO-2022-JP to UTF-8': function(test) { + var input = new Buffer('GyRCM1g5OzU7PVEwdzgmPSQ4IUYkMnFKczlwGyhC', 'base64'), + expected = new Buffer('5a2m5qCh5oqA6KGT5ZOh56CU5L+u5qSc6KiO5Lya5aCx5ZGK', 'base64'); + test.deepEqual(encoding.convert(input, 'utf-8', 'ISO-2022-JP'), expected); + test.done(); + } +}; \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/mimelib/package.json b/node_modules/emailjs/node_modules/mimelib/package.json new file mode 100644 index 0000000..3fb95f4 --- /dev/null +++ b/node_modules/emailjs/node_modules/mimelib/package.json @@ -0,0 +1,55 @@ +{ + "name": "mimelib", + "description": "MIME functions to encode/decode e-mails etc.", + "version": "0.2.14", + "author": { + "name": "Andris Reinman" + }, + "homepage": "http://github.com/andris9/mimelib", + "maintainers": [ + { + "name": "andris", + "email": "andris@node.ee" + } + ], + "contributors": [ + { + "name": "Swift", + "email": "theycallmeswift@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/andris9/mimelib.git" + }, + "scripts": { + "test": "nodeunit test/" + }, + "main": "index.js", + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/andris9/mimelib/blob/master/LICENSE" + } + ], + "dependencies": { + "encoding": "~0.1", + "addressparser": "~0.2.0" + }, + "devDependencies": { + "nodeunit": "*" + }, + "keywords": [ + "e-mail", + "mime", + "email" + ], + "readme": "# mimelib\n\n*mimelib* is a collection of useful functions to deal with mime-encoded data.\n\n## Installation\n\nInstall with *npm*\n\n npm install mimelib\n \n## Usage\n\n var mimelib = require(\"mimelib\");\n\n## Reference\n\n### foldLine\n\nFolds a long line according to the RFC 5322 \n\n mimelib.foldLine(str [, maxLength][, foldAnywhere][, afterSpace]) -> String\n \n - `str` (String): mime string that might need folding\n - `maxLength` (Number): max length for a line, defaults to 78\n - `foldAnywhere` (Boolean): can fold at any location (ie. in base64)\n - `afterSpace` (Boolean): If `true` fold after the space\n \n\nFor example:\n\n Content-Type: multipart/alternative; boundary=\"----zzzz----\"\n\nwill become\n\n Content-Type: multipart/alternative;\n boundary=\"----zzzz----\"\n\n### encodeMimeWord\n\nEncodes a string into mime encoded word format (see also `decodeMimeWord`)\n\n mimelib.encodeMimeWord = function(str [, encoding][, charset])\n\n - `str` (String): String to be encoded\n - `encoding` (String): Encoding Q for quoted printable or B (def.) for base64\n - `charset` (String): Charset to be used\n \nFor example:\n\n See on õhin test\n\nBecomes with UTF-8 and Quoted-printable encoding\n\n =?UTF-8?Q?See_on_=C3=B5hin_test?=\n \n### decodeMimeWord\n\nDecodes a string from mime encoded word format (see also `encodeMimeWord`)\n\n mimelib.decodeMimeWord(str) -> String\n \n - `str` (String): String to be decoded\n\nFor example\n\n mimelib.decodeMimeWord(\"=?UTF-8?Q?See_on_=C3=B5hin_test?=\");\n\nwill become\n\n See on õhin test\n\n### encodeQuotedPrintable\n\nEncodes a string into Quoted-printable format (see also `decodeQuotedPrintable`)\n\n mimelib.encodeQuotedPrintable(str [, mimeWord][, charset]) -> String\n \n - `str` (String): String to be encoded into Quoted-printable\n - `mimeWord` (Boolean): Deprecated, has no effect, ignore it\n - `charset` (String): Destination charset, defaults to UTF-8\n\n### decodeQuotedPrintable\n\nDecodes a string from Quoted-printable format (see also `encodeQuotedPrintable`)\n\n mimelib.decodeQuotedPrintable(str [, mimeWord][, charset]) -> String\n \n - `str` (String): String to be decoded\n - `mimeWord` (Boolean): Deprecated, has no effect, ignore it\n - `charset` (String): Charset to be used, defaults to UTF-8\n \n### encodeBase64\n\nEncodes a string into Base64 format. Base64 is mime-word safe (see also `decodeBase64`)\n\n mimelib.encodeBase64(str [, charset]) -> String\n \n - `str` (String): String to be encoded into Base64\n - `charset` (String): Destination charset, defaults to UTF-8\n\n### decodeBase64\n\nDecodes a string from Base64 format. Base64 is mime-word safe (see also `encodeBase64`)\n\nNB! Always returns UTF-8\n\n mimelib.decodeBase64(str) -> String\n\n - `str` (String): String to be decoded from Base64\n - `charset` (String): Source charset, defaults to UTF-8\n \n### parseHeaders\n\nParses header lines into an array of objects (see `parseHeaderLine`)\n\n mimelib.parseHeaders(headers) -> Array\n \n - `headers` (String): header section of the e-mail\n\nExample:\n\n var headers = [\n \"From: andris@node.ee\",\n \"To: juulius@node.ee\",\n \"To: juulius2@node.ee\",\n \"Content-type: text/html;\",\n \" charset=utf-8\"\n ].join(\"\\r\\n\");\n mimelib.parseHeaders(headers);\n\nResults in \n\n {\"from\": [ 'andris@node.ee' ],\n \"to\": [ 'juulius@node.ee', 'juulius2@node.ee' ],\n \"content-type\": [ 'text/html; charset=utf-8' ] }\n\n### parseAddresses\n\nParses names and addresses from a from, to, cc or bcc line\n\n mimelib.parseAddresses(addresses) -> Array\n \n - `addresses` (String): string with comma separated e-mail addresses \n \nExample:\n\n var to = '\"Andris Reinman\" , juulius@node.ee'\n mimelib.parseAddresses(to);\n \nResults in\n\n [{ address: 'andris@node.ee', name: 'Andris Reinman' },\n { address: 'juulius@node.ee', name: false }]\n\n### parseMimeWords\n\nParses mime-words into UTF-8 strings\n\n mimelib.parseMimeWords(str) -> String\n\n - `str` (String): string to be parsed, if includes any mime words, then these are converted to UTF-8 strings\n \n \nFor example:\n\n mimelib.parseMimeWords(\"Hello: =?UTF-8?Q?See_on_=C3=B5hin_test?=\");\n\nResults in\n\n \"Hello: See on õhin test\"\n \n### parseHeaderLine\n\nParses a header line to search for additional parameters.\n\n mimelib.parseHeaderLine(line) -> Object\n \n - `line` (String): a line from a message headers\n \nFor example:\n\n mimelib.parseHeaderLine(\"text/plain; charset=utf-8\")imelib\n\nResults in\n\n {\"defaultValue\": 'text/plain',\n \"charset\": 'utf-8' }\n\n### contentTypes\n\n**NB! this feature is deprecated**, use [mime](https://github.com/broofa/node-mime) module instead to detect content types and extensions\n\n`mimelib.contentTypes` is an object to provide content type strings for common\nfile extensions\n\n mimelib.contentTypes[\"xls\"]; // \"application/vnd.ms-excel\"\n\n## iconv support\n\nBy default only iconv-lite support is bundled. If you need node-iconv support, you need to add it\nas an additional dependency for your project:\n\n ...,\n \"dependencies\":{\n \"mimelib\": \"*\",\n \"iconv\": \"*\"\n },\n ...\n\n## License\n\nmimelib license is", + "readmeFilename": "README.md", + "_id": "mimelib@0.2.14", + "dist": { + "shasum": "8462ec56b40fa88f639e615030d1a411db2d2e41" + }, + "_from": "mimelib@0.2.14", + "_resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.14.tgz" +} diff --git a/node_modules/emailjs/node_modules/moment/.jshintrc b/node_modules/emailjs/node_modules/moment/.jshintrc new file mode 100644 index 0000000..27ae76d --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/.jshintrc @@ -0,0 +1,26 @@ +{ + "node" : true, + "es5" : true, + "browser" : true, + "boss" : false, + "curly": true, + "debug": false, + "devel": false, + "eqeqeq": true, + "eqnull": true, + "evil": false, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "onevar": true, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": true +} diff --git a/node_modules/emailjs/node_modules/moment/.npmignore b/node_modules/emailjs/node_modules/moment/.npmignore new file mode 100644 index 0000000..12ac647 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +.DS_Store \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/.travis.yml b/node_modules/emailjs/node_modules/moment/.travis.yml new file mode 100644 index 0000000..54dbb95 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.4 + - 0.6 + - 0.8 \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/LICENSE b/node_modules/emailjs/node_modules/moment/LICENSE new file mode 100644 index 0000000..8beeefc --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011-2012 Tim Wood + +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. \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/Makefile b/node_modules/emailjs/node_modules/moment/Makefile new file mode 100644 index 0000000..cc2681c --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/Makefile @@ -0,0 +1,71 @@ +LANG_ALL = $(wildcard lang/*.js) +MIN_LANG_ALL = $(addprefix min/,$(LANG_ALL)) + + +.PHONY: all +all: moment langs + +min/: + mkdir min/ + +min/lang/: + mkdir -p min/lang/ + +.PHONY: moment pretty +moment: min/ min/moment.min.js pretty + +pretty: min/ min/moment.min.pretty.js + +min/moment.min.js: moment.js + node_modules/.bin/uglifyjs -o $@ $< + +min/moment.min.pretty.js: moment.js + node_modules/.bin/uglifyjs -b -o $@ $< + +min/lang/%: lang/% + node_modules/.bin/uglifyjs -o $@ $< + +min/lang-all.min.js: $(LANG_ALL) + cat $^ | node_modules/.bin/uglifyjs -o $@ + +.PHONY: langs +langs: min/lang/ $(MIN_LANG_ALL) min/lang-all.min.js + +.PHONY: size +size: moment langs + # FILESIZE FOR ALL LANGS + cp min/lang-all.min.js min/lang-all.min.gzip.js + gzip min/lang-all.min.gzip.js + gzip -l min/lang-all.min.gzip.js.gz + rm min/lang-all.min.gzip.js.gz + # FILESIZE FOR LIBRARY + cp min/moment.min.js min/moment.min.gzip.js + gzip min/moment.min.gzip.js + gzip -l min/moment.min.gzip.js.gz + rm min/moment.min.gzip.js.gz + +.PHONY: size-history +size-history: moment + node test/filesize-history.js + +size-diff: moment + node test/filesize-diff.js + + +.PHONY: test hint test-moment test-lang +test: hint test-moment test-lang +test-zone: + node test/zone + +hint: + node_modules/.bin/jshint moment.js + +test-moment: + node_modules/.bin/nodeunit ./test/moment + +test-lang: + node_modules/.bin/nodeunit ./test/lang + +.PHONY: clean +clean: + rm -rf min/ diff --git a/node_modules/emailjs/node_modules/moment/ender.js b/node_modules/emailjs/node_modules/moment/ender.js new file mode 100644 index 0000000..71462a7 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/ender.js @@ -0,0 +1 @@ +$.ender({ moment: require('moment') }) diff --git a/node_modules/emailjs/node_modules/moment/lang/bg.js b/node_modules/emailjs/node_modules/moment/lang/bg.js new file mode 100644 index 0000000..dc13ac9 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/bg.js @@ -0,0 +1,66 @@ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz +(function () { + var lang = { + months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"), + monthsShort : "янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"), + weekdays : "неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"), + weekdaysShort : "нед_пон_вто_сря_чет_пет_съб".split("_"), + weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "h:mm", + L : "D.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : "след %s", + past : "преди %s", + s : "няколко секунди", + m : "минута", + mm : "%d минути", + h : "час", + hh : "%d часа", + d : "ден", + dd : "%d дни", + M : "месец", + MM : "%d месеца", + y : "година", + yy : "%d години" + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined') { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('bg', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/ca.js b/node_modules/emailjs/node_modules/moment/lang/ca.js new file mode 100644 index 0000000..5eae6e7 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/ca.js @@ -0,0 +1,64 @@ +// moment.js language configuration +// language : catalan (ca) +// author : Juan G. Hurtado : https://github.com/juanghurtado +(function () { + var lang = { + months : "Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"), + monthsShort : "Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"), + weekdays : "Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"), + weekdaysShort : "Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"), + weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "fa %s", + s : "uns segons", + m : "un minut", + mm : "%d minuts", + h : "una hora", + hh : "%d hores", + d : "un dia", + dd : "%d dies", + M : "un mes", + MM : "%d mesos", + y : "un any", + yy : "%d anys" + }, + ordinal : function (number) { + return 'º'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('ca', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/cv.js b/node_modules/emailjs/node_modules/moment/lang/cv.js new file mode 100644 index 0000000..a0598f4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/cv.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : chuvash (cv) +// author : Anatoly Mironov : https://github.com/mirontoli +(function () { + var lang = { + months : "кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"), + monthsShort : "кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"), + weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"), + weekdaysShort : "выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"), + weekdaysMin : "вр_тн_ыт_юн_кç_эр_шм".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "YYYY çулхи MMMM уйăхĕн D-мĕшĕ", + LLL : "YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT", + LLLL : "dddd, YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT" + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ĕнер] LT [сехетре]', + nextWeek: '[Çитес] dddd LT [сехетре]', + lastWeek: '[Иртнĕ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : "%sран", + past : "%s каялла", + s : "пĕр-ик çеккунт", + m : "пĕр минут", + mm : "%d минут", + h : "пĕр сехет", + hh : "%d сехет", + d : "пĕр кун", + dd : "%d кун", + M : "пĕр уйăх", + MM : "%d уйăх", + y : "пĕр çул", + yy : "%d çул" + }, + ordinal : function (number) { + return '-мĕш'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('cv', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/da.js b/node_modules/emailjs/node_modules/moment/lang/da.js new file mode 100644 index 0000000..0c3c36c --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/da.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : danish (da) +// author : Ulrik Nielsen : https://github.com/mrbase +(function () { + var lang = { + months : "Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"), + weekdays : "Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"), + weekdaysShort : "Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"), + weekdaysMin : "Sø_Ma_Ti_On_To_Fr_Lø".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY h:mm A", + LLLL : "dddd D. MMMM, YYYY h:mm A" + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : "om %s", + past : "%s siden", + s : "få sekunder", + m : "minut", + mm : "%d minutter", + h : "time", + hh : "%d timer", + d : "dag", + dd : "%d dage", + M : "månede", + MM : "%d måneder", + y : "år", + yy : "%d år" + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('da', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/de.js b/node_modules/emailjs/node_modules/moment/lang/de.js new file mode 100644 index 0000000..bbe4e13 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/de.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : german (de) +// author : lluchs : https://github.com/lluchs +(function () { + var lang = { + months : "Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"), + monthsShort : "Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"), + weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"), + weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"), + weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"), + longDateFormat : { + LT: "H:mm U\\hr", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[Heute um] LT", + sameElse: "L", + nextDay: '[Morgen um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gestern um] LT', + lastWeek: '[letzten] dddd [um] LT' + }, + relativeTime : { + future : "in %s", + past : "vor %s", + s : "ein paar Sekunden", + m : "einer Minute", + mm : "%d Minuten", + h : "einer Stunde", + hh : "%d Stunden", + d : "einem Tag", + dd : "%d Tagen", + M : "einem Monat", + MM : "%d Monaten", + y : "einem Jahr", + yy : "%d Jahren" + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('de', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/en-ca.js b/node_modules/emailjs/node_modules/moment/lang/en-ca.js new file mode 100644 index 0000000..efa6d03 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/en-ca.js @@ -0,0 +1,58 @@ +// moment.js language configuration +// language : canadian english (en-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +(function () { + var lang = { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "YYYY-MM-DD", + LL : "D MMMM, YYYY", + LLL : "D MMMM, YYYY LT", + LLLL : "dddd, D MMMM, YYYY LT" + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10; + return (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('en-gb', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/en-gb.js b/node_modules/emailjs/node_modules/moment/lang/en-gb.js new file mode 100644 index 0000000..a01a7d0 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/en-gb.js @@ -0,0 +1,58 @@ +// moment.js language configuration +// language : great britain english (en-gb) +// author : Chris Gedrim : https://github.com/chrisgedrim +(function () { + var lang = { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10; + return (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('en-gb', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/es.js b/node_modules/emailjs/node_modules/moment/lang/es.js new file mode 100644 index 0000000..f093d1a --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/es.js @@ -0,0 +1,64 @@ +// moment.js language configuration +// language : spanish (es) +// author : Julio Napurí : https://github.com/julionc +(function () { + var lang = { + months : "Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre".split("_"), + monthsShort : "Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.".split("_"), + weekdays : "Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado".split("_"), + weekdaysShort : "Dom._Lun._Mar._Mié._Jue._Vie._Sáb.".split("_"), + weekdaysMin : "Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "hace %s", + s : "unos segundos", + m : "un minuto", + mm : "%d minutos", + h : "una hora", + hh : "%d horas", + d : "un día", + dd : "%d días", + M : "un mes", + MM : "%d meses", + y : "un año", + yy : "%d años" + }, + ordinal : function (number) { + return 'º'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('es', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/eu.js b/node_modules/emailjs/node_modules/moment/lang/eu.js new file mode 100644 index 0000000..79e224e --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/eu.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : euskara (eu) +// author : Eneko Illarramendi : https://github.com/eillarra +(function () { + var lang = { + months : "urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"), + monthsShort : "urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"), + weekdays : "igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"), + weekdaysShort : "ig._al._ar._az._og._ol._lr.".split("_"), + weekdaysMin : "ig_al_ar_az_og_ol_lr".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "YYYYko MMMMren D[a]", + LLL : "YYYYko MMMMren D[a] LT", + LLLL : "dddd, YYYYko MMMMren D[a] LT" + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : "%s barru", + past : "duela %s", + s : "segundo batzuk", + m : "minutu bat", + mm : "%d minutu", + h : "ordu bat", + hh : "%d ordu", + d : "egun bat", + dd : "%d egun", + M : "hilabete bat", + MM : "%d hilabete", + y : "urte bat", + yy : "%d urte" + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('eu', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/fi.js b/node_modules/emailjs/node_modules/moment/lang/fi.js new file mode 100644 index 0000000..826259b --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/fi.js @@ -0,0 +1,98 @@ +// moment.js language configuration +// language : finnish (fi) +// author : Tarmo Aidantausta : https://github.com/bleadof +(function () { + var numbers_past = ['nolla', 'yksi', 'kaksi', 'kolme', 'neljä', 'viisi', + 'kuusi', 'seitsemän', 'kahdeksan', 'yhdeksän']; + var numbers_future = ['nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', + 'kuuden', numbers_past[7], numbers_past[8], numbers_past[9]]; + + function translate(number, withoutSuffix, key, isFuture) { + var result = ""; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbal_number(number, isFuture) + " " + result; + return result; + } + + function verbal_number(number, isFuture) { + return number < 10 ? (isFuture ? numbers_future[number] : numbers_past[number]) : number; + } + + var lang = { + months : "tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"), + monthsShort : "tam_hel_maa_huh_tou_kes_hei_elo_syy_lok_mar_jou".split("_"), + weekdays : "sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"), + weekdaysShort : "su_ma_ti_ke_to_pe_la".split("_"), + weekdaysMin : "su_ma_ti_ke_to_pe_la".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD.MM.YYYY", + LL : "Do MMMMt\\a YYYY", + LLL : "Do MMMMt\\a YYYY, klo LT", + LLLL : "dddd, Do MMMMt\\a YYYY, klo LT" + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s päästä", + past : "%s sitten", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : function (number) { + return "."; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('fi', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/fr-ca.js b/node_modules/emailjs/node_modules/moment/lang/fr-ca.js new file mode 100644 index 0000000..062fd0f --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/fr-ca.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : canadian french (fr-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +(function () { + var lang = { + months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"), + monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"), + weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), + weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[Aujourd'hui à] LT", + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dans %s", + past : "il y a %s", + s : "quelques secondes", + m : "une minute", + mm : "%d minutes", + h : "une heure", + hh : "%d heures", + d : "un jour", + dd : "%d jours", + M : "un mois", + MM : "%d mois", + y : "une année", + yy : "%d années" + }, + ordinal : function (number) { + return number === 1 ? 'er' : 'ème'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('fr', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/fr.js b/node_modules/emailjs/node_modules/moment/lang/fr.js new file mode 100644 index 0000000..819f48c --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/fr.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : french (fr) +// author : John Fischer : https://github.com/jfroffice +(function () { + var lang = { + months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"), + monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"), + weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), + weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[Aujourd'hui à] LT", + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dans %s", + past : "il y a %s", + s : "quelques secondes", + m : "une minute", + mm : "%d minutes", + h : "une heure", + hh : "%d heures", + d : "un jour", + dd : "%d jours", + M : "un mois", + MM : "%d mois", + y : "une année", + yy : "%d années" + }, + ordinal : function (number) { + return number === 1 ? 'er' : 'ème'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('fr', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/gl.js b/node_modules/emailjs/node_modules/moment/lang/gl.js new file mode 100644 index 0000000..51c8569 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/gl.js @@ -0,0 +1,64 @@ +// moment.js language configuration +// language : galician (gl) +// author : Juan G. Hurtado : https://github.com/juanghurtado +(function () { + var lang = { + months : "Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Octubro_Novembro_Decembro".split("_"), + monthsShort : "Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"), + weekdays : "Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"), + weekdaysShort : "Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"), + weekdaysMin : "Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "fai %s", + s : "uns segundo", + m : "un minuto", + mm : "%d minutos", + h : "unha hora", + hh : "%d horas", + d : "un día", + dd : "%d días", + M : "un mes", + MM : "%d meses", + y : "un ano", + yy : "%d anos" + }, + ordinal : function (number) { + return 'º'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('gl', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/hu.js b/node_modules/emailjs/node_modules/moment/lang/hu.js new file mode 100644 index 0000000..4745cbb --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/hu.js @@ -0,0 +1,108 @@ +// moment.js language configuration +// language : hungarian (hu) +// author : Adam Brunner : https://github.com/adambrunner +(function() +{ + function translate(number, withoutSuffix, key, isFuture) { + var num = number; + + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + + case 'm': + num = 'egy'; + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + break; + + case 'h': + num = 'egy'; + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + + case 'd': + num = 'egy'; + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + + case 'M': + num = 'egy'; + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + + case 'y': + num = 'egy'; + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + + default: + } + + return ''; + } + + function week(isFuture) { + var ending = ''; + switch (this.day()) { + case 0: ending = 'vasárnap'; break; + case 1: ending = 'hétfőn'; break; + case 2: ending = 'kedden'; break; + case 3: ending = 'szerdán'; break; + case 4: ending = 'csütörtökön'; break; + case 5: ending = 'pénteken'; break; + case 6: ending = 'szombaton'; break; + } + return (isFuture ? '' : 'múlt ')+'['+ending+'] LT[-kor]'; + } + + var lang = { + months : "január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"), + monthsShort : "jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"), + weekdays : "vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"), + weekdaysShort : "v_h_k_sze_cs_p_szo".split("_"), + longDateFormat : { + LT : "H:mm", + L : "YYYY.MM.DD.", + LL : "YYYY. MMMM D.", + LLL : "YYYY. MMMM D., LT", + LLLL : "YYYY. MMMM D., dddd LT" + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function(){return week.call(this, true);}, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function(){return week.call(this, false);}, + sameElse : 'L' + }, + relativeTime : { + future : "%s múlva", + past : "%s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : function(number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('hu', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/is.js b/node_modules/emailjs/node_modules/moment/lang/is.js new file mode 100644 index 0000000..c845665 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/is.js @@ -0,0 +1,132 @@ +// moment.js language configuration +// language : icelandic (is) +// author : Hinrik Örn Sigurðsson : https://github.com/hinrik +(function () { + var plural = function (n) { + if (n % 100 == 11) { + return true; + } else if (n % 10 == 1) { + return false; + } else { + return true; + } + }, + + translate = function (number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } else { + return result + 'mínútu'; + } + case 'hh': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } else { + return result + 'klukkustund'; + } + case 'd': + if (withoutSuffix) { + return 'dagur' + } else { + return isFuture ? 'dag' : 'degi'; + } + case 'dd': + if (plural(number)) { + if (withoutSuffix) { + return result + 'dagar' + } else { + return result + (isFuture ? 'daga' : 'dögum'); + } + } else if (withoutSuffix) { + return result + 'dagur' + } else { + return result + (isFuture ? 'dag' : 'degi'); + } + case 'M': + if (withoutSuffix) { + return 'mánuður' + } else { + return isFuture ? 'mánuð' : 'mánuði'; + } + case 'MM': + if (plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir' + } else { + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } + } else if (withoutSuffix) { + return result + 'mánuður'; + } else { + return result + (isFuture ? 'mánuð' : 'mánuði'); + } + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } else { + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } + } + }, + + lang = { + months : "janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"), + monthsShort : "jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"), + weekdays : "sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"), + weekdaysShort : "sun_mán_þri_mið_fim_fös_lau".split("_"), + weekdaysMin : "Su_Má_Þr_Mi_Fi_Fö_La".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY kl. LT", + LLLL : "dddd, D. MMMM YYYY kl. LT" + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : "eftir %s", + past : "fyrir %s síðan", + s : translate, + m : translate, + mm : translate, + h : "klukkustund", + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate, + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('is', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/it.js b/node_modules/emailjs/node_modules/moment/lang/it.js new file mode 100644 index 0000000..965f2ad --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/it.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : italian (it) +// author : Lorenzo : https://github.com/aliem +(function () { + var lang = { + months : "Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settebre_Ottobre_Novembre_Dicembre".split("_"), + monthsShort : "Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"), + weekdays : "Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"), + weekdaysShort : "Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"), + weekdaysMin : "D_L_Ma_Me_G_V_S".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: '[lo scorso] dddd [alle] LT', + sameElse: 'L' + }, + relativeTime : { + future : "in %s", + past : "%s fa", + s : "secondi", + m : "un minuto", + mm : "%d minuti", + h : "un'ora", + hh : "%d ore", + d : "un giorno", + dd : "%d giorni", + M : "un mese", + MM : "%d mesi", + y : "un anno", + yy : "%d anni" + }, + ordinal: function () { + return 'º'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('it', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/ja.js b/node_modules/emailjs/node_modules/moment/lang/ja.js new file mode 100644 index 0000000..0a83027 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/ja.js @@ -0,0 +1,61 @@ +// moment.js language configuration +// language : japanese (ja) +// author : LI Long : https://github.com/baryon +(function () { + var lang = { + months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"), + weekdaysShort : "日_月_火_水_木_金_土".split("_"), + weekdaysMin : "日_月_火_水_木_金_土".split("_"), + longDateFormat : { + LT : "Ah時m分", + L : "YYYY/MM/DD", + LL : "YYYY年M月D日", + LLL : "YYYY年M月D日LT", + LLLL : "YYYY年M月D日LT dddd" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "午前"; + } else { + return "午後"; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s後", + past : "%s前", + s : "数秒", + m : "1分", + mm : "%d分", + h : "1時間", + hh : "%d時間", + d : "1日", + dd : "%d日", + M : "1ヶ月", + MM : "%dヶ月", + y : "1年", + yy : "%d年" + }, + ordinal : function (number) { + return ''; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('ja', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/jp.js b/node_modules/emailjs/node_modules/moment/lang/jp.js new file mode 100644 index 0000000..53a85e5 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/jp.js @@ -0,0 +1,64 @@ +// moment.js language configuration +// language : japanese (jp) +// author : LI Long : https://github.com/baryon + +// This language config was incorrectly named 'jp' instead of 'ja'. +// In version 2.0.0, this will be deprecated and you should use 'ja' instead. +(function () { + var lang = { + months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"), + weekdaysShort : "日_月_火_水_木_金_土".split("_"), + weekdaysMin : "日_月_火_水_木_金_土".split("_"), + longDateFormat : { + LT : "Ah時m分", + L : "YYYY/MM/DD", + LL : "YYYY年M月D日", + LLL : "YYYY年M月D日LT", + LLLL : "YYYY年M月D日LT dddd" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "午前"; + } else { + return "午後"; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s後", + past : "%s前", + s : "数秒", + m : "1分", + mm : "%d分", + h : "1時間", + hh : "%d時間", + d : "1日", + dd : "%d日", + M : "1ヶ月", + MM : "%dヶ月", + y : "1年", + yy : "%d年" + }, + ordinal : function (number) { + return ''; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('jp', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/ko.js b/node_modules/emailjs/node_modules/moment/lang/ko.js new file mode 100644 index 0000000..74fcefe --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/ko.js @@ -0,0 +1,58 @@ +// moment.js language configuration +// language : korean (ko) +// author : Kyungwook, Park : https://github.com/kyungw00k +(function () { + var lang = { + months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"), + weekdaysShort : "일_월_화_수_목_금_토".split("_"), + weekdaysMin : "일_월_화_수_목_금_토".split("_"), + longDateFormat : { + LT : "A h시 mm분", + L : "YYYY.MM.DD", + LL : "YYYY년 MMMM D일", + LLL : "YYYY년 MMMM D일 LT", + LLLL : "YYYY년 MMMM D일 dddd LT" + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s 후", + past : "%s 전", + s : "몇초", + ss : "%d초", + m : "일분", + mm : "%d분", + h : "한시간", + hh : "%d시간", + d : "하루", + dd : "%d일", + M : "한달", + MM : "%d달", + y : "일년", + yy : "%d년" + }, + ordinal : function (number) { + return '일'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('ko', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/kr.js b/node_modules/emailjs/node_modules/moment/lang/kr.js new file mode 100644 index 0000000..5b932e2 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/kr.js @@ -0,0 +1,61 @@ +// moment.js language configuration +// language : korean (kr) +// author : Kyungwook, Park : https://github.com/kyungw00k + +// This language config was incorrectly named 'kr' instead of 'ko'. +// In version 2.0.0, this will be deprecated and you should use 'ko' instead. +(function () { + var lang = { + months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"), + weekdaysShort : "일_월_화_수_목_금_토".split("_"), + weekdaysMin : "일_월_화_수_목_금_토".split("_"), + longDateFormat : { + LT : "A h시 mm분", + L : "YYYY.MM.DD", + LL : "YYYY년 MMMM D일", + LLL : "YYYY년 MMMM D일 LT", + LLLL : "YYYY년 MMMM D일 dddd LT" + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s 후", + past : "%s 전", + s : "몇초", + ss : "%d초", + m : "일분", + mm : "%d분", + h : "한시간", + hh : "%d시간", + d : "하루", + dd : "%d일", + M : "한달", + MM : "%d달", + y : "일년", + yy : "%d년" + }, + ordinal : function (number) { + return '일'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('kr', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/nb.js b/node_modules/emailjs/node_modules/moment/lang/nb.js new file mode 100644 index 0000000..dd0a266 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/nb.js @@ -0,0 +1,54 @@ +// moment.js language configuration +// language : norwegian bokmål (nb) +// author : Espen Hovlandsdal : https://github.com/rexxars +(function () { + var lang = { + months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"), + weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"), + weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"), + weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[I dag klokken] LT', + nextDay: '[I morgen klokken] LT', + nextWeek: 'dddd [klokken] LT', + lastDay: '[I går klokken] LT', + lastWeek: '[Forrige] dddd [klokken] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "for %s siden", + s : "noen sekunder", + m : "ett minutt", + mm : "%d minutter", + h : "en time", + hh : "%d timer", + d : "en dag", + dd : "%d dager", + M : "en måned", + MM : "%d måneder", + y : "ett år", + yy : "%d år" + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('nb', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/nl.js b/node_modules/emailjs/node_modules/moment/lang/nl.js new file mode 100644 index 0000000..53deafb --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/nl.js @@ -0,0 +1,62 @@ +// moment.js language configuration +// language : dutch (nl) +// author : Joris Röling : https://github.com/jjupiter +(function () { + var monthsShortWithDots = "jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"); + var monthsShortWithoutDots = "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"); + var lang = { + months : "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + weekdays : "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"), + weekdaysShort : "zo._ma._di._wo._do._vr._za.".split("_"), + weekdaysMin : "Zo_Ma_Di_Wo_Do_Vr_Za".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Vandaag om] LT', + nextDay: '[Morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[Gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : "over %s", + past : "%s geleden", + s : "een paar seconden", + m : "één minuut", + mm : "%d minuten", + h : "één uur", + hh : "%d uur", + d : "één dag", + dd : "%d dagen", + M : "één maand", + MM : "%d maanden", + y : "één jaar", + yy : "%d jaar" + }, + ordinal : function (number) { + return (number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('nl', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/pl.js b/node_modules/emailjs/node_modules/moment/lang/pl.js new file mode 100644 index 0000000..5c4193c --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/pl.js @@ -0,0 +1,76 @@ +// moment.js language configuration +// language : polish (pl) +// author : Rafal Hirsz : https://github.com/evoL +(function () { + var plural = function (n) { + return (n % 10 < 5) && (n % 10 > 1) && (~~(n / 10) !== 1); + }, + + translate = function (number, withoutSuffix, key) { + var result = number + " "; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (plural(number) ? 'lata' : 'lat'); + } + }, + + lang = { + months : "styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"), + monthsShort : "sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"), + weekdays : "niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"), + weekdaysShort : "nie_pon_wt_śr_czw_pt_sb".split("_"), + weekdaysMin : "N_Pn_Wt_Śr_Cz_Pt_So".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: '[W zeszły/łą] dddd [o] LT', + sameElse: 'L' + }, + relativeTime : { + future : "za %s", + past : "%s temu", + s : "kilka sekund", + m : translate, + mm : translate, + h : translate, + hh : translate, + d : "1 dzień", + dd : '%d dni', + M : "miesiąc", + MM : translate, + y : "rok", + yy : translate + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('pl', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/pt-br.js b/node_modules/emailjs/node_modules/moment/lang/pt-br.js new file mode 100644 index 0000000..c83d4ac --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/pt-br.js @@ -0,0 +1,58 @@ +// moment.js language configuration +// language : brazilian portuguese (pt-br) +// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira +(function () { + var lang = { + months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"), + monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"), + weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"), + weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"), + weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D \\de MMMM \\de YYYY", + LLL : "D \\de MMMM \\de YYYY LT", + LLLL : "dddd, D \\de MMMM \\de YYYY LT" + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : "em %s", + past : "%s atrás", + s : "segundos", + m : "um minuto", + mm : "%d minutos", + h : "uma hora", + hh : "%d horas", + d : "um dia", + dd : "%d dias", + M : "um mês", + MM : "%d meses", + y : "um ano", + yy : "%d anos" + }, + ordinal : function (number) { + return 'º'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('pt-br', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/pt.js b/node_modules/emailjs/node_modules/moment/lang/pt.js new file mode 100644 index 0000000..55eb540 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/pt.js @@ -0,0 +1,58 @@ +// moment.js language configuration +// language : portuguese (pt) +// author : Jefferson : https://github.com/jalex79 +(function () { + var lang = { + months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"), + monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"), + weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"), + weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"), + weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D \\de MMMM \\de YYYY", + LLL : "D \\de MMMM \\de YYYY LT", + LLLL : "dddd, D \\de MMMM \\de YYYY LT" + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : "em %s", + past : "%s atrás", + s : "segundos", + m : "um minuto", + mm : "%d minutos", + h : "uma hora", + hh : "%d horas", + d : "um dia", + dd : "%d dias", + M : "um mês", + MM : "%d meses", + y : "um ano", + yy : "%d anos" + }, + ordinal : function (number) { + return 'º'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('pt', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/ru.js b/node_modules/emailjs/node_modules/moment/lang/ru.js new file mode 100644 index 0000000..5c9617a --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/ru.js @@ -0,0 +1,133 @@ +// moment.js language configuration +// language : russian (ru) +// author : Viktorminator : https://github.com/Viktorminator +(function () { + + var pluralRules = [ + function (n) { return ((n % 10 === 1) && (n % 100 !== 11)); }, + function (n) { return ((n % 10) >= 2 && (n % 10) <= 4 && ((n % 10) % 1) === 0) && ((n % 100) < 12 || (n % 100) > 14); }, + function (n) { return ((n % 10) === 0 || ((n % 10) >= 5 && (n % 10) <= 9 && ((n % 10) % 1) === 0) || ((n % 100) >= 11 && (n % 100) <= 14 && ((n % 100) % 1) === 0)); }, + function (n) { return true; } + ], + + plural = function (word, num) { + var forms = word.split('_'), + minCount = Math.min(pluralRules.length, forms.length), + i = -1; + + while (++i < minCount) { + if (pluralRules[i](num)) { + return forms[i]; + } + } + return forms[minCount - 1]; + }, + + relativeTimeWithPlural = function (number, withoutSuffix, key) { + var format = { + 'mm': 'минута_минуты_минут_минуты', + 'hh': 'час_часа_часов_часа', + 'dd': 'день_дня_дней_дня', + 'MM': 'месяц_месяца_месяцев_месяца', + 'yy': 'год_года_лет_года' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + plural(format[key], +number); + } + }, + + monthsCaseReplace = function (m, format) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, + + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; + }, + + weekdaysCaseReplace = function (m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'), + }, + + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + + return weekdays[nounCase][m.day()]; + }, + + lang = { + months : monthsCaseReplace, + monthsShort : "янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "вск_пнд_втр_срд_чтв_птн_сбт".split("_"), + weekdaysMin : "вс_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY г.", + LLL : "D MMMM YYYY г., LT", + LLLL : "dddd, D MMMM YYYY г., LT" + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function () { + return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + }, + sameElse: 'L' + }, + // It needs checking (adding) russian plurals and cases. + relativeTime : { + future : "через %s", + past : "%s назад", + s : "несколько секунд", + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : "час", + hh : relativeTimeWithPlural, + d : "день", + dd : relativeTimeWithPlural, + M : "месяц", + MM : relativeTimeWithPlural, + y : "год", + yy : relativeTimeWithPlural + }, + ordinal : function (number) { + return '.'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('ru', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/sv.js b/node_modules/emailjs/node_modules/moment/lang/sv.js new file mode 100644 index 0000000..cb32ae8 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/sv.js @@ -0,0 +1,58 @@ +// moment.js language configuration +// language : swedish (sv) +// author : Jens Alm : https://github.com/ulmus +(function () { + var lang = { + months : "januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"), + monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"), + weekdays : "söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"), + weekdaysShort : "sön_mån_tis_ons_tor_fre_lör".split("_"), + weekdaysMin : "sö_må_ti_on_to_fr_lö".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Idag klockan] LT', + nextDay: '[Imorgon klockan] LT', + lastDay: '[Igår klockan] LT', + nextWeek: 'dddd [klockan] LT', + lastWeek: '[Förra] dddd[en klockan] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "för %s sen", + s : "några sekunder", + m : "en minut", + mm : "%d minuter", + h : "en timme", + hh : "%d timmar", + d : "en dag", + dd : "%d dagar", + M : "en månad", + MM : "%d månader", + y : "ett år", + yy : "%d år" + }, + ordinal : function (number) { + var b = number % 10; + return (~~ (number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('sv', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/tr.js b/node_modules/emailjs/node_modules/moment/lang/tr.js new file mode 100644 index 0000000..746899e --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/tr.js @@ -0,0 +1,88 @@ +// moment.js language configuration +// language : turkish (tr) +// authors : Erhan Gundogan : https://github.com/erhangundogan, +// Burak Yiğit Kaya: https://github.com/BYK +(function () { + var suffixes = { + 1: "'inci", + 5: "'inci", + 8: "'inci", + 70: "'inci", + 80: "'inci", + + 2: "'nci", + 7: "'nci", + 20: "'nci", + 50: "'nci", + + 3: "'üncü", + 4: "'üncü", + 100: "'üncü", + + 6: "'ncı", + + 9: "'uncu", + 10: "'uncu", + 30: "'uncu", + + 60: "'ıncı", + 90: "'ıncı" + }; + var lang = { + months : "Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"), + monthsShort : "Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"), + weekdays : "Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"), + weekdaysShort : "Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"), + weekdaysMin : "Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s sonra", + past : "%s önce", + s : "birkaç saniye", + m : "bir dakika", + mm : "%d dakika", + h : "bir saat", + hh : "%d saat", + d : "bir gün", + dd : "%d gün", + M : "bir ay", + MM : "%d ay", + y : "bir yıl", + yy : "%d yıl" + }, + ordinal : function (number) { + if (number === 0) { // special case for zero + return "'ıncı"; + } + + var a = number % 10; + var b = number % 100 - a; + var c = number >= 100 ? 100 : null; + + return suffixes[a] || suffixes[b] || suffixes[c]; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('tr', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/zh-cn.js b/node_modules/emailjs/node_modules/moment/lang/zh-cn.js new file mode 100644 index 0000000..0dd1ebb --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/zh-cn.js @@ -0,0 +1,67 @@ +// moment.js language configuration +// language : chinese +// author : suupic : https://github.com/suupic +(function () { + var lang = { + months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"), + weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"), + weekdaysMin : "日_一_二_三_四_五_六".split("_"), + longDateFormat : { + LT : "Ah点mm", + L : "YYYY年MMMD日", + LL : "YYYY年MMMD日", + LLL : "YYYY年MMMD日LT", + LLLL : "YYYY年MMMD日ddddLT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 9) { + return "早上"; + } else if (hour < 11 && minute < 30) { + return "上午"; + } else if (hour < 13 && minute < 30) { + return "中午"; + } else if (hour < 18) { + return "下午"; + } else { + return "晚上"; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + relativeTime : { + future : "%s内", + past : "%s前", + s : "几秒", + m : "1分钟", + mm : "%d分钟", + h : "1小时", + hh : "%d小时", + d : "1天", + dd : "%d天", + M : "1个月", + MM : "%d个月", + y : "1年", + yy : "%d年" + }, + ordinal : function (number) { + return ''; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('zh-cn', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/lang/zh-tw.js b/node_modules/emailjs/node_modules/moment/lang/zh-tw.js new file mode 100644 index 0000000..0938718 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/lang/zh-tw.js @@ -0,0 +1,67 @@ +// moment.js language configuration +// language : traditional chinese (zh-tw) +// author : Ben : https://github.com/ben-lin +(function () { + var lang = { + months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"), + weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"), + weekdaysMin : "日_一_二_三_四_五_六".split("_"), + longDateFormat : { + LT : "Ah點mm", + L : "YYYY年MMMD日", + LL : "YYYY年MMMD日", + LLL : "YYYY年MMMD日LT", + LLLL : "YYYY年MMMD日ddddLT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 9) { + return "早上"; + } else if (hour < 11 && minute < 30) { + return "上午"; + } else if (hour < 13 && minute < 30) { + return "中午"; + } else if (hour < 18) { + return "下午"; + } else { + return "晚上"; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + relativeTime : { + future : "%s內", + past : "%s前", + s : "幾秒", + m : "一分鐘", + mm : "%d分鐘", + h : "一小時", + hh : "%d小時", + d : "一天", + dd : "%d天", + M : "一個月", + MM : "%d個月", + y : "一年", + yy : "%d年" + }, + ordinal : function (number) { + return ''; + } + }; + + // Node + if (typeof module !== 'undefined' && module.exports) { + module.exports = lang; + } + // Browser + if (typeof window !== 'undefined' && this.moment && this.moment.lang) { + this.moment.lang('zh-tw', lang); + } +}()); diff --git a/node_modules/emailjs/node_modules/moment/min/lang-all.min.js b/node_modules/emailjs/node_modules/moment/min/lang-all.min.js new file mode 100644 index 0000000..f870207 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang-all.min.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz +(function(){var a={months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"h:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinal:function(a){return"."}};typeof module!="undefined"&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("bg",a)})(),function(){var a={months:"Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"),monthsShort:"Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"),weekdays:"Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"),weekdaysShort:"Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(this.hours()!==1?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(this.hours()!==1?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(this.hours()!==1?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(this.hours()!==1?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(this.hours()!==1?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ca",a)}(),function(){var a={months:"кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),monthsShort:"кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кç_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ",LLL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT",LLLL:"dddd, YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ĕнер] LT [сехетре]",nextWeek:"[Çитес] dddd LT [сехетре]",lastWeek:"[Иртнĕ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:"%sран",past:"%s каялла",s:"пĕр-ик çеккунт",m:"пĕр минут",mm:"%d минут",h:"пĕр сехет",hh:"%d сехет",d:"пĕр кун",dd:"%d кун",M:"пĕр уйăх",MM:"%d уйăх",y:"пĕр çул",yy:"%d çул"},ordinal:function(a){return"-мĕш"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("cv",a)}(),function(){var a={months:"Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"),weekdays:"Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"),weekdaysShort:"Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"),weekdaysMin:"Sø_Ma_Ti_On_To_Fr_Lø".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd D. MMMM, YYYY h:mm A"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"minut",mm:"%d minutter",h:"time",hh:"%d timer",d:"dag",dd:"%d dage",M:"månede",MM:"%d måneder",y:"år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("da",a)}(),function(){var a={months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm U\\hr",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:"einer Minute",mm:"%d Minuten",h:"einer Stunde",hh:"%d Stunden",d:"einem Tag",dd:"%d Tagen",M:"einem Monat",MM:"%d Monaten",y:"einem Jahr",yy:"%d Jahren"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("de",a)}(),function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-gb",a)}(),function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-gb",a)}(),function(){var a={months:"Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre".split("_"),monthsShort:"Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.".split("_"),weekdays:"Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mié._Jue._Vie._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(this.hours()!==1?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(this.hours()!==1?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(this.hours()!==1?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(this.hours()!==1?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(this.hours()!==1?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("es",a)}(),function(){var a={months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYYko MMMMren D[a]",LLL:"YYYYko MMMMren D[a] LT",LLLL:"dddd, YYYYko MMMMren D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("eu",a)}(),function(){function c(a,b,c,e){var f="";switch(c){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=d(a,e)+" "+f,f}function d(c,d){return c<10?d?b[c]:a[c]:c}var a=["nolla","yksi","kaksi","kolme","neljä","viisi","kuusi","seitsemän","kahdeksan","yhdeksän"],b=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",a[7],a[8],a[9]],e={months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tam_hel_maa_huh_tou_kes_hei_elo_syy_lok_mar_jou".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMMt\\a YYYY",LLL:"Do MMMMt\\a YYYY, klo LT",LLLL:"dddd, Do MMMMt\\a YYYY, klo LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=e),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fi",e)}(),function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr",a)}(),function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr",a)}(),function(){var a={months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Octubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(this.hours()!==1?"ás":"a")+"] LT"},nextDay:function(){return"[mañá "+(this.hours()!==1?"ás":"a")+"] LT"},nextWeek:function(){return"dddd ["+(this.hours()!==1?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(this.hours()!==1?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(this.hours()!==1?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fai %s",s:"uns segundo",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("gl",a)}(),function(){function a(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":e="egy";case"mm":return e+(d||b?" perc":" perce");case"h":e="egy";case"hh":return e+(d||b?" óra":" órája");case"d":e="egy";case"dd":return e+(d||b?" nap":" napja");case"M":e="egy";case"MM":return e+(d||b?" hónap":" hónapja");case"y":e="egy";case"yy":return e+(d||b?" év":" éve");default:}return""}function b(a){var b="";switch(this.day()){case 0:b="vasárnap";break;case 1:b="hétfőn";break;case 2:b="kedden";break;case 3:b="szerdán";break;case 4:b="csütörtökön";break;case 5:b="pénteken";break;case 6:b="szombaton"}return(a?"":"múlt ")+"["+b+"] LT[-kor]"}var c={months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return b.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return b.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("hu",c)}(),function(){var a=function(a){return a%100==11?!0:a%10==1?!1:!0},b=function(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return a(b)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return a(b)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return a(b)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return a(b)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return a(b)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}},c={months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY kl. LT",LLLL:"dddd, D. MMMM YYYY kl. LT"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:b,m:b,mm:b,h:"klukkustund",hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("is",c)}(),function(){var a={months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settebre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s fa",s:"secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:function(){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("it",a)}(),function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ja",a)}(),function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("jp",a)}(),function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ko",a)}(),function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("kr",a)}(),function(){var a={months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokken] LT",nextDay:"[I morgen klokken] LT",nextWeek:"dddd [klokken] LT",lastDay:"[I går klokken] LT",lastWeek:"[Forrige] dddd [klokken] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nb",a)}(),function(){var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),b="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),c={months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(c,d){return/-MMM-/.test(d)?b[c.month()]:a[c.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Vandaag om] LT",nextDay:"[Morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinal:function(a){return a===1||a===8||a>=20?"ste":"de"}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nl",c)}(),function(){var a=function(a){return a%10<5&&a%10>1&&~~(a/10)!==1},b=function(b,c,d){var e=b+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(a(b)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(a(b)?"godziny":"godzin");case"MM":return e+(a(b)?"miesiące":"miesięcy");case"yy":return e+(a(b)?"lata":"lat")}},c={months:"styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:"[W zeszły/łą] dddd [o] LT",sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:b,mm:b,h:b,hh:b,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:b,y:"rok",yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pl",c)}(),function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt-br",a)}(),function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt",a)}(),function(){var a=[function(a){return a%10===1&&a%100!==11},function(a){return a%10>=2&&a%10<=4&&a%10%1===0&&(a%100<12||a%100>14)},function(a){return a%10===0||a%10>=5&&a%10<=9&&a%10%1===0||a%100>=11&&a%100<=14&&a%100%1===0},function(a){return!0}],b=function(b,c){var d=b.split("_"),e=Math.min(a.length,d.length),f=-1;while(++f=100?100:null;return a[c]||a[d]||a[e]}};typeof module!="undefined"&&module.exports&&(module.exports=b),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("tr",b)}(),function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1分钟",mm:"%d分钟",h:"1小时",hh:"%d小时",d:"1天",dd:"%d天",M:"1个月",MM:"%d个月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-cn",a)}(),function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"一分鐘",mm:"%d分鐘",h:"一小時",hh:"%d小時",d:"一天",dd:"%d天",M:"一個月",MM:"%d個月",y:"一年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-tw",a)}(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/bg.js b/node_modules/emailjs/node_modules/moment/min/lang/bg.js new file mode 100644 index 0000000..94beac4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/bg.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz +(function(){var a={months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"h:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinal:function(a){return"."}};typeof module!="undefined"&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("bg",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/ca.js b/node_modules/emailjs/node_modules/moment/min/lang/ca.js new file mode 100644 index 0000000..3c9b566 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : catalan (ca) +// author : Juan G. Hurtado : https://github.com/juanghurtado +(function(){var a={months:"Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"),monthsShort:"Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"),weekdays:"Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"),weekdaysShort:"Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(this.hours()!==1?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(this.hours()!==1?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(this.hours()!==1?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(this.hours()!==1?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(this.hours()!==1?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ca",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/cv.js b/node_modules/emailjs/node_modules/moment/min/lang/cv.js new file mode 100644 index 0000000..92c1c88 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/cv.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : chuvash (cv) +// author : Anatoly Mironov : https://github.com/mirontoli +(function(){var a={months:"кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),monthsShort:"кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кç_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ",LLL:"YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT",LLLL:"dddd, YYYY çулхи MMMM уйăхĕн D-мĕшĕ, LT"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ĕнер] LT [сехетре]",nextWeek:"[Çитес] dddd LT [сехетре]",lastWeek:"[Иртнĕ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:"%sран",past:"%s каялла",s:"пĕр-ик çеккунт",m:"пĕр минут",mm:"%d минут",h:"пĕр сехет",hh:"%d сехет",d:"пĕр кун",dd:"%d кун",M:"пĕр уйăх",MM:"%d уйăх",y:"пĕр çул",yy:"%d çул"},ordinal:function(a){return"-мĕш"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("cv",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/da.js b/node_modules/emailjs/node_modules/moment/min/lang/da.js new file mode 100644 index 0000000..9a6391f --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/da.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : danish (da) +// author : Ulrik Nielsen : https://github.com/mrbase +(function(){var a={months:"Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"),weekdays:"Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"),weekdaysShort:"Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"),weekdaysMin:"Sø_Ma_Ti_On_To_Fr_Lø".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd D. MMMM, YYYY h:mm A"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"minut",mm:"%d minutter",h:"time",hh:"%d timer",d:"dag",dd:"%d dage",M:"månede",MM:"%d måneder",y:"år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("da",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/de.js b/node_modules/emailjs/node_modules/moment/min/lang/de.js new file mode 100644 index 0000000..524da56 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/de.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : german (de) +// author : lluchs : https://github.com/lluchs +(function(){var a={months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm U\\hr",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:"einer Minute",mm:"%d Minuten",h:"einer Stunde",hh:"%d Stunden",d:"einem Tag",dd:"%d Tagen",M:"einem Monat",MM:"%d Monaten",y:"einem Jahr",yy:"%d Jahren"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("de",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/en-ca.js b/node_modules/emailjs/node_modules/moment/min/lang/en-ca.js new file mode 100644 index 0000000..3c7bce4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/en-ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : canadian english (en-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +(function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-gb",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/en-gb.js b/node_modules/emailjs/node_modules/moment/min/lang/en-gb.js new file mode 100644 index 0000000..f86fa43 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/en-gb.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : great britain english (en-gb) +// author : Chris Gedrim : https://github.com/chrisgedrim +(function(){var a={months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("en-gb",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/es.js b/node_modules/emailjs/node_modules/moment/min/lang/es.js new file mode 100644 index 0000000..53ac4d2 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/es.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : spanish (es) +// author : Julio Napurí : https://github.com/julionc +(function(){var a={months:"Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre".split("_"),monthsShort:"Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.".split("_"),weekdays:"Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mié._Jue._Vie._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(this.hours()!==1?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(this.hours()!==1?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(this.hours()!==1?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(this.hours()!==1?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(this.hours()!==1?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("es",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/eu.js b/node_modules/emailjs/node_modules/moment/min/lang/eu.js new file mode 100644 index 0000000..453d512 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/eu.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : euskara (eu) +// author : Eneko Illarramendi : https://github.com/eillarra +(function(){var a={months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYYko MMMMren D[a]",LLL:"YYYYko MMMMren D[a] LT",LLLL:"dddd, YYYYko MMMMren D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("eu",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/fi.js b/node_modules/emailjs/node_modules/moment/min/lang/fi.js new file mode 100644 index 0000000..97c1b22 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/fi.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : finnish (fi) +// author : Tarmo Aidantausta : https://github.com/bleadof +(function(){function c(a,b,c,e){var f="";switch(c){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=d(a,e)+" "+f,f}function d(c,d){return c<10?d?b[c]:a[c]:c}var a=["nolla","yksi","kaksi","kolme","neljä","viisi","kuusi","seitsemän","kahdeksan","yhdeksän"],b=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",a[7],a[8],a[9]],e={months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tam_hel_maa_huh_tou_kes_hei_elo_syy_lok_mar_jou".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMMt\\a YYYY",LLL:"Do MMMMt\\a YYYY, klo LT",LLLL:"dddd, Do MMMMt\\a YYYY, klo LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=e),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fi",e)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/fr-ca.js b/node_modules/emailjs/node_modules/moment/min/lang/fr-ca.js new file mode 100644 index 0000000..7c19ae4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/fr-ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : canadian french (fr-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +(function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/fr.js b/node_modules/emailjs/node_modules/moment/min/lang/fr.js new file mode 100644 index 0000000..53589d9 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/fr.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : french (fr) +// author : John Fischer : https://github.com/jfroffice +(function(){var a={months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"une année",yy:"%d années"},ordinal:function(a){return a===1?"er":"ème"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("fr",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/gl.js b/node_modules/emailjs/node_modules/moment/min/lang/gl.js new file mode 100644 index 0000000..9e6d6fd --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/gl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : galician (gl) +// author : Juan G. Hurtado : https://github.com/juanghurtado +(function(){var a={months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Octubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(this.hours()!==1?"ás":"a")+"] LT"},nextDay:function(){return"[mañá "+(this.hours()!==1?"ás":"a")+"] LT"},nextWeek:function(){return"dddd ["+(this.hours()!==1?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(this.hours()!==1?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(this.hours()!==1?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fai %s",s:"uns segundo",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("gl",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/hu.js b/node_modules/emailjs/node_modules/moment/min/lang/hu.js new file mode 100644 index 0000000..1101c17 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/hu.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : hungarian (hu) +// author : Adam Brunner : https://github.com/adambrunner +(function(){function a(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":e="egy";case"mm":return e+(d||b?" perc":" perce");case"h":e="egy";case"hh":return e+(d||b?" óra":" órája");case"d":e="egy";case"dd":return e+(d||b?" nap":" napja");case"M":e="egy";case"MM":return e+(d||b?" hónap":" hónapja");case"y":e="egy";case"yy":return e+(d||b?" év":" éve");default:}return""}function b(a){var b="";switch(this.day()){case 0:b="vasárnap";break;case 1:b="hétfőn";break;case 2:b="kedden";break;case 3:b="szerdán";break;case 4:b="csütörtökön";break;case 5:b="pénteken";break;case 6:b="szombaton"}return(a?"":"múlt ")+"["+b+"] LT[-kor]"}var c={months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return b.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return b.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("hu",c)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/is.js b/node_modules/emailjs/node_modules/moment/min/lang/is.js new file mode 100644 index 0000000..9da0426 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/is.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : icelandic (is) +// author : Hinrik Örn Sigurðsson : https://github.com/hinrik +(function(){var a=function(a){return a%100==11?!0:a%10==1?!1:!0},b=function(b,c,d,e){var f=b+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return a(b)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return a(b)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return a(b)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return a(b)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return a(b)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}},c={months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY kl. LT",LLLL:"dddd, D. MMMM YYYY kl. LT"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:b,m:b,mm:b,h:"klukkustund",hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("is",c)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/it.js b/node_modules/emailjs/node_modules/moment/min/lang/it.js new file mode 100644 index 0000000..3773f38 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/it.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : italian (it) +// author : Lorenzo : https://github.com/aliem +(function(){var a={months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settebre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s fa",s:"secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:function(){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("it",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/ja.js b/node_modules/emailjs/node_modules/moment/min/lang/ja.js new file mode 100644 index 0000000..c4f01ab --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/ja.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : japanese (ja) +// author : LI Long : https://github.com/baryon +(function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ja",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/jp.js b/node_modules/emailjs/node_modules/moment/min/lang/jp.js new file mode 100644 index 0000000..dbf237a --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/jp.js @@ -0,0 +1,6 @@ +// moment.js language configuration +// language : japanese (jp) +// author : LI Long : https://github.com/baryon +// This language config was incorrectly named 'jp' instead of 'ja'. +// In version 2.0.0, this will be deprecated and you should use 'ja' instead. +(function(){var a={months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a,b,c){return a<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("jp",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/ko.js b/node_modules/emailjs/node_modules/moment/min/lang/ko.js new file mode 100644 index 0000000..f54a5ae --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/ko.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : korean (ko) +// author : Kyungwook, Park : https://github.com/kyungw00k +(function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("ko",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/kr.js b/node_modules/emailjs/node_modules/moment/min/lang/kr.js new file mode 100644 index 0000000..d2ac35f --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/kr.js @@ -0,0 +1,6 @@ +// moment.js language configuration +// language : korean (kr) +// author : Kyungwook, Park : https://github.com/kyungw00k +// This language config was incorrectly named 'kr' instead of 'ko'. +// In version 2.0.0, this will be deprecated and you should use 'ko' instead. +(function(){var a={months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a,b,c){return a<12?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:function(a){return"일"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("kr",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/nb.js b/node_modules/emailjs/node_modules/moment/min/lang/nb.js new file mode 100644 index 0000000..d476a33 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/nb.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : norwegian bokmål (nb) +// author : Espen Hovlandsdal : https://github.com/rexxars +(function(){var a={months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokken] LT",nextDay:"[I morgen klokken] LT",nextWeek:"dddd [klokken] LT",lastDay:"[I går klokken] LT",lastWeek:"[Forrige] dddd [klokken] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nb",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/nl.js b/node_modules/emailjs/node_modules/moment/min/lang/nl.js new file mode 100644 index 0000000..a9084b7 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/nl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : dutch (nl) +// author : Joris Röling : https://github.com/jjupiter +(function(){var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),b="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),c={months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(c,d){return/-MMM-/.test(d)?b[c.month()]:a[c.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Vandaag om] LT",nextDay:"[Morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinal:function(a){return a===1||a===8||a>=20?"ste":"de"}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("nl",c)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/pl.js b/node_modules/emailjs/node_modules/moment/min/lang/pl.js new file mode 100644 index 0000000..aeab208 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/pl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : polish (pl) +// author : Rafal Hirsz : https://github.com/evoL +(function(){var a=function(a){return a%10<5&&a%10>1&&~~(a/10)!==1},b=function(b,c,d){var e=b+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(a(b)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(a(b)?"godziny":"godzin");case"MM":return e+(a(b)?"miesiące":"miesięcy");case"yy":return e+(a(b)?"lata":"lat")}},c={months:"styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:"[W zeszły/łą] dddd [o] LT",sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:b,mm:b,h:b,hh:b,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:b,y:"rok",yy:b},ordinal:function(a){return"."}};typeof module!="undefined"&&module.exports&&(module.exports=c),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pl",c)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/pt-br.js b/node_modules/emailjs/node_modules/moment/min/lang/pt-br.js new file mode 100644 index 0000000..fcba685 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/pt-br.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : brazilian portuguese (pt-br) +// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira +(function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt-br",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/pt.js b/node_modules/emailjs/node_modules/moment/min/lang/pt.js new file mode 100644 index 0000000..7b9f4c9 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/pt.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : portuguese (pt) +// author : Jefferson : https://github.com/jalex79 +(function(){var a={months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D \\de MMMM \\de YYYY",LLL:"D \\de MMMM \\de YYYY LT",LLLL:"dddd, D \\de MMMM \\de YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return this.day()===0||this.day()===6?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:function(a){return"º"}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("pt",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/ru.js b/node_modules/emailjs/node_modules/moment/min/lang/ru.js new file mode 100644 index 0000000..66bf414 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/ru.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : russian (ru) +// author : Viktorminator : https://github.com/Viktorminator +(function(){var a=[function(a){return a%10===1&&a%100!==11},function(a){return a%10>=2&&a%10<=4&&a%10%1===0&&(a%100<12||a%100>14)},function(a){return a%10===0||a%10>=5&&a%10<=9&&a%10%1===0||a%100>=11&&a%100<=14&&a%100%1===0},function(a){return!0}],b=function(b,c){var d=b.split("_"),e=Math.min(a.length,d.length),f=-1;while(++f=100?100:null;return a[c]||a[d]||a[e]}};typeof module!="undefined"&&module.exports&&(module.exports=b),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("tr",b)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/zh-cn.js b/node_modules/emailjs/node_modules/moment/min/lang/zh-cn.js new file mode 100644 index 0000000..9f435f6 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/zh-cn.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : chinese +// author : suupic : https://github.com/suupic +(function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1分钟",mm:"%d分钟",h:"1小时",hh:"%d小时",d:"1天",dd:"%d天",M:"1个月",MM:"%d个月",y:"1年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-cn",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/lang/zh-tw.js b/node_modules/emailjs/node_modules/moment/min/lang/zh-tw.js new file mode 100644 index 0000000..915bdba --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/lang/zh-tw.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : traditional chinese (zh-tw) +// author : Ben : https://github.com/ben-lin +(function(){var a={months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT"},meridiem:function(a,b,c){return a<9?"早上":a<11&&b<30?"上午":a<13&&b<30?"中午":a<18?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"一分鐘",mm:"%d分鐘",h:"一小時",hh:"%d小時",d:"一天",dd:"%d天",M:"一個月",MM:"%d個月",y:"一年",yy:"%d年"},ordinal:function(a){return""}};typeof module!="undefined"&&module.exports&&(module.exports=a),typeof window!="undefined"&&this.moment&&this.moment.lang&&this.moment.lang("zh-tw",a)})(); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/min/moment.min.js b/node_modules/emailjs/node_modules/moment/min/moment.min.js new file mode 100644 index 0000000..4c35923 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/min/moment.min.js @@ -0,0 +1,6 @@ +// moment.js +// version : 1.7.0 +// author : Tim Wood +// license : MIT +// momentjs.com +(function(a,b){function G(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,a._a=null,this._lang=c||!1}function H(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=I(j/1e3),b.seconds=i%60,h+=I(i/60),b.minutes=h%60,g+=I(h/60),b.hours=g%24,f+=I(g/24),f+=e*7,b.days=f%30,d+=I(f/30),b.months=d%12,c+=I(d/12),b.years=c,this._lang=!1}function I(a){return a<0?Math.ceil(a):Math.floor(a)}function J(a,b){var c=a+"";while(c.length70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(z),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}}function X(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(l),f,g;for(f=0;f0,j[4]=c,$.apply({},j)}function ab(a,b){c.fn[a]=function(a){var c=this._isUTC?"UTC":"";return a!=null?(this._d["set"+c+b](a),this):this._d["get"+c+b]()}}function bb(a){c.duration.fn[a]=function(){return this._data[a]}}function cb(a,b){c.duration.fn["as"+a]=function(){return+this/b}}var c,d="1.7.0",e=Math.round,f,g={},h="en",i=typeof module!="undefined"&&module.exports,j="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),k=/^\/?Date\((\-?\d+)/i,l=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?)/g,m=/(LT|LL?L?L?)/g,n=/(^\[)|(\\)|\]$/g,o=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,p=/\d\d?/,q=/\d{1,3}/,r=/\d{3}/,s=/\d{1,4}/,t=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,u=/Z|[\+\-]\d\d:?\d\d/i,v=/T/i,w=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,x="YYYY-MM-DDTHH:mm:ssZ",y=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],z=/([\+\-]|\d\d)/gi,A="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),B={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},C={},D={M:"(a=t.month()+1)",MMM:'v("monthsShort",t.month())',MMMM:'v("months",t.month())',D:"(a=t.date())",DDD:"(a=new Date(t.year(),t.month(),t.date()),b=new Date(t.year(),0,1),a=~~(((a-b)/864e5)+1.5))",d:"(a=t.day())",dd:'v("weekdaysMin",t.day())',ddd:'v("weekdaysShort",t.day())',dddd:'v("weekdays",t.day())',w:"(a=new Date(t.year(),t.month(),t.date()-t.day()+5),b=new Date(a.getFullYear(),0,4),a=~~((a-b)/864e5/7+1.5))",YY:"p(t.year()%100,2)",YYYY:"p(t.year(),4)",a:"m(t.hours(),t.minutes(),!0)",A:"m(t.hours(),t.minutes(),!1)",H:"t.hours()",h:"t.hours()%12||12",m:"t.minutes()",s:"t.seconds()",S:"~~(t.milliseconds()/100)",SS:"p(~~(t.milliseconds()/10),2)",SSS:"p(t.milliseconds(),3)",Z:'((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(a/60),2)+":"+p(~~a%60,2)',ZZ:'((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(10*a/6),4)'},E="DDD w M D d".split(" "),F="M D H h m s w".split(" ");while(E.length)f=E.pop(),D[f+"o"]=D[f]+"+o(a)";while(F.length)f=F.pop(),D[f+f]="p("+D[f]+",2)";D.DDDD="p("+D.DDD+",3)",c=function(d,e){if(d===null||d==="")return null;var f,g;return c.isMoment(d)?new G(new a(+d._d),d._isUTC,d._lang):(e?L(e)?f=Y(d,e):f=X(d,e):(g=k.exec(d),f=d===b?new a:g?new a(+g[1]):d instanceof a?d:L(d)?N(d):typeof d=="string"?Z(d):new a(d)),new G(f))},c.utc=function(a,b){return L(a)?new G(N(a,!0),!0):(typeof a=="string"&&!u.exec(a)&&(a+=" +0000",b&&(b+=" Z")),c(a,b).utc())},c.unix=function(a){return c(a*1e3)},c.duration=function(a,b){var d=c.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(b?f[b]=a:f.milliseconds=a),g=new H(f),d&&(g._lang=a._lang),g},c.humanizeDuration=function(a,b,d){return c.duration(a,b===!0?null:b).humanize(b===!0?!0:d)},c.version=d,c.defaultFormat=x,c.lang=function(a,b){var d;if(!a)return h;(b||!g[a])&&O(a,b);if(g[a]){for(d=0;d11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),c.fn=G.prototype={clone:function(){return c(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?!M(this._a,(this._a[7]?c.utc(this):this).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return U(this,a?a:c.defaultFormat)},add:function(a,b){var d=b?c.duration(+b,a):c.duration(a);return K(this,d,1),this},subtract:function(a,b){var d=b?c.duration(+b,a):c.duration(a);return K(this,d,-1),this},diff:function(a,b,d){var f=this._isUTC?c(a).utc():c(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return b==="months"?l=i*12+j+k/30:b==="years"?l=i+(j+k/30)/12:l=b==="seconds"?h/1e3:b==="minutes"?h/6e4:b==="hours"?h/36e5:b==="days"?h/864e5:b==="weeks"?h/6048e5:h,d?l:e(l)},from:function(a,b){return c.duration(this.diff(a)).lang(this._lang).humanize(!b)},fromNow:function(a){return this.from(c(),a)},calendar:function(){var a=this.diff(c().sod(),"days",!0),b=this.lang().calendar,d=b.sameElse,e=a<-6?d:a<-1?b.lastWeek:a<0?b.lastDay:a<1?b.sameDay:a<2?b.nextDay:a<7?b.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone() 70 ? 1900 : 2e3); + break; + case "YYYY": + c[0] = ~~Math.abs(b); + break; + case "a": + case "A": + d.isPm = (b + "").toLowerCase() === "pm"; + break; + case "H": + case "HH": + case "h": + case "hh": + c[3] = ~~b; + break; + case "m": + case "mm": + c[4] = ~~b; + break; + case "s": + case "ss": + c[5] = ~~b; + break; + case "S": + case "SS": + case "SSS": + c[6] = ~~(("0." + b) * 1e3); + break; + case "Z": + case "ZZ": + d.isUTC = !0, e = (b + "").match(z), e && e[1] && (d.tzh = ~~e[1]), e && e[2] && (d.tzm = ~~e[2]), e && e[0] === "+" && (d.tzh = -d.tzh, d.tzm = -d.tzm); + } + } + function X(a, b) { + var c = [ 0, 0, 1, 0, 0, 0, 0 ], d = { + tzh: 0, + tzm: 0 + }, e = b.match(l), f, g; + for (f = 0; f < e.length; f++) g = (V(e[f]).exec(a) || [])[0], a = a.replace(V(e[f]), ""), W(e[f], g, c, d); + return d.isPm && c[3] < 12 && (c[3] += 12), d.isPm === !1 && c[3] === 12 && (c[3] = 0), c[3] += d.tzh, c[4] += d.tzm, N(c, d.isUTC); + } + function Y(a, b) { + var c, d = a.match(o) || [], e, f = 99, g, h, i; + for (g = 0; g < b.length; g++) h = X(a, b[g]), e = U(new G(h), b[g]).match(o) || [], i = M(d, e), i < f && (f = i, c = h); + return c; + } + function Z(b) { + var c = "YYYY-MM-DDT", d; + if (w.exec(b)) { + for (d = 0; d < 4; d++) if (y[d][1].exec(b)) { + c += y[d][0]; + break; + } + return u.exec(b) ? X(b, c + " Z") : X(b, c); + } + return new a(b); + } + function $(a, b, c, d, e) { + var f = e.relativeTime[a]; + return typeof f == "function" ? f(b || 1, !!c, a, d) : f.replace(/%d/i, b || 1); + } + function _(a, b, c) { + var d = e(Math.abs(a) / 1e3), f = e(d / 60), g = e(f / 60), h = e(g / 24), i = e(h / 365), j = d < 45 && [ "s", d ] || f === 1 && [ "m" ] || f < 45 && [ "mm", f ] || g === 1 && [ "h" ] || g < 22 && [ "hh", g ] || h === 1 && [ "d" ] || h <= 25 && [ "dd", h ] || h <= 45 && [ "M" ] || h < 345 && [ "MM", e(h / 30) ] || i === 1 && [ "y" ] || [ "yy", i ]; + return j[2] = b, j[3] = a > 0, j[4] = c, $.apply({}, j); + } + function ab(a, b) { + c.fn[a] = function(a) { + var c = this._isUTC ? "UTC" : ""; + return a != null ? (this._d["set" + c + b](a), this) : this._d["get" + c + b](); + }; + } + function bb(a) { + c.duration.fn[a] = function() { + return this._data[a]; + }; + } + function cb(a, b) { + c.duration.fn["as" + a] = function() { + return +this / b; + }; + } + var c, d = "1.7.0", e = Math.round, f, g = {}, h = "en", i = typeof module != "undefined" && module.exports, j = "months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"), k = /^\/?Date\((\-?\d+)/i, l = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?)/g, m = /(LT|LL?L?L?)/g, n = /(^\[)|(\\)|\]$/g, o = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi, p = /\d\d?/, q = /\d{1,3}/, r = /\d{3}/, s = /\d{1,4}/, t = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, u = /Z|[\+\-]\d\d:?\d\d/i, v = /T/i, w = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/, x = "YYYY-MM-DDTHH:mm:ssZ", y = [ [ "HH:mm:ss.S", /T\d\d:\d\d:\d\d\.\d{1,3}/ ], [ "HH:mm:ss", /T\d\d:\d\d:\d\d/ ], [ "HH:mm", /T\d\d:\d\d/ ], [ "HH", /T\d\d/ ] ], z = /([\+\-]|\d\d)/gi, A = "Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"), B = { + Milliseconds: 1, + Seconds: 1e3, + Minutes: 6e4, + Hours: 36e5, + Days: 864e5, + Months: 2592e6, + Years: 31536e6 + }, C = {}, D = { + M: "(a=t.month()+1)", + MMM: 'v("monthsShort",t.month())', + MMMM: 'v("months",t.month())', + D: "(a=t.date())", + DDD: "(a=new Date(t.year(),t.month(),t.date()),b=new Date(t.year(),0,1),a=~~(((a-b)/864e5)+1.5))", + d: "(a=t.day())", + dd: 'v("weekdaysMin",t.day())', + ddd: 'v("weekdaysShort",t.day())', + dddd: 'v("weekdays",t.day())', + w: "(a=new Date(t.year(),t.month(),t.date()-t.day()+5),b=new Date(a.getFullYear(),0,4),a=~~((a-b)/864e5/7+1.5))", + YY: "p(t.year()%100,2)", + YYYY: "p(t.year(),4)", + a: "m(t.hours(),t.minutes(),!0)", + A: "m(t.hours(),t.minutes(),!1)", + H: "t.hours()", + h: "t.hours()%12||12", + m: "t.minutes()", + s: "t.seconds()", + S: "~~(t.milliseconds()/100)", + SS: "p(~~(t.milliseconds()/10),2)", + SSS: "p(t.milliseconds(),3)", + Z: '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(a/60),2)+":"+p(~~a%60,2)', + ZZ: '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(10*a/6),4)' + }, E = "DDD w M D d".split(" "), F = "M D H h m s w".split(" "); + while (E.length) f = E.pop(), D[f + "o"] = D[f] + "+o(a)"; + while (F.length) f = F.pop(), D[f + f] = "p(" + D[f] + ",2)"; + D.DDDD = "p(" + D.DDD + ",3)", c = function(d, e) { + if (d === null || d === "") return null; + var f, g; + return c.isMoment(d) ? new G(new a(+d._d), d._isUTC, d._lang) : (e ? L(e) ? f = Y(d, e) : f = X(d, e) : (g = k.exec(d), f = d === b ? new a : g ? new a(+g[1]) : d instanceof a ? d : L(d) ? N(d) : typeof d == "string" ? Z(d) : new a(d)), new G(f)); + }, c.utc = function(a, b) { + return L(a) ? new G(N(a, !0), !0) : (typeof a == "string" && !u.exec(a) && (a += " +0000", b && (b += " Z")), c(a, b).utc()); + }, c.unix = function(a) { + return c(a * 1e3); + }, c.duration = function(a, b) { + var d = c.isDuration(a), e = typeof a == "number", f = d ? a._data : e ? {} : a, g; + return e && (b ? f[b] = a : f.milliseconds = a), g = new H(f), d && (g._lang = a._lang), g; + }, c.humanizeDuration = function(a, b, d) { + return c.duration(a, b === !0 ? null : b).humanize(b === !0 ? !0 : d); + }, c.version = d, c.defaultFormat = x, c.lang = function(a, b) { + var d; + if (!a) return h; + (b || !g[a]) && O(a, b); + if (g[a]) { + for (d = 0; d < j.length; d++) c[j[d]] = g[a][j[d]]; + c.monthsParse = g[a].monthsParse, h = a; + } + }, c.langData = P, c.isMoment = function(a) { + return a instanceof G; + }, c.isDuration = function(a) { + return a instanceof H; + }, c.lang("en", { + months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort: "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin: "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat: { + LT: "h:mm A", + L: "MM/DD/YYYY", + LL: "MMMM D YYYY", + LLL: "MMMM D YYYY LT", + LLLL: "dddd, MMMM D YYYY LT" + }, + meridiem: function(a, b, c) { + return a > 11 ? c ? "pm" : "PM" : c ? "am" : "AM"; + }, + calendar: { + sameDay: "[Today at] LT", + nextDay: "[Tomorrow at] LT", + nextWeek: "dddd [at] LT", + lastDay: "[Yesterday at] LT", + lastWeek: "[last] dddd [at] LT", + sameElse: "L" + }, + relativeTime: { + future: "in %s", + past: "%s ago", + s: "a few seconds", + m: "a minute", + mm: "%d minutes", + h: "an hour", + hh: "%d hours", + d: "a day", + dd: "%d days", + M: "a month", + MM: "%d months", + y: "a year", + yy: "%d years" + }, + ordinal: function(a) { + var b = a % 10; + return ~~(a % 100 / 10) === 1 ? "th" : b === 1 ? "st" : b === 2 ? "nd" : b === 3 ? "rd" : "th"; + } + }), c.fn = G.prototype = { + clone: function() { + return c(this); + }, + valueOf: function() { + return +this._d; + }, + unix: function() { + return Math.floor(+this._d / 1e3); + }, + toString: function() { + return this._d.toString(); + }, + toDate: function() { + return this._d; + }, + toArray: function() { + var a = this; + return [ a.year(), a.month(), a.date(), a.hours(), a.minutes(), a.seconds(), a.milliseconds(), !!this._isUTC ]; + }, + isValid: function() { + return this._a ? !M(this._a, (this._a[7] ? c.utc(this) : this).toArray()) : !isNaN(this._d.getTime()); + }, + utc: function() { + return this._isUTC = !0, this; + }, + local: function() { + return this._isUTC = !1, this; + }, + format: function(a) { + return U(this, a ? a : c.defaultFormat); + }, + add: function(a, b) { + var d = b ? c.duration(+b, a) : c.duration(a); + return K(this, d, 1), this; + }, + subtract: function(a, b) { + var d = b ? c.duration(+b, a) : c.duration(a); + return K(this, d, -1), this; + }, + diff: function(a, b, d) { + var f = this._isUTC ? c(a).utc() : c(a).local(), g = (this.zone() - f.zone()) * 6e4, h = this._d - f._d - g, i = this.year() - f.year(), j = this.month() - f.month(), k = this.date() - f.date(), l; + return b === "months" ? l = i * 12 + j + k / 30 : b === "years" ? l = i + (j + k / 30) / 12 : l = b === "seconds" ? h / 1e3 : b === "minutes" ? h / 6e4 : b === "hours" ? h / 36e5 : b === "days" ? h / 864e5 : b === "weeks" ? h / 6048e5 : h, d ? l : e(l); + }, + from: function(a, b) { + return c.duration(this.diff(a)).lang(this._lang).humanize(!b); + }, + fromNow: function(a) { + return this.from(c(), a); + }, + calendar: function() { + var a = this.diff(c().sod(), "days", !0), b = this.lang().calendar, d = b.sameElse, e = a < -6 ? d : a < -1 ? b.lastWeek : a < 0 ? b.lastDay : a < 1 ? b.sameDay : a < 2 ? b.nextDay : a < 7 ? b.nextWeek : d; + return this.format(typeof e == "function" ? e.apply(this) : e); + }, + isLeapYear: function() { + var a = this.year(); + return a % 4 === 0 && a % 100 !== 0 || a % 400 === 0; + }, + isDST: function() { + return this.zone() < c([ this.year() ]).zone() || this.zone() < c([ this.year(), 5 ]).zone(); + }, + day: function(a) { + var b = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + return a == null ? b : this.add({ + d: a - b + }); + }, + startOf: function(a) { + switch (a.replace(/s$/, "")) { + case "year": + this.month(0); + case "month": + this.date(1); + case "day": + this.hours(0); + case "hour": + this.minutes(0); + case "minute": + this.seconds(0); + case "second": + this.milliseconds(0); + } + return this; + }, + endOf: function(a) { + return this.startOf(a).add(a.replace(/s?$/, "s"), 1).subtract("ms", 1); + }, + sod: function() { + return this.clone().startOf("day"); + }, + eod: function() { + return this.clone().endOf("day"); + }, + zone: function() { + return this._isUTC ? 0 : this._d.getTimezoneOffset(); + }, + daysInMonth: function() { + return c.utc([ this.year(), this.month() + 1, 0 ]).date(); + }, + lang: function(a) { + return a === b ? P(this) : (this._lang = a, this); + } + }; + for (f = 0; f < A.length; f++) ab(A[f].toLowerCase(), A[f]); + ab("year", "FullYear"), c.duration.fn = H.prototype = { + weeks: function() { + return I(this.days() / 7); + }, + valueOf: function() { + return this._milliseconds + this._days * 864e5 + this._months * 2592e6; + }, + humanize: function(a) { + var b = +this, c = this.lang().relativeTime, d = _(b, !a, this.lang()); + return a && (d = (b <= 0 ? c.past : c.future).replace(/%s/i, d)), d; + }, + lang: c.fn.lang + }; + for (f in B) B.hasOwnProperty(f) && (cb(f, B[f]), bb(f.toLowerCase())); + cb("Weeks", 6048e5), i && (module.exports = c), typeof ender == "undefined" && (this.moment = c), typeof define == "function" && define.amd && define("moment", [], function() { + return c; + }); +}).call(this, Date); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/moment.js b/node_modules/emailjs/node_modules/moment/moment.js new file mode 100644 index 0000000..95520c0 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/moment.js @@ -0,0 +1,1106 @@ +// moment.js +// version : 1.7.0 +// author : Tim Wood +// license : MIT +// momentjs.com + +(function (Date, undefined) { + + /************************************ + Constants + ************************************/ + + var moment, + VERSION = "1.7.0", + round = Math.round, i, + // internal storage for language config files + languages = {}, + currentLanguage = 'en', + + // check for nodeJS + hasModule = (typeof module !== 'undefined' && module.exports), + + // Parameters to check for on the lang config. This list of properties + // will be inherited from English if not provided in a language + // definition. monthsParse is also a lang config property, but it + // cannot be inherited and as such cannot be enumerated here. + langConfigProperties = 'months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'), + + // ASP.NET json date format regex + aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + + // format tokens + formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?)/g, + localFormattingTokens = /(LT|LL?L?L?)/g, + formattingRemoveEscapes = /(^\[)|(\\)|\]$/g, + + // parsing tokens + parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi, + + // parsing token regexes + parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 + parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 + parseTokenThreeDigits = /\d{3}/, // 000 - 999 + parseTokenFourDigits = /\d{1,4}/, // 0 - 9999 + parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers + parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z + parseTokenT = /T/i, // T (ISO seperator) + + // preliminary iso regex + // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 + isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/, + isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', + + // iso time formats and regexes + isoTimes = [ + ['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/], + ['HH:mm:ss', /T\d\d:\d\d:\d\d/], + ['HH:mm', /T\d\d:\d\d/], + ['HH', /T\d\d/] + ], + + // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, + + // getter and setter names + proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, + + // format function strings + formatFunctions = {}, + + /* + * moment.fn.format uses new Function() to create an inlined formatting function. + * Results are a 3x speed boost + * http://jsperf.com/momentjs-cached-format-functions + * + * These strings are appended into a function using replaceFormatTokens and makeFormatFunction + */ + formatFunctionStrings = { + // a = placeholder + // b = placeholder + // t = the current moment being formatted + // v = getValueAtKey function + // o = language.ordinal function + // p = leftZeroFill function + // m = language.meridiem value or function + M : '(a=t.month()+1)', + MMM : 'v("monthsShort",t.month())', + MMMM : 'v("months",t.month())', + D : '(a=t.date())', + DDD : '(a=new Date(t.year(),t.month(),t.date()),b=new Date(t.year(),0,1),a=~~(((a-b)/864e5)+1.5))', + d : '(a=t.day())', + dd : 'v("weekdaysMin",t.day())', + ddd : 'v("weekdaysShort",t.day())', + dddd : 'v("weekdays",t.day())', + w : '(a=new Date(t.year(),t.month(),t.date()-t.day()+5),b=new Date(a.getFullYear(),0,4),a=~~((a-b)/864e5/7+1.5))', + YY : 'p(t.year()%100,2)', + YYYY : 'p(t.year(),4)', + a : 'm(t.hours(),t.minutes(),!0)', + A : 'm(t.hours(),t.minutes(),!1)', + H : 't.hours()', + h : 't.hours()%12||12', + m : 't.minutes()', + s : 't.seconds()', + S : '~~(t.milliseconds()/100)', + SS : 'p(~~(t.milliseconds()/10),2)', + SSS : 'p(t.milliseconds(),3)', + Z : '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(a/60),2)+":"+p(~~a%60,2)', + ZZ : '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(10*a/6),4)' + }, + + ordinalizeTokens = 'DDD w M D d'.split(' '), + paddedTokens = 'M D H h m s w'.split(' '); + + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatFunctionStrings[i + 'o'] = formatFunctionStrings[i] + '+o(a)'; + } + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatFunctionStrings[i + i] = 'p(' + formatFunctionStrings[i] + ',2)'; + } + formatFunctionStrings.DDDD = 'p(' + formatFunctionStrings.DDD + ',3)'; + + + /************************************ + Constructors + ************************************/ + + + // Moment prototype object + function Moment(date, isUTC, lang) { + this._d = date; + this._isUTC = !!isUTC; + this._a = date._a || null; + date._a = null; + this._lang = lang || false; + } + + // Duration Constructor + function Duration(duration) { + var data = this._data = {}, + years = duration.years || duration.y || 0, + months = duration.months || duration.M || 0, + weeks = duration.weeks || duration.w || 0, + days = duration.days || duration.d || 0, + hours = duration.hours || duration.h || 0, + minutes = duration.minutes || duration.m || 0, + seconds = duration.seconds || duration.s || 0, + milliseconds = duration.milliseconds || duration.ms || 0; + + // representation for dateAddRemove + this._milliseconds = milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = months + + years * 12; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + seconds += absRound(milliseconds / 1000); + + data.seconds = seconds % 60; + minutes += absRound(seconds / 60); + + data.minutes = minutes % 60; + hours += absRound(minutes / 60); + + data.hours = hours % 24; + days += absRound(hours / 24); + + days += weeks * 7; + data.days = days % 30; + + months += absRound(days / 30); + + data.months = months % 12; + years += absRound(months / 12); + + data.years = years; + + this._lang = false; + } + + + /************************************ + Helpers + ************************************/ + + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength) { + var output = number + ''; + while (output.length < targetLength) { + output = '0' + output; + } + return output; + } + + // helper function for _.addTime and _.subtractTime + function addOrSubtractDurationFromMoment(mom, duration, isAdding) { + var ms = duration._milliseconds, + d = duration._days, + M = duration._months, + currentDate; + + if (ms) { + mom._d.setTime(+mom + ms * isAdding); + } + if (d) { + mom.date(mom.date() + d * isAdding); + } + if (M) { + currentDate = mom.date(); + mom.date(1) + .month(mom.month() + M * isAdding) + .date(Math.min(currentDate, mom.daysInMonth())); + } + } + + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if (~~array1[i] !== ~~array2[i]) { + diffs++; + } + } + return diffs + lengthDiff; + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromArray(input, asUTC) { + var i, date; + for (i = 1; i < 7; i++) { + input[i] = (input[i] == null) ? (i === 2 ? 1 : 0) : input[i]; + } + // we store whether we used utc or not in the input array + input[7] = asUTC; + date = new Date(0); + if (asUTC) { + date.setUTCFullYear(input[0], input[1], input[2]); + date.setUTCHours(input[3], input[4], input[5], input[6]); + } else { + date.setFullYear(input[0], input[1], input[2]); + date.setHours(input[3], input[4], input[5], input[6]); + } + date._a = input; + return date; + } + + // Loads a language definition into the `languages` cache. The function + // takes a key and optionally values. If not in the browser and no values + // are provided, it will load the language file module. As a convenience, + // this function also returns the language values. + function loadLang(key, values) { + var i, m, + parse = []; + + if (!values && hasModule) { + values = require('./lang/' + key); + } + + for (i = 0; i < langConfigProperties.length; i++) { + // If a language definition does not provide a value, inherit + // from English + values[langConfigProperties[i]] = values[langConfigProperties[i]] || + languages.en[langConfigProperties[i]]; + } + + for (i = 0; i < 12; i++) { + m = moment([2000, i]); + parse[i] = new RegExp('^' + (values.months[i] || values.months(m, '')) + + '|^' + (values.monthsShort[i] || values.monthsShort(m, '')).replace('.', ''), 'i'); + } + values.monthsParse = values.monthsParse || parse; + + languages[key] = values; + + return values; + } + + // Determines which language definition to use and returns it. + // + // With no parameters, it will return the global language. If you + // pass in a language key, such as 'en', it will return the + // definition for 'en', so long as 'en' has already been loaded using + // moment.lang. If you pass in a moment or duration instance, it + // will decide the language based on that, or default to the global + // language. + function getLangDefinition(m) { + var langKey = (typeof m === 'string') && m || + m && m._lang || + null; + + return langKey ? (languages[langKey] || loadLang(langKey)) : moment; + } + + + /************************************ + Formatting + ************************************/ + + + // helper for building inline formatting functions + function replaceFormatTokens(token) { + return formatFunctionStrings[token] ? + ("'+(" + formatFunctionStrings[token] + ")+'") : + token.replace(formattingRemoveEscapes, "").replace(/\\?'/g, "\\'"); + } + + // helper for recursing long date formatting tokens + function replaceLongDateFormatTokens(input) { + return getLangDefinition().longDateFormat[input] || input; + } + + function makeFormatFunction(format) { + var output = "var a,b;return '" + + format.replace(formattingTokens, replaceFormatTokens) + "';", + Fn = Function; // get around jshint + // t = the current moment being formatted + // v = getValueAtKey function + // o = language.ordinal function + // p = leftZeroFill function + // m = language.meridiem value or function + return new Fn('t', 'v', 'o', 'p', 'm', output); + } + + function makeOrGetFormatFunction(format) { + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + return formatFunctions[format]; + } + + // format date using native date object + function formatMoment(m, format) { + var lang = getLangDefinition(m); + + function getValueFromArray(key, index) { + return lang[key].call ? lang[key](m, format) : lang[key][index]; + } + + while (localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + } + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m, getValueFromArray, lang.ordinal, leftZeroFill, lang.meridiem); + } + + + /************************************ + Parsing + ************************************/ + + + // get the regex to find the next token + function getParseRegexForToken(token) { + switch (token) { + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + return parseTokenFourDigits; + case 'S': + case 'SS': + case 'SSS': + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + case 'a': + case 'A': + return parseTokenWord; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'MM': + case 'DD': + case 'YY': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + return parseTokenOneOrTwoDigits; + default : + return new RegExp(token.replace('\\', '')); + } + } + + // function to convert string input to date + function addTimeToArrayFromToken(token, input, datePartArray, config) { + var a; + //console.log('addTime', format, input); + switch (token) { + // MONTH + case 'M' : // fall through to MM + case 'MM' : + datePartArray[1] = (input == null) ? 0 : ~~input - 1; + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + for (a = 0; a < 12; a++) { + if (getLangDefinition().monthsParse[a].test(input)) { + datePartArray[1] = a; + break; + } + } + break; + // DAY OF MONTH + case 'D' : // fall through to DDDD + case 'DD' : // fall through to DDDD + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + datePartArray[2] = ~~input; + } + break; + // YEAR + case 'YY' : + input = ~~input; + datePartArray[0] = input + (input > 70 ? 1900 : 2000); + break; + case 'YYYY' : + datePartArray[0] = ~~Math.abs(input); + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config.isPm = ((input + '').toLowerCase() === 'pm'); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[3] = ~~input; + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[4] = ~~input; + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[5] = ~~input; + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + datePartArray[6] = ~~ (('0.' + input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config.isUTC = true; + a = (input + '').match(parseTimezoneChunker); + if (a && a[1]) { + config.tzh = ~~a[1]; + } + if (a && a[2]) { + config.tzm = ~~a[2]; + } + // reverse offsets + if (a && a[0] === '+') { + config.tzh = -config.tzh; + config.tzm = -config.tzm; + } + break; + } + } + + // date from string and format string + function makeDateFromStringAndFormat(string, format) { + var datePartArray = [0, 0, 1, 0, 0, 0, 0], + config = { + tzh : 0, // timezone hour offset + tzm : 0 // timezone minute offset + }, + tokens = format.match(formattingTokens), + i, parsedInput; + + for (i = 0; i < tokens.length; i++) { + parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0]; + string = string.replace(getParseRegexForToken(tokens[i]), ''); + addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config); + } + // handle am pm + if (config.isPm && datePartArray[3] < 12) { + datePartArray[3] += 12; + } + // if is 12 am, change hours to 0 + if (config.isPm === false && datePartArray[3] === 12) { + datePartArray[3] = 0; + } + // handle timezone + datePartArray[3] += config.tzh; + datePartArray[4] += config.tzm; + // return + return dateFromArray(datePartArray, config.isUTC); + } + + // date from string and array of format strings + function makeDateFromStringAndArray(string, formats) { + var output, + inputParts = string.match(parseMultipleFormatChunker) || [], + formattedInputParts, + scoreToBeat = 99, + i, + currentDate, + currentScore; + for (i = 0; i < formats.length; i++) { + currentDate = makeDateFromStringAndFormat(string, formats[i]); + formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || []; + currentScore = compareArrays(inputParts, formattedInputParts); + if (currentScore < scoreToBeat) { + scoreToBeat = currentScore; + output = currentDate; + } + } + return output; + } + + // date from iso format + function makeDateFromString(string) { + var format = 'YYYY-MM-DDT', + i; + if (isoRegex.exec(string)) { + for (i = 0; i < 4; i++) { + if (isoTimes[i][1].exec(string)) { + format += isoTimes[i][0]; + break; + } + } + return parseTokenTimezone.exec(string) ? + makeDateFromStringAndFormat(string, format + ' Z') : + makeDateFromStringAndFormat(string, format); + } + return new Date(string); + } + + + /************************************ + Relative Time + ************************************/ + + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { + var rt = lang.relativeTime[string]; + return (typeof rt === 'function') ? + rt(number || 1, !!withoutSuffix, string, isFuture) : + rt.replace(/%d/i, number || 1); + } + + function relativeTime(milliseconds, withoutSuffix, lang) { + var seconds = round(Math.abs(milliseconds) / 1000), + minutes = round(seconds / 60), + hours = round(minutes / 60), + days = round(hours / 24), + years = round(days / 365), + args = seconds < 45 && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < 45 && ['mm', minutes] || + hours === 1 && ['h'] || + hours < 22 && ['hh', hours] || + days === 1 && ['d'] || + days <= 25 && ['dd', days] || + days <= 45 && ['M'] || + days < 345 && ['MM', round(days / 30)] || + years === 1 && ['y'] || ['yy', years]; + args[2] = withoutSuffix; + args[3] = milliseconds > 0; + args[4] = lang; + return substituteTimeAgo.apply({}, args); + } + + + /************************************ + Top Level Functions + ************************************/ + + + moment = function (input, format) { + if (input === null || input === '') { + return null; + } + var date, + matched; + // parse Moment object + if (moment.isMoment(input)) { + return new Moment(new Date(+input._d), input._isUTC, input._lang); + // parse string and format + } else if (format) { + if (isArray(format)) { + date = makeDateFromStringAndArray(input, format); + } else { + date = makeDateFromStringAndFormat(input, format); + } + // evaluate it as a JSON-encoded date + } else { + matched = aspNetJsonRegex.exec(input); + date = input === undefined ? new Date() : + matched ? new Date(+matched[1]) : + input instanceof Date ? input : + isArray(input) ? dateFromArray(input) : + typeof input === 'string' ? makeDateFromString(input) : + new Date(input); + } + + return new Moment(date); + }; + + // creating with utc + moment.utc = function (input, format) { + if (isArray(input)) { + return new Moment(dateFromArray(input, true), true); + } + // if we don't have a timezone, we need to add one to trigger parsing into utc + if (typeof input === 'string' && !parseTokenTimezone.exec(input)) { + input += ' +0000'; + if (format) { + format += ' Z'; + } + } + return moment(input, format).utc(); + }; + + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; + + // duration + moment.duration = function (input, key) { + var isDuration = moment.isDuration(input), + isNumber = (typeof input === 'number'), + duration = (isDuration ? input._data : (isNumber ? {} : input)), + ret; + + if (isNumber) { + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } + + ret = new Duration(duration); + + if (isDuration) { + ret._lang = input._lang; + } + + return ret; + }; + + // humanizeDuration + // This method is deprecated in favor of the new Duration object. Please + // see the moment.duration method. + moment.humanizeDuration = function (num, type, withSuffix) { + return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix); + }; + + // version number + moment.version = VERSION; + + // default format + moment.defaultFormat = isoFormat; + + // This function will load languages and then set the global language. If + // no arguments are passed in, it will simply return the current global + // language key. + moment.lang = function (key, values) { + var i; + + if (!key) { + return currentLanguage; + } + if (values || !languages[key]) { + loadLang(key, values); + } + if (languages[key]) { + // deprecated, to get the language definition variables, use the + // moment.fn.lang method or the getLangDefinition function. + for (i = 0; i < langConfigProperties.length; i++) { + moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]]; + } + moment.monthsParse = languages[key].monthsParse; + currentLanguage = key; + } + }; + + // returns language data + moment.langData = getLangDefinition; + + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment; + }; + + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; + + // Set default language, other languages will inherit from English. + moment.lang('en', { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "MM/DD/YYYY", + LL : "MMMM D YYYY", + LLL : "MMMM D YYYY LT", + LLLL : "dddd, MMMM D YYYY LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10; + return (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + } + }); + + + /************************************ + Moment Prototype + ************************************/ + + + moment.fn = Moment.prototype = { + + clone : function () { + return moment(this); + }, + + valueOf : function () { + return +this._d; + }, + + unix : function () { + return Math.floor(+this._d / 1000); + }, + + toString : function () { + return this._d.toString(); + }, + + toDate : function () { + return this._d; + }, + + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds(), + !!this._isUTC + ]; + }, + + isValid : function () { + if (this._a) { + return !compareArrays(this._a, (this._a[7] ? moment.utc(this) : this).toArray()); + } + return !isNaN(this._d.getTime()); + }, + + utc : function () { + this._isUTC = true; + return this; + }, + + local : function () { + this._isUTC = false; + return this; + }, + + format : function (inputString) { + return formatMoment(this, inputString ? inputString : moment.defaultFormat); + }, + + add : function (input, val) { + var dur = val ? moment.duration(+val, input) : moment.duration(input); + addOrSubtractDurationFromMoment(this, dur, 1); + return this; + }, + + subtract : function (input, val) { + var dur = val ? moment.duration(+val, input) : moment.duration(input); + addOrSubtractDurationFromMoment(this, dur, -1); + return this; + }, + + diff : function (input, val, asFloat) { + var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(), + zoneDiff = (this.zone() - inputMoment.zone()) * 6e4, + diff = this._d - inputMoment._d - zoneDiff, + year = this.year() - inputMoment.year(), + month = this.month() - inputMoment.month(), + date = this.date() - inputMoment.date(), + output; + if (val === 'months') { + output = year * 12 + month + date / 30; + } else if (val === 'years') { + output = year + (month + date / 30) / 12; + } else { + output = val === 'seconds' ? diff / 1e3 : // 1000 + val === 'minutes' ? diff / 6e4 : // 1000 * 60 + val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60 + val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24 + val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7 + diff; + } + return asFloat ? output : round(output); + }, + + from : function (time, withoutSuffix) { + return moment.duration(this.diff(time)).lang(this._lang).humanize(!withoutSuffix); + }, + + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, + + calendar : function () { + var diff = this.diff(moment().sod(), 'days', true), + calendar = this.lang().calendar, + allElse = calendar.sameElse, + format = diff < -6 ? allElse : + diff < -1 ? calendar.lastWeek : + diff < 0 ? calendar.lastDay : + diff < 1 ? calendar.sameDay : + diff < 2 ? calendar.nextDay : + diff < 7 ? calendar.nextWeek : allElse; + return this.format(typeof format === 'function' ? format.apply(this) : format); + }, + + isLeapYear : function () { + var year = this.year(); + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + }, + + isDST : function () { + return (this.zone() < moment([this.year()]).zone() || + this.zone() < moment([this.year(), 5]).zone()); + }, + + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + return input == null ? day : + this.add({ d : input - day }); + }, + + startOf: function (val) { + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (val.replace(/s$/, '')) { + case 'year': + this.month(0); + /* falls through */ + case 'month': + this.date(1); + /* falls through */ + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } + return this; + }, + + endOf: function (val) { + return this.startOf(val).add(val.replace(/s?$/, 's'), 1).subtract('ms', 1); + }, + + sod: function () { + return this.clone().startOf('day'); + }, + + eod: function () { + // end of day = start of day plus 1 day, minus 1 millisecond + return this.clone().endOf('day'); + }, + + zone : function () { + return this._isUTC ? 0 : this._d.getTimezoneOffset(); + }, + + daysInMonth : function () { + return moment.utc([this.year(), this.month() + 1, 0]).date(); + }, + + // If passed a language key, it will set the language for this + // instance. Otherwise, it will return the language configuration + // variables for this instance. + lang : function (lang) { + if (lang === undefined) { + return getLangDefinition(this); + } else { + this._lang = lang; + return this; + } + } + }; + + // helper for adding shortcuts + function makeGetterAndSetter(name, key) { + moment.fn[name] = function (input) { + var utc = this._isUTC ? 'UTC' : ''; + if (input != null) { + this._d['set' + utc + key](input); + return this; + } else { + return this._d['get' + utc + key](); + } + }; + } + + // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds) + for (i = 0; i < proxyGettersAndSetters.length; i ++) { + makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]); + } + + // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') + makeGetterAndSetter('year', 'FullYear'); + + + /************************************ + Duration Prototype + ************************************/ + + + moment.duration.fn = Duration.prototype = { + weeks : function () { + return absRound(this.days() / 7); + }, + + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + this._months * 2592e6; + }, + + humanize : function (withSuffix) { + var difference = +this, + rel = this.lang().relativeTime, + output = relativeTime(difference, !withSuffix, this.lang()); + + if (withSuffix) { + output = (difference <= 0 ? rel.past : rel.future).replace(/%s/i, output); + } + + return output; + }, + + lang : moment.fn.lang + }; + + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; + } + + function makeDurationAsGetter(name, factor) { + moment.duration.fn['as' + name] = function () { + return +this / factor; + }; + } + + for (i in unitMillisecondFactors) { + if (unitMillisecondFactors.hasOwnProperty(i)) { + makeDurationAsGetter(i, unitMillisecondFactors[i]); + makeDurationGetter(i.toLowerCase()); + } + } + + makeDurationAsGetter('Weeks', 6048e5); + + + /************************************ + Exposing Moment + ************************************/ + + + // CommonJS module is defined + if (hasModule) { + module.exports = moment; + } + /*global ender:false */ + if (typeof ender === 'undefined') { + // here, `this` means `window` in the browser, or `global` on the server + // add `moment` as a global object via a string identifier, + // for Closure Compiler "advanced" mode + this['moment'] = moment; + } + /*global define:false */ + if (typeof define === "function" && define.amd) { + define("moment", [], function () { + return moment; + }); + } +}).call(this, Date); diff --git a/node_modules/emailjs/node_modules/moment/package.json b/node_modules/emailjs/node_modules/moment/package.json new file mode 100755 index 0000000..2a221c0 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/package.json @@ -0,0 +1,61 @@ +{ + "name": "moment", + "version": "1.7.0", + "description": "Parse, manipulate, and display dates.", + "homepage": "http://momentjs.com", + "author": { + "name": "Tim Wood", + "email": "washwithcare@gmail.com", + "url": "http://timwoodcreates.com/" + }, + "contributors": [ + { + "name": "Rocky Meza", + "url": "http://rockymeza.com" + } + ], + "keywords": [ + "moment", + "date", + "time", + "parse", + "format", + "validate", + "i18n", + "l10n", + "ender" + ], + "main": "./moment.js", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/timrwood/moment.git" + }, + "bugs": { + "url": "https://github.com/timrwood/moment/issues" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "devDependencies": { + "jshint": "latest", + "uglify-js": "latest", + "nodeunit": "latest" + }, + "scripts": { + "test": "make test" + }, + "ender": "./ender.js", + "readme": "[Moment.js](http://momentjs.com)\n================================\n\nA lightweight javascript date library for parsing, validating, manipulating, and formatting dates.\n\n### [Check out the website](http://momentjs.com)\n\n### [Read the documentation](http://momentjs.com/docs/)\n\n### [Run the unit tests](http://momentjs.com/test/)\n\n\nUpgrading to 1.6.0\n==================\n\nThere are a few things being deprecated in the 1.6.0 release.\n\n1. The format tokens `z` and `zz` (timezone abbreviations like EST CST MST etc) will no longer be supported. Due to inconsistent browser support, we are unable to consistently produce this value. See [this issue](https://github.com/timrwood/moment/issues/162) for more background.\n\n2. The method `moment.fn.native` is deprecated in favor of `moment.fn.toDate`. There continue to be issues with Google Closure Compiler throwing errors when using `native`, even in valid instances.\n\n3. The way to customize am/pm strings is being changed. This would only affect you if you created a custom language file. For more information, see [this issue](https://github.com/timrwood/moment/pull/222).\n\n\nContributing\n============\n\nTo contribute, fork the library and install these npm packages.\n\n npm install jshint uglify-js nodeunit\n\nYou can add tests to the files in `/test/moment` or add a new test file if you are adding a new feature.\n\nTo run the tests, do `make test` to run all tests, `make test-moment` to test the core library, and `make test-lang` to test all the languages.\n\nTo check the filesize, you can use `make size`.\n\nTo minify all the files, use `make moment` to minify moment, `make langs` to minify all the lang files, or just `make` to minfy everything.\n\nIf your code passes the unit tests (including the ones you wrote), submit a pull request.\n\nSubmitting pull requests\n========================\n\nMoment.js now uses [git-flow](https://github.com/nvie/gitflow). If you're not familiar with git-flow, please read up on it, you'll be glad you did.\n\nWhen submitting new features, please create a new feature branch using `git flow feature start ` and submit the pull request to the `develop` branch.\n\nPull requests for enhancements for features should be submitted to the `develop` branch as well.\n\nWhen submitting a bugfix, please check if there is an existing bugfix branch. If the latest stable version is `1.5.0`, the bugfix branch would be `hotfix/1.5.1`. All pull requests for bug fixes should be on a `hotfix` branch, unless the bug fix depends on a new feature.\n\nThe `master` branch should always have the latest stable version. When bugfix or minor releases are needed, the develop/hotfix branch will be merged into master and released.\n\nChangelog\n=========\n\n\n### 1.7.0 [See discussion](https://github.com/timrwood/moment/issues/288)\n\nAdded `moment.fn.endOf()` and `moment.fn.startOf()`.\n\nAdded validation via `moment.fn.isValid()`.\n\nMade formatting method 3x faster. http://jsperf.com/momentjs-cached-format-functions\n\nAdd support for month/weekday callbacks in `moment.fn.format()`\n\nAdded instance specific languages.\n\nAdded two letter weekday abbreviations with the formatting token `dd`.\n\nVarious language updates.\n\nVarious bugfixes.\n\n### 1.6.0 [See discussion](https://github.com/timrwood/moment/pull/268)\n\nAdded Durations.\n\nRevamped parser to support parsing non-separated strings (YYYYMMDD vs YYYY-MM-DD).\n\nAdded support for millisecond parsing and formatting tokens (S SS SSS)\n\nAdded a getter for `moment.lang()`\n\nVarious bugfixes.\n\n### 1.5.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=10&page=1&state=closed)\n\nAdded UTC mode.\n\nAdded automatic ISO8601 parsing.\n\nVarious bugfixes.\n\n### 1.4.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=8&state=closed)\n\nAdded `moment.fn.toDate` as a replacement for `moment.fn.native`.\n\nAdded `moment.fn.sod` and `moment.fn.eod` to get the start and end of day.\n\nVarious bugfixes.\n\n### 1.3.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=7&state=closed)\n\nAdded support for parsing month names in the current language.\n\nAdded escape blocks for parsing tokens.\n\nAdded `moment.fn.calendar` to format strings like 'Today 2:30 PM', 'Tomorrow 1:25 AM', and 'Last Sunday 4:30 AM'.\n\nAdded `moment.fn.day` as a setter.\n\nVarious bugfixes\n\n### 1.2.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=4&state=closed)\n\nAdded timezones to parser and formatter.\n\nAdded `moment.fn.isDST`.\n\nAdded `moment.fn.zone` to get the timezone offset in minutes.\n\n### 1.1.2 [See milestone](https://github.com/timrwood/moment/issues?milestone=6&state=closed)\n\nVarious bugfixes\n\n### 1.1.1 [See milestone](https://github.com/timrwood/moment/issues?milestone=5&state=closed)\n\nAdded time specific diffs (months, days, hours, etc)\n\n### 1.1.0\n\nAdded `moment.fn.format` localized masks. 'L LL LLL LLLL' [issue 29](https://github.com/timrwood/moment/pull/29)\n\nFixed [issue 31](https://github.com/timrwood/moment/pull/31).\n\n### 1.0.1\n\nAdded `moment.version` to get the current version.\n\nRemoved `window !== undefined` when checking if module exists to support browserify. [issue 25](https://github.com/timrwood/moment/pull/25)\n\n### 1.0.0\n\nAdded convenience methods for getting and setting date parts.\n\nAdded better support for `moment.add()`.\n\nAdded better lang support in NodeJS.\n\nRenamed library from underscore.date to Moment.js\n\n### 0.6.1\n\nAdded Portuguese, Italian, and French language support\n\n### 0.6.0\n\nAdded _date.lang() support.\nAdded support for passing multiple formats to try to parse a date. _date(\"07-10-1986\", [\"MM-DD-YYYY\", \"YYYY-MM-DD\"]);\nMade parse from string and single format 25% faster.\n\n### 0.5.2 \n\nBuxfix for [issue 8](https://github.com/timrwood/underscore.date/pull/8) and [issue 9](https://github.com/timrwood/underscore.date/pull/9).\n\n### 0.5.1 \n\nBuxfix for [issue 5](https://github.com/timrwood/underscore.date/pull/5).\n\n### 0.5.0\n\nDropped the redundant `_date.date()` in favor of `_date()`.\nRemoved `_date.now()`, as it is a duplicate of `_date()` with no parameters.\nRemoved `_date.isLeapYear(yearNuumber)`. Use `_date([yearNumber]).isLeapYear()` instead.\nExposed customization options through the `_date.relativeTime`, `_date.weekdays`, `_date.weekdaysShort`, `_date.months`, `_date.monthsShort`, and `_date.ordinal` variables instead of the `_date.customize()` function.\n\n### 0.4.1 \n\nAdded date input formats for input strings.\n\n### 0.4.0 \n\nAdded underscore.date to npm. Removed dependancies on underscore.\n\n### 0.3.2\n\nAdded `'z'` and `'zz'` to `_.date().format()`. Cleaned up some redundant code to trim off some bytes.\n\n### 0.3.1\n\nCleaned up the namespace. Moved all date manipulation and display functions to the _.date() object. \n\n### 0.3.0\n\nSwitched to the Underscore methodology of not mucking with the native objects' prototypes.\nMade chaining possible.\n\n### 0.2.1\n\nChanged date names to be a more pseudo standardized 'dddd, MMMM Do YYYY, h:mm:ss a'.\nAdded `Date.prototype` functions `add`, `subtract`, `isdst`, and `isleapyear`.\n\n### 0.2.0\n\nChanged function names to be more concise.\nChanged date format from php date format to custom format.\n\n### 0.1.0\n\nInitial release\n\nLicense\n=======\n\nMoment.js is freely distributable under the terms of the MIT license.\n\nCopyright (c) 2011-2012 Tim Wood\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use,\ncopy, 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.", + "readmeFilename": "readme.md", + "_id": "moment@1.7.0", + "dist": { + "shasum": "df72acd4aa40b23faff93bdf063bd427ac2979df" + }, + "_from": "moment@= 1.7.0", + "_resolved": "https://registry.npmjs.org/moment/-/moment-1.7.0.tgz" +} diff --git a/node_modules/emailjs/node_modules/moment/readme.md b/node_modules/emailjs/node_modules/moment/readme.md new file mode 100755 index 0000000..a037921 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/readme.md @@ -0,0 +1,228 @@ +[Moment.js](http://momentjs.com) +================================ + +A lightweight javascript date library for parsing, validating, manipulating, and formatting dates. + +### [Check out the website](http://momentjs.com) + +### [Read the documentation](http://momentjs.com/docs/) + +### [Run the unit tests](http://momentjs.com/test/) + + +Upgrading to 1.6.0 +================== + +There are a few things being deprecated in the 1.6.0 release. + +1. The format tokens `z` and `zz` (timezone abbreviations like EST CST MST etc) will no longer be supported. Due to inconsistent browser support, we are unable to consistently produce this value. See [this issue](https://github.com/timrwood/moment/issues/162) for more background. + +2. The method `moment.fn.native` is deprecated in favor of `moment.fn.toDate`. There continue to be issues with Google Closure Compiler throwing errors when using `native`, even in valid instances. + +3. The way to customize am/pm strings is being changed. This would only affect you if you created a custom language file. For more information, see [this issue](https://github.com/timrwood/moment/pull/222). + + +Contributing +============ + +To contribute, fork the library and install these npm packages. + + npm install jshint uglify-js nodeunit + +You can add tests to the files in `/test/moment` or add a new test file if you are adding a new feature. + +To run the tests, do `make test` to run all tests, `make test-moment` to test the core library, and `make test-lang` to test all the languages. + +To check the filesize, you can use `make size`. + +To minify all the files, use `make moment` to minify moment, `make langs` to minify all the lang files, or just `make` to minfy everything. + +If your code passes the unit tests (including the ones you wrote), submit a pull request. + +Submitting pull requests +======================== + +Moment.js now uses [git-flow](https://github.com/nvie/gitflow). If you're not familiar with git-flow, please read up on it, you'll be glad you did. + +When submitting new features, please create a new feature branch using `git flow feature start ` and submit the pull request to the `develop` branch. + +Pull requests for enhancements for features should be submitted to the `develop` branch as well. + +When submitting a bugfix, please check if there is an existing bugfix branch. If the latest stable version is `1.5.0`, the bugfix branch would be `hotfix/1.5.1`. All pull requests for bug fixes should be on a `hotfix` branch, unless the bug fix depends on a new feature. + +The `master` branch should always have the latest stable version. When bugfix or minor releases are needed, the develop/hotfix branch will be merged into master and released. + +Changelog +========= + + +### 1.7.0 [See discussion](https://github.com/timrwood/moment/issues/288) + +Added `moment.fn.endOf()` and `moment.fn.startOf()`. + +Added validation via `moment.fn.isValid()`. + +Made formatting method 3x faster. http://jsperf.com/momentjs-cached-format-functions + +Add support for month/weekday callbacks in `moment.fn.format()` + +Added instance specific languages. + +Added two letter weekday abbreviations with the formatting token `dd`. + +Various language updates. + +Various bugfixes. + +### 1.6.0 [See discussion](https://github.com/timrwood/moment/pull/268) + +Added Durations. + +Revamped parser to support parsing non-separated strings (YYYYMMDD vs YYYY-MM-DD). + +Added support for millisecond parsing and formatting tokens (S SS SSS) + +Added a getter for `moment.lang()` + +Various bugfixes. + +### 1.5.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=10&page=1&state=closed) + +Added UTC mode. + +Added automatic ISO8601 parsing. + +Various bugfixes. + +### 1.4.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=8&state=closed) + +Added `moment.fn.toDate` as a replacement for `moment.fn.native`. + +Added `moment.fn.sod` and `moment.fn.eod` to get the start and end of day. + +Various bugfixes. + +### 1.3.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=7&state=closed) + +Added support for parsing month names in the current language. + +Added escape blocks for parsing tokens. + +Added `moment.fn.calendar` to format strings like 'Today 2:30 PM', 'Tomorrow 1:25 AM', and 'Last Sunday 4:30 AM'. + +Added `moment.fn.day` as a setter. + +Various bugfixes + +### 1.2.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=4&state=closed) + +Added timezones to parser and formatter. + +Added `moment.fn.isDST`. + +Added `moment.fn.zone` to get the timezone offset in minutes. + +### 1.1.2 [See milestone](https://github.com/timrwood/moment/issues?milestone=6&state=closed) + +Various bugfixes + +### 1.1.1 [See milestone](https://github.com/timrwood/moment/issues?milestone=5&state=closed) + +Added time specific diffs (months, days, hours, etc) + +### 1.1.0 + +Added `moment.fn.format` localized masks. 'L LL LLL LLLL' [issue 29](https://github.com/timrwood/moment/pull/29) + +Fixed [issue 31](https://github.com/timrwood/moment/pull/31). + +### 1.0.1 + +Added `moment.version` to get the current version. + +Removed `window !== undefined` when checking if module exists to support browserify. [issue 25](https://github.com/timrwood/moment/pull/25) + +### 1.0.0 + +Added convenience methods for getting and setting date parts. + +Added better support for `moment.add()`. + +Added better lang support in NodeJS. + +Renamed library from underscore.date to Moment.js + +### 0.6.1 + +Added Portuguese, Italian, and French language support + +### 0.6.0 + +Added _date.lang() support. +Added support for passing multiple formats to try to parse a date. _date("07-10-1986", ["MM-DD-YYYY", "YYYY-MM-DD"]); +Made parse from string and single format 25% faster. + +### 0.5.2 + +Buxfix for [issue 8](https://github.com/timrwood/underscore.date/pull/8) and [issue 9](https://github.com/timrwood/underscore.date/pull/9). + +### 0.5.1 + +Buxfix for [issue 5](https://github.com/timrwood/underscore.date/pull/5). + +### 0.5.0 + +Dropped the redundant `_date.date()` in favor of `_date()`. +Removed `_date.now()`, as it is a duplicate of `_date()` with no parameters. +Removed `_date.isLeapYear(yearNuumber)`. Use `_date([yearNumber]).isLeapYear()` instead. +Exposed customization options through the `_date.relativeTime`, `_date.weekdays`, `_date.weekdaysShort`, `_date.months`, `_date.monthsShort`, and `_date.ordinal` variables instead of the `_date.customize()` function. + +### 0.4.1 + +Added date input formats for input strings. + +### 0.4.0 + +Added underscore.date to npm. Removed dependancies on underscore. + +### 0.3.2 + +Added `'z'` and `'zz'` to `_.date().format()`. Cleaned up some redundant code to trim off some bytes. + +### 0.3.1 + +Cleaned up the namespace. Moved all date manipulation and display functions to the _.date() object. + +### 0.3.0 + +Switched to the Underscore methodology of not mucking with the native objects' prototypes. +Made chaining possible. + +### 0.2.1 + +Changed date names to be a more pseudo standardized 'dddd, MMMM Do YYYY, h:mm:ss a'. +Added `Date.prototype` functions `add`, `subtract`, `isdst`, and `isleapyear`. + +### 0.2.0 + +Changed function names to be more concise. +Changed date format from php date format to custom format. + +### 0.1.0 + +Initial release + +License +======= + +Moment.js is freely distributable under the terms of the MIT license. + +Copyright (c) 2011-2012 Tim Wood + +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. \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/test/filesize-diff.js b/node_modules/emailjs/node_modules/moment/test/filesize-diff.js new file mode 100644 index 0000000..6c18e3e --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/filesize-diff.js @@ -0,0 +1,55 @@ +var https = require("https"), + zlib = require('zlib'), + path = require('path'), + fs = require('fs'); + + +var stable = '1.6.2'; + +function getVersion(path, cb) { + var data = '', + + req = https.request({ + host: 'raw.github.com', + port: 443, + path: '/timrwood/moment/' + path + }, function(res) { + res.setEncoding('utf8'); + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function(e) { + zlib.gzip(data, function(error, result) { + cb(data.length, result.length); + }); + }); + }); + req.on('error', function(e) { + console.log('problem with request: ' + e.message); + }); + req.end(); +} + +function printDiffs(stableLen, stableGzip, currentLen, currentGzip) { + var diff = currentLen - stableLen, + gzipDiff = currentGzip - stableGzip; + + console.log("Filesize difference from current branch to " + stable); + console.log(stable + " " + stableLen + ' / ' + stableGzip); + console.log("curr " + currentLen + ' / ' + currentGzip); + console.log("diff " + (diff > 0 ? '+' : '') + diff); + console.log("gzip " + (gzipDiff > 0 ? '+' : '') + gzipDiff); +} + +(function(){ + fs.readFile(path.normalize(__dirname + '/../min/moment.min.js'), 'utf8', function(err, data){ + if (err) { + throw err; + } + zlib.gzip(data, function(error, result) { + getVersion(stable + '/min/moment.min.js', function (stableLength, stableGzipLength) { + printDiffs(stableLength, stableGzipLength, data.length, result.length); + }); + }); + }); +}()); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/test/filesize-history.js b/node_modules/emailjs/node_modules/moment/test/filesize-history.js new file mode 100644 index 0000000..f78f1fb --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/filesize-history.js @@ -0,0 +1,108 @@ +var https = require("https"), + zlib = require('zlib'), + path = require('path'), + fs = require('fs'); + +var count = 0; +var resolved = 0; + +var outputs = []; + +function check() { + if (resolved === count) { + normalize(); + display(); + } +} + +function makeBar(length) { + var i = ''; + while (i.length < length) { + i += '='; + } + return i; +} + +function normalize() { + var i, + max = 0, + max2 = 0; + for (i = 0; i < count; i ++) { + max = Math.max(max, outputs[i].gzip); + max2 = Math.max(max2, outputs[i].original); + } + for (i = 0; i < count; i ++) { + outputs[i].bargraph = makeBar((outputs[i].gzip / max) * 80); + outputs[i].bargraph2 = makeBar((outputs[i].original / max2) * 80); + } +} + +function display() { + var i; + for (i = 0; i < count; i ++) { + console.log(outputs[i].version + ' ' + outputs[i].gzip + ' ' + outputs[i].original); + console.log('gzip ' + outputs[i].bargraph); + console.log('orig ' + outputs[i].bargraph2); + } +} + +function getSizeAtVersion(version, path) { + var data = ''; + var op = {}; + + var req = https.request({ + host: 'raw.github.com', + port: 443, + path: '/timrwood/moment/' + version + path + }, function(res) { + res.setEncoding('utf8'); + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function(e) { + zlib.gzip(data, function(error, result) { + op.version = version; + op.gzip = result.length; + op.original = data.length; + resolved ++; + check(); + }); + }); + }); + + req.on('error', function(e) { + console.log('problem with request: ' + e.message); + }); + req.end(); + count++; + outputs.push(op); +} + +(function(){ + var old_versions = '1.0.1 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.4.0'.split(' '); + var new_versions = '1.5.0 1.5.1 1.6.0 1.6.1'.split(' '); + var i; + + for (i = 0; i < old_versions.length; i++) { + getSizeAtVersion(old_versions[i], '/moment.min.js'); + } + for (i = 0; i < new_versions.length; i++) { + getSizeAtVersion(new_versions[i], '/min/moment.min.js'); + } +}()); + +(function(){ + count ++; + var op = {}; + outputs.push(op); + fs.readFile(path.normalize(__dirname + '/../min/moment.min.js'), 'utf8', function(err, data){ + if (err) throw err; + zlib.gzip(data, function(error, result) { + op.version = '.next'; + op.gzip = result.length; + op.original = data.length; + resolved ++; + check(); + }); + }); +}()); \ No newline at end of file diff --git a/node_modules/emailjs/node_modules/moment/test/lang/bg.js b/node_modules/emailjs/node_modules/moment/test/lang/bg.js new file mode 100644 index 0000000..732d84f --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/bg.js @@ -0,0 +1,265 @@ +var moment = require("../../moment"); + + + /************************************************** + Bulgarian + *************************************************/ + +exports["lang:bg"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('bg'); + var tests = 'януари янр_февруари фев_март мар_април апр_май май_юни юни_юли юли_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('bg'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'неделя, февруари 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'нед, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 февруари фев'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. неделя нед нд'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '14.02.2010'], + ['LL', '14 февруари 2010'], + ['LLL', '14 февруари 2010 3:25'], + ['LLLL', 'неделя, 14 февруари 2010 3:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('bg'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('bg'); + var expected = 'януари янр_февруари фев_март мар_април апр_май май_юни юни_юли юли_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('bg'); + var expected = 'неделя нед нд_понеделник пон пн_вторник вто вт_сряда сря ср_четвъртък чет чт_петък пет пт_събота съб сб'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('bg'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "няколко секунди", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "минута", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "минута", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 минути", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 минути", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "час", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "час", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 часа", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 часа", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 часа", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "ден", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "ден", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 дни", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "ден", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 дни", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 дни", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "месец", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "месец", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "месец", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 месеца", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 месеца", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 месеца", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "месец", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 месеца", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 месеца", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "година", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "година", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 години", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "година", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 години", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('bg'); + test.equal(moment(30000).from(0), "след няколко секунди", "prefix"); + test.equal(moment(0).from(30000), "преди няколко секунди", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('bg'); + test.equal(moment().fromNow(), "преди няколко секунди", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('bg'); + test.equal(moment().add({s:30}).fromNow(), "след няколко секунди", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "след 5 дни", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('bg'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Днес в 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Днес в 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Днес в 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Утре в 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Днес в 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Вчера в 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('bg'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [в] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [в] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [в] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('bg'); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('bg'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/ca.js b/node_modules/emailjs/node_modules/moment/test/lang/ca.js new file mode 100644 index 0000000..ac7377d --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/ca.js @@ -0,0 +1,221 @@ +var moment = require("../../moment"); + + + /************************************************** + Català + *************************************************/ + +exports["lang:ca"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('ca'); + + var tests = "Gener Gen._Febrer Febr._Març Mar._Abril Abr._Maig Mai._Juny Jun._Juliol Jul._Agost Ag._Setembre Set._Octubre Oct._Novembre Nov._Desembre Des.".split("_"); + + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('ca'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('ca'); + var expected = "Gener Gen._Febrer Febr._Març Mar._Abril Abr._Maig Mai._Juny Jun._Juliol Jul._Agost Ag._Setembre Set._Octubre Oct._Novembre Nov._Desembre Des.".split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('ca'); + var expected = "Diumenge Dg. Dg_Dilluns Dl. Dl_Dimarts Dt. Dt_Dimecres Dc. Dc_Dijous Dj. Dj_Divendres Dv. Dv_Dissabte Ds. Ds".split("_"); + + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('ca'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "uns segons", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuts", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuts", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "una hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "una hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hores", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hores", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hores", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un dia", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un dia", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dies", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un dia", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dies", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dies", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mes", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mes", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mes", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mesos", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mesos", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mesos", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mes", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mesos", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mesos", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un any", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un any", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anys", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un any", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anys", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('ca'); + test.equal(moment(30000).from(0), "en uns segons", "prefix"); + test.equal(moment(0).from(30000), "fa uns segons", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('ca'); + test.equal(moment().fromNow(), "fa uns segons", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('ca'); + test.equal(moment().add({s:30}).fromNow(), "en uns segons", "en uns segons"); + test.equal(moment().add({d:5}).fromNow(), "en 5 dies", "en 5 dies"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + moment.lang('ca'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "avui a les 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "avui a les 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "avui a les 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "demà a les 2:00", "tomorrow at the same time"); + test.equal(moment(a).add({ d: 1, h : -1 }).calendar(), "demà a la 1:00", "tomorrow minus 1 hour"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "avui a la 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "ahir a les 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('ca'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('ca'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('ca'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/cv.js b/node_modules/emailjs/node_modules/moment/test/lang/cv.js new file mode 100644 index 0000000..c42cdce --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/cv.js @@ -0,0 +1,246 @@ +var moment = require("../../moment"); + + + /************************************************** + Chuvash + *************************************************/ + +exports["lang:cv"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('cv'); + var tests = 'кăрлач кăр_нарăс нар_пуш пуш_ака ака_май май_çĕртме çĕр_утă утă_çурла çур_авăн ав_юпа юпа_чӳк чӳк_раштав раш'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('cv'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'вырсарникун, нарăс 14-мĕш 2010, 3:25:50 pm'], + ['ddd, hA', 'выр, 3PM'], + ['M Mo MM MMMM MMM', '2 2-мĕш 02 нарăс нар'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-мĕш 14'], + ['d do dddd ddd dd', '0 0-мĕш вырсарникун выр вр'], + ['DDD DDDo DDDD', '45 45-мĕш 045'], + ['w wo ww', '8 8-мĕш 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['Çулăн DDDo кунĕ', 'Çулăн 45-мĕш кунĕ'], + ['L', '14-02-2010'], + ['LL', '2010 çулхи нарăс уйăхĕн 14-мĕшĕ'], + ['LLL', '2010 çулхи нарăс уйăхĕн 14-мĕшĕ, 15:25'], + ['LLLL', 'вырсарникун, 2010 çулхи нарăс уйăхĕн 14-мĕшĕ, 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('cv'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1-мĕш', '1-мĕш'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2-мĕш', '2-мĕш'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3-мĕш', '3-мĕш'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4-мĕш', '4-мĕш'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5-мĕш', '5-мĕш'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6-мĕш', '6-мĕш'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7-мĕш', '7-мĕш'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8-мĕш', '8-мĕш'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9-мĕш', '9-мĕш'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10-мĕш', '10-мĕш'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11-мĕш', '11-мĕш'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12-мĕш', '12-мĕш'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13-мĕш', '13-мĕш'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14-мĕш', '14-мĕш'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15-мĕш', '15-мĕш'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16-мĕш', '16-мĕш'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17-мĕш', '17-мĕш'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18-мĕш', '18-мĕш'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19-мĕш', '19-мĕш'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20-мĕш', '20-мĕш'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21-мĕш', '21-мĕш'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22-мĕш', '22-мĕш'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23-мĕш', '23-мĕш'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24-мĕш', '24-мĕш'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25-мĕш', '25-мĕш'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26-мĕш', '26-мĕш'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27-мĕш', '27-мĕш'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28-мĕш', '28-мĕш'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29-мĕш', '29-мĕш'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30-мĕш', '30-мĕш'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31-мĕш', '31-мĕш'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('cv'); + var expected = 'кăрлач кăр_нарăс нар_пуш пуш_ака ака_май май_çĕртме çĕр_утă утă_çурла çур_авăн ав_юпа юпа_чӳк чӳк_раштав раш'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('cv'); + var expected = 'вырсарникун выр вр_тунтикун тун тн_ытларикун ытл ыт_юнкун юн юн_кĕçнерникун кĕç кç_эрнекун эрн эр_шăматкун шăм шм'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('cv'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "пĕр-ик çеккунт", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "пĕр минут", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "пĕр минут", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 минут", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 минут", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "пĕр сехет", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "пĕр сехет", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 сехет", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 сехет", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 сехет", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "пĕр кун", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "пĕр кун", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 кун", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "пĕр кун", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 кун", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 кун", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "пĕр уйăх", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "пĕр уйăх", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "пĕр уйăх", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 уйăх", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 уйăх", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 уйăх", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "пĕр уйăх", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 уйăх", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 уйăх", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "пĕр çул", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "пĕр çул", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 çул", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "пĕр çул", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 çул", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('cv'); + test.equal(moment(30000).from(0), "пĕр-ик çеккунтран", "prefix"); + test.equal(moment(0).from(30000), "пĕр-ик çеккунт каялла", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('cv'); + test.equal(moment().fromNow(), "пĕр-ик çеккунт каялла", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('cv'); + test.equal(moment().add({s:30}).fromNow(), "пĕр-ик çеккунтран", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 кунран", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('cv'); + var a = moment().hours(2).minutes(0).seconds(0); + test.equal(moment(a).calendar(), "Паян 02:00 сехетре", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Паян 02:25 сехетре", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Паян 03:00 сехетре", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Ыран 02:00 сехетре", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Паян 01:00 сехетре", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ĕнер 02:00 сехетре", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('cv'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[Çитес] dddd LT [сехетре]'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Çитес] dddd LT [сехетре]'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Çитес] dddd LT [сехетре]'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('cv'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Иртнĕ] dddd LT [сехетре]'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Иртнĕ] dddd LT [сехетре]'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Иртнĕ] dddd LT [сехетре]'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('cv'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/da.js b/node_modules/emailjs/node_modules/moment/test/lang/da.js new file mode 100644 index 0000000..2bcf26c --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/da.js @@ -0,0 +1,183 @@ +var moment = require("../../moment"); + + + /************************************************** + Danish + *************************************************/ + +exports["lang:da"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('da'); + var tests = 'Januar Jan_Februar Feb_Marts Mar_April Apr_Maj Maj_Juni Jun_Juli Jul_August Aug_September Sep_Oktober Okt_November Nov_December Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('da'); + var a = [ + ['dddd \\den MMMM Do YYYY, h:mm:ss a', 'Søndag den Februar 14. 2010, 3:25:50 pm'], + ['ddd hA', 'Søn 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 Februar Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. Søndag Søn Sø'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[den] DDDo \\d\\ag på året', 'den 45. dag på året'], + ['L', '14/02/2010'], + ['LL', '14 Februar 2010'], + ['LLL', '14 Februar 2010 3:25 PM'], + ['LLLL', 'Søndag 14. Februar, 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('da'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('da'); + var expected = 'Januar Jan_Februar Feb_Marts Mar_April Apr_Maj Maj_Juni Jun_Juli Jul_August Aug_September Sep_Oktober Okt_November Nov_December Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('da'); + var expected = 'Søndag Søn Sø_Mandag Man Ma_Tirsdag Tir Ti_Onsdag Ons On_Torsdag Tor To_Fredag Fre Fr_Lørdag Lør Lø'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('da'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "få sekunder", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutter", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutter", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "time", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "time", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timer", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timer", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timer", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dage", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dage", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dage", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "månede", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "månede", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "månede", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 måneder", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 måneder", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 måneder", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "månede", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 måneder", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 måneder", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('da'); + test.equal(moment(30000).from(0), "om få sekunder", "prefix"); + test.equal(moment(0).from(30000), "få sekunder siden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('da'); + test.equal(moment().fromNow(), "få sekunder siden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('da'); + test.equal(moment().add({s:30}).fromNow(), "om få sekunder", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dage", "in 5 days"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/de.js b/node_modules/emailjs/node_modules/moment/test/lang/de.js new file mode 100644 index 0000000..59d5358 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/de.js @@ -0,0 +1,241 @@ +var moment = require("../../moment"); + + + /************************************************** + German + *************************************************/ + +exports["lang:de"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('de'); + var tests = 'Januar Jan._Februar Febr._März Mrz._April Apr._Mai Mai_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('de'); + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'Sonntag, 14. Februar 2010, 3:25:50 pm'], + ['ddd, hA', 'So., 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 Februar Febr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. Sonntag So. So'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '14.02.2010'], + ['LL', '14. Februar 2010'], + ['LLL', '14. Februar 2010 15:25 Uhr'], + ['LLLL', 'Sonntag, 14. Februar 2010 15:25 Uhr'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('de'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('de'); + var expected = 'Januar Jan._Februar Febr._März Mrz._April Apr._Mai Mai_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('de'); + var expected = 'Sonntag So. So_Montag Mo. Mo_Dienstag Di. Di_Mittwoch Mi. Mi_Donnerstag Do. Do_Freitag Fr. Fr_Samstag Sa. Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('de'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "ein paar Sekunden", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "einer Minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "einer Minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 Minuten", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 Minuten", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "einer Stunde", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "einer Stunde", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 Stunden", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 Stunden", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 Stunden", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "einem Tag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "einem Tag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 Tagen", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "einem Tag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 Tagen", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 Tagen", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "einem Monat", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "einem Monat", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "einem Monat", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 Monaten", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 Monaten", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 Monaten", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "einem Monat", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 Monaten", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 Monaten", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "einem Jahr", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "einem Jahr", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 Jahren", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "einem Jahr", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 Jahren", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('de'); + test.equal(moment(30000).from(0), "in ein paar Sekunden", "prefix"); + test.equal(moment(0).from(30000), "vor ein paar Sekunden", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('de'); + test.equal(moment().add({s:30}).fromNow(), "in ein paar Sekunden", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 Tagen", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('de'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Heute um 2:00 Uhr", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Heute um 2:25 Uhr", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Heute um 3:00 Uhr", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Morgen um 2:00 Uhr", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Heute um 1:00 Uhr", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Gestern um 2:00 Uhr", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('de'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [um] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [um] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [um] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('de'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[letzten] dddd [um] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[letzten] dddd [um] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[letzten] dddd [um] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('de'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/en-ca.js b/node_modules/emailjs/node_modules/moment/test/lang/en-ca.js new file mode 100644 index 0000000..d59de28 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/en-ca.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + English + *************************************************/ + +exports["lang:en-ca"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('en-ca'); + var tests = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('en-ca'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sunday, February 14th 2010, 3:25:50 pm'], + ['ddd, hA', 'Sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2nd 02 February Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14th 14'], + ['d do dddd ddd dd', '0 0th Sunday Sun Su'], + ['DDD DDDo DDDD', '45 45th 045'], + ['w wo ww', '8 8th 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45th day of the year'], + ['L', '2010-02-14'], + ['LL', '14 February, 2010'], + ['LLL', '14 February, 2010 3:25 PM'], + ['LLLL', 'Sunday, 14 February, 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('en-gb'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('en-gb'); + var expected = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('en-gb'); + var expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('en-gb'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "a few seconds", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "a minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "a minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "an hour", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "an hour", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hours", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hours", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hours", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "a day", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "a day", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 days", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "a day", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 days", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 days", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "a month", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "a month", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "a month", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 months", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 months", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 months", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "a month", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 months", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 months", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "a year", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "a year", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 years", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "a year", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 years", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('en-gb'); + test.equal(moment(30000).from(0), "in a few seconds", "prefix"); + test.equal(moment(0).from(30000), "a few seconds ago", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('en-gb'); + test.equal(moment().fromNow(), "a few seconds ago", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('en-gb'); + test.equal(moment().add({s:30}).fromNow(), "in a few seconds", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 days", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('en-gb'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at 2:00 AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at 2:25 AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at 3:00 AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at 2:00 AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at 1:00 AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at 2:00 AM", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('en-gb'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('en-gb'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('en-gb'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/en-gb.js b/node_modules/emailjs/node_modules/moment/test/lang/en-gb.js new file mode 100644 index 0000000..6641b81 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/en-gb.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + English + *************************************************/ + +exports["lang:en-gb"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('en-gb'); + var tests = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('en-gb'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sunday, February 14th 2010, 3:25:50 pm'], + ['ddd, hA', 'Sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2nd 02 February Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14th 14'], + ['d do dddd ddd dd', '0 0th Sunday Sun Su'], + ['DDD DDDo DDDD', '45 45th 045'], + ['w wo ww', '8 8th 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45th day of the year'], + ['L', '14/02/2010'], + ['LL', '14 February 2010'], + ['LLL', '14 February 2010 3:25 PM'], + ['LLLL', 'Sunday, 14 February 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('en-gb'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('en-gb'); + var expected = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('en-gb'); + var expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('en-gb'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "a few seconds", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "a minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "a minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "an hour", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "an hour", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hours", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hours", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hours", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "a day", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "a day", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 days", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "a day", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 days", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 days", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "a month", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "a month", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "a month", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 months", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 months", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 months", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "a month", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 months", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 months", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "a year", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "a year", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 years", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "a year", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 years", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('en-gb'); + test.equal(moment(30000).from(0), "in a few seconds", "prefix"); + test.equal(moment(0).from(30000), "a few seconds ago", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('en-gb'); + test.equal(moment().fromNow(), "a few seconds ago", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('en-gb'); + test.equal(moment().add({s:30}).fromNow(), "in a few seconds", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 days", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('en-gb'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at 2:00 AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at 2:25 AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at 3:00 AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at 2:00 AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at 1:00 AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at 2:00 AM", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('en-gb'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('en-gb'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('en-gb'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/en.js b/node_modules/emailjs/node_modules/moment/test/lang/en.js new file mode 100644 index 0000000..5f368b8 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/en.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + English + *************************************************/ + +exports["lang:en"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('en'); + var tests = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('en'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sunday, February 14th 2010, 3:25:50 pm'], + ['ddd, hA', 'Sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2nd 02 February Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14th 14'], + ['d do dddd ddd dd', '0 0th Sunday Sun Su'], + ['DDD DDDo DDDD', '45 45th 045'], + ['w wo ww', '8 8th 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45th day of the year'], + ['L', '02/14/2010'], + ['LL', 'February 14 2010'], + ['LLL', 'February 14 2010 3:25 PM'], + ['LLLL', 'Sunday, February 14 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('en'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('en'); + var expected = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('en'); + var expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('en'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "a few seconds", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "a minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "a minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "an hour", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "an hour", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hours", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hours", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hours", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "a day", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "a day", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 days", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "a day", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 days", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 days", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "a month", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "a month", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "a month", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 months", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 months", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 months", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "a month", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 months", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 months", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "a year", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "a year", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 years", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "a year", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 years", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('en'); + test.equal(moment(30000).from(0), "in a few seconds", "prefix"); + test.equal(moment(0).from(30000), "a few seconds ago", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('en'); + test.equal(moment().fromNow(), "a few seconds ago", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('en'); + test.equal(moment().add({s:30}).fromNow(), "in a few seconds", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 days", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('en'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at 2:00 AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at 2:25 AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at 3:00 AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at 2:00 AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at 1:00 AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at 2:00 AM", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('en'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('en'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[last] dddd [at] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('en'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/es.js b/node_modules/emailjs/node_modules/moment/test/lang/es.js new file mode 100644 index 0000000..53095f5 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/es.js @@ -0,0 +1,218 @@ +var moment = require("../../moment"); + + + /************************************************** + Spanish + *************************************************/ + +exports["lang:es"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('es'); + var tests = 'Enero Ene._Febrero Feb._Marzo Mar._Abril Abr._Mayo May._Junio Jun._Julio Jul._Agosto Ago._Septiembre Sep._Octubre Oct._Noviembre Nov._Diciembre Dic.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('es'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('es'); + var expected = 'Enero Ene._Febrero Feb._Marzo Mar._Abril Abr._Mayo May._Junio Jun._Julio Jul._Agosto Ago._Septiembre Sep._Octubre Oct._Noviembre Nov._Diciembre Dic.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('es'); + var expected = 'Domingo Dom. Do_Lunes Lun. Lu_Martes Mar. Ma_Miércoles Mié. Mi_Jueves Jue. Ju_Viernes Vie. Vi_Sábado Sáb. Sá'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('es'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "unos segundos", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "una hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "una hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un día", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un día", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 días", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un día", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 días", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 días", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mes", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mes", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mes", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mes", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un año", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un año", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 años", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un año", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 años", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('es'); + test.equal(moment(30000).from(0), "en unos segundos", "prefix"); + test.equal(moment(0).from(30000), "hace unos segundos", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('es'); + test.equal(moment().fromNow(), "hace unos segundos", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('es'); + test.equal(moment().add({s:30}).fromNow(), "en unos segundos", "en unos segundos"); + test.equal(moment().add({d:5}).fromNow(), "en 5 días", "en 5 días"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + moment.lang('es'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "hoy a las 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "hoy a las 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "hoy a las 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "mañana a las 2:00", "tomorrow at the same time"); + test.equal(moment(a).add({ d: 1, h : -1 }).calendar(), "mañana a la 1:00", "tomorrow minus 1 hour"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "hoy a la 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "ayer a las 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('es'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('es'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('es'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/eu.js b/node_modules/emailjs/node_modules/moment/test/lang/eu.js new file mode 100644 index 0000000..b701e46 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/eu.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + Euskara + *************************************************/ + +exports["lang:eu"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('eu'); + var tests = 'urtarrila urt._otsaila ots._martxoa mar._apirila api._maiatza mai._ekaina eka._uztaila uzt._abuztua abu._iraila ira._urria urr._azaroa aza._abendua abe.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('eu'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'igandea, otsaila 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'ig., 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 otsaila ots.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. igandea ig. ig'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '2010-02-14'], + ['LL', '2010ko otsailaren 14a'], + ['LLL', '2010ko otsailaren 14a 15:25'], + ['LLLL', 'igandea, 2010ko otsailaren 14a 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('eu'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('eu'); + var expected = 'urtarrila urt._otsaila ots._martxoa mar._apirila api._maiatza mai._ekaina eka._uztaila uzt._abuztua abu._iraila ira._urria urr._azaroa aza._abendua abe.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('eu'); + var expected = 'igandea ig. ig_astelehena al. al_asteartea ar. ar_asteazkena az. az_osteguna og. og_ostirala ol. ol_larunbata lr. lr'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('eu'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "segundo batzuk", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minutu bat", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minutu bat", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutu", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutu", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "ordu bat", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "ordu bat", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ordu", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ordu", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ordu", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "egun bat", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "egun bat", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 egun", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "egun bat", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 egun", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 egun", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "hilabete bat", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "hilabete bat", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "hilabete bat", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 hilabete", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 hilabete", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 hilabete", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "hilabete bat", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 hilabete", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 hilabete", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "urte bat", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "urte bat", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 urte", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "urte bat", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 urte", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('eu'); + test.equal(moment(30000).from(0), "segundo batzuk barru", "prefix"); + test.equal(moment(0).from(30000), "duela segundo batzuk", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('eu'); + test.equal(moment().fromNow(), "duela segundo batzuk", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('eu'); + test.equal(moment().add({s:30}).fromNow(), "segundo batzuk barru", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 egun barru", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('eu'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "gaur 02:00etan", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "gaur 02:25etan", "now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "gaur 03:00etan", "now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "bihar 02:00etan", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "gaur 01:00etan", "now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "atzo 02:00etan", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('eu'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd LT[etan]'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd LT[etan]'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd LT[etan]'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('eu'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('eu'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/fi.js b/node_modules/emailjs/node_modules/moment/test/lang/fi.js new file mode 100644 index 0000000..6c83ff4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/fi.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + Finnish + *************************************************/ + +exports["lang:fi"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('fi'); + var tests = 'tammikuu tam_helmikuu hel_maaliskuu maa_huhtikuu huh_toukokuu tou_kesäkuu kes_heinäkuu hei_elokuu elo_syyskuu syys_lokakuu lok_marraskuu mar_joulukuu jou'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('fi'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'sunnuntai, helmikuu 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'su, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 helmikuu hel'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. sunnuntai su su'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['vuo\\den DDDo päivä', 'vuoden 45. päivä'], + ['L', '14.02.2010'], + ['LL', '14. helmikuuta 2010'], + ['LLL', '14. helmikuuta 2010, klo 15.25'], + ['LLLL', 'sunnuntai, 14. helmikuuta 2010, klo 15.25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('fi'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('fi'); + var expected = 'tammikuu tam_helmikuu hel_maaliskuu maa_huhtikuu huh_toukokuu tou_kesäkuu kes_heinäkuu hei_elokuu elo_syyskuu syy_lokakuu lok_marraskuu mar_joulukuu jou'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('fi'); + var expected = 'sunnuntai su su_maanantai ma ma_tiistai ti ti_keskiviikko ke ke_torstai to to_perjantai pe pe_lauantai la la'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('fi'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "muutama sekunti", "44 seconds = few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuutti", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuutti", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "kaksi minuuttia", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuuttia", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "tunti", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "tunti", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "kaksi tuntia", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "viisi tuntia", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 tuntia", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "päivä", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "päivä", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "kaksi päivää", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "päivä", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "viisi päivää", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 päivää", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "kuukausi", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "kuukausi", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "kuukausi", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "kaksi kuukautta", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "kaksi kuukautta", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "kolme kuukautta", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "kuukausi", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "viisi kuukautta", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 kuukautta", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "vuosi", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "vuosi", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "kaksi vuotta", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "vuosi", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "viisi vuotta", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('fi'); + test.equal(moment(30000).from(0), "muutaman sekunnin päästä", "prefix"); + test.equal(moment(0).from(30000), "muutama sekunti sitten", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('fi'); + test.equal(moment().fromNow(), "muutama sekunti sitten", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('fi'); + test.equal(moment().add({s:30}).fromNow(), "muutaman sekunnin päästä", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "viiden päivän päästä", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('fi'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "tänään klo 02.00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "tänään klo 02.25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "tänään klo 03.00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "huomenna klo 02.00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "tänään klo 01.00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "eilen klo 02.00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('fi'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [klo] LT'), "today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [klo] LT'), "today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [klo] LT'), "today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('fi'); + + for (var i = 2; i < 7; i++) { + var m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), "today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), "today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), "today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('fi'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "yksi viikko sitten"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "yhden viikon päästä"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "kaksi viikkoa sitten"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "kaden viikon päästä"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/fr-ca.js b/node_modules/emailjs/node_modules/moment/test/lang/fr-ca.js new file mode 100644 index 0000000..83c165b --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/fr-ca.js @@ -0,0 +1,241 @@ +var moment = require("../../moment"); + + + /************************************************** + French + *************************************************/ + +exports["lang:fr-ca"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('fr-ca'); + var tests = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('fr-ca'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'dimanche, février 14ème 2010, 3:25:50 pm'], + ['ddd, hA', 'dim., 3PM'], + ['M Mo MM MMMM MMM', '2 2ème 02 février févr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14ème 14'], + ['d do dddd ddd dd', '0 0ème dimanche dim. Di'], + ['DDD DDDo DDDD', '45 45ème 045'], + ['w wo ww', '8 8ème 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45ème day of the year'], + ['L', '2010-02-14'], + ['LL', '14 février 2010'], + ['LLL', '14 février 2010 15:25'], + ['LLLL', 'dimanche 14 février 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('fr'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1er', '1er'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2ème', '2ème'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3ème', '3ème'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4ème', '4ème'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5ème', '5ème'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6ème', '6ème'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7ème', '7ème'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8ème', '8ème'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9ème', '9ème'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10ème', '10ème'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11ème', '11ème'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12ème', '12ème'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13ème', '13ème'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14ème', '14ème'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15ème', '15ème'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16ème', '16ème'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17ème', '17ème'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18ème', '18ème'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19ème', '19ème'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20ème', '20ème'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21ème', '21ème'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22ème', '22ème'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23ème', '23ème'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24ème', '24ème'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25ème', '25ème'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26ème', '26ème'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27ème', '27ème'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28ème', '28ème'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29ème', '29ème'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30ème', '30ème'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31ème', '31ème'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('fr'); + var expected = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('fr'); + var expected = 'dimanche dim. Di_lundi lun. Lu_mardi mar. Ma_mercredi mer. Me_jeudi jeu. Je_vendredi ven. Ve_samedi sam. Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('fr'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "quelques secondes", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "une minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "une minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "une heure", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "une heure", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 heures", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 heures", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 heures", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un jour", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un jour", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 jours", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un jour", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 jours", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 jours", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mois", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mois", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mois", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mois", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mois", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mois", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mois", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mois", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mois", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "une année", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "une année", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 années", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "une année", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 années", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('fr'); + test.equal(moment(30000).from(0), "dans quelques secondes", "prefix"); + test.equal(moment(0).from(30000), "il y a quelques secondes", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('fr'); + test.equal(moment().add({s:30}).fromNow(), "dans quelques secondes", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "dans 5 jours", "in 5 days"); + test.done(); + }, + + "same day" : function(test) { + test.expect(6); + moment.lang('fr'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Aujourd'hui à 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Aujourd'hui à 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Aujourd'hui à 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Demain à 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Aujourd'hui à 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Hier à 02:00", "yesterday at the same time"); + test.done(); + }, + + "same next week" : function(test) { + test.expect(15); + moment.lang('fr'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "same last week" : function(test) { + test.expect(15); + moment.lang('fr'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "same all else" : function(test) { + test.expect(4); + moment.lang('fr'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/fr.js b/node_modules/emailjs/node_modules/moment/test/lang/fr.js new file mode 100644 index 0000000..170bdb7 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/fr.js @@ -0,0 +1,241 @@ +var moment = require("../../moment"); + + + /************************************************** + French + *************************************************/ + +exports["lang:fr"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('fr'); + var tests = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('fr'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'dimanche, février 14ème 2010, 3:25:50 pm'], + ['ddd, hA', 'dim., 3PM'], + ['M Mo MM MMMM MMM', '2 2ème 02 février févr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14ème 14'], + ['d do dddd ddd dd', '0 0ème dimanche dim. Di'], + ['DDD DDDo DDDD', '45 45ème 045'], + ['w wo ww', '8 8ème 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45ème day of the year'], + ['L', '14/02/2010'], + ['LL', '14 février 2010'], + ['LLL', '14 février 2010 15:25'], + ['LLLL', 'dimanche 14 février 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('fr'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1er', '1er'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2ème', '2ème'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3ème', '3ème'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4ème', '4ème'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5ème', '5ème'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6ème', '6ème'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7ème', '7ème'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8ème', '8ème'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9ème', '9ème'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10ème', '10ème'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11ème', '11ème'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12ème', '12ème'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13ème', '13ème'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14ème', '14ème'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15ème', '15ème'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16ème', '16ème'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17ème', '17ème'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18ème', '18ème'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19ème', '19ème'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20ème', '20ème'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21ème', '21ème'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22ème', '22ème'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23ème', '23ème'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24ème', '24ème'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25ème', '25ème'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26ème', '26ème'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27ème', '27ème'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28ème', '28ème'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29ème', '29ème'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30ème', '30ème'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31ème', '31ème'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('fr'); + var expected = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('fr'); + var expected = 'dimanche dim. Di_lundi lun. Lu_mardi mar. Ma_mercredi mer. Me_jeudi jeu. Je_vendredi ven. Ve_samedi sam. Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('fr'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "quelques secondes", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "une minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "une minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "une heure", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "une heure", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 heures", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 heures", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 heures", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un jour", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un jour", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 jours", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un jour", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 jours", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 jours", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mois", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mois", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mois", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mois", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mois", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mois", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mois", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mois", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mois", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "une année", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "une année", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 années", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "une année", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 années", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('fr'); + test.equal(moment(30000).from(0), "dans quelques secondes", "prefix"); + test.equal(moment(0).from(30000), "il y a quelques secondes", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('fr'); + test.equal(moment().add({s:30}).fromNow(), "dans quelques secondes", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "dans 5 jours", "in 5 days"); + test.done(); + }, + + "same day" : function(test) { + test.expect(6); + moment.lang('fr'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Aujourd'hui à 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Aujourd'hui à 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Aujourd'hui à 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Demain à 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Aujourd'hui à 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Hier à 02:00", "yesterday at the same time"); + test.done(); + }, + + "same next week" : function(test) { + test.expect(15); + moment.lang('fr'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "same last week" : function(test) { + test.expect(15); + moment.lang('fr'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "same all else" : function(test) { + test.expect(4); + moment.lang('fr'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/gl.js b/node_modules/emailjs/node_modules/moment/test/lang/gl.js new file mode 100644 index 0000000..a4d34b4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/gl.js @@ -0,0 +1,232 @@ +var moment = require("../../moment"); + + + /************************************************** + Galego + *************************************************/ + +exports["lang:gl"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('gl'); + var tests = "Xaneiro Xan._Febreiro Feb._Marzo Mar._Abril Abr._Maio Mai._Xuño Xuñ._Xullo Xul._Agosto Ago._Setembro Set._Octubro Out._Novembro Nov._Decembro Dec.".split("_"); + + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('es'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('gl'); + var expected = "Xaneiro Xan._Febreiro Feb._Marzo Mar._Abril Abr._Maio Mai._Xuño Xuñ._Xullo Xul._Agosto Ago._Setembro Set._Octubro Out._Novembro Nov._Decembro Dec.".split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('gl'); + var expected = "Domingo Dom. Do_Luns Lun. Lu_Martes Mar. Ma_Mércores Mér. Mé_Xoves Xov. Xo_Venres Ven. Ve_Sábado Sáb. Sá".split("_"); + + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('gl'); + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "uns segundo", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "unha hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "unha hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un día", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un día", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 días", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un día", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 días", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 días", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mes", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mes", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mes", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mes", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un ano", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un ano", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anos", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un ano", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anos", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('gl'); + test.equal(moment(30000).from(0), "en uns segundo", "prefix"); + test.equal(moment(0).from(30000), "fai uns segundo", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('gl'); + test.equal(moment().fromNow(), "fai uns segundo", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('gl'); + test.equal(moment().add({s:30}).fromNow(), "en uns segundo", "en unos segundos"); + test.equal(moment().add({d:5}).fromNow(), "en 5 días", "en 5 días"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + moment.lang('gl'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "hoxe ás 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "hoxe ás 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "hoxe ás 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "mañá ás 2:00", "tomorrow at the same time"); + test.equal(moment(a).add({ d: 1, h : -1 }).calendar(), "mañá a 1:00", "tomorrow minus 1 hour"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "hoxe a 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "onte á 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('gl'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('gl'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('gl'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "regression tests" : function(test) { + test.expect(1); + moment.lang('gl'); + + var lastWeek = moment().subtract({ d: 4 }).hours(1); + test.equal(lastWeek.calendar(), lastWeek.format('[o] dddd [pasado a] LT'), "1 o'clock bug"); + + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/hu.js b/node_modules/emailjs/node_modules/moment/test/lang/hu.js new file mode 100644 index 0000000..a2ef512 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/hu.js @@ -0,0 +1,250 @@ +var moment = require("../../moment"); + + /************************************************** + English + *************************************************/ + +exports["lang:hu"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('hu'); + var tests = 'január jan_február feb_március márc_április ápr_május máj_június jún_július júl_augusztus aug_szeptember szept_október okt_november nov_december dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(16); + moment.lang('hu'); + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'vasárnap, február 14. 2010, 15:25:50'], + ['ddd, HH', 'v, 15'], + ['M Mo MM MMMM MMM', '2 2. 02 február feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd', '0 0. vasárnap v'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['\\az év DDDo n\\apj\\a', 'az év 45. napja'], + ['L', '2010.02.14.'], + ['LL', '2010. február 14.'], + ['LLL', '2010. február 14., 15:25'], + ['LLLL', '2010. február 14., vasárnap 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('hu'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('hu'); + var expected = 'január jan_február feb_március márc_április ápr_május máj_június jún_július júl_augusztus aug_szeptember szept_október okt_november nov_december dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('hu'); + var expected = 'vasárnap v_hétfő h_kedd k_szerda sze_csütörtök cs_péntek p_szombat szo'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('hu'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "néhány másodperc", "44 másodperc = néhány másodperc"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "egy perc", "45 másodperc = egy perc"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "egy perc", "89 másodperc = egy perc"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 perc", "90 másodperc = 2 perc"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 perc", "44 perc = 44 perc"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "egy óra", "45 perc = egy óra"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "egy óra", "89 perc = egy óra"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 óra", "90 perc = 2 óra"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 óra", "5 óra = 5 óra"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 óra", "21 óra = 21 óra"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "egy nap", "22 óra = egy nap"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "egy nap", "35 óra = egy nap"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 nap", "36 óra = 2 nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "egy nap", "1 nap = egy nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 nap", "5 nap = 5 nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 nap", "25 nap = 25 nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "egy hónap", "26 nap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "egy hónap", "30 nap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "egy hónap", "45 nap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 hónap", "46 nap = 2 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 hónap", "75 nap = 2 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 hónap", "76 nap = 3 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "egy hónap", "1 hónap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 hónap", "5 hónap = 5 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 hónap", "344 nap = 11 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "egy év", "345 nap = egy év"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "egy év", "547 nap = egy év"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 év", "548 nap = 2 év"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "egy év", "1 év = egy év"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 év", "5 év = 5 év"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('hu'); + test.equal(moment(30000).from(0), "néhány másodperc múlva", "prefix"); + test.equal(moment(0).from(30000), "néhány másodperce", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('hu'); + test.equal(moment().fromNow(), "néhány másodperce", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('hu'); + test.equal(moment().add({s:30}).fromNow(), "néhány másodperc múlva", "néhány másodperc múlva"); + test.equal(moment().add({d:5}).fromNow(), "5 nap múlva", "5 nap múlva"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('hu'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "ma 2:00-kor", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "ma 2:25-kor", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "ma 3:00-kor", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "holnap 2:00-kor", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "ma 1:00-kor", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "tegnap 2:00-kor", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('hu'); + + var i; + var m; + var days = 'vasárnap_hétfőn_kedden_szerdán_csütörtökön_pénteken_szombaton'.split('_'); + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('['+days[m.day()]+'] LT[-kor]'), "today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('['+days[m.day()]+'] LT[-kor]'), "today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('['+days[m.day()]+'] LT[-kor]'), "today + " + i + " days end of day"); + } + + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('hu'); + + var days = 'vasárnap_hétfőn_kedden_szerdán_csütörtökön_pénteken_szombaton'.split('_'); + + for (var i = 2; i < 7; i++) { + var m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('múlt ['+days[m.day()]+'] LT[-kor]'), "today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('múlt ['+days[m.day()]+'] LT[-kor]'), "today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('múlt ['+days[m.day()]+'] LT[-kor]'), "today - " + i + " days end of day"); + } + + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('hu'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "egy héte"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "egy hét múlva"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 hete"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "2 hét múlva"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/is.js b/node_modules/emailjs/node_modules/moment/test/lang/is.js new file mode 100644 index 0000000..a59ed44 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/is.js @@ -0,0 +1,254 @@ +var moment = require("../../moment"); + + + /************************************************** + Icelandic + *************************************************/ + +exports["lang:is"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('is'); + var tests = 'janúar jan_febrúar feb_mars mar_apríl apr_maí maí_júní jún_júlí júl_ágúst ágú_september sep_október okt_nóvember nóv_desember des'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('is'); + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'sunnudagur, 14. febrúar 2010, 3:25:50 pm'], + ['ddd, hA', 'sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 febrúar feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. sunnudagur sun Su'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '14/02/2010'], + ['LL', '14. febrúar 2010'], + ['LLL', '14. febrúar 2010 kl. 15:25'], + ['LLLL', 'sunnudagur, 14. febrúar 2010 kl. 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('is'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('is'); + var expected = 'janúar jan_febrúar feb_mars mar_apríl apr_maí maí_júní jún_júlí júl_ágúst ágú_september sep_október okt_nóvember nóv_desember des'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('is'); + var expected = 'sunnudagur sun Su_mánudagur mán Má_þriðjudagur þri Þr_miðvikudagur mið Mi_fimmtudagur fim Fi_föstudagur fös Fö_laugardagur lau La'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(34); + moment.lang('is'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "nokkrar sekúndur", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "mínúta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "mínúta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 mínútur", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 mínútur", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:21}), true), "21 mínúta", "21 minutes = 21 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "klukkustund", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "klukkustund", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 klukkustundir", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 klukkustundir", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 klukkustund", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "dagur", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "dagur", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagar", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "dagur", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagar", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagar", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:11}), true), "11 dagar", "11 days = 11 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:21}), true), "21 dagur", "21 days = 21 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "mánuður", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "mánuður", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "mánuður", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mánuðir", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mánuðir", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mánuðir", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "mánuður", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mánuðir", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mánuðir", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ár", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ár", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ár", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ár", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ár", "5 years = 5 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:21}), true), "21 ár", "21 years = 21 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(3); + moment.lang('is'); + test.equal(moment(30000).from(0), "eftir nokkrar sekúndur", "prefix"); + test.equal(moment(0).from(30000), "fyrir nokkrum sekúndum síðan", "suffix"); + test.equal(moment().subtract({m:1}).fromNow(), "fyrir mínútu síðan", "a minute ago"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('is'); + test.equal(moment().fromNow(), "fyrir nokkrum sekúndum síðan", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(3); + moment.lang('is'); + test.equal(moment().add({s:30}).fromNow(), "eftir nokkrar sekúndur", "in a few seconds"); + test.equal(moment().add({m:1}).fromNow(), "eftir mínútu", "in a minute"); + test.equal(moment().add({d:5}).fromNow(), "eftir 5 daga", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('is'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "í dag kl. 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "í dag kl. 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "í dag kl. 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "á morgun kl. 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "í dag kl. 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "í gær kl. 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('is'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [kl.] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [kl.] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [kl.] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('is'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('is'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/it.js b/node_modules/emailjs/node_modules/moment/test/lang/it.js new file mode 100644 index 0000000..03695f1 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/it.js @@ -0,0 +1,241 @@ +var moment = require("../../moment"); + + + /************************************************** + Italian + *************************************************/ + +exports["lang:it"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('it'); + var tests = 'Gennaio Gen_Febbraio Feb_Marzo Mar_Aprile Apr_Maggio Mag_Giugno Giu_Luglio Lug_Agosto Ago_Settebre Set_Ottobre Ott_Novembre Nov_Dicembre Dic'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('it'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domenica, Febbraio 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom, 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Febbraio Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd dd', '0 0º Domenica Dom D'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '8 8º 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 Febbraio 2010'], + ['LLL', '14 Febbraio 2010 15:25'], + ['LLLL', 'Domenica, 14 Febbraio 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('it'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('it'); + var expected = 'Gennaio Gen_Febbraio Feb_Marzo Mar_Aprile Apr_Maggio Mag_Giugno Giu_Luglio Lug_Agosto Ago_Settebre Set_Ottobre Ott_Novembre Nov_Dicembre Dic'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('it'); + var expected = 'Domenica Dom D_Lunedì Lun L_Martedì Mar Ma_Mercoledì Mer Me_Giovedì Gio G_Venerdì Ven V_Sabato Sab S'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('it'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "secondi", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuti", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuti", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "un'ora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "un'ora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ore", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ore", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ore", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un giorno", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un giorno", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 giorni", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un giorno", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 giorni", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 giorni", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mese", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mese", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mese", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mesi", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mesi", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mesi", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mese", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mesi", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mesi", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un anno", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un anno", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anni", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un anno", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anni", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('it'); + test.equal(moment(30000).from(0), "in secondi", "prefix"); + test.equal(moment(0).from(30000), "secondi fa", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('it'); + test.equal(moment().add({s:30}).fromNow(), "in secondi", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 giorni", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('it'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Oggi alle 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Oggi alle 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Oggi alle 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Domani alle 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Oggi alle 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ieri alle 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('it'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [alle] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [alle] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [alle] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('it'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[lo scorso] dddd [alle] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[lo scorso] dddd [alle] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[lo scorso] dddd [alle] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('it'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/ja.js b/node_modules/emailjs/node_modules/moment/test/lang/ja.js new file mode 100644 index 0000000..0705ae7 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/ja.js @@ -0,0 +1,208 @@ +var moment = require("../../moment"); + + + /************************************************** + Japanese + *************************************************/ + +exports["lang:jp"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('ja'); + var tests = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('ja'); + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '日曜日, 2月 14 2010, 午後 3:25:50'], + ['ddd, Ah', '日, 午後3'], + ['M Mo MM MMMM MMM', '2 2 02 2月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 日曜日 日 日'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '午後 午後'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45 day of the year'], + ['L', '2010/02/14'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日午後3時25分'], + ['LLLL', '2010年2月14日午後3時25分 日曜日'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('ja'); + var expected = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('ja'); + var expected = '日曜日 日 日_月曜日 月 月_火曜日 火 火_水曜日 水 水_木曜日 木 木_金曜日 金 金_土曜日 土 土'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('ja'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "数秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "1分", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "1分", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "1時間", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "1時間", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2時間", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5時間", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21時間", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1日", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1日", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2日", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1日", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5日", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25日", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "1ヶ月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "1ヶ月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "1ヶ月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2ヶ月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2ヶ月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3ヶ月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "1ヶ月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5ヶ月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11ヶ月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "1年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "1年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "1年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('ja'); + test.equal(moment(30000).from(0), "数秒後", "prefix"); + test.equal(moment(0).from(30000), "数秒前", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('ja'); + test.equal(moment().fromNow(), "数秒前", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('ja'); + test.equal(moment().add({s:30}).fromNow(), "数秒後", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5日後", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('ja'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今日 午前2時0分", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今日 午前2時25分", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今日 午前3時0分", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明日 午前2時0分", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今日 午前1時0分", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨日 午前2時0分", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('ja'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('ja'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('ja'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/jp.js b/node_modules/emailjs/node_modules/moment/test/lang/jp.js new file mode 100644 index 0000000..8b47f7a --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/jp.js @@ -0,0 +1,208 @@ +var moment = require("../../moment"); + + + /************************************************** + Japanese + *************************************************/ + +exports["lang:jp"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('jp'); + var tests = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('jp'); + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '日曜日, 2月 14 2010, 午後 3:25:50'], + ['ddd, Ah', '日, 午後3'], + ['M Mo MM MMMM MMM', '2 2 02 2月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 日曜日 日 日'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '午後 午後'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45 day of the year'], + ['L', '2010/02/14'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日午後3時25分'], + ['LLLL', '2010年2月14日午後3時25分 日曜日'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('jp'); + var expected = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('jp'); + var expected = '日曜日 日 日_月曜日 月 月_火曜日 火 火_水曜日 水 水_木曜日 木 木_金曜日 金 金_土曜日 土 土'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('jp'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "数秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "1分", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "1分", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "1時間", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "1時間", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2時間", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5時間", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21時間", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1日", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1日", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2日", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1日", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5日", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25日", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "1ヶ月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "1ヶ月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "1ヶ月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2ヶ月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2ヶ月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3ヶ月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "1ヶ月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5ヶ月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11ヶ月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "1年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "1年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "1年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('jp'); + test.equal(moment(30000).from(0), "数秒後", "prefix"); + test.equal(moment(0).from(30000), "数秒前", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('jp'); + test.equal(moment().fromNow(), "数秒前", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('jp'); + test.equal(moment().add({s:30}).fromNow(), "数秒後", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5日後", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('jp'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今日 午前2時0分", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今日 午前2時25分", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今日 午前3時0分", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明日 午前2時0分", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今日 午前1時0分", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨日 午前2時0分", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('jp'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('jp'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('jp'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/ko.js b/node_modules/emailjs/node_modules/moment/test/lang/ko.js new file mode 100644 index 0000000..8e55ca4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/ko.js @@ -0,0 +1,247 @@ +var moment = require("../../moment"); + + + /************************************************** + Korean + *************************************************/ + +exports["lang:kr"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('ko'); + var tests = '1월 1월_2월 2월_3월 3월_4월 4월_5월 5월_6월 6월_7월 7월_8월 8월_9월 9월_10월 10월_11월 11월_12월 12월'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + "format" : function(test) { + test.expect(18); + moment.lang('ko'); + var a = [ + ['YYYY년 MMMM Do dddd a h:mm:ss', '2010년 2월 14일 일요일 오후 3:25:50'], + ['ddd A h', '일 오후 3'], + ['M Mo MM MMMM MMM', '2 2일 02 2월 2월'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14일 14'], + ['d do dddd ddd dd', '0 0일 일요일 일 일'], + ['DDD DDDo DDDD', '45 45일 045'], + ['w wo ww', '8 8일 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '오후 오후'], + ['일년 중 DDDo째 되는 날', '일년 중 45일째 되는 날'], + ['L', '2010.02.14'], + ['LL', '2010년 2월 14일'], + ['LLL', '2010년 2월 14일 오후 3시 25분'], + ['LLLL', '2010년 2월 14일 일요일 오후 3시 25분'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('ko'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1일', '1일'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2일', '2일'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3일', '3일'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4일', '4일'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5일', '5일'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6일', '6일'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7일', '7일'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8일', '8일'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9일', '9일'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10일', '10일'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11일', '11일'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12일', '12일'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13일', '13일'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14일', '14일'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15일', '15일'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16일', '16일'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17일', '17일'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18일', '18일'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19일', '19일'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20일', '20일'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21일', '21일'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22일', '22일'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23일', '23일'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24일', '24일'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25일', '25일'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26일', '26일'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27일', '27일'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28일', '28일'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29일', '29일'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30일', '30일'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31일', '31일'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('ko'); + var expected = '1월 1월_2월 2월_3월 3월_4월 4월_5월 5월_6월 6월_7월 7월_8월 8월_9월 9월_10월 10월_11월 11월_12월 12월'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('ko'); + var expected = '일요일 일 일_월요일 월 월_화요일 화 화_수요일 수 수_목요일 목 목_금요일 금 금_토요일 토 토'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('ko'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "몇초", "44초 = 몇초"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "일분", "45초 = 일분"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "일분", "89초 = 일분"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2분", "90초 = 2분"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44분", "44분 = 44분"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "한시간", "45분 = 한시간"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "한시간", "89분 = 한시간"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2시간", "90분 = 2시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5시간", "5시간 = 5시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21시간", "21시간 = 21시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "하루", "22시간 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "하루", "35시간 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2일", "36시간 = 2일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "하루", "하루 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5일", "5일 = 5일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25일", "25일 = 25일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "한달", "26일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "한달", "30일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "한달", "45일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2달", "46일 = 2달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2달", "75일 = 2달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3달", "76일 = 3달"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "한달", "1달 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5달", "5달 = 5달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11달", "344일 = 11달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "일년", "345일 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "일년", "547일 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2년", "548일 = 2년"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "일년", "일년 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5년", "5년 = 5년"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('ko'); + test.equal(moment(30000).from(0), "몇초 후", "prefix"); + test.equal(moment(0).from(30000), "몇초 전", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('ko'); + test.equal(moment().fromNow(), "몇초 전", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('ko'); + test.equal(moment().add({s:30}).fromNow(), "몇초 후", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5일 후", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('ko'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "오늘 오전 2시 00분", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "오늘 오전 2시 25분", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "오늘 오전 3시 00분", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "내일 오전 2시 00분", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "오늘 오전 1시 00분", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "어제 오전 2시 00분", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('ko'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('ko'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('ko'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/kr.js b/node_modules/emailjs/node_modules/moment/test/lang/kr.js new file mode 100644 index 0000000..67314eb --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/kr.js @@ -0,0 +1,247 @@ +var moment = require("../../moment"); + + + /************************************************** + Korean + *************************************************/ + +exports["lang:kr"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('kr'); + var tests = '1월 1월_2월 2월_3월 3월_4월 4월_5월 5월_6월 6월_7월 7월_8월 8월_9월 9월_10월 10월_11월 11월_12월 12월'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + "format" : function(test) { + test.expect(18); + moment.lang('kr'); + var a = [ + ['YYYY년 MMMM Do dddd a h:mm:ss', '2010년 2월 14일 일요일 오후 3:25:50'], + ['ddd A h', '일 오후 3'], + ['M Mo MM MMMM MMM', '2 2일 02 2월 2월'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14일 14'], + ['d do dddd ddd dd', '0 0일 일요일 일 일'], + ['DDD DDDo DDDD', '45 45일 045'], + ['w wo ww', '8 8일 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '오후 오후'], + ['일년 중 DDDo째 되는 날', '일년 중 45일째 되는 날'], + ['L', '2010.02.14'], + ['LL', '2010년 2월 14일'], + ['LLL', '2010년 2월 14일 오후 3시 25분'], + ['LLLL', '2010년 2월 14일 일요일 오후 3시 25분'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('kr'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1일', '1일'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2일', '2일'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3일', '3일'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4일', '4일'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5일', '5일'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6일', '6일'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7일', '7일'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8일', '8일'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9일', '9일'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10일', '10일'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11일', '11일'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12일', '12일'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13일', '13일'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14일', '14일'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15일', '15일'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16일', '16일'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17일', '17일'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18일', '18일'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19일', '19일'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20일', '20일'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21일', '21일'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22일', '22일'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23일', '23일'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24일', '24일'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25일', '25일'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26일', '26일'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27일', '27일'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28일', '28일'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29일', '29일'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30일', '30일'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31일', '31일'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('kr'); + var expected = '1월 1월_2월 2월_3월 3월_4월 4월_5월 5월_6월 6월_7월 7월_8월 8월_9월 9월_10월 10월_11월 11월_12월 12월'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('kr'); + var expected = '일요일 일 일_월요일 월 월_화요일 화 화_수요일 수 수_목요일 목 목_금요일 금 금_토요일 토 토'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('kr'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "몇초", "44초 = 몇초"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "일분", "45초 = 일분"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "일분", "89초 = 일분"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2분", "90초 = 2분"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44분", "44분 = 44분"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "한시간", "45분 = 한시간"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "한시간", "89분 = 한시간"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2시간", "90분 = 2시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5시간", "5시간 = 5시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21시간", "21시간 = 21시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "하루", "22시간 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "하루", "35시간 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2일", "36시간 = 2일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "하루", "하루 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5일", "5일 = 5일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25일", "25일 = 25일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "한달", "26일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "한달", "30일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "한달", "45일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2달", "46일 = 2달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2달", "75일 = 2달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3달", "76일 = 3달"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "한달", "1달 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5달", "5달 = 5달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11달", "344일 = 11달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "일년", "345일 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "일년", "547일 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2년", "548일 = 2년"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "일년", "일년 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5년", "5년 = 5년"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('kr'); + test.equal(moment(30000).from(0), "몇초 후", "prefix"); + test.equal(moment(0).from(30000), "몇초 전", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('kr'); + test.equal(moment().fromNow(), "몇초 전", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('kr'); + test.equal(moment().add({s:30}).fromNow(), "몇초 후", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5일 후", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('kr'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "오늘 오전 2시 00분", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "오늘 오전 2시 25분", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "오늘 오전 3시 00분", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "내일 오전 2시 00분", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "오늘 오전 1시 00분", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "어제 오전 2시 00분", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('kr'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('kr'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('kr'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/nb.js b/node_modules/emailjs/node_modules/moment/test/lang/nb.js new file mode 100644 index 0000000..6d0ab02 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/nb.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + Norwegian bokmål + *************************************************/ + +exports["lang:nb"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('nb'); + var tests = 'januar jan_februar feb_mars mar_april apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('nb'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'søndag, februar 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'søn, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 februar feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. søndag søn sø'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '2010-02-14'], + ['LL', '14 februar 2010'], + ['LLL', '14 februar 2010 15:25'], + ['LLLL', 'søndag 14 februar 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('nb'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('nb'); + var expected = 'januar jan_februar feb_mars mar_april apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('nb'); + var expected = 'søndag søn sø_mandag man ma_tirsdag tir ti_onsdag ons on_torsdag tor to_fredag fre fr_lørdag lør lø'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('nb'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "noen sekunder", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ett minutt", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ett minutt", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutter", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutter", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "en time", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "en time", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timer", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timer", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timer", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dager", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dager", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dager", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en måned", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en måned", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en måned", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 måneder", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 måneder", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 måneder", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en måned", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 måneder", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 måneder", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ett år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ett år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ett år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('nb'); + test.equal(moment(30000).from(0), "om noen sekunder", "prefix"); + test.equal(moment(0).from(30000), "for noen sekunder siden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('nb'); + test.equal(moment().fromNow(), "for noen sekunder siden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('nb'); + test.equal(moment().add({s:30}).fromNow(), "om noen sekunder", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dager", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('nb'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "I dag klokken 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "I dag klokken 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "I dag klokken 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "I morgen klokken 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "I dag klokken 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "I går klokken 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('nb'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [klokken] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [klokken] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [klokken] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('nb'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Forrige] dddd [klokken] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Forrige] dddd [klokken] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Forrige] dddd [klokken] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('nb'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/nl.js b/node_modules/emailjs/node_modules/moment/test/lang/nl.js new file mode 100644 index 0000000..6d65255 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/nl.js @@ -0,0 +1,258 @@ +var moment = require("../../moment"); + + + /************************************************** + Dutch + *************************************************/ + +exports["lang:nl"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('nl'); + var tests = 'januari jan._februari feb._maart mrt._april apr._mei mei._juni jun._juli jul._augustus aug._september sep._oktober okt._november nov._december dec.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('nl'); + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'zondag, februari 14de 2010, 15:25:50'], + ['ddd, HH', 'zo., 15'], + ['M Mo MM MMMM MMM', '2 2de 02 februari feb.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14de 14'], + ['d do dddd ddd dd', '0 0de zondag zo. Zo'], + ['DDD DDDo DDDD', '45 45ste 045'], + ['w wo ww', '8 8ste 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45ste day of the year'], + ['L', '14-02-2010'], + ['LL', '14 februari 2010'], + ['LLL', '14 februari 2010 15:25'], + ['LLLL', 'zondag 14 februari 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('nl'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1ste', '1ste'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2de', '2de'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3de', '3de'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4de', '4de'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5de', '5de'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6de', '6de'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7de', '7de'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8ste', '8ste'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9de', '9de'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10de', '10de'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11de', '11de'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12de', '12de'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13de', '13de'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14de', '14de'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15de', '15de'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16de', '16de'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17de', '17de'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18de', '18de'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19de', '19de'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20ste', '20ste'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21ste', '21ste'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22ste', '22ste'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23ste', '23ste'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24ste', '24ste'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25ste', '25ste'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26ste', '26ste'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27ste', '27ste'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28ste', '28ste'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29ste', '29ste'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30ste', '30ste'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31ste', '31ste'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('nl'); + var expected = 'januari jan._februari feb._maart mrt._april apr._mei mei_juni jun._juli jul._augustus aug._september sep._oktober okt._november nov._december dec.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('nl'); + var expected = 'zondag zo. Zo_maandag ma. Ma_dinsdag di. Di_woensdag wo. Wo_donderdag do. Do_vrijdag vr. Vr_zaterdag za. Za'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('nl'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "een paar seconden", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "één minuut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "één minuut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuten", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuten", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "één uur", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "één uur", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 uur", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 uur", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 uur", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "één dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "één dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagen", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "één dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagen", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagen", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "één maand", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "één maand", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "één maand", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 maanden", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 maanden", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 maanden", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "één maand", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 maanden", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 maanden", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "één jaar", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "één jaar", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 jaar", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "één jaar", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 jaar", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('nl'); + test.equal(moment(30000).from(0), "over een paar seconden", "prefix"); + test.equal(moment(0).from(30000), "een paar seconden geleden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('nl'); + test.equal(moment().fromNow(), "een paar seconden geleden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('nl'); + test.equal(moment().add({s:30}).fromNow(), "over een paar seconden", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "over 5 dagen", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('nl'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Vandaag om 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Vandaag om 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Vandaag om 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Morgen om 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Vandaag om 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Gisteren om 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('nl'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [om] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [om] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [om] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('nl'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('nl'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "month abbreviation" : function(test) { + test.expect(2); + moment.lang('nl'); + + test.equal(moment([2012, 5, 23]).format('D-MMM-YYYY'), '23-jun-2012', 'format month abbreviation surrounded by dashes should not include a dot'); + test.equal(moment([2012, 5, 23]).format('D MMM YYYY'), '23 jun. 2012', 'format month abbreviation not surrounded by dashes should include a dot'); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/pl.js b/node_modules/emailjs/node_modules/moment/test/lang/pl.js new file mode 100644 index 0000000..9e315f5 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/pl.js @@ -0,0 +1,249 @@ +var moment = require("../../moment"); + + + /************************************************** + Polish + *************************************************/ + +exports["lang:pl"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('pl'); + var tests = 'styczeń sty_luty lut_marzec mar_kwiecień kwi_maj maj_czerwiec cze_lipiec lip_sierpień sie_wrzesień wrz_październik paź_listopad lis_grudzień gru'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('pl'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'niedziela, luty 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'nie, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 luty lut'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. niedziela nie N'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '14-02-2010'], + ['LL', '14 luty 2010'], + ['LLL', '14 luty 2010 15:25'], + ['LLLL', 'niedziela, 14 luty 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('pl'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('pl'); + var expected = 'styczeń sty_luty lut_marzec mar_kwiecień kwi_maj maj_czerwiec cze_lipiec lip_sierpień sie_wrzesień wrz_październik paź_listopad lis_grudzień gru'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('pl'); + var expected = 'niedziela nie N_poniedziałek pon Pn_wtorek wt Wt_środa śr Śr_czwartek czw Cz_piątek pt Pt_sobota sb So'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('pl'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "kilka sekund", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuty", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuty", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "godzina", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "godzina", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 godziny", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 godzin", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 godzin", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1 dzień", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1 dzień", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dni", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1 dzień", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dni", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dni", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "miesiąc", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "miesiąc", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "miesiąc", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 miesiące", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 miesiące", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 miesiące", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "miesiąc", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 miesięcy", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 miesięcy", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "rok", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "rok", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 lata", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "rok", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 lat", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('pl'); + test.equal(moment(30000).from(0), "za kilka sekund", "prefix"); + test.equal(moment(0).from(30000), "kilka sekund temu", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('pl'); + test.equal(moment().fromNow(), "kilka sekund temu", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(3); + moment.lang('pl'); + test.equal(moment().add({s:30}).fromNow(), "za kilka sekund", "in a few seconds"); + test.equal(moment().add({h:1}).fromNow(), "za godzinę", "in an hour"); + test.equal(moment().add({d:5}).fromNow(), "za 5 dni", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('pl'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Dziś o 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Dziś o 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Dziś o 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Jutro o 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Dziś o 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Wczoraj o 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('pl'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[W] dddd [o] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[W] dddd [o] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[W] dddd [o] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('pl'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[W zeszły/łą] dddd [o] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[W zeszły/łą] dddd [o] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[W zeszły/łą] dddd [o] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('pl'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/pt-br.js b/node_modules/emailjs/node_modules/moment/test/lang/pt-br.js new file mode 100644 index 0000000..9f6b935 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/pt-br.js @@ -0,0 +1,241 @@ +var moment = require("../../moment"); + + + /************************************************** + Portuguese - Brazilian + *************************************************/ + +exports["lang:pt-br"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('pt-br'); + var tests = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('pt-br'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domingo, Fevereiro 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom, 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Fevereiro Fev'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd', '0 0º Domingo Dom'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '8 8º 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 de Fevereiro de 2010'], + ['LLL', '14 de Fevereiro de 2010 15:25'], + ['LLLL', 'Domingo, 14 de Fevereiro de 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('pt-br'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('pt-br'); + var expected = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('pt-br'); + var expected = 'Domingo Dom_Segunda-feira Seg_Terça-feira Ter_Quarta-feira Qua_Quinta-feira Qui_Sexta-feira Sex_Sábado Sáb'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('pt-br'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "segundos", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "um minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "um minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "uma hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "uma hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "um dia", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "um dia", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dias", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "um dia", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dias", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dias", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "um mês", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "um mês", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "um mês", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "um mês", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "um ano", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "um ano", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anos", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "um ano", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anos", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('pt-br'); + test.equal(moment(30000).from(0), "em segundos", "prefix"); + test.equal(moment(0).from(30000), "segundos atrás", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('pt-br'); + test.equal(moment().add({s:30}).fromNow(), "em segundos", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "em 5 dias", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('pt-br'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hoje às 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hoje às 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hoje às 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Amanhã às 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hoje às 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ontem às 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('pt-br'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('pt-br'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('pt-br'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/pt.js b/node_modules/emailjs/node_modules/moment/test/lang/pt.js new file mode 100644 index 0000000..27731d8 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/pt.js @@ -0,0 +1,241 @@ +var moment = require("../../moment"); + + + /************************************************** + Portuguese + *************************************************/ + +exports["lang:pt"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('pt'); + var tests = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('pt'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domingo, Fevereiro 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom, 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Fevereiro Fev'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd dd', '0 0º Domingo Dom Dom'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '8 8º 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 de Fevereiro de 2010'], + ['LLL', '14 de Fevereiro de 2010 15:25'], + ['LLLL', 'Domingo, 14 de Fevereiro de 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('pt'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('pt'); + var expected = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('pt'); + var expected = 'Domingo Dom Dom_Segunda-feira Seg 2ª_Terça-feira Ter 3ª_Quarta-feira Qua 4ª_Quinta-feira Qui 5ª_Sexta-feira Sex 6ª_Sábado Sáb Sáb'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('pt'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "segundos", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "um minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "um minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "uma hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "uma hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "um dia", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "um dia", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dias", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "um dia", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dias", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dias", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "um mês", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "um mês", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "um mês", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "um mês", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "um ano", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "um ano", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anos", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "um ano", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anos", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('pt'); + test.equal(moment(30000).from(0), "em segundos", "prefix"); + test.equal(moment(0).from(30000), "segundos atrás", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('pt'); + test.equal(moment().add({s:30}).fromNow(), "em segundos", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "em 5 dias", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('pt'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hoje às 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hoje às 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hoje às 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Amanhã às 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hoje às 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ontem às 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('pt'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('pt'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('pt'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/ru.js b/node_modules/emailjs/node_modules/moment/test/lang/ru.js new file mode 100644 index 0000000..05af6a0 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/ru.js @@ -0,0 +1,280 @@ +var moment = require("../../moment"); + + + /************************************************** + Russian + *************************************************/ + +exports["lang:ru"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('ru'); + var tests = 'январь янв_февраль фев_март мар_апрель апр_май май_июнь июн_июль июл_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('ru'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'воскресенье, февраль 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'вск, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 февраль фев'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. воскресенье вск вс'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '8 8. 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45. day of the year'], + ['L', '14.02.2010'], + ['LL', '14 февраля 2010 г.'], + ['LLL', '14 февраля 2010 г., 15:25'], + ['LLLL', 'воскресенье, 14 февраля 2010 г., 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('ru'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('ru'); + var expected = 'январь янв_февраль фев_март мар_апрель апр_май май_июнь июн_июль июл_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format month case" : function(test) { + test.expect(24); + moment.lang('ru'); + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }; + var i; + for (i = 0; i < 12; i++) { + test.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + test.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('ru'); + var expected = 'воскресенье вск вс_понедельник пнд пн_вторник втр вт_среда срд ср_четверг чтв чт_пятница птн пт_суббота сбт сб'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(32); + moment.lang('ru'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "несколько секунд", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "минута", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "минута", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 минуты", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 минуты", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "час", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "час", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 часа", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 часов", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 час", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "день", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "день", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 дня", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "день", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 дней", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:11}), true), "11 дней", "11 days = 11 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:21}), true), "21 день", "21 days = 21 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 дней", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "месяц", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "месяц", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "месяц", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 месяца", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 месяца", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 месяца", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "месяц", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 месяцев", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 месяцев", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "год", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "год", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 года", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "год", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 лет", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('ru'); + test.equal(moment(30000).from(0), "через несколько секунд", "prefix"); + test.equal(moment(0).from(30000), "несколько секунд назад", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('ru'); + test.equal(moment().add({s:30}).fromNow(), "через несколько секунд", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "через 5 дней", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('ru'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Сегодня в 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Сегодня в 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Сегодня в 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Завтра в 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Сегодня в 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Вчера в 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('ru'); + + var i; + var m; + + function makeFormat(d) { + return d.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; + } + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('ru'); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('ru'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/sv.js b/node_modules/emailjs/node_modules/moment/test/lang/sv.js new file mode 100644 index 0000000..43c7f60 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/sv.js @@ -0,0 +1,248 @@ +var moment = require("../../moment"); + + + /************************************************** + English + *************************************************/ + +exports["lang:sv"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('sv'); + var tests = 'januari jan_februari feb_mars mar_april apr_maj maj_juni jun_juli jul_augusti aug_september sep_oktober okt_november nov_december dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('sv'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'söndag, februari 14e 2010, 3:25:50 pm'], + ['ddd, hA', 'sön, 3PM'], + ['M Mo MM MMMM MMM', '2 2a 02 februari feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14e 14'], + ['d do dddd ddd dd', '0 0e söndag sön sö'], + ['DDD DDDo DDDD', '45 45e 045'], + ['w wo ww', '8 8e 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45e day of the year'], + ['L', '2010-02-14'], + ['LL', '14 februari 2010'], + ['LLL', '14 februari 2010 15:25'], + ['LLLL', 'söndag 14 februari 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('sv'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1a', '1a'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2a', '2a'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3e', '3e'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4e', '4e'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5e', '5e'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6e', '6e'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7e', '7e'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8e', '8e'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9e', '9e'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10e', '10e'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11e', '11e'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12e', '12e'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13e', '13e'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14e', '14e'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15e', '15e'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16e', '16e'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17e', '17e'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18e', '18e'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19e', '19e'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20e', '20e'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21a', '21a'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22a', '22a'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23e', '23e'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24e', '24e'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25e', '25e'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26e', '26e'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27e', '27e'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28e', '28e'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29e', '29e'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30e', '30e'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31a', '31a'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('sv'); + var expected = 'januari jan_februari feb_mars mar_april apr_maj maj_juni jun_juli jul_augusti aug_september sep_oktober okt_november nov_december dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('sv'); + var expected = 'söndag sön sö_måndag mån må_tisdag tis ti_onsdag ons on_torsdag tor to_fredag fre fr_lördag lör lö'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('sv'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "några sekunder", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "en minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "en minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuter", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuter", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "en timme", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "en timme", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timmar", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timmar", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timmar", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagar", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagar", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagar", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en månad", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en månad", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en månad", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 månader", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 månader", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 månader", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en månad", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 månader", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 månader", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ett år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ett år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ett år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('sv'); + test.equal(moment(30000).from(0), "om några sekunder", "prefix"); + test.equal(moment(0).from(30000), "för några sekunder sen", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('sv'); + test.equal(moment().fromNow(), "för några sekunder sen", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('sv'); + test.equal(moment().add({s:30}).fromNow(), "om några sekunder", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dagar", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('sv'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Idag klockan 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Idag klockan 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Idag klockan 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Imorgon klockan 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Idag klockan 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Igår klockan 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('sv'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [klockan] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [klockan] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [klockan] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('sv'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Förra] dddd[en klockan] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Förra] dddd[en klockan] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Förra] dddd[en klockan] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('sv'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/tr.js b/node_modules/emailjs/node_modules/moment/test/lang/tr.js new file mode 100644 index 0000000..2fce8a3 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/tr.js @@ -0,0 +1,259 @@ +var moment = require("../../moment"); + + + /************************************************** + Turkish + *************************************************/ + +exports["lang:tr"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('tr'); + var tests = 'Ocak Oca_Şubat Şub_Mart Mar_Nisan Nis_Mayıs May_Haziran Haz_Temmuz Tem_Ağustos Ağu_Eylül Eyl_Ekim Eki_Kasım Kas_Aralık Ara'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + moment.lang('tr'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Pazar, Şubat 14\'üncü 2010, 3:25:50 pm'], + ['ddd, hA', 'Paz, 3PM'], + ['M Mo MM MMMM MMM', '2 2\'nci 02 Şubat Şub'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14\'üncü 14'], + ['d do dddd ddd dd', '0 0\'ıncı Pazar Paz Pz'], + ['DDD DDDo DDDD', '45 45\'inci 045'], + ['w wo ww', '8 8\'inci 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['yılın DDDo günü', 'yılın 45\'inci günü'], + ['L', '14.02.2010'], + ['LL', '14 Şubat 2010'], + ['LLL', '14 Şubat 2010 15:25'], + ['LLLL', 'Pazar, 14 Şubat 2010 15:25'] + ], + DDDo = [ + [359, '360\'ıncı'], + [199, '200\'üncü'], + [149, '150\'nci'] + ], + dt = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + DDDoDt, + i; + test.expect(a.length + DDDo.length); + + for (i = 0; i < a.length; i++) { + test.equal(dt.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + for (i = 0; i < DDDo.length; i++) { + DDDoDt = moment([2010]); + test.equal(DDDoDt.add('days', DDDo[i][0]).format('DDDo'), DDDo[i][1], DDDo[i][0] + ' ---> ' + DDDo[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('tr'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1\'inci', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2\'nci', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3\'üncü', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4\'üncü', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5\'inci', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6\'ncı', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7\'nci', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8\'inci', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9\'uncu', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10\'uncu', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11\'inci', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12\'nci', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13\'üncü', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14\'üncü', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15\'inci', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16\'ncı', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17\'nci', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18\'inci', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19\'uncu', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20\'nci', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21\'inci', '21th'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22\'nci', '22th'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23\'üncü', '23th'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24\'üncü', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25\'inci', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26\'ncı', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27\'nci', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28\'inci', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29\'uncu', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30\'uncu', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31\'inci', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('tr'); + var expected = 'Ocak Oca_Şubat Şub_Mart Mar_Nisan Nis_Mayıs May_Haziran Haz_Temmuz Tem_Ağustos Ağu_Eylül Eyl_Ekim Eki_Kasım Kas_Aralık Ara'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('tr'); + var expected = 'Pazar Paz Pz_Pazartesi Pts Pt_Salı Sal Sa_Çarşamba Çar Ça_Perşembe Per Pe_Cuma Cum Cu_Cumartesi Cts Ct'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('tr'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "birkaç saniye", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "bir dakika", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "bir dakika", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 dakika", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 dakika", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "bir saat", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "bir saat", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 saat", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 saat", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 saat", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "bir gün", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "bir gün", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 gün", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "bir gün", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 gün", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 gün", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "bir ay", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "bir ay", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "bir ay", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 ay", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 ay", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 ay", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "bir ay", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 ay", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 ay", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "bir yıl", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "bir yıl", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 yıl", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "bir yıl", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 yıl", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('tr'); + test.equal(moment(30000).from(0), "birkaç saniye sonra", "prefix"); + test.equal(moment(0).from(30000), "birkaç saniye önce", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('tr'); + test.equal(moment().fromNow(), "birkaç saniye önce", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('tr'); + test.equal(moment().add({s:30}).fromNow(), "birkaç saniye sonra", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 gün sonra", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('tr'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "bugün saat 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "bugün saat 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "bugün saat 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "yarın saat 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "bugün saat 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "dün 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('tr'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('tr'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('tr'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/zh-cn.js b/node_modules/emailjs/node_modules/moment/test/lang/zh-cn.js new file mode 100644 index 0000000..7bcfef5 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/zh-cn.js @@ -0,0 +1,227 @@ +var moment = require("../../moment"); + + + /************************************************** + Simplified Chinese + *************************************************/ + +exports["lang:zh-cn"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('zh-cn'); + var tests = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('zh-cn'); + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '星期日, 二月 14 2010, 下午 3:25:50'], + ['ddd, Ah', '周日, 下午3'], + ['M Mo MM MMMM MMM', '2 2 02 二月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 星期日 周日 日'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '下午 下午'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45 day of the year'], + ['L', '2010年2月14日'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日下午3点25'], + ['LLLL', '2010年2月14日星期日下午3点25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('zh-cn'); + var expected = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('zh-cn'); + var expected = '星期日 周日 日_星期一 周一 一_星期二 周二 二_星期三 周三 三_星期四 周四 四_星期五 周五 五_星期六 周六 六'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('zh-cn'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "几秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "1分钟", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "1分钟", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分钟", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分钟", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "1小时", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "1小时", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2小时", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5小时", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21小时", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1天", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1天", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2天", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1天", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5天", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25天", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "1个月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "1个月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "1个月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2个月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2个月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3个月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "1个月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5个月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11个月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "1年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "1年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "1年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('zh-cn'); + test.equal(moment(30000).from(0), "几秒内", "prefix"); + test.equal(moment(0).from(30000), "几秒前", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('zh-cn'); + test.equal(moment().fromNow(), "几秒前", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('zh-cn'); + test.equal(moment().add({s:30}).fromNow(), "几秒内", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5天内", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('zh-cn'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今天早上2点00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今天早上2点25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今天早上3点00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明天早上2点00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今天早上1点00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨天早上2点00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('zh-cn'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('zh-cn'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('zh-cn'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "meridiem" : function(test) { + test.expect(10); + moment.lang('zh-cn'); + + test.equal(moment([2011, 2, 23, 0, 0]).format('a'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('a'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('a'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('a'), "下午", "after noon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('a'), "晚上", "night"); + + test.equal(moment([2011, 2, 23, 0, 0]).format('A'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('A'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('A'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('A'), "下午", "afternoon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('A'), "晚上", "night"); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/lang/zh-tw.js b/node_modules/emailjs/node_modules/moment/test/lang/zh-tw.js new file mode 100644 index 0000000..bba8cc4 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/lang/zh-tw.js @@ -0,0 +1,227 @@ +var moment = require("../../moment"); + + + /************************************************** + Traditional Chinese + *************************************************/ + +exports["lang:zh-tw"] = { + "parse" : function(test) { + test.expect(96); + moment.lang('zh-tw'); + var tests = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + moment.lang('zh-tw'); + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '星期日, 二月 14 2010, 下午 3:25:50'], + ['ddd, Ah', '週日, 下午3'], + ['M Mo MM MMMM MMM', '2 2 02 二月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 星期日 週日 日'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '下午 下午'], + ['t\\he DDDo \\d\\ay of t\\he ye\\ar', 'the 45 day of the year'], + ['L', '2010年2月14日'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日下午3點25'], + ['LLLL', '2010年2月14日星期日下午3點25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('zh-tw'); + var expected = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('zh-tw'); + var expected = '星期日 週日 日_星期一 週一 一_星期二 週二 二_星期三 週三 三_星期四 週四 四_星期五 週五 五_星期六 週六 六'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('zh-tw'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "幾秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "一分鐘", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "一分鐘", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分鐘", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分鐘", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "一小時", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "一小時", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2小時", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5小時", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21小時", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "一天", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "一天", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2天", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "一天", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5天", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25天", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "一個月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "一個月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "一個月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2個月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2個月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3個月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "一個月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5個月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11個月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "一年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "一年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "一年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('zh-tw'); + test.equal(moment(30000).from(0), "幾秒內", "prefix"); + test.equal(moment(0).from(30000), "幾秒前", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('zh-tw'); + test.equal(moment().fromNow(), "幾秒前", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('zh-tw'); + test.equal(moment().add({s:30}).fromNow(), "幾秒內", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5天內", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('zh-tw'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今天早上2點00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今天早上2點25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今天早上3點00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明天早上2點00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今天早上1點00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨天早上2點00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('zh-tw'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('zh-tw'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('zh-tw'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "meridiem" : function(test) { + test.expect(10); + moment.lang('zh-cn'); + + test.equal(moment([2011, 2, 23, 0, 0]).format('a'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('a'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('a'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('a'), "下午", "after noon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('a'), "晚上", "night"); + + test.equal(moment([2011, 2, 23, 0, 0]).format('A'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('A'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('A'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('A'), "下午", "afternoon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('A'), "晚上", "night"); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/add_subtract.js b/node_modules/emailjs/node_modules/moment/test/moment/add_subtract.js new file mode 100644 index 0000000..1241bef --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/add_subtract.js @@ -0,0 +1,128 @@ +var moment = require("../../moment"); + +exports.add_subtract = { + "add and subtract short" : function(test) { + test.expect(12); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add({ms:50}).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add({s:1}).seconds(), 9, 'Add seconds'); + test.equal(a.add({m:1}).minutes(), 8, 'Add minutes'); + test.equal(a.add({h:1}).hours(), 7, 'Add hours'); + test.equal(a.add({d:1}).date(), 13, 'Add date'); + test.equal(a.add({w:1}).date(), 20, 'Add week'); + test.equal(a.add({M:1}).month(), 10, 'Add month'); + test.equal(a.add({y:1}).year(), 2012, 'Add year'); + + var b = moment([2010, 0, 31]).add({M:1}); + var c = moment([2010, 1, 28]).subtract({M:1}); + + test.equal(b.month(), 1, 'add month, jan 31st to feb 28th'); + test.equal(b.date(), 28, 'add month, jan 31st to feb 28th'); + test.equal(c.month(), 0, 'subtract month, feb 28th to jan 28th'); + test.equal(c.date(), 28, 'subtract month, feb 28th to jan 28th'); + test.done(); + }, + + "add and subtract long" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add({milliseconds:50}).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add({seconds:1}).seconds(), 9, 'Add seconds'); + test.equal(a.add({minutes:1}).minutes(), 8, 'Add minutes'); + test.equal(a.add({hours:1}).hours(), 7, 'Add hours'); + test.equal(a.add({days:1}).date(), 13, 'Add date'); + test.equal(a.add({weeks:1}).date(), 20, 'Add week'); + test.equal(a.add({months:1}).month(), 10, 'Add month'); + test.equal(a.add({years:1}).year(), 2012, 'Add year'); + test.done(); + }, + + "add and subtract string long" : function(test) { + test.expect(9); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + var b = a.clone(); + + test.equal(a.add('milliseconds', 50).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add('seconds', 1).seconds(), 9, 'Add seconds'); + test.equal(a.add('minutes', 1).minutes(), 8, 'Add minutes'); + test.equal(a.add('hours', 1).hours(), 7, 'Add hours'); + test.equal(a.add('days', 1).date(), 13, 'Add date'); + test.equal(a.add('weeks', 1).date(), 20, 'Add week'); + test.equal(a.add('months', 1).month(), 10, 'Add month'); + test.equal(a.add('years', 1).year(), 2012, 'Add year'); + test.equal(b.add('days', '01').date(), 13, 'Add date'); + test.done(); + }, + + "add and subtract string short" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add('ms', 50).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add('s', 1).seconds(), 9, 'Add seconds'); + test.equal(a.add('m', 1).minutes(), 8, 'Add minutes'); + test.equal(a.add('h', 1).hours(), 7, 'Add hours'); + test.equal(a.add('d', 1).date(), 13, 'Add date'); + test.equal(a.add('w', 1).date(), 20, 'Add week'); + test.equal(a.add('M', 1).month(), 10, 'Add month'); + test.equal(a.add('y', 1).year(), 2012, 'Add year'); + test.done(); + }, + + "add across DST" : function(test) { + test.expect(3); + + var a = moment(new Date(2011, 2, 12, 5, 0, 0)); + var b = moment(new Date(2011, 2, 12, 5, 0, 0)); + var c = moment(new Date(2011, 2, 12, 5, 0, 0)); + var d = moment(new Date(2011, 2, 12, 5, 0, 0)); + a.add('days', 1); + b.add('hours', 24); + c.add('months', 1); + test.equal(a.hours(), 5, 'adding days over DST difference should result in the same hour'); + if (b.isDST() && !d.isDST()) { + test.equal(b.hours(), 6, 'adding hours over DST difference should result in a different hour'); + } else if (!b.isDST() && d.isDST()) { + test.equal(b.hours(), 4, 'adding hours over DST difference should result in a different hour'); + } else { + test.equal(b.hours(), 5, 'adding hours over DST difference should result in a same hour if the timezone does not have daylight savings time'); + } + test.equal(c.hours(), 5, 'adding months over DST difference should result in the same hour'); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/create.js b/node_modules/emailjs/node_modules/moment/test/moment/create.js new file mode 100644 index 0000000..480386d --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/create.js @@ -0,0 +1,319 @@ +var moment = require("../../moment"); + +exports.create = { + "array" : function(test) { + test.expect(8); + test.ok(moment([2010]).toDate() instanceof Date, "[2010]"); + test.ok(moment([2010, 1]).toDate() instanceof Date, "[2010, 1]"); + test.ok(moment([2010, 1, 12]).toDate() instanceof Date, "[2010, 1, 12]"); + test.ok(moment([2010, 1, 12, 1]).toDate() instanceof Date, "[2010, 1, 12, 1]"); + test.ok(moment([2010, 1, 12, 1, 1]).toDate() instanceof Date, "[2010, 1, 12, 1, 1]"); + test.ok(moment([2010, 1, 12, 1, 1, 1]).toDate() instanceof Date, "[2010, 1, 12, 1, 1, 1]"); + test.ok(moment([2010, 1, 12, 1, 1, 1, 1]).toDate() instanceof Date, "[2010, 1, 12, 1, 1, 1, 1]"); + test.equal(+moment(new Date(2010, 1, 14, 15, 25, 50, 125)), +moment([2010, 1, 14, 15, 25, 50, 125]), "constructing with array === constructing with new Date()"); + test.done(); + }, + + "number" : function(test) { + test.expect(3); + test.ok(moment(1000).toDate() instanceof Date, "1000"); + test.ok((moment(1000).valueOf() === 1000), "testing valueOf"); + test.ok((moment.utc(1000).valueOf() === 1000), "testing valueOf"); + test.done(); + }, + + "unix" : function(test) { + test.expect(8); + test.equal(moment.unix(1).valueOf(), 1000, "1 unix timestamp == 1000 Date.valueOf"); + test.equal(moment(1000).unix(), 1, "1000 Date.valueOf == 1 unix timestamp"); + test.equal(moment.unix(1000).valueOf(), 1000000, "1000 unix timestamp == 1000000 Date.valueOf"); + test.equal(moment(1500).unix(), 1, "1500 Date.valueOf == 1 unix timestamp"); + test.equal(moment(1900).unix(), 1, "1900 Date.valueOf == 1 unix timestamp"); + test.equal(moment(2100).unix(), 2, "2100 Date.valueOf == 2 unix timestamp"); + test.equal(moment(1333129333524).unix(), 1333129333, "1333129333524 Date.valueOf == 1333129333 unix timestamp"); + test.equal(moment(1333129333524000).unix(), 1333129333524, "1333129333524000 Date.valueOf == 1333129333524 unix timestamp"); + test.done(); + }, + + "date" : function(test) { + test.expect(1); + test.ok(moment(new Date()).toDate() instanceof Date, "new Date()"); + test.done(); + }, + + "moment" : function(test) { + test.expect(2); + test.ok(moment(moment()).toDate() instanceof Date, "moment(moment())"); + test.ok(moment(moment(moment())).toDate() instanceof Date, "moment(moment(moment()))"); + test.done(); + }, + + "undefined" : function(test) { + test.expect(1); + test.ok(moment().toDate() instanceof Date, "undefined"); + test.done(); + }, + + "string without format" : function(test) { + test.expect(2); + test.ok(moment("Aug 9, 1995").toDate() instanceof Date, "Aug 9, 1995"); + test.ok(moment("Mon, 25 Dec 1995 13:30:00 GMT").toDate() instanceof Date, "Mon, 25 Dec 1995 13:30:00 GMT"); + test.done(); + }, + + "string from Date.toString" : function(test) { + test.expect(1); + var str = (new Date()).toString(); + test.equal(moment(str).toString(), str, "Parsing a string from Date.prototype.toString should match moment.fn.toString"); + test.done(); + }, + + "string without format - json" : function(test) { + test.expect(5); + test.equal(moment("Date(1325132654000)").valueOf(), 1325132654000, "Date(1325132654000)"); + test.equal(moment("Date(-1325132654000)").valueOf(), -1325132654000, "Date(-1325132654000)"); + test.equal(moment("/Date(1325132654000)/").valueOf(), 1325132654000, "/Date(1325132654000)/"); + test.equal(moment("/Date(1325132654000+0700)/").valueOf(), 1325132654000, "/Date(1325132654000+0700)/"); + test.equal(moment("/Date(1325132654000-0700)/").valueOf(), 1325132654000, "/Date(1325132654000-0700)/"); + test.done(); + }, + + "string with format dropped am/pm bug" : function(test) { + moment.lang('en'); + test.expect(3); + + test.equal(moment('05/1/2012', 'MM/DD/YYYY h:m:s a').format('MM/DD/YYYY'), '05/01/2012', 'should not break if am/pm is left off from the parsing tokens'); + test.equal(moment('05/1/2012 12:25:00 am', 'MM/DD/YYYY h:m:s a').format('MM/DD/YYYY'), '05/01/2012', 'should not break if am/pm is left off from the parsing tokens'); + test.equal(moment('05/1/2012 12:25:00 pm', 'MM/DD/YYYY h:m:s a').format('MM/DD/YYYY'), '05/01/2012', 'should not break if am/pm is left off from the parsing tokens'); + + test.done(); + }, + + "empty string with formats" : function(test) { + test.expect(3); + + test.equal(moment(' ', 'MM').format('YYYY-MM-DD HH:mm:ss'), '0000-01-01 00:00:00', 'should not break if input is an empty string'); + test.equal(moment(' ', 'DD').format('YYYY-MM-DD HH:mm:ss'), '0000-01-01 00:00:00', 'should not break if input is an empty string'); + test.equal(moment(' ', ['MM', "DD"]).format('YYYY-MM-DD HH:mm:ss'), '0000-01-01 00:00:00', 'should not break if input is an empty string'); + + test.done(); + }, + + "string with format" : function(test) { + moment.lang('en'); + var a = [ + ['MM-DD-YYYY', '12-02-1999'], + ['DD-MM-YYYY', '12-02-1999'], + ['DD/MM/YYYY', '12/02/1999'], + ['DD_MM_YYYY', '12_02_1999'], + ['DD:MM:YYYY', '12:02:1999'], + ['D-M-YY', '2-2-99'], + ['YY', '99'], + ['DDD-YYYY', '300-1999'], + ['DD-MM-YYYY h:m:s', '12-02-1999 2:45:10'], + ['DD-MM-YYYY h:m:s a', '12-02-1999 2:45:10 am'], + ['DD-MM-YYYY h:m:s a', '12-02-1999 2:45:10 pm'], + ['h:mm a', '12:00 pm'], + ['h:mm a', '12:30 pm'], + ['h:mm a', '12:00 am'], + ['h:mm a', '12:30 am'], + ['HH:mm', '12:00'], + ['YYYY-MM-DDTHH:mm:ss', '2011-11-11T11:11:11'], + ['MM-DD-YYYY \\M', '12-02-1999 M'], + ['ddd MMM DD HH:mm:ss YYYY', 'Tue Apr 07 22:52:51 2009'], + ['HH:mm:ss', '12:00:00'], + ['HH:mm:ss', '12:30:00'], + ['HH:mm:ss', '00:00:00'], + ['HH:mm:ss S', '00:30:00 1'], + ['HH:mm:ss SS', '00:30:00 12'], + ['HH:mm:ss SSS', '00:30:00 123'], + ['HH:mm:ss S', '00:30:00 7'], + ['HH:mm:ss SS', '00:30:00 78'], + ['HH:mm:ss SSS', '00:30:00 789'] + ], + i; + + test.expect(a.length); + for (i = 0; i < a.length; i++) { + test.equal(moment(a[i][1], a[i][0]).format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "string with format no separators" : function(test) { + moment.lang('en'); + var a = [ + ['MMDDYYYY', '12021999'], + ['DDMMYYYY', '12021999'], + ['YYYYMMDD', '19991202'] + ],i; + + test.expect(a.length); + + for (i = 0; i < a.length; i++) { + test.equal(moment(a[i][1], a[i][0]).format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "string with format (timezone)" : function(test) { + test.expect(8); + test.equal(moment('5 -0700', 'H ZZ').toDate().getUTCHours(), 12, 'parse hours "5 -0700" ---> "H ZZ"'); + test.equal(moment('5 -07:00', 'H Z').toDate().getUTCHours(), 12, 'parse hours "5 -07:00" ---> "H Z"'); + test.equal(moment('5 -0730', 'H ZZ').toDate().getUTCMinutes(), 30, 'parse hours "5 -0730" ---> "H ZZ"'); + test.equal(moment('5 -07:30', 'H Z').toDate().getUTCMinutes(), 30, 'parse hours "5 -07:30" ---> "H Z"'); + test.equal(moment('5 +0100', 'H ZZ').toDate().getUTCHours(), 4, 'parse hours "5 +0100" ---> "H ZZ"'); + test.equal(moment('5 +01:00', 'H Z').toDate().getUTCHours(), 4, 'parse hours "5 +01:00" ---> "H Z"'); + test.equal(moment('5 +0130', 'H ZZ').toDate().getUTCMinutes(), 30, 'parse hours "5 +0130" ---> "H ZZ"'); + test.equal(moment('5 +01:30', 'H Z').toDate().getUTCMinutes(), 30, 'parse hours "5 +01:30" ---> "H Z"'); + test.done(); + }, + + "string with format (timezone offset)" : function(test) { + test.expect(4); + var a = new Date(Date.UTC(2011, 0, 1, 1)); + var b = moment('2011 1 1 0 -01:00', 'YYYY MM DD HH Z'); + test.equal(a.getHours(), b.hours(), 'date created with utc == parsed string with timezone offset'); + test.equal(+a, +b, 'date created with utc == parsed string with timezone offset'); + var c = moment('2011 2 1 10 -05:00', 'YYYY MM DD HH Z'); + var d = moment('2011 2 1 8 -07:00', 'YYYY MM DD HH Z'); + test.equal(c.hours(), d.hours(), '10 am central time == 8 am pacific time'); + var e = moment.utc('Fri, 20 Jul 2012 17:15:00', 'ddd, DD MMM YYYY HH:mm:ss'); + var f = moment.utc('Fri, 20 Jul 2012 10:15:00 -0700', 'ddd, DD MMM YYYY HH:mm:ss ZZ'); + test.equal(e.hours(), f.hours(), 'parse timezone offset in utc'); + test.done(); + }, + + "string with array of formats" : function(test) { + test.expect(3); + test.equal(moment('13-02-1999', ['MM-DD-YYYY', 'DD-MM-YYYY']).format('MM DD YYYY'), '02 13 1999', 'switching month and day'); + test.equal(moment('02-13-1999', ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY']).format('MM DD YYYY'), '02 13 1999', 'year last'); + test.equal(moment('1999-02-13', ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY']).format('MM DD YYYY'), '02 13 1999', 'year first'); + test.done(); + }, + + "string with format - years" : function(test) { + test.expect(2); + test.equal(moment('71', 'YY').format('YYYY'), '1971', '71 > 1971'); + test.equal(moment('69', 'YY').format('YYYY'), '2069', '69 > 2069'); + test.done(); + }, + + "implicit cloning" : function(test) { + test.expect(2); + var momentA = moment([2011, 10, 10]); + var momentB = moment(momentA); + momentA.month(5); + test.equal(momentB.month(), 10, "Calling moment() on a moment will create a clone"); + test.equal(momentA.month(), 5, "Calling moment() on a moment will create a clone"); + test.done(); + }, + + "explicit cloning" : function(test) { + test.expect(2); + var momentA = moment([2011, 10, 10]); + var momentB = momentA.clone(); + momentA.month(5); + test.equal(momentB.month(), 10, "Calling moment() on a moment will create a clone"); + test.equal(momentA.month(), 5, "Calling moment() on a moment will create a clone"); + test.done(); + }, + + "cloning carrying over utc mode" : function(test) { + test.expect(8); + + test.equal(moment().local().clone()._isUTC, false, "An explicit cloned local moment should have _isUTC == false"); + test.equal(moment().utc().clone()._isUTC, true, "An cloned utc moment should have _isUTC == true"); + test.equal(moment().clone()._isUTC, false, "An explicit cloned local moment should have _isUTC == false"); + test.equal(moment.utc().clone()._isUTC, true, "An explicit cloned utc moment should have _isUTC == true"); + test.equal(moment(moment().local())._isUTC, false, "An implicit cloned local moment should have _isUTC == false"); + test.equal(moment(moment().utc())._isUTC, true, "An implicit cloned utc moment should have _isUTC == true"); + test.equal(moment(moment())._isUTC, false, "An implicit cloned local moment should have _isUTC == false"); + test.equal(moment(moment.utc())._isUTC, true, "An implicit cloned utc moment should have _isUTC == true"); + + test.done(); + }, + + "parsing iso" : function(test) { + var offset = moment([2011, 9, 08]).zone(); + var pad = function(input) { + if (input < 10) { + return '0' + input; + } + return '' + input; + } + var hourOffset = (offset > 0) ? Math.floor(offset / 60) : Math.ceil(offset / 60); + var minOffset = offset - (hourOffset * 60); + var tz = (offset > 0) ? '-' + pad(hourOffset) + ':' + pad(minOffset) : '+' + pad(-hourOffset) + ':' + pad(-minOffset); + var tz2 = tz.replace(':', ''); + var formats = [ + ['2011-10-08', '2011-10-08T00:00:00.000' + tz], + ['2011-10-08T18', '2011-10-08T18:00:00.000' + tz], + ['2011-10-08T18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-10-08T18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-10-08T18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-10-08T18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-10-08T18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-10-08T18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz] + ]; + test.expect(formats.length); + for (var i = 0; i < formats.length; i++) { + test.equal(formats[i][1], moment(formats[i][0]).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), "moment should be able to parse ISO " + formats[i][0]); + } + test.done(); + }, + + "parsing iso Z timezone" : function(test) { + var i, + formats = [ + ['2011-10-08T18:04Z', '2011-10-08T18:04:00.000+00:00'], + ['2011-10-08T18:04:20Z', '2011-10-08T18:04:20.000+00:00'], + ['2011-10-08T18:04:20.111Z', '2011-10-08T18:04:20.111+00:00'] + ]; + test.expect(formats.length); + for (i = 0; i < formats.length; i++) { + test.equal(moment.utc(formats[i][0]).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), formats[i][1], "moment should be able to parse ISO " + formats[i][0]); + } + test.done(); + }, + + "parsing iso Z timezone into local" : function(test) { + test.expect(1); + + var m = moment('2011-10-08T18:04:20.111Z'); + + test.equal(m.utc().format('YYYY-MM-DDTHH:mm:ss.SSS'), '2011-10-08T18:04:20.111', "moment should be able to parse ISO 2011-10-08T18:04:20.111Z"); + + test.done(); + }, + + "null" : function(test) { + test.expect(3); + test.equal(moment(''), null, "Calling moment('')"); + test.equal(moment(null), null, "Calling moment(null)"); + test.equal(moment('', 'YYYY-MM-DD'), null, "Calling moment('', 'YYYY-MM-DD')"); + test.done(); + }, + + "first century" : function(test) { + test.expect(6); + test.equal(moment([0, 0, 1]).format("YYYY-MM-DD"), "0000-01-01", "Year AD 0"); + test.equal(moment([99, 0, 1]).format("YYYY-MM-DD"), "0099-01-01", "Year AD 99"); + test.equal(moment([999, 0, 1]).format("YYYY-MM-DD"), "0999-01-01", "Year AD 999"); + test.equal(moment('0 1 1', 'YYYY MM DD').format("YYYY-MM-DD"), "0000-01-01", "Year AD 0"); + test.equal(moment('99 1 1', 'YYYY MM DD').format("YYYY-MM-DD"), "0099-01-01", "Year AD 99"); + test.equal(moment('999 1 1', 'YYYY MM DD').format("YYYY-MM-DD"), "0999-01-01", "Year AD 999"); + test.done(); + }, + + "six digit years" : function(test) { + test.expect(2); + test.equal(moment([-270000, 0, 1]).format("YYYY-MM-DD"), "-270000-01-01", "format BC 270,000"); + test.equal(moment([ 270000, 0, 1]).format("YYYY-MM-DD"), "270000-01-01", "format AD 270,000"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/days_in_month.js b/node_modules/emailjs/node_modules/moment/test/moment/days_in_month.js new file mode 100644 index 0000000..ffa2546 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/days_in_month.js @@ -0,0 +1,28 @@ +var moment = require("../../moment"); + +exports.days_in_month = { + "days in month" : function(test) { + test.expect(24); + var months = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + for (var i = 0; i < 12; i++) { + test.equal(moment([2012, i]).daysInMonth(), + months[i], + moment([2012, i]).format('L') + " should have " + months[i] + " days. (beginning of month " + i + ')') + } + for (var i = 0; i < 12; i++) { + test.equal(moment([2012, i, months[i]]).daysInMonth(), + months[i], + moment([2012, i, months[i]]).format('L') + " should have " + months[i] + " days. (end of month " + i + ')') + } + test.done(); + }, + + "days in month leap years" : function(test) { + test.expect(4); + test.equal(moment([2010, 1]).daysInMonth(), 28, "Feb 2010 should have 28 days"); + test.equal(moment([2100, 1]).daysInMonth(), 28, "Feb 2100 should have 28 days"); + test.equal(moment([2008, 1]).daysInMonth(), 29, "Feb 2008 should have 29 days"); + test.equal(moment([2000, 1]).daysInMonth(), 29, "Feb 2000 should have 29 days"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/diff.js b/node_modules/emailjs/node_modules/moment/test/moment/diff.js new file mode 100644 index 0000000..849c166 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/diff.js @@ -0,0 +1,94 @@ +var moment = require("../../moment"); + +exports.diff = { + "diff" : function(test) { + test.expect(5); + + test.equal(moment(1000).diff(0), 1000, "1 second - 0 = 1000"); + test.equal(moment(1000).diff(500), 500, "1 second - 0.5 seconds = 500"); + test.equal(moment(0).diff(1000), -1000, "0 - 1 second = -1000"); + test.equal(moment(new Date(1000)).diff(1000), 0, "1 second - 1 second = 0"); + var oneHourDate = new Date(), + nowDate = new Date(); + oneHourDate.setHours(oneHourDate.getHours() + 1); + test.equal(moment(oneHourDate).diff(nowDate), 60 * 60 * 1000, "1 hour from now = 360000"); + test.done(); + }, + + "diff key after" : function(test) { + test.expect(9); + + test.equal(moment([2010]).diff([2011], 'years'), -1, "year diff"); + test.equal(moment([2010]).diff([2011, 6], 'years', true), -1.5, "year diff, float"); + test.equal(moment([2010]).diff([2010, 2], 'months'), -2, "month diff"); + test.equal(moment([2010]).diff([2010, 0, 7], 'weeks'), -1, "week diff"); + test.equal(moment([2010]).diff([2010, 0, 21], 'weeks'), -3, "week diff"); + test.equal(moment([2010]).diff([2010, 0, 4], 'days'), -3, "day diff"); + test.equal(moment([2010]).diff([2010, 0, 1, 4], 'hours'), -4, "hour diff"); + test.equal(moment([2010]).diff([2010, 0, 1, 0, 5], 'minutes'), -5, "minute diff"); + test.equal(moment([2010]).diff([2010, 0, 1, 0, 0, 6], 'seconds'), -6, "second diff"); + test.done(); + }, + + "diff key before" : function(test) { + test.expect(9); + + test.equal(moment([2011]).diff([2010], 'years'), 1, "year diff"); + test.equal(moment([2011, 6]).diff([2010], 'years', true), 1.5, "year diff, float"); + test.equal(moment([2010, 2]).diff([2010], 'months'), 2, "month diff"); + test.equal(moment([2010, 0, 4]).diff([2010], 'days'), 3, "day diff"); + test.equal(moment([2010, 0, 7]).diff([2010], 'weeks'), 1, "week diff"); + test.equal(moment([2010, 0, 21]).diff([2010], 'weeks'), 3, "week diff"); + test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hours'), 4, "hour diff"); + test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minutes'), 5, "minute diff"); + test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'seconds'), 6, "second diff"); + test.done(); + }, + + "diff month" : function(test) { + test.expect(1); + + test.equal(moment([2011, 0, 31]).diff([2011, 2, 1], 'months'), -1, "month diff"); + test.done(); + }, + + "diff across DST" : function(test) { + test.expect(2); + + test.equal(moment([2012, 2, 24]).diff([2012, 2, 10], 'weeks', true), 2, "diff weeks across DST"); + test.equal(moment([2012, 2, 24]).diff([2012, 2, 10], 'days', true), 14, "diff weeks across DST"); + test.done(); + }, + + "diff overflow" : function(test) { + test.expect(4); + + test.equal(moment([2011]).diff([2010], 'months'), 12, "month diff"); + test.equal(moment([2010, 0, 2]).diff([2010], 'hours'), 24, "hour diff"); + test.equal(moment([2010, 0, 1, 2]).diff([2010], 'minutes'), 120, "minute diff"); + test.equal(moment([2010, 0, 1, 0, 4]).diff([2010], 'seconds'), 240, "second diff"); + test.done(); + }, + + "diff between utc and local" : function(test) { + test.expect(7); + + test.equal(moment([2011]).utc().diff([2010], 'years'), 1, "year diff"); + test.equal(moment([2010, 2]).utc().diff([2010], 'months'), 2, "month diff"); + test.equal(moment([2010, 0, 4]).utc().diff([2010], 'days'), 3, "day diff"); + test.equal(moment([2010, 0, 21]).utc().diff([2010], 'weeks'), 3, "week diff"); + test.equal(moment([2010, 0, 1, 4]).utc().diff([2010], 'hours'), 4, "hour diff"); + test.equal(moment([2010, 0, 1, 0, 5]).utc().diff([2010], 'minutes'), 5, "minute diff"); + test.equal(moment([2010, 0, 1, 0, 0, 6]).utc().diff([2010], 'seconds'), 6, "second diff"); + + test.done(); + }, + + "year diffs include dates" : function(test) { + test.expect(1); + + test.ok(moment([2012, 1, 19]).diff(moment([2002, 1, 20]), 'years', true) < 10, "year diff should include date of month"); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/duration.js b/node_modules/emailjs/node_modules/moment/test/moment/duration.js new file mode 100644 index 0000000..37ac454 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/duration.js @@ -0,0 +1,212 @@ +var moment = require("../../moment"); + +exports.duration = { + "object instantiation" : function(test) { + var d = moment.duration({ + years: 2, + months: 3, + weeks: 2, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(8); + test.equal(d.years(), 2, "years"); + test.equal(d.months(), 3, "months"); + test.equal(d.weeks(), 2, "weeks"); + test.equal(d.days(), 15, "days"); // two weeks + 1 day + test.equal(d.hours(), 8, "hours"); + test.equal(d.minutes(), 9, "minutes"); + test.equal(d.seconds(), 20, "seconds"); + test.equal(d.milliseconds(), 12, "milliseconds"); + test.done(); + }, + + "milliseconds instantiation" : function(test) { + test.expect(1); + test.equal(moment.duration(72).milliseconds(), 72, "milliseconds"); + test.done(); + }, + + "instantiation by type" : function(test) { + test.expect(16); + test.equal(moment.duration(1, "years").years(), 1, "years"); + test.equal(moment.duration(1, "y").years(), 1, "y"); + test.equal(moment.duration(2, "months").months(), 2, "months"); + test.equal(moment.duration(2, "M").months(), 2, "M"); + test.equal(moment.duration(3, "weeks").weeks(), 3, "weeks"); + test.equal(moment.duration(3, "w").weeks(), 3, "weeks"); + test.equal(moment.duration(4, "days").days(), 4, "days"); + test.equal(moment.duration(4, "d").days(), 4, "d"); + test.equal(moment.duration(5, "hours").hours(), 5, "hours"); + test.equal(moment.duration(5, "h").hours(), 5, "h"); + test.equal(moment.duration(6, "minutes").minutes(), 6, "minutes"); + test.equal(moment.duration(6, "m").minutes(), 6, "m"); + test.equal(moment.duration(7, "seconds").seconds(), 7, "seconds"); + test.equal(moment.duration(7, "s").seconds(), 7, "s"); + test.equal(moment.duration(8, "milliseconds").milliseconds(), 8, "milliseconds"); + test.equal(moment.duration(8, "ms").milliseconds(), 8, "ms"); + test.done(); + }, + + "shortcuts" : function(test) { + test.expect(8); + test.equal(moment.duration({y: 1}).years(), 1, "years = y"); + test.equal(moment.duration({M: 2}).months(), 2, "months = M"); + test.equal(moment.duration({w: 3}).weeks(), 3, "weeks = w"); + test.equal(moment.duration({d: 4}).days(), 4, "days = d"); + test.equal(moment.duration({h: 5}).hours(), 5, "hours = h"); + test.equal(moment.duration({m: 6}).minutes(), 6, "minutes = m"); + test.equal(moment.duration({s: 7}).seconds(), 7, "seconds = s"); + test.equal(moment.duration({ms: 8}).milliseconds(), 8, "milliseconds = ms"); + test.done(); + }, + + "instantiation from another duration" : function(test) { + var simple = moment.duration(1234), + complicated = moment.duration({ + years: 2, + months: 3, + weeks: 4, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(2); + test.deepEqual(moment.duration(simple), simple, "simple clones are equal"); + test.deepEqual(moment.duration(complicated), complicated, "complicated clones are equal"); + test.done(); + }, + + "humanize" : function(test) { + test.expect(32); + moment.lang('en'); + test.equal(moment.duration({seconds: 44}).humanize(), "a few seconds", "44 seconds = a few seconds"); + test.equal(moment.duration({seconds: 45}).humanize(), "a minute", "45 seconds = a minute"); + test.equal(moment.duration({seconds: 89}).humanize(), "a minute", "89 seconds = a minute"); + test.equal(moment.duration({seconds: 90}).humanize(), "2 minutes", "90 seconds = 2 minutes"); + test.equal(moment.duration({minutes: 44}).humanize(), "44 minutes", "44 minutes = 44 minutes"); + test.equal(moment.duration({minutes: 45}).humanize(), "an hour", "45 minutes = an hour"); + test.equal(moment.duration({minutes: 89}).humanize(), "an hour", "89 minutes = an hour"); + test.equal(moment.duration({minutes: 90}).humanize(), "2 hours", "90 minutes = 2 hours"); + test.equal(moment.duration({hours: 5}).humanize(), "5 hours", "5 hours = 5 hours"); + test.equal(moment.duration({hours: 21}).humanize(), "21 hours", "21 hours = 21 hours"); + test.equal(moment.duration({hours: 22}).humanize(), "a day", "22 hours = a day"); + test.equal(moment.duration({hours: 35}).humanize(), "a day", "35 hours = a day"); + test.equal(moment.duration({hours: 36}).humanize(), "2 days", "36 hours = 2 days"); + test.equal(moment.duration({days: 1}).humanize(), "a day", "1 day = a day"); + test.equal(moment.duration({days: 5}).humanize(), "5 days", "5 days = 5 days"); + test.equal(moment.duration({weeks: 1}).humanize(), "7 days", "1 week = 7 days"); + test.equal(moment.duration({days: 25}).humanize(), "25 days", "25 days = 25 days"); + test.equal(moment.duration({days: 26}).humanize(), "a month", "26 days = a month"); + test.equal(moment.duration({days: 30}).humanize(), "a month", "30 days = a month"); + test.equal(moment.duration({days: 45}).humanize(), "a month", "45 days = a month"); + test.equal(moment.duration({days: 46}).humanize(), "2 months", "46 days = 2 months"); + test.equal(moment.duration({days: 74}).humanize(), "2 months", "75 days = 2 months"); + test.equal(moment.duration({days: 76}).humanize(), "3 months", "76 days = 3 months"); + test.equal(moment.duration({months: 1}).humanize(), "a month", "1 month = a month"); + test.equal(moment.duration({months: 5}).humanize(), "5 months", "5 months = 5 months"); + test.equal(moment.duration({days: 344}).humanize(), "11 months", "344 days = 11 months"); + test.equal(moment.duration({days: 345}).humanize(), "a year", "345 days = a year"); + test.equal(moment.duration({days: 547}).humanize(), "a year", "547 days = a year"); + test.equal(moment.duration({days: 548}).humanize(), "2 years", "548 days = 2 years"); + test.equal(moment.duration({years: 1}).humanize(), "a year", "1 year = a year"); + test.equal(moment.duration({years: 5}).humanize(), "5 years", "5 years = 5 years"); + test.equal(moment.duration(7200000).humanize(), "2 hours", "7200000 = 2 minutes"); + test.done(); + }, + + "humanize duration with suffix" : function(test) { + test.expect(2); + moment.lang('en'); + test.equal(moment.duration({seconds: 44}).humanize(true), "in a few seconds", "44 seconds = a few seconds"); + test.equal(moment.duration({seconds: -44}).humanize(true), "a few seconds ago", "44 seconds = a few seconds"); + test.done(); + }, + + "bubble value up" : function(test) { + test.expect(5); + test.equal(moment.duration({milliseconds: 61001}).milliseconds(), 1, "61001 milliseconds has 1 millisecond left over"); + test.equal(moment.duration({milliseconds: 61001}).seconds(), 1, "61001 milliseconds has 1 second left over"); + test.equal(moment.duration({milliseconds: 61001}).minutes(), 1, "61001 milliseconds has 1 minute left over"); + + test.equal(moment.duration({minutes: 350}).minutes(), 50, "350 minutes has 50 minutes left over"); + test.equal(moment.duration({minutes: 350}).hours(), 5, "350 minutes has 5 hours left over"); + test.done(); + }, + + "clipping" : function(test) { + test.expect(18); + test.equal(moment.duration({months: 11}).months(), 11, "11 months is 11 months"); + test.equal(moment.duration({months: 11}).years(), 0, "11 months makes no year"); + test.equal(moment.duration({months: 12}).months(), 0, "12 months is 0 months left over"); + test.equal(moment.duration({months: 12}).years(), 1, "12 months makes 1 year"); + test.equal(moment.duration({months: 13}).months(), 1, "13 months is 1 month left over"); + test.equal(moment.duration({months: 13}).years(), 1, "13 months makes 1 year"); + + test.equal(moment.duration({days: 29}).days(), 29, "29 days is 29 days"); + test.equal(moment.duration({days: 29}).months(), 0, "29 days makes no month"); + test.equal(moment.duration({days: 30}).days(), 0, "30 days is 0 days left over"); + test.equal(moment.duration({days: 30}).months(), 1, "30 days is a month"); + test.equal(moment.duration({days: 31}).days(), 1, "31 days is 1 day left over"); + test.equal(moment.duration({days: 31}).months(), 1, "31 days is a month"); + + test.equal(moment.duration({hours: 23}).hours(), 23, "23 hours is 23 hours"); + test.equal(moment.duration({hours: 23}).days(), 0, "23 hours makes no day"); + test.equal(moment.duration({hours: 24}).hours(), 0, "24 hours is 0 hours left over"); + test.equal(moment.duration({hours: 24}).days(), 1, "24 hours makes 1 day"); + test.equal(moment.duration({hours: 25}).hours(), 1, "25 hours is 1 hour left over"); + test.equal(moment.duration({hours: 25}).days(), 1, "25 hours makes 1 day"); + test.done(); + }, + + "effective equivalency" : function(test) { + test.expect(7); + test.deepEqual(moment.duration({seconds: 1})._data, moment.duration({milliseconds: 1000})._data, "1 second is the same as 1000 milliseconds"); + test.deepEqual(moment.duration({seconds: 60})._data, moment.duration({minutes: 1})._data, "1 minute is the same as 60 seconds"); + test.deepEqual(moment.duration({minutes: 60})._data, moment.duration({hours: 1})._data, "1 hour is the same as 60 minutes"); + test.deepEqual(moment.duration({hours: 24})._data, moment.duration({days: 1})._data, "1 day is the same as 24 hours"); + test.deepEqual(moment.duration({days: 7})._data, moment.duration({weeks: 1})._data, "1 week is the same as 7 days"); + test.deepEqual(moment.duration({days: 30})._data, moment.duration({months: 1})._data, "1 month is the same as 30 days"); + test.deepEqual(moment.duration({months: 12})._data, moment.duration({years: 1})._data, "1 years is the same as 12 months"); + test.done(); + }, + + "asGetters" : function(test) { + var d = moment.duration({ + years: 2, + months: 3, + weeks: 2, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(8); + test.equal(Math.round(d.asYears() * 100) / 100, 2.26, "years"); + test.equal(Math.round(d.asMonths() * 100) / 100, 27.51, "months"); + test.equal(Math.round(d.asWeeks() * 100) / 100, 117.91, "weeks"); + test.equal(Math.round(d.asDays() * 100) / 100, 825.34, "days"); + test.equal(Math.round(d.asHours() * 100) / 100, 19808.16, "hours"); + test.equal(Math.round(d.asMinutes() * 100) / 100, 1188489.33, "minutes"); + test.equal(Math.round(d.asSeconds() * 100) / 100, 71309360.01, "seconds"); + test.equal(d.asMilliseconds(), 71309360012, "milliseconds"); + test.done(); + }, + + "isDuration" : function(test) { + test.expect(3); + test.ok(moment.isDuration(moment.duration(12345678)), "correctly says true"); + test.ok(!moment.isDuration(moment()), "moment object is not a duration"); + test.ok(!moment.isDuration({milliseconds: 1}), "plain object is not a duration"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/format.js b/node_modules/emailjs/node_modules/moment/test/moment/format.js new file mode 100644 index 0000000..3f38173 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/format.js @@ -0,0 +1,111 @@ +var moment = require("../../moment"); + +exports.format = { + "format YY" : function(test) { + test.expect(1); + + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 125)); + test.equal(b.format('YY'), '09', 'YY ---> 09'); + test.done(); + }, + + "format escape brackets" : function(test) { + test.expect(5); + + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 125)); + test.equal(b.format('[day]'), 'day', 'Single bracket'); + test.equal(b.format('[day] YY [YY]'), 'day 09 YY', 'Double bracket'); + test.equal(b.format('[YY'), '[09', 'Un-ended bracket'); + test.equal(b.format('[[YY]]'), '[YY]', 'Double nested brackets'); + test.equal(b.format('[[]'), '[', 'Escape open bracket'); + test.done(); + }, + + "format milliseconds" : function(test) { + test.expect(6); + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 123)); + test.equal(b.format('S'), '1', 'Deciseconds'); + test.equal(b.format('SS'), '12', 'Centiseconds'); + test.equal(b.format('SSS'), '123', 'Milliseconds'); + b.milliseconds(789); + test.equal(b.format('S'), '7', 'Deciseconds'); + test.equal(b.format('SS'), '78', 'Centiseconds'); + test.equal(b.format('SSS'), '789', 'Milliseconds'); + test.done(); + }, + + "format timezone" : function(test) { + test.expect(2); + + var b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)); + var explanation = 'moment().format("z") = ' + b.format('z') + ' It should be something like "PST"' + if (moment().zone() === -60) { + explanation += "For UTC+1 this is a known issue, see https://github.com/timrwood/moment/issues/162"; + } + test.ok(b.format('Z').match(/^[\+\-]\d\d:\d\d$/), b.format('Z') + ' should be something like "+07:30"'); + test.ok(b.format('ZZ').match(/^[\+\-]\d{4}$/), b.format('ZZ') + ' should be something like "+0700"'); + test.done(); + }, + + "format multiple with zone" : function(test) { + test.expect(1); + + var b = moment('2012-10-08 -1200', ['YYYY ZZ', 'YYYY-MM-DD ZZ']); + test.equals(b.format('YYYY-MM'), '2012-10', 'Parsing multiple formats should not crash with different sized formats'); + test.done(); + }, + + "isDST" : function(test) { + test.expect(2); + + var janOffset = new Date(2011, 0, 1).getTimezoneOffset(), + julOffset = new Date(2011, 6, 1).getTimezoneOffset(), + janIsDst = janOffset < julOffset, + julIsDst = julOffset < janOffset, + jan1 = moment([2011]), + jul1 = moment([2011, 6]); + + if (janIsDst && julIsDst) { + test.ok(0, 'January and July cannot both be in DST'); + test.ok(0, 'January and July cannot both be in DST'); + } else if (janIsDst) { + test.ok(jan1.isDST(), 'January 1 is DST'); + test.ok(!jul1.isDST(), 'July 1 is not DST'); + } else if (julIsDst) { + test.ok(!jan1.isDST(), 'January 1 is not DST'); + test.ok(jul1.isDST(), 'July 1 is DST'); + } else { + test.ok(!jan1.isDST(), 'January 1 is not DST'); + test.ok(!jul1.isDST(), 'July 1 is not DST'); + } + test.done(); + }, + + "zone" : function(test) { + test.expect(3); + + if (moment().zone() > 0) { + test.ok(moment().format('ZZ').indexOf('-') > -1, 'When the zone() offset is greater than 0, the ISO offset should be less than zero'); + } + if (moment().zone() < 0) { + test.ok(moment().format('ZZ').indexOf('+') > -1, 'When the zone() offset is less than 0, the ISO offset should be greater than zero'); + } + if (moment().zone() == 0) { + test.ok(moment().format('ZZ').indexOf('+') > -1, 'When the zone() offset is equal to 0, the ISO offset should be positive zero'); + } + if (moment().zone() === 0) { + test.equal(moment().zone(), 0, 'moment.fn.zone should be a multiple of 15 (was ' + moment().zone() + ')'); + } else { + test.equal(moment().zone() % 15, 0, 'moment.fn.zone should be a multiple of 15 (was ' + moment().zone() + ')'); + } + test.equal(moment().zone(), new Date().getTimezoneOffset(), 'zone should equal getTimezoneOffset'); + test.done(); + }, + + "default format" : function(test) { + test.expect(1); + var isoRegex = /\d{4}.\d\d.\d\dT\d\d.\d\d.\d\d[\+\-]\d\d:\d\d/; + test.ok(isoRegex.exec(moment().format()), "default format (" + moment().format() + ") should match ISO"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/getters_setters.js b/node_modules/emailjs/node_modules/moment/test/moment/getters_setters.js new file mode 100644 index 0000000..dc3d77b --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/getters_setters.js @@ -0,0 +1,103 @@ +var moment = require("../../moment"); + +exports.getters_setters = { + "getters" : function(test) { + test.expect(8); + + var a = moment([2011, 9, 12, 6, 7, 8, 9]); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hours(), 6, 'hour'); + test.equal(a.minutes(), 7, 'minute'); + test.equal(a.seconds(), 8, 'second'); + test.equal(a.milliseconds(), 9, 'milliseconds'); + test.done(); + }, + + "setters" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(9); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hours(), 6, 'hour'); + test.equal(a.minutes(), 7, 'minute'); + test.equal(a.seconds(), 8, 'second'); + test.equal(a.milliseconds(), 9, 'milliseconds'); + test.done(); + }, + + "setters - falsey values" : function(test) { + test.expect(1); + + var a = moment(); + // ensure minutes wasn't coincidentally 0 already + a.minutes(1); + a.minutes(0); + test.equal(a.minutes(), 0, 'falsey value'); + test.done(); + }, + + "chaining setters" : function(test) { + test.expect(7); + + var a = moment(); + a.year(2011) + .month(9) + .date(12) + .hours(6) + .minutes(7) + .seconds(8); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hours(), 6, 'hour'); + test.equal(a.minutes(), 7, 'minute'); + test.equal(a.seconds(), 8, 'second'); + test.done(); + }, + + "day setter" : function(test) { + test.expect(18); + + var a = moment([2011, 0, 15]); + test.equal(moment(a).day(0).date(), 9, 'set from saturday to sunday'); + test.equal(moment(a).day(6).date(), 15, 'set from saturday to saturday'); + test.equal(moment(a).day(3).date(), 12, 'set from saturday to wednesday'); + + a = moment([2011, 0, 9]); + test.equal(moment(a).day(0).date(), 9, 'set from sunday to sunday'); + test.equal(moment(a).day(6).date(), 15, 'set from sunday to saturday'); + test.equal(moment(a).day(3).date(), 12, 'set from sunday to wednesday'); + + a = moment([2011, 0, 12]); + test.equal(moment(a).day(0).date(), 9, 'set from wednesday to sunday'); + test.equal(moment(a).day(6).date(), 15, 'set from wednesday to saturday'); + test.equal(moment(a).day(3).date(), 12, 'set from wednesday to wednesday'); + + test.equal(moment(a).day(-7).date(), 2, 'set from wednesday to last sunday'); + test.equal(moment(a).day(-1).date(), 8, 'set from wednesday to last saturday'); + test.equal(moment(a).day(-4).date(), 5, 'set from wednesday to last wednesday'); + + test.equal(moment(a).day(7).date(), 16, 'set from wednesday to next sunday'); + test.equal(moment(a).day(13).date(), 22, 'set from wednesday to next saturday'); + test.equal(moment(a).day(10).date(), 19, 'set from wednesday to next wednesday'); + + test.equal(moment(a).day(14).date(), 23, 'set from wednesday to second next sunday'); + test.equal(moment(a).day(20).date(), 29, 'set from wednesday to second next saturday'); + test.equal(moment(a).day(17).date(), 26, 'set from wednesday to second next wednesday'); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/humanize_duration.js b/node_modules/emailjs/node_modules/moment/test/moment/humanize_duration.js new file mode 100644 index 0000000..b539851 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/humanize_duration.js @@ -0,0 +1,52 @@ +var moment = require("../../moment"); + +exports.humanize_duration = { + "humanize duration" : function(test) { + test.expect(32); + moment.lang('en'); + // this syntax is deprecated. + // see moment.duration instead. + test.equal(moment.humanizeDuration(44, "seconds"), "a few seconds", "44 seconds = a few seconds"); + test.equal(moment.humanizeDuration(45, "seconds"), "a minute", "45 seconds = a minute"); + test.equal(moment.humanizeDuration(89, "seconds"), "a minute", "89 seconds = a minute"); + test.equal(moment.humanizeDuration(90, "seconds"), "2 minutes", "90 seconds = 2 minutes"); + test.equal(moment.humanizeDuration(44, "minutes"), "44 minutes", "44 minutes = 44 minutes"); + test.equal(moment.humanizeDuration(45, "minutes"), "an hour", "45 minutes = an hour"); + test.equal(moment.humanizeDuration(89, "minutes"), "an hour", "89 minutes = an hour"); + test.equal(moment.humanizeDuration(90, "minutes"), "2 hours", "90 minutes = 2 hours"); + test.equal(moment.humanizeDuration(5, "hours"), "5 hours", "5 hours = 5 hours"); + test.equal(moment.humanizeDuration(21, "hours"), "21 hours", "21 hours = 21 hours"); + test.equal(moment.humanizeDuration(22, "hours"), "a day", "22 hours = a day"); + test.equal(moment.humanizeDuration(35, "hours"), "a day", "35 hours = a day"); + test.equal(moment.humanizeDuration(36, "hours"), "2 days", "36 hours = 2 days"); + test.equal(moment.humanizeDuration(1, "days"), "a day", "1 day = a day"); + test.equal(moment.humanizeDuration(5, "days"), "5 days", "5 days = 5 days"); + test.equal(moment.humanizeDuration(1, "weeks"), "7 days", "1 week = 7 days"); + test.equal(moment.humanizeDuration(25, "days"), "25 days", "25 days = 25 days"); + test.equal(moment.humanizeDuration(26, "days"), "a month", "26 days = a month"); + test.equal(moment.humanizeDuration(30, "days"), "a month", "30 days = a month"); + test.equal(moment.humanizeDuration(45, "days"), "a month", "45 days = a month"); + test.equal(moment.humanizeDuration(46, "days"), "2 months", "46 days = 2 months"); + test.equal(moment.humanizeDuration(74, "days"), "2 months", "75 days = 2 months"); + test.equal(moment.humanizeDuration(76, "days"), "3 months", "76 days = 3 months"); + test.equal(moment.humanizeDuration(1, "months"), "a month", "1 month = a month"); + test.equal(moment.humanizeDuration(5, "months"), "5 months", "5 months = 5 months"); + test.equal(moment.humanizeDuration(344, "days"), "11 months", "344 days = 11 months"); + test.equal(moment.humanizeDuration(345, "days"), "a year", "345 days = a year"); + test.equal(moment.humanizeDuration(547, "days"), "a year", "547 days = a year"); + test.equal(moment.humanizeDuration(548, "days"), "2 years", "548 days = 2 years"); + test.equal(moment.humanizeDuration(1, "years"), "a year", "1 year = a year"); + test.equal(moment.humanizeDuration(5, "years"), "5 years", "5 years = 5 years"); + test.equal(moment.humanizeDuration(7200000), "2 hours", "7200000 = 2 minutes"); + test.done(); + }, + + "humanize duration with suffix" : function(test) { + test.expect(3); + moment.lang('en'); + test.equal(moment.humanizeDuration(44, "seconds", true), "in a few seconds", "44 seconds = a few seconds"); + test.equal(moment.humanizeDuration(-44, "seconds", true), "a few seconds ago", "44 seconds = a few seconds"); + test.equal(moment.humanizeDuration(44000, true), "in a few seconds", "44000 milliseconds = a few seconds"); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/is_moment.js b/node_modules/emailjs/node_modules/moment/test/moment/is_moment.js new file mode 100644 index 0000000..9b085cc --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/is_moment.js @@ -0,0 +1,27 @@ +var moment = require('../../moment'); + +exports.is_moment = { + "is moment object": function(test) { + test.expect(11); + + var MyObj = function() {}; + MyObj.prototype.toDate = function() { + return new Date(); + } + + test.ok(moment.isMoment(moment()), 'simple moment object'); + test.ok(moment.isMoment(moment('invalid date')), 'invalid moment object'); + + test.ok(!moment.isMoment(new MyObj()), 'myObj is not moment object'); + test.ok(!moment.isMoment(moment), 'moment function is not moment object'); + test.ok(!moment.isMoment(new Date()), 'date object is not moment object'); + test.ok(!moment.isMoment(Object), 'Object is not moment object'); + test.ok(!moment.isMoment('foo'), 'string is not moment object'); + test.ok(!moment.isMoment(1), 'number is not moment object'); + test.ok(!moment.isMoment(NaN), 'NaN is not moment object'); + test.ok(!moment.isMoment(null), 'null is not moment object'); + test.ok(!moment.isMoment(undefined), 'undefined is not moment object'); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/is_valid.js b/node_modules/emailjs/node_modules/moment/test/moment/is_valid.js new file mode 100644 index 0000000..2934128 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/is_valid.js @@ -0,0 +1,118 @@ +var moment = require("../../moment"); + +exports.is_valid = { + "array bad month" : function (test) { + test.expect(2); + + test.equal(moment([2010, -1]).isValid(), false, 'month -1'); + test.equal(moment([2100, 12]).isValid(), false, 'month 12'); + + test.done(); + }, + + "array good month" : function (test) { + test.expect(24); + + for (var i = 0; i < 12; i++) { + test.equal(moment([2010, i]).isValid(), true, 'month ' + i); + test.equal(moment.utc([2010, i]).isValid(), true, 'month ' + i); + } + + test.done(); + }, + + "array bad date" : function (test) { + test.expect(4); + + test.equal(moment([2010, 0, 0]).isValid(), false, 'date 0'); + test.equal(moment([2100, 0, 32]).isValid(), false, 'date 32'); + + test.equal(moment.utc([2010, 0, 0]).isValid(), false, 'utc date 0'); + test.equal(moment.utc([2100, 0, 32]).isValid(), false, 'utc date 32'); + + test.done(); + }, + + "array bad date leap year" : function (test) { + test.expect(8); + + test.equal(moment([2010, 1, 29]).isValid(), false, '2010 feb 29'); + test.equal(moment([2100, 1, 29]).isValid(), false, '2100 feb 29'); + test.equal(moment([2008, 1, 30]).isValid(), false, '2008 feb 30'); + test.equal(moment([2000, 1, 30]).isValid(), false, '2000 feb 30'); + + test.equal(moment.utc([2010, 1, 29]).isValid(), false, 'utc 2010 feb 29'); + test.equal(moment.utc([2100, 1, 29]).isValid(), false, 'utc 2100 feb 29'); + test.equal(moment.utc([2008, 1, 30]).isValid(), false, 'utc 2008 feb 30'); + test.equal(moment.utc([2000, 1, 30]).isValid(), false, 'utc 2000 feb 30'); + + test.done(); + }, + + "string nonsensical" : function (test) { + test.expect(1); + + test.equal(moment('fail').isValid(), false, 'string "fail"'); + test.done(); + }, + + "invalid string iso 8601" : function (test) { + + var tests = [ + '2010-00-00', + '2010-01-00', + '2010-01-40', + '2010-01-01T24', + '2010-01-01T23:60', + '2010-01-01T23:59:60' + ]; + + test.expect(tests.length * 2); + + for (var i = 0; i < tests.length; i++) { + test.equal(moment(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + test.equal(moment.utc(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + } + test.done(); + }, + + "invalid string iso 8601 + timezone" : function (test) { + + var tests = [ + '2010-00-00+00:00', + '2010-01-00+00:00', + '2010-01-40+00:00', + '2010-01-40T24+00:00', + '2010-01-40T23:60+00:00', + '2010-01-40T23:59:60+00:00', + '2010-01-40T23:59:59.9999+00:00' + ]; + + test.expect(tests.length * 2); + + for (var i = 0; i < tests.length; i++) { + test.equal(moment(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + test.equal(moment.utc(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + } + test.done(); + }, + + "valid string iso 8601 + timezone" : function (test) { + var tests = [ + '2010-01-01', + '2010-01-30', + '2010-01-30T23+00:00', + '2010-01-30T23:59+00:00', + '2010-01-30T23:59:59+00:00', + '2010-01-30T23:59:59.999+00:00' + ]; + + test.expect(tests.length * 2); + + for (var i = 0; i < tests.length; i++) { + test.equal(moment(tests[i]).isValid(), true, tests[i] + ' should be valid'); + test.equal(moment.utc(tests[i]).isValid(), true, tests[i] + ' should be valid'); + } + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/lang.js b/node_modules/emailjs/node_modules/moment/test/moment/lang.js new file mode 100644 index 0000000..b4823f1 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/lang.js @@ -0,0 +1,197 @@ +var moment = require("../../moment"); + +exports.lang = { + "library getter" : function(test) { + test.expect(4); + + moment.lang('en'); + test.equal(moment.lang(), 'en', 'Lang should return en by default'); + + moment.lang('fr'); + test.equal(moment.lang(), 'fr', 'Lang should return the changed language'); + + moment.lang('en-gb'); + test.equal(moment.lang(), 'en-gb', 'Lang should return the changed language'); + + moment.lang('en'); + test.equal(moment.lang(), 'en', 'Lang should reset'); + + test.done(); + }, + + "library ensure inheritance" : function(test) { + test.expect(2); + + moment.lang('made-up', { + // I put them out of order + months : "February_March_April_May_June_July_August_September_October_November_December_January".split("_") + // the rest of the properties should be inherited. + }); + + test.equal(moment([2012, 5, 6]).format('MMMM'), 'July', 'Override some of the configs'); + test.equal(moment([2012, 5, 6]).format('MMM'), 'Jun', 'But not all of them'); + + test.done(); + }, + + "library langData" : function(test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment.langData().months[0], 'January', 'no arguments returns global'); + test.equal(moment.langData('zh-cn').months[0], '一月', 'a string returns the language based on key'); + test.equal(moment.langData(moment().lang('es')).months[0], 'Enero', "if you pass in a moment it uses the moment's language"); + + test.done(); + }, + + "instance lang method" : function(test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment([2012, 5, 6]).format('MMMM'), 'June', 'Normally default to global'); + test.equal(moment([2012, 5, 6]).lang('es').format('MMMM'), 'Junio', 'Use the instance specific language'); + test.equal(moment([2012, 5, 6]).format('MMMM'), 'June', 'Using an instance specific language does not affect other moments'); + + test.done(); + }, + + "instance lang persists with manipulation" : function(test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment([2012, 5, 6]).lang('es').add({days: 1}).format('MMMM'), 'Junio', 'With addition'); + test.equal(moment([2012, 5, 6]).lang('es').day(0).format('MMMM'), 'Junio', 'With day getter'); + test.equal(moment([2012, 5, 6]).lang('es').eod().format('MMMM'), 'Junio', 'With eod'); + + test.done(); + }, + + "instance lang persists with cloning" : function(test) { + test.expect(2); + moment.lang('en'); + + var a = moment([2012, 5, 6]).lang('es'), + b = a.clone(), + c = moment(a); + + test.equal(b.format('MMMM'), 'Junio', 'using moment.fn.clone()'); + test.equal(b.format('MMMM'), 'Junio', 'using moment()'); + + test.done(); + }, + + "duration lang method" : function(test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', 'Normally default to global'); + test.equal(moment.duration({seconds: 44}).lang('es').humanize(), 'unos segundos', 'Use the instance specific language'); + test.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', 'Using an instance specific language does not affect other durations'); + + test.done(); + }, + + "duration lang persists with cloning" : function(test) { + test.expect(1); + moment.lang('en'); + + var a = moment.duration({seconds: 44}).lang('es'), + b = moment.duration(a); + + test.equal(b.humanize(), 'unos segundos', 'using moment.duration()'); + test.done(); + }, + + "instance lang used with from" : function(test) { + test.expect(2); + moment.lang('en'); + + var a = moment([2012, 5, 6]).lang('es'), + b = moment([2012, 5, 7]); + + test.equal(a.from(b), 'hace un día', 'preserve language of first moment'); + test.equal(b.from(a), 'in a day', 'do not preserve language of second moment'); + + test.done(); + }, + + "month name callback function" : function(test) { + test.expect(3); + + function fakeReplace(m, format) { + if (/test/.test(format)) { + return "test"; + } + if (m.date() === 1) { + return "date"; + } + return 'default'; + } + + moment.lang('made-up', { + months : fakeReplace, + monthsShort : fakeReplace, + weekdays : fakeReplace, + weekdaysShort : fakeReplace, + weekdaysMin : fakeReplace + }); + + test.equal(moment().format('[test] dd ddd dddd MMM MMMM'), 'test test test test test test', 'format month name function should be able to access the format string'); + test.equal(moment([2011, 0, 1]).format('dd ddd dddd MMM MMMM'), 'date date date date date', 'format month name function should be able to access the moment object'); + test.equal(moment([2011, 0, 2]).format('dd ddd dddd MMM MMMM'), 'default default default default default', 'format month name function should be able to access the moment object'); + + test.done(); + }, + + // the following tests should be removed after the 2.0.0 release as they will be deprecated + "lang accessors on the global object should exist < 2.0.0" : function(test) { + moment.lang('en'); + + var a = 'months|monthsShort|monthsParse|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'); + var i; + + test.expect(a.length); + + for (i = 0; i < a.length; i++) { + test.ok(moment[a[i]], "moment." + a[i] + " should exist"); + } + + test.done(); + }, + + // the following tests should be removed after the 2.0.0 release as they will be deprecated + "lang accessors on the global object should change < 2.0.0" : function(test) { + moment.lang('en'); + + var a = 'months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal'.split('|'); + var i; + var en = {}; + + test.expect(a.length); + + for (i = 0; i < a.length; i++) { + en[a[i]] = moment[a[i]]; + } + + moment.lang('fr'); + + for (i = 0; i < a.length; i++) { + test.notDeepEqual(en[a[i]], moment[a[i]], "the " + a[i] + " lang data should change on the global object"); + } + + test.done(); + }, + + "manip lang accessors on the global object < 2.0.0" : function(test) { + test.expect(1); + moment.lang('en'); + + moment.months = ["test"]; + test.equal(moment([2011, 0]).format('MMMM'), "test", "Should be able to manipulate the objects on the global object"); + + moment.lang('en'); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/leapyear.js b/node_modules/emailjs/node_modules/moment/test/moment/leapyear.js new file mode 100644 index 0000000..7a3dd26 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/leapyear.js @@ -0,0 +1,13 @@ +var moment = require("../../moment"); + +exports.leapyear = { + "leap year" : function(test) { + test.expect(4); + + test.equal(moment([2010, 0, 1]).isLeapYear(), false, '2010'); + test.equal(moment([2100, 0, 1]).isLeapYear(), false, '2100'); + test.equal(moment([2008, 0, 1]).isLeapYear(), true, '2008'); + test.equal(moment([2000, 0, 1]).isLeapYear(), true, '2000'); + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/mutable.js b/node_modules/emailjs/node_modules/moment/test/moment/mutable.js new file mode 100644 index 0000000..4d45c94 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/mutable.js @@ -0,0 +1,56 @@ +var moment = require("../../moment"); + +exports.mutable = { + "manipulation methods" : function (test) { + + var mutableMethods = { + 'year': function (m){ return m.year(2011); }, + 'month': function (m){ return m.month(1); }, + 'date': function (m){ return m.date(9); }, + 'hours': function (m){ return m.hours(7); }, + 'minutes': function (m){ return m.minutes(33); }, + 'seconds': function (m){ return m.seconds(44); }, + 'milliseconds': function (m){ return m.milliseconds(55); }, + 'day': function (m){ return m.day(2); }, + 'startOf': function (m){ return m.startOf('week') }, + 'endOf': function (m){ return m.endOf('week') }, + 'add': function (m){ return m.add('days', 1) }, + 'subtract': function (m){ return m.subtract('years', 2) }, + 'local': function (m){ return m.local() }, + 'utc': function (m){ return m.utc() } + }; + + test.expect(14); + + for (method in mutableMethods) { + if (mutableMethods.hasOwnProperty(method)) { + var d = new Date(); + var d2 = mutableMethods[method](moment(d)).toDate(); + test.equal(d, d2, method + "() should be mutable"); + } + } + + test.done(); + }, + + "non mutable methods" : function (test) { + + var nonMutableMethods = { + 'sod': function (m){ return m.sod() }, + 'eod': function (m){ return m.eod() } + }; + + test.expect(2); + + for (method in nonMutableMethods){ + if (nonMutableMethods.hasOwnProperty(method)) { + var d = new Date(); + var d2 = nonMutableMethods[method](moment(d)).toDate(); + test.notEqual(d, d2, method + "() should not be mutable"); + } + } + + test.done(); + } + +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/sod_eod.js b/node_modules/emailjs/node_modules/moment/test/moment/sod_eod.js new file mode 100644 index 0000000..fd3a856 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/sod_eod.js @@ -0,0 +1,232 @@ +var moment = require("../../moment"); + +exports.eod_sod = { + "sod" : function(test) { + test.expect(7); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).sod(); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "eod" : function(test) { + test.expect(7); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).eod(); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "eod utc" : function(test) { + test.expect(1); + + var m2 = moment.utc(new Date(2011, 1, 2, 3, 4, 5, 6)); + test.equal(m2.eod().valueOf(), m2.hours(23).minutes(59).seconds(59).milliseconds(999).valueOf(), "Eod should equal manual hours/mins/seconds"); + + test.done(); + }, + + "start of year" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('year'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('years'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 0, "strip out the month"); + test.equal(m.date(), 1, "strip out the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of year" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('year'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('years'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 11, "set the month"); + test.equal(m.date(), 31, "set the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of month" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('month'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('months'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 1, "strip out the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of month" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('month'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('months'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 28, "set the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of day" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('day'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('days'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of day" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('day'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('days'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of hour" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('hour'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('hours'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of hour" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('hour'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('hours'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of minute" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('minute'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('minutes'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of minute" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('minute'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('minutes'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of second" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('second'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('seconds'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 5, "keep the the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of second" : function(test) { + test.expect(8); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('second'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('seconds'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 5, "keep the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, +}; diff --git a/node_modules/emailjs/node_modules/moment/test/moment/utc.js b/node_modules/emailjs/node_modules/moment/test/moment/utc.js new file mode 100644 index 0000000..26a66a2 --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/moment/utc.js @@ -0,0 +1,63 @@ +var moment = require("../../moment"); + +exports.utc = { + "utc and local" : function(test) { + test.expect(7); + + var m = moment(Date.UTC(2011, 1, 2, 3, 4, 5, 6)); + m.utc(); + // utc + test.equal(m.date(), 2, "the day should be correct for utc"); + test.equal(m.day(), 3, "the date should be correct for utc"); + test.equal(m.hours(), 3, "the hours should be correct for utc"); + + // local + m.local(); + if (m.zone() > 180) { + test.equal(m.date(), 1, "the date should be correct for local"); + test.equal(m.day(), 2, "the day should be correct for local"); + } else { + test.equal(m.date(), 2, "the date should be correct for local"); + test.equal(m.day(), 3, "the day should be correct for local"); + } + var zone = Math.ceil(m.zone() / 60); + var expected = (24 + 3 - zone) % 24; + test.equal(m.hours(), expected, "the hours (" + m.hours() + ") should be correct for local"); + test.equal(moment().utc().zone(), 0, "timezone in utc should always be zero"); + test.done(); + }, + + "creating with utc" : function(test) { + test.expect(7); + + test.equal(moment.utc().valueOf(), moment().valueOf(), "Calling moment.utc() should default to the current time"); + + var m = moment.utc([2011, 1, 2, 3, 4, 5, 6]); + test.equal(m.date(), 2, "the day should be correct for utc array"); + test.equal(m.hours(), 3, "the hours should be correct for utc array"); + + m = moment.utc("2011-02-02 3:04:05", "YYYY-MM-DD HH:mm:ss"); + test.equal(m.date(), 2, "the day should be correct for utc parsing format"); + test.equal(m.hours(), 3, "the hours should be correct for utc parsing format"); + + m = moment.utc("2011-02-02T03:04:05+00:00"); + test.equal(m.date(), 2, "the day should be correct for utc parsing iso"); + test.equal(m.hours(), 3, "the hours should be correct for utc parsing iso"); + + test.done(); + }, + + "creating with utc without timezone" : function(test) { + test.expect(4); + + var m = moment.utc("2012-01-02T08:20:00"); + test.equal(m.date(), 2, "the day should be correct for utc parse without timezone"); + test.equal(m.hours(), 8, "the hours should be correct for utc parse without timezone"); + + m = moment.utc("2012-01-02T08:20:00+09:00"); + test.equal(m.date(), 1, "the day should be correct for utc parse with timezone"); + test.equal(m.hours(), 23, "the hours should be correct for utc parse with timezone"); + + test.done(); + } +}; diff --git a/node_modules/emailjs/node_modules/moment/test/zone.js b/node_modules/emailjs/node_modules/moment/test/zone.js new file mode 100644 index 0000000..5813fbc --- /dev/null +++ b/node_modules/emailjs/node_modules/moment/test/zone.js @@ -0,0 +1,181 @@ +var terminal = require('child_process').spawn('bash'), + path = require('path'), + util = require('util'), + nodeunit = require('nodeunit'); + +var ZONES; + + +/****************************** + Get Timezone +******************************/ + +var currentTimezone = ''; + +function getTimezone() { + var term = require('child_process').spawn('bash'); + + term.stdout.on('data', function (data) { + currentTimezone = data.toString().replace('Time Zone: ', ''); + getTimezoneList(); + }); + + term.stdin.write('systemsetup gettimezone'); + term.stdin.end(); +} + +function getTimezoneList() { + var term = require('child_process').spawn('bash'), + data = ''; + + term.stdout.on('data', function (d) { + data += d; + }); + + term.stdout.on('end', function () { + data = data.replace('Time Zones:', ''); + ZONES = data.match(/\S+/g); + // console.log(ZONES); + startTests(); + }); + + term.stdin.write('systemsetup listtimezones'); + term.stdin.end(); + +} + + + +/****************************** + Set Timezone +******************************/ + +var currentTimezone = ''; + +function setTimezone() { + terminal.stdin.write('systemsetup settimezone ' + currentTimezone); + terminal.stdin.end(); +} + + +/****************************** + Tests +******************************/ + + +var files = ['test/moment'], + paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + +var globalfailures = ''; + +var f = 0; +var p = 0; + +function errorLog(assertion) { + if (!assertion.error) { + return assertion; + } + + var e = assertion.error; + if (e.actual && e.expected) { + var actual = util.inspect(e.actual, false, 10).replace(/\n$/, ''), + expected = util.inspect(e.expected, false, 10).replace(/\n$/, ''), + multiline = (actual.indexOf('\n') !== -1 || expected.indexOf('\n') !== -1), + spacing = (multiline ? '\n' : ' '); + e._message = e.message; + e.stack = ( + e.name + ':' + spacing + + actual + spacing + e.operator + spacing + + expected + '\n' + + e.stack.split('\n').slice(1).join('\n') + ); + } + return assertion; +} + +var zone = '', + nextZone = ''; + +function runTestIfNeeded() { + if (zone === nextZone) { + return; + } + nextZone = zone; + + console.log("-----------------------"); + console.log(zone + " testing started..."); + nodeunit.runFiles(paths, { + testDone: function (name, assertions) { + if (assertions.failures()) { + console.log('\nFAILURE: ' + name); + assertions.forEach(function (a) { + if (a.failed()) { + a = errorLog(a); + if (a.error && a.message) { + console.log('Assertion Message: ' + a.message); + } + console.log(a.error.stack); + } + }); + } + }, + done: function (assertions) { + if (assertions.failures()) { + console.log('\n' + zone + ' had ' + assertions.failures() + ' failures'); + globalfailures += zone + ' had ' + assertions.failures() + ' failures\n'; + f++; + } else { + console.log(zone + ' passed all tests!'); + p++; + } + console.log("-----------------------"); + nextTest(); + } + }); +} + +function runTest(zoned) { + zone = zoned; + terminal.stdin.write('systemsetup settimezone ' + zone + '\n'); +} + +terminal.stdout.on('data', function(d) { + setTimeout(runTestIfNeeded, 100); +}); + + +var i = 0; + +function startTests() { + nextTest(); + //setTimezone(); +} + +function nextTest() { + if (i < ZONES.length) { + runTest(ZONES[i]); + } else { + console.log("----------------------"); + console.log("----------------------"); + console.log(globalfailures); + console.log("----------------------"); + console.log("----------------------"); + console.log("--- Total Failing " + f); + console.log("----------------------"); + console.log("--- Total Passing " + p); + console.log("----------------------"); + console.log("----------------------"); + setTimezone(); + } + i++; +} + + +/****************************** + Start it off +******************************/ + + +getTimezone(); \ No newline at end of file diff --git a/node_modules/emailjs/package.json b/node_modules/emailjs/package.json new file mode 100644 index 0000000..c7212c0 --- /dev/null +++ b/node_modules/emailjs/package.json @@ -0,0 +1,56 @@ +{ + "name": "emailjs", + "description": "send text/html emails and attachments (files, streams and strings) from node.js to any smtp server", + "version": "0.3.10", + "author": { + "name": "eleith" + }, + "contributors": [ + { + "name": "izuzak" + }, + { + "name": "Hiverness" + }, + { + "name": "mscdex" + }, + { + "name": "jimmybergman" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/eleith/emailjs.git" + }, + "dependencies": { + "moment": "= 1.7.0", + "mimelib": "0.2.14", + "bufferjs": "=1.1.0" + }, + "optionalDependencies": { + "bufferjs": "=1.1.0" + }, + "devDependencies": { + "mocha": "= 1.7.4", + "chai": "= 1.1.0", + "simplesmtp": "0.3.32", + "mailparser": "0.4.1", + "iconv": "2.0.7" + }, + "engine": [ + "node >= 0.10" + ], + "main": "email", + "scripts": { + "test": "mocha -R spec -t 5000" + }, + "readme": "# emailjs [![Build Status](https://secure.travis-ci.org/eleith/emailjs.png)](http://travis-ci.org/eleith/emailjs)\n\nsend emails, html and attachments (files, streams and strings) from node.js to any smtp server\n\n## INSTALLING\n\n\tnpm install emailjs\n\n## FEATURES\n - works with SSL and TLS smtp servers \n - supports smtp authentication (PLAIN, LOGIN, CRAMMD5)\n - emails are queued and the queue is sent asynchronously\n - supports sending html emails and emails with multiple attachments (MIME)\n - attachments can be added as strings, streams or file paths\n - supports utf-8 headers and body\n\n## REQUIRES\n - auth access to an SMTP Server\n - if your service (ex: gmail) uses two-step authentication, use an applicaiton specific password\n\n## EXAMPLE USAGE - text only emails\n\n```javascript\nvar email \t= require(\"./path/to/emailjs/email\");\nvar server \t= email.server.connect({\n user: \"username\", \n password:\"password\", \n host: \"smtp.your-email.com\", \n ssl: true\n});\n\n// send the message and get a callback with an error or details of the message that was sent\nserver.send({\n text: \"i hope this works\", \n from: \"you \", \n to: \"someone , another \",\n cc: \"else \",\n subject: \"testing emailjs\"\n}, function(err, message) { console.log(err || message); });\n```\n\n## EXAMPLE USAGE - html emails and attachments\n\n```javascript\nvar email \t= require(\"./path/to/emailjs/email\");\nvar server \t= email.server.connect({\n user:\t\"username\", \n password:\"password\", \n host:\t\"smtp.your-email.com\", \n ssl:\t\ttrue\n});\n\nvar message\t= {\n text:\t\"i hope this works\", \n from:\t\"you \", \n to:\t\t\"someone , another \",\n cc:\t\t\"else \",\n subject:\t\"testing emailjs\",\n attachment: \n [\n {data:\"i hope this works!\", alternative:true},\n {path:\"path/to/file.zip\", type:\"application/zip\", name:\"renamed.zip\"}\n ]\n};\n\n// send the message and get a callback with an error or details of the message that was sent\nserver.send(message, function(err, message) { console.log(err || message); });\n\n// you can continue to send more messages with successive calls to 'server.send', \n// they will be queued on the same smtp connection\n\n// or you can create a new server connection with 'email.server.connect' \n// to asynchronously send individual emails instead of a queue\n```\n\n## EXAMPLE USAGE - sending through hotmail/outlook\n\n```javascript\nvar email \t= require(\"./path/to/emailjs/email\");\nvar server \t= email.server.connect({\n user:\t\"username\", \n password:\"password\", \n host:\t\"smtp-mail.outlook.com\", \n tls: {ciphers: \"SSLv3\"}\n});\n\nvar message\t= {\n text:\t\"i hope this works\", \n from:\t\"you \", \n to:\t\t\"someone , another \",\n cc:\t\t\"else \",\n subject:\t\"testing emailjs\",\n attachment: \n [\n {data:\"i hope this works!\", alternative:true},\n {path:\"path/to/file.zip\", type:\"application/zip\", name:\"renamed.zip\"}\n ]\n};\n\n// send the message and get a callback with an error or details of the message that was sent\nserver.send(message, function(err, message) { console.log(err || message); });\n```\n\n# API \n\n## email.server.connect(options)\n\n\t// options is an object with the following keys\n\toptions =\n\t{\n\t\tuser \t\t// username for logging into smtp \n\t\tpassword // password for logging into smtp\n\t\thost\t\t// smtp host\n\t\tport\t\t// smtp port (if null a standard port number will be used)\n\t\tssl\t\t// boolean or object {key, ca, cert} (if true or object, ssl connection will be made)\n\t\ttls\t\t// boolean or object (if true or object, starttls will be initiated)\n\t\ttimeout\t// max number of milliseconds to wait for smtp responses (defaults to 5000)\n\t\tdomain\t// domain to greet smtp with (defaults to os.hostname)\n\t}\n\t\n## email.server.send(message, callback)\n\t\n\t// message can be a smtp.Message (as returned by email.message.create)\n\t// or an object identical to the first argument accepted by email.message.create\n\n\t// callback will be executed with (err, message)\n\t// either when message is sent or an error has occurred\n\n## message\n\n\t// headers is an object ('from' and 'to' are required)\n\t// returns a Message object\n\n\t// you can actually pass more message headers than listed, the below are just the\n\t// most common ones you would want to use\n\n\theaders =\n\t{\n\t\ttext\t\t// text of the email \n\t\tfrom\t\t// sender of the format (address or name
or \"name\"
)\n\t\tto\t\t\t// recipients (same format as above), multiple recipients are separated by a comma\n\t\tcc\t\t\t// carbon copied recipients (same format as above)\n\t\tbcc\t\t// blind carbon copied recipients (same format as above)\n\t\tsubject\t// string subject of the email\n attachment // one attachment or array of attachments\n\t}\n\n## attachment\n\n\t// can be called multiple times, each adding a new attachment\n\t// options is an object with the following possible keys:\n \n options =\n {\n // one of these fields is required\n path // string to where the file is located\n data // string of the data you want to attach\n stream // binary stream that will provide attachment data (make sure it is in the paused state)\n // better performance for binary streams is achieved if buffer.length % (76*6) == 0\n // current max size of buffer must be no larger than Message.BUFFERSIZE\n \n // optionally these fields are also accepted\n type\t // string of the file mime type\n name // name to give the file as perceived by the recipient\n alternative // if true, will be attached inline as an alternative (also defaults type='text/html')\n inline // if true, will be attached inline\n encoded // set this to true if the data is already base64 encoded, (avoid this if possible)\n headers // object containing header=>value pairs for inclusion in this attachment's header\n related // an array of attachments that you want to be related to the parent attachment\n }\n\t\n## Authors\n\neleith\n\n## Testing\n\n\tnpm install -d\n\tnpm test\n\n## Contributions\n\nissues and pull requests are welcome\n", + "readmeFilename": "Readme.md", + "_id": "emailjs@0.3.10", + "dist": { + "shasum": "cccd50cab389af3145e1db3487d658971723d81a" + }, + "_from": "emailjs@0.3.10", + "_resolved": "https://registry.npmjs.org/emailjs/-/emailjs-0.3.10.tgz" +} diff --git a/node_modules/emailjs/smtp/address.js b/node_modules/emailjs/smtp/address.js new file mode 100644 index 0000000..de603c2 --- /dev/null +++ b/node_modules/emailjs/smtp/address.js @@ -0,0 +1,416 @@ +/* + * Email address parsing code. + * rewritten with python's (2.7) email/_parseaddr.py as the starting point +*/ + +var SPACE = ' '; +var EMPTYSTRING = ''; +var COMMASPACE = ', '; + +var quote = function(str) +{ + // Add quotes around a string. + return str.replace(/\\\\/g, '\\\\').replace(/"/g, '\\"'); +}; + +/* + * To understand what this class does, it helps to have a copy of RFC 2822 in + * front of you. + */ + +var Address = function(field) +{ + /* + * Initialize a new instance. + * `field' is an unparsed address header field, containing + * one or more addresses. + */ + + this.specials = '()<>@,:;.\"[]'; + this.pos = 0; + this.LWS = ' \t'; + this.CR = '\r\n'; + this.FWS = this.LWS + this.CR; + this.atomends = this.specials + this.LWS + this.CR; + + // Note that RFC 2822 now specifies `.' as obs-phrase, meaning that it + // is obsolete syntax. RFC 2822 requires that we recognize obsolete + // syntax, so allow dots in phrases. + + this.phraseends = this.atomends.replace(/\./g, ''); + this.field = field || ""; + this.commentlist = []; +}; + +Address.prototype = +{ + gotonext: function() + { + //Parse up to the start of the next address. + while(this.pos < this.field.length) + { + if((this.LWS + '\n\r').indexOf(this.field[this.pos]) != -1) + this.pos++; + + else if(this.field[this.pos] == '(') + this.commentlist.push(this.getcomment()); + + else + break; + } + }, + + getlist: function() + { + // Parse all addresses. Returns a list containing all of the addresses + var result = [], ad; + + while(this.pos < this.field.length) + { + ad = this.get(); + + if(ad) + result.push(ad); + + else + result.push({label:'', address:''}); + } + + return result; + }, + + get: function() + { + // Parse the next address + this.commentlist = []; + this.gotonext(); + + var oldpos = this.pos, oldcl = this.commentlist, plist = this.getphraselist(), returnlist = [], + addrspec, fieldlen, routeaddr; + + this.gotonext(); + + if(this.pos >= this.field.length) + { + // Bad email address, no domain + if(plist.length) + returnlist = {label:this.commentlist.join(SPACE), address:plist[0]}; + } + + else if('.@'.indexOf(this.field[this.pos]) != -1) + { + // email address is just an addrspec + // this isn't very efficient since we start over + this.pos = oldpos; + this.commentlist = oldcl; + addrspec = this.getspec(); + returnlist = {label:this.commentlist.join(SPACE), address:addrspec}; + } + + else if(this.field[this.pos] == ':') + { + // address is a group + returnlist = []; + fieldlen = this.field.length; + this.pos++; + + while(this.pos < this.field.length) + { + this.gotonext(); + + if(this.pos < fieldlen && this.field[this.pos] == ';') + { + this.pos += 1; + break; + } + + returnlist = returnlist.push(this.get()); + } + } + + else if(this.field[this.pos] == '<') + { + // Address is a prhase then a route addr + routeaddr = this.getroute(); + + if(this.commentlist.length) + returnlist = {label:plist.join(SPACE) + ' (' + this.commentlist.join(SPACE) + ')', address:routeaddr}; + + else + returnlist = {label:plist.join(SPACE), address:routeaddr}; + } + + else + { + if(plist.length) + returnlist = {label:this.commentlist.join(SPACE), address:plist[0]}; + + else if(this.specials.indexOf(this.field[this.pos]) != -1) + this.pos++; + } + + this.gotonext(); + + if(this.pos < this.field.length && this.field[this.pos] == ',') + this.pos++; + + return returnlist; + }, + + getroute: function() + { + // Parse a route address. this method skips all route stuff and returns addrspec + if(this.field[this.pos] != '<') + return ''; + + var expectroute = false, adlist = ''; + + this.pos++; + this.gotonext(); + + while(this.pos < this.field.length) + { + if(expectroute) + { + this.getdomain(); + expectroute = false; + } + else if(this.field[this.pos] == '>') + { + this.pos += 1; + break; + } + else if(this.field[this.pos] == '@') + { + this.pos += 1; + expectroute = true; + } + else if(this.field[this.pos] == ':') + { + this.pos++; + } + else + { + adlist = this.getspec(); + this.pos++; + break; + } + + this.gotonext(); + } + + return adlist; + }, + + getspec: function() + { + //parse an RFC 2822 addr-spec + var aslist = []; + + this.gotonext(); + + while(this.pos < this.field.length) + { + if(this.field[this.pos] == '.') + { + aslist.push('.'); + this.pos++; + } + + else if(this.field[this.pos] == '"') + aslist.push('"' + this.getquote() + '"'); + + else if(this.atomends.indexOf(this.field[this.pos]) != -1) + break; + + else + aslist.push(this.getatom()); + + this.gotonext(); + } + + if(this.pos >= this.field.length || this.field[this.pos] != '@') + return aslist.join(EMPTYSTRING); + + aslist.push('@'); + this.pos++; + this.gotonext(); + + return aslist.join(EMPTYSTRING) + this.getdomain(); + }, + + getdomain: function() + { + // get the complete domain name from an address + var sdlist = []; + + while(this.pos < this.field.length) + { + if(this.LWS.indexOf(this.field[this.pos]) != -1) + this.pos++; + + else if(this.field[this.pos] == '(') + this.commentlist.push(this.getcomment()); + + else if(this.field[this.pos] == '[') + sdlist.push(this.getdomainliteral()); + + else if(this.field[this.pos] == '.') + { + this.pos++; + sdlist.push('.'); + } + + else if(this.atomends.indexOf(this.field[this.pos]) != -1) + break; + + else + sdlist.push(this.getatom()); + } + + return sdlist.join(EMPTYSTRING); + }, + + getdelimited: function(beginchar, endchars, allowcomments) + { + /* + * Parse a header fragment delimited by special characters. + * + * `beginchar' is the start character for the fragment. + * If self is not looking at an instance of `beginchar' then + * getdelimited returns the empty string. + * + * `endchars' is a sequence of allowable end-delimiting characters. + * Parsing stops when one of these is encountered. + * + * If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed + * within the parsed fragment. + */ + + if(this.field[this.pos] != beginchar) + return ''; + + allowcomments = (allowcomments === false) ? false : true; + var slist = [''], quote = false; + this.pos++; + + while(this.pos < this.field.length) + { + if(quote) + { + slist.push(this.field[this.pos]); + quote = false; + } + else if(endchars.indexOf(this.field[this.pos]) != -1) + { + this.pos++; + break; + } + else if(allowcomments && this.field[this.pos] == '(') + { + slist.push(this.getcomment()); + continue; + } + + else if(this.field[this.pos] == '\\') + quote = true; + + else + slist.push(this.field[this.pos]); + + this.pos++; + + } + + return slist.join(EMPTYSTRING); + }, + + getquote: function() + { + // get a quote-delimited fragment from self's field + return this.getdelimited('"', '"\r', false); + }, + + getcomment: function() + { + // Get a parenthesis-delimited fragment from self's field. + return this.getdelimited('(', ')\r', true); + }, + + getdomainliteral: function() + { + // parse an rfc 2822 domain literal + return '[' + this.getdelimited('[', ']\r', false) + ']'; + }, + + getatom: function(atomends) + { + /* + * Parse an RFC 2822 atom. + * + * Optional atomends specifies a different set of end token delimiters + * (the default is to use this.atomends). This is used e.g. in + * getphraselist() since phrase endings must not include the `.' (which + * is legal in phrases). + */ + + var atomlist = ['']; + + if(atomends === undefined) + atomends = this.atomends; + + while(this.pos < this.field.length) + { + if(atomends.indexOf(this.field[this.pos]) != -1) + break; + + else + atomlist.push(this.field[this.pos]); + + this.pos++; + } + + return atomlist.join(EMPTYSTRING); + }, + + getphraselist: function() + { + /* + * Parse a sequence of RFC 2822 phrases. + * + * A phrase is a sequence of words, which are in turn either RFC 2822 + * atoms or quoted-strings. Phrases are canonicalized by squeezing all + * runs of continuous whitespace into one space. + */ + + var plist = []; + + while(this.pos < this.field.length) + { + if(this.FWS.indexOf(this.field[this.pos]) != -1) + this.pos++; + + else if(this.field[this.pos] == '"') + plist.push(this.getquote()); + + else if(this.field[this.pos] == '(') + this.commentlist.push(this.getcomment()); + + else if(this.phraseends.indexOf(this.field[this.pos]) != -1) + break; + + else + plist.push(this.getatom(this.phraseends)); + } + + return plist; + } +}; + +exports.Address = Address; +exports.parse = function(field) +{ + var addresses = (new Address(field)).getlist(); + + return addresses.length ? addresses : []; +}; diff --git a/node_modules/emailjs/smtp/client.js b/node_modules/emailjs/smtp/client.js new file mode 100644 index 0000000..7a88653 --- /dev/null +++ b/node_modules/emailjs/smtp/client.js @@ -0,0 +1,209 @@ +var smtp = require('./smtp'); +var smtpError = require('./error'); +var message = require('./message'); +var address = require('./address'); + +var Client = function(server) +{ + this.smtp = new smtp.SMTP(server); + //this.smtp.debug(1); + + this.queue = []; + this.timer = null; + this.sending = false; + this.ready = false; +}; + +Client.prototype = +{ + _poll: function() + { + var self = this; + + clearTimeout(self.timer); + + if(self.queue.length) + { + if(self.smtp.state() == smtp.state.NOTCONNECTED) + self._connect(self.queue[0]); + + else if(self.smtp.state() == smtp.state.CONNECTED && !self.sending && self.ready) + self._sendmail(self.queue.shift()); + } + // wait around 1 seconds in case something does come in, otherwise close out SMTP connection if still open + else if(self.smtp.state() == smtp.state.CONNECTED) + self.timer = setTimeout(function() { self.smtp.quit(); }, 1000); + }, + + _connect: function(stack) + { + var self = this, + + connect = function(err) + { + if(!err) + { + var begin = function(err) + { + if(!err) + { + self.ready = true; + self._poll(); + } + else { + stack.callback(err, stack.message); + + // clear out the queue so all callbacks can be called with the same error message + self.queue.shift(); + self._poll(); + } + }; + + if(!self.smtp.authorized()) + self.smtp.login(begin); + + else + self.smtp.ehlo_or_helo_if_needed(begin); + } + else { + stack.callback(err, stack.message); + + // clear out the queue so all callbacks can be called with the same error message + self.queue.shift(); + self._poll(); + } + }; + + self.ready = false; + self.smtp.connect(connect); + }, + + send: function(msg, callback) + { + var self = this; + + if(!(msg instanceof message.Message) + && msg.from + && (msg.to || msg.cc || msg.bcc) + && (msg.text || this._containsInlinedHtml(msg.attachment))) + msg = message.create(msg); + + if(msg instanceof message.Message) + { + msg.valid(function(valid, why) + { + if(valid) + { + var stack = + { + message: msg, + to: address.parse(msg.header.to), + from: address.parse(msg.header.from)[0].address, + callback: callback || function() {} + }; + + if(msg.header.cc) + stack.to = stack.to.concat(address.parse(msg.header.cc)); + + if(msg.header.bcc) + stack.to = stack.to.concat(address.parse(msg.header.bcc)); + + if(msg.header['return-path'] && address.parse(msg.header['return-path']).length) + stack.returnPath = address.parse(msg.header['return-path'])[0].address; + + self.queue.push(stack); + self._poll(); + } + else + callback(new Error(why), msg); + }); + } + else + callback(new Error("message is not a valid Message instance"), msg); + }, + + _containsInlinedHtml: function(attachment) { + if (Array.isArray(attachment)) { + return attachment.some((function(ctx) { + return function(att) { + return ctx._isAttachmentInlinedHtml(att); + }; + })(this)); + } else { + return this._isAttachmentInlinedHtml(attachment); + } + }, + + _isAttachmentInlinedHtml: function(attachment) { + return attachment && + (attachment.data || attachment.path) && + attachment.alternative === true; + }, + + _sendsmtp: function(stack, next) + { + var self = this; + var check= function(err) + { + if(!err && next) + { + next.apply(self, [stack]); + } + else + { + // if we snag on SMTP commands, call done, passing the error + // but first reset SMTP state so queue can continue polling + self.smtp.rset(function() { self._senddone(err, stack); }); + } + }; + + return check; + }, + + _sendmail: function(stack) + { + var self = this; + var from = stack.returnPath || stack.from; + self.sending = true; + self.smtp.mail(self._sendsmtp(stack, self._sendrcpt), '<' + from + '>'); + }, + + _sendrcpt: function(stack) + { + var self = this, to = stack.to.shift().address; + self.smtp.rcpt(self._sendsmtp(stack, stack.to.length ? self._sendrcpt : self._senddata), '<'+ to +'>'); + }, + + _senddata: function(stack) + { + var self = this; + self.smtp.data(self._sendsmtp(stack, self._sendmessage)); + }, + + _sendmessage: function(stack) + { + var self = this, stream = stack.message.stream(); + + stream.on('data', function(data) { self.smtp.message(data); }); + stream.on('end', function() { self.smtp.data_end(self._sendsmtp(stack, function() { self._senddone(null, stack) })); }); + + // there is no way to cancel a message while in the DATA portion, so we have to close the socket to prevent + // a bad email from going out + stream.on('error', function(err) { self.smtp.close(); self._senddone(err, stack); }); + }, + + _senddone: function(err, stack) + { + var self = this; + self.sending = false; + stack.callback(err, stack.message); + self._poll(); + } +}; + +exports.Client = Client; + +exports.connect = function(server) +{ + return new Client(server); +}; diff --git a/node_modules/emailjs/smtp/error.js b/node_modules/emailjs/smtp/error.js new file mode 100644 index 0000000..0bb8f7d --- /dev/null +++ b/node_modules/emailjs/smtp/error.js @@ -0,0 +1,21 @@ +module.exports = function(message, code, error, smtp) +{ + var err = new Error(message); + err.code = code; + if(error) + err.previous = error; + err.smtp = smtp; + + return err; +}; + +module.exports.COULDNOTCONNECT = 1; +module.exports.BADRESPONSE = 2; +module.exports.AUTHFAILED = 3; +module.exports.TIMEDOUT = 4; +module.exports.ERROR = 5; +module.exports.NOCONNECTION = 6; +module.exports.AUTHNOTSUPPORTED = 7; +module.exports.CONNECTIONCLOSED = 8; +module.exports.CONNECTIONENDED = 9; +module.exports.CONNECTIONAUTH = 10; diff --git a/node_modules/emailjs/smtp/message.js b/node_modules/emailjs/smtp/message.js new file mode 100644 index 0000000..4d050f4 --- /dev/null +++ b/node_modules/emailjs/smtp/message.js @@ -0,0 +1,622 @@ +var stream = require('stream'); +var util = require('util'); +var fs = require('fs'); +var os = require('os'); +var path = require('path'); +var moment = require('moment'); +var mimelib = require('mimelib'); +var CRLF = "\r\n"; +var MIMECHUNK = 76; // MIME standard wants 76 char chunks when sending out. +var BASE64CHUNK= 24; // BASE64 bits needed before padding is used +var MIME64CHUNK= MIMECHUNK * 6; // meets both base64 and mime divisibility +var BUFFERSIZE = MIMECHUNK*24*7; // size of the message stream buffer +var counter = 0; + +// support for nodejs without Buffer.concat native function +if(!Buffer.concat) +{ + require("bufferjs/concat"); +} + +var generate_boundary = function() +{ + var text = ""; + var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-./:=?"; + + for(var i=0; i < 69; i++) + text += possible.charAt(Math.floor(Math.random() * possible.length)); + + return text; +}; + +function person2address(l) +{ + // an array of emails or name+emails + if (Array.isArray(l)) { + l = l.join(', '); + } + + // a string of comma separated emails or comma separated name+ + if(typeof l == 'string') { + return l.replace(/([^<]+[^\s])(\s*)(<[^>]+>)/g, function(full, name, space, email) { return mimelib.encodeMimeWord(name, 'Q', 'utf-8') + space + email; }); + } + + return null; +} + +var fix_header_name_case = function(header_name) { + return header_name.toLowerCase().replace(/^(.)|-(.)/g, function(match) { + return match.toUpperCase(); + }); +}; + +var Message = function(headers) +{ + this.attachments = []; + this.alternative = null; + var now = new Date(); + this.header = { + "message-id":"<" + now.getTime() + "." + (counter++) + "." + process.pid + "@" + os.hostname() +">", + "date":moment().format("ddd, DD MMM YYYY HH:mm:ss ") + moment().format("Z").replace(/:/, '') + }; + this.content = "text/plain; charset=utf-8"; + + for(var header in headers) + { + // allow user to override default content-type to override charset or send a single non-text message + if(/^content-type$/i.test(header)) + { + this.content = headers[header]; + } + else if(header == 'text') + { + this.text = headers[header]; + } + else if(header == "attachment" && typeof (headers[header]) == "object") + { + if(Array.isArray(headers[header])) { + var that = this; + + for (var i = 0, l = headers[header].length; i < l; i++) { + this.attach(headers[header][i]); + } + } else { + this.attach(headers[header]); + } + } + else if(header == 'subject') + { + this.header.subject = mimelib.encodeMimeWord(headers.subject, 'Q', 'utf-8'); + } + else if(/cc|bcc|to|from/i.test(header)) + { + this.header[header.toLowerCase()] = person2address(headers[header]); + } + else + { + // allow any headers the user wants to set?? + // if(/cc|bcc|to|from|reply-to|sender|subject|date|message-id/i.test(header)) + this.header[header.toLowerCase()] = headers[header]; + } + } +}; + +Message.prototype = +{ + attach: function(options) + { + /* + legacy support, will remove eventually... + arguments -> (path, type, name, headers) + */ + if (arguments.length > 1) + options = {path:options, type:arguments[1], name:arguments[2]}; + + // sender can specify an attachment as an alternative + if(options.alternative) + { + this.alternative = options; + this.alternative.charset = options.charset || "utf-8"; + this.alternative.type = options.type || "text/html"; + this.alternative.inline = true; + } + else + this.attachments.push(options); + + return this; + }, + + /* + legacy support, will remove eventually... + should use Message.attach() instead + */ + attach_alternative: function(html, charset) + { + this.alternative = + { + data: html, + charset: charset || "utf-8", + type: "text/html", + inline: true + }; + + return this; + }, + + valid: function(callback) + { + var self = this; + + if(!self.header.from) + { + callback(false, "message does not have a valid sender"); + } + if(!(self.header.to || self.header.cc || self.header.bcc)) + { + callback(false, "message does not have a valid recipient"); + } + else if(self.attachments.length === 0) + { + callback(true); + } + else + { + var check = []; + var failed = []; + + self.attachments.forEach(function(attachment, index) + { + if(attachment.path) + { + // migrating path->fs for existsSync) + if(!(fs.existsSync || path.existsSync)(attachment.path)) + failed.push(attachment.path + " does not exist"); + } + else if(attachment.stream) + { + if(!attachment.stream.readable) + failed.push("attachment stream is not readable"); + } + else if(!attachment.data) + { + failed.push("attachment has no data associated with it"); + } + }); + + callback(failed.length === 0, failed.join(", ")); + } + }, + + stream: function() + { + return new MessageStream(this); + }, + + read: function(callback) + { + var buffer = ""; + + var capture = function(data) + { + buffer += data; + }; + + var output = function(err) + { + callback(err, buffer); + }; + + var str = this.stream(); + + str.on('data', capture); + str.on('end', output); + str.on('error', output); + } +}; + +var MessageStream = function(message) +{ + var self = this; + + stream.Stream.call(self); + + self.message = message; + self.readable = true; + self.paused = false; + self.buffer = new Buffer(MIMECHUNK*24*7); + self.bufferIndex = 0; + + var output_process = function(next, args) + { + if(self.paused) + { + self.resumed = function() { next.apply(null, args); }; + } + else + { + next.apply(null, args); + } + + next.apply(null, args); + }; + + var output_mixed = function() + { + var boundary = generate_boundary(); + var data = ["Content-Type: multipart/mixed; boundary=\"", boundary, "\"", CRLF, CRLF, "--", boundary, CRLF]; + + output(data.join('')); + + if(!self.message.alternative) + { + output_text(self.message); + output_message(boundary, self.message.attachments, 0, close); + } + else + { + output_alternative(self.message, function() { output_message(boundary, self.message.attachments, 0, close); }); + } + }; + + var output_message = function(boundary, list, index, callback) + { + if(index < list.length) + { + output(["--", boundary, CRLF].join('')); + + if(list[index].related) + { + output_related(list[index], function() { output_message(boundary, list, index + 1, callback); }); + } + else + { + output_attachment(list[index], function() { output_message(boundary, list, index + 1, callback); }); + } + } + else + { + output([CRLF, "--", boundary, "--", CRLF, CRLF].join('')); + callback(); + } + }; + + var output_attachment_headers = function(attachment) + { + var data = [], + header, + headers = + { + 'content-type': attachment.type + (attachment.charset ? "; charset=" + attachment.charset : ""), + 'content-transfer-encoding': 'base64', + 'content-disposition': attachment.inline ? 'inline' : 'attachment; filename="' + mimelib.encodeMimeWord(attachment.name, 'Q', 'utf-8') + '"' + }; + + for(header in (attachment.headers || {})) + { + // allow sender to override default headers + headers[header.toLowerCase()] = attachment.headers[header]; + } + + for(header in headers) + { + data = data.concat([fix_header_name_case(header), ': ', headers[header], CRLF]); + } + + output(data.concat([CRLF]).join('')); + }; + + var output_attachment = function(attachment, callback) + { + var build = attachment.path ? output_file : attachment.stream ? output_stream : output_data; + output_attachment_headers(attachment); + build(attachment, callback); + }; + + var output_data = function(attachment, callback) + { + output_base64(attachment.encoded ? attachment.data : new Buffer(attachment.data).toString("base64"), callback); + }; + + var output_file = function(attachment, next) + { + var chunk = MIME64CHUNK*16; + var buffer = new Buffer(chunk); + var closed = function(fd) { fs.close(fd); }; + var opened = function(err, fd) + { + if(!err) + { + var read = function(err, bytes) + { + if(!err && self.readable) + { + // guaranteed to be encoded without padding unless it is our last read + output_base64(buffer.toString("base64", 0, bytes), function() + { + if(bytes == chunk) // we read a full chunk, there might be more + { + fs.read(fd, buffer, 0, chunk, null, read); + } + else // that was the last chunk, we are done reading the file + { + self.removeListener("error", closed); + fs.close(fd, next); + } + }); + } + else + { + self.emit('error', err || {message:"message stream was interrupted somehow!"}); + } + }; + + fs.read(fd, buffer, 0, chunk, null, read); + self.once("error", closed); + } + else + self.emit('error', err); + }; + + fs.open(attachment.path, 'r', opened); + }; + + var output_stream = function(attachment, callback) + { + if(attachment.stream.readable) + { + var previous = null; + + attachment.stream.resume(); + attachment.stream.on('end', function() + { + output_base64((previous || new Buffer(0)).toString("base64"), callback); + self.removeListener('pause', attachment.stream.pause); + self.removeListener('resume', attachment.stream.resume); + self.removeListener('error', attachment.stream.resume); + }); + + attachment.stream.on('data', function(buffer) + { + // do we have bytes from a previous stream data event? + if(previous) + { + var buffer2 = Buffer.concat([previous, buffer]); + previous = null; // free up the buffer + buffer = null; // free up the buffer + buffer = buffer2; + } + + var padded = buffer.length % (MIME64CHUNK); + + // encode as much of the buffer to base64 without empty bytes + if(padded) + { + previous = new Buffer(padded); + // copy dangling bytes into previous buffer + buffer.copy(previous, 0, buffer.length - padded); + } + + output_base64(buffer.toString("base64", 0, buffer.length - padded)); + }); + + self.on('pause', attachment.stream.pause); + self.on('resume', attachment.stream.resume); + self.on('error', attachment.stream.resume); + } + else + self.emit('error', {message:"stream not readable"}); + }; + + var output_base64 = function(data, callback) + { + var loops = Math.ceil(data.length / MIMECHUNK); + var loop = 0; + + while(loop < loops) + { + output(data.substring(MIMECHUNK * loop, MIMECHUNK * (loop + 1)) + CRLF); + loop++; + } + + if(callback) + callback(); + }; + + var output_text = function(message) + { + var data = []; + + data = data.concat(["Content-Type:", message.content, CRLF, "Content-Transfer-Encoding: 7bit", CRLF]); + data = data.concat(["Content-Disposition: inline", CRLF, CRLF]); + data = data.concat([message.text || "", CRLF, CRLF]); + + output(data.join('')); + }; + + var output_alternative = function(message, callback) + { + var data = [], boundary = generate_boundary(); + + data = data.concat(["Content-Type: multipart/alternative; boundary=\"", boundary, "\"", CRLF, CRLF]); + data = data.concat(["--", boundary, CRLF]); + + output(data.join('')); + output_text(message); + output(["--", boundary, CRLF].join('')); + + var finish = function() + { + output([CRLF, "--", boundary, "--", CRLF, CRLF].join('')); + callback(); + }; + + if(message.alternative.related) + { + output_related(message.alternative, finish); + } + else + { + output_attachment(message.alternative, finish); + } + }; + + var output_related = function(message, callback) + { + var data = [], boundary = generate_boundary(); + + data = data.concat(["Content-Type: multipart/related; boundary=\"", boundary, "\"", CRLF, CRLF]); + data = data.concat(["--", boundary, CRLF]); + + output(data.join('')); + + output_attachment(message, function() + { + output_message(boundary, message.related, 0, function() + { + output([CRLF, "--", boundary, "--", CRLF, CRLF].join('')); + callback(); + }); + }); + }; + + var output_header_data = function() + { + if(self.message.attachments.length || self.message.alternative) + { + output("MIME-Version: 1.0" + CRLF); + output_mixed(); + } + else // you only have a text message! + { + output_text(self.message); + close(); + } + }; + + var output_header = function() + { + var data = []; + + for(var header in self.message.header) + { + // do not output BCC in the headers... + if(!(/bcc/i.test(header))) + data = data.concat([fix_header_name_case(header), ": ", self.message.header[header], CRLF]); + } + + output(data.join('')); + output_header_data(); + }; + + var output = function(data, callback, args) + { + var bytes = Buffer.byteLength(data); + + // can we buffer the data? + if(bytes + self.bufferIndex < self.buffer.length) + { + self.buffer.write(data, self.bufferIndex); + self.bufferIndex += bytes; + + if(callback) + callback.apply(null, args); + } + // we can't buffer the data, so ship it out! + else if(bytes > self.buffer.length) + { + if(self.bufferIndex) + { + self.emit('data', self.buffer.toString("utf-8", 0, self.bufferIndex)); + self.bufferIndex = 0; + } + + var loops = Math.ceil(data.length / self.buffer.length); + var loop = 0; + + while(loop < loops) + { + self.emit('data', data.substring(self.buffer.length*loop, self.buffer.length*(loop + 1))); + loop++; + } + } + else // we need to clean out the buffer, it is getting full + { + if(!self.paused) + { + self.emit('data', self.buffer.toString("utf-8", 0, self.bufferIndex)); + self.buffer.write(data, 0); + self.bufferIndex = bytes; + + // we could get paused after emitting data... + if(self.paused) + { + self.once("resume", function() { callback.apply(null, args); }); + } + else if(callback) + { + callback.apply(null, args); + } + } + else // we can't empty out the buffer, so let's wait till we resume before adding to it + { + self.once("resume", function() { output(data, callback, args); }); + } + } + }; + + var close = function(err) + { + if(err) + { + self.emit("error", err); + } + else + { + self.emit('data', self.buffer.toString("utf-8", 0, self.bufferIndex)); + self.emit('end'); + } + + self.buffer = null; + self.bufferIndex = 0; + self.readable = false; + self.removeAllListeners("resume"); + self.removeAllListeners("pause"); + self.removeAllListeners("error"); + self.removeAllListeners("data"); + self.removeAllListeners("end"); + }; + + self.once("destroy", close); + process.nextTick(output_header); +}; + +util.inherits(MessageStream, stream.Stream); + +MessageStream.prototype.pause = function() +{ + this.paused = true; + this.emit('pause'); +}; + +MessageStream.prototype.resume = function() +{ + this.paused = false; + this.emit('resume'); +}; + +MessageStream.prototype.destroy = function() +{ + this.emit("destroy", self.bufferIndex > 0 ? {message:"message stream destroyed"} : null); +}; + +MessageStream.prototype.destroySoon = function() +{ + this.emit("destroy"); +}; + +exports.Message = Message; +exports.BUFFERSIZE = BUFFERSIZE; +exports.create = function(headers) +{ + return new Message(headers); +}; diff --git a/node_modules/emailjs/smtp/response.js b/node_modules/emailjs/smtp/response.js new file mode 100644 index 0000000..79e5f69 --- /dev/null +++ b/node_modules/emailjs/smtp/response.js @@ -0,0 +1,75 @@ +var SMTPError = require('./error'); + +var SMTPResponse = function(stream, timeout, onerror) +{ + var buffer = '', + + notify = function() + { + if(buffer.length) + { + // parse buffer for response codes + var line = buffer.replace("\r", ''); + var match = line ? line.match(/(\d+)\s?(.*)/) : null; + + stream.emit('response', null, match ? {code:match[1], message:match[2], data:line} : {code:-1, data:line}); + buffer = ''; + } + }, + + error = function(err) + { + stream.emit('response', SMTPError('connection encountered an error', SMTPError.ERROR, err)); + }, + + timedout = function(err) + { + stream.emit('response', SMTPError('timedout while connecting to smtp server', SMTPError.TIMEDOUT, err)); + }, + + watch = function() + { + var data = stream.read(); + + if (data !== null) { + var decoded = data.toString(); + var emit = false; + var code = 0; + + buffer += decoded; + notify(); + } + }, + + close = function(err) + { + stream.emit('response', SMTPError('connection has closed', SMTPError.CONNECTIONCLOSED, err)); + }, + + end = function(err) + { + stream.emit('response', SMTPError('connection has ended', SMTPError.CONNECTIONENDED, err)); + }; + + this.stop = function(err) { + stream.removeAllListeners('response'); + stream.removeListener('readable', watch); + stream.removeListener('end', end); + stream.removeListener('close', close); + stream.removeListener('error', error); + + if(err && typeof(onerror) == "function") + onerror(err); + }; + + stream.on('readable', watch); + stream.on('end', end); + stream.on('close', close); + stream.on('error', error); + stream.setTimeout(timeout, timedout); +}; + +exports.monitor = function(stream, timeout, onerror) +{ + return new SMTPResponse(stream, timeout, onerror); +}; diff --git a/node_modules/emailjs/smtp/smtp.js b/node_modules/emailjs/smtp/smtp.js new file mode 100644 index 0000000..35d791c --- /dev/null +++ b/node_modules/emailjs/smtp/smtp.js @@ -0,0 +1,537 @@ +/* + * SMTP class written using python's (2.7) smtplib.py as a base + */ +var net = require('net'); +var crypto = require('crypto'); +var os = require('os'); +var tls = require('tls'); +var util = require('util'); +var events = require('events'); +var starttls = require('./tls'); + +var SMTPResponse = require('./response'); +var SMTPError = require('./error'); + +var SMTP_PORT = 25; +var SMTP_SSL_PORT = 465; +var SMTP_TLS_PORT = 587; +var CRLF = "\r\n"; +var AUTH_METHODS = { + PLAIN: 'PLAIN', + CRAM_MD5: 'CRAM-MD5', + LOGIN: 'LOGIN', + XOAUTH2: 'XOAUTH2' +}; +var TIMEOUT = 5000; +var DEBUG = 0; + +var log = function() { + if (DEBUG) { + Array.prototype.slice.call(arguments).forEach(function(d) { + console.log(d); + }); + } +}; + +var quotedata = function(data) { + // Quote data for email. + // Double leading '.', and change Unix newline '\\n', or Mac '\\r' into + // Internet CRLF end-of-line. + + return data.replace(/(?:\r\n|\n|\r(?!\n))/g, CRLF).replace(/^\./gm, '..'); +}; + +var caller = function(callback) { + if (typeof(callback) == 'function') { + var args = Array.prototype.slice.call(arguments); + args.shift(); + + callback.apply(null, args); + } +}; + +var SMTPState = { + NOTCONNECTED: 0, + CONNECTING: 1, + CONNECTED: 2 +}; + +var SMTP = function(options) { + events.EventEmitter.call(this); + + options = options || {}; + + this.sock = null; + this.timeout = options.timeout || TIMEOUT; + this.features = null; + this._state = SMTPState.NOTCONNECTED; + this._secure = false; + this.loggedin = (options.user && options.password) ? false : true; + this.domain = options.domain || os.hostname(); + this.host = options.host || 'localhost'; + this.port = options.port || (options.ssl ? SMTP_SSL_PORT : options.tls ? SMTP_TLS_PORT : SMTP_PORT); + this.ssl = options.ssl || false; + this.tls = options.tls || false; + this.monitor = null; + + // keep these strings hidden when quicky debugging/logging + this.user = function() { + return options.user; + }; + this.password = function() { + return options.password; + }; +}; + +SMTP.prototype = { + debug: function(level) { + DEBUG = level; + }, + + state: function() { + return this._state; + }, + + authorized: function() { + return this.loggedin; + }, + + connect: function(callback, port, host, options) { + options = options || {}; + + var self = this; + + self.host = host || self.host; + self.port = port || self.port; + self.ssl = options.ssl || self.ssl; + + if (self._state != SMTPState.NOTCONNECTED) { + self.quit(function() { + self.connect(callback, port, host, options); + }); + return; + } + + var connected = function(err) { + if (!err) { + log("connected: " + self.host + ":" + self.port); + + if (self.ssl && !self.tls) { + // if key/ca/cert was passed in, check if connection is authorized + if (typeof(self.ssl) != 'boolean' && !self.sock.authorized) { + self.close(true); + caller(callback, SMTPError('could not establish an ssl connection', SMTPError.CONNECTIONAUTH, err)); + } else self._secure = true; + } + } else { + self.close(true); + caller(callback, SMTPError("could not connect", SMTPError.COULDNOTCONNECT, err)); + } + }; + + var response = function(err, msg) { + if (err) { + self.close(true); + caller(callback, err); + } else if (msg.code == '220') { + log(msg.data); + + // might happen first, so no need to wait on connected() + self._state = SMTPState.CONNECTED; + caller(callback, null, msg.data); + } else { + log("response (data): " + msg.data); + self.quit(function() { + caller(callback, SMTPError("bad response on connection", SMTPError.BADRESPONSE, err, msg.data)); + }); + } + }; + + self._state = SMTPState.CONNECTING; + log("connecting: " + self.host + ":" + self.port); + + if (self.ssl) { + self.sock = tls.connect(self.port, self.host, self.ssl, connected); + } else { + self.sock = new net.Socket(); + self.sock.connect(self.port, self.host, connected); + } + + self.monitor = SMTPResponse.monitor(self.sock, self.timeout, function() { + self.close(true); + }); + self.sock.once('response', response); + self.sock.once('error', response); // the socket could reset or throw, so let's handle it and let the user know + }, + + send: function(str, callback) { + var self = this; + + if (self.sock && self._state == SMTPState.CONNECTED) { + log(str); + + var response = function(err, msg) { + if (err) { + caller(callback, err); + } else { + log(msg.data); + caller(callback, null, msg); + } + }; + + self.sock.once('response', response); + self.sock.write(str); + } else { + self.close(true); + caller(callback, SMTPError('no connection has been established', SMTPError.NOCONNECTION)); + } + }, + + command: function(cmd, callback, codes, failed) { + codes = Array.isArray(codes) ? codes : typeof(codes) == 'number' ? [codes] : [250]; + + var response = function(err, msg) { + if (err) { + caller(callback, err); + } else { + if (codes.indexOf(Number(msg.code)) != -1) caller(callback, err, msg.data, msg.message); + + else caller(callback, SMTPError("bad response on command '" + cmd.split(' ')[0] + "'", SMTPError.BADRESPONSE, null, msg.data)); + } + }; + + this.send(cmd + CRLF, response); + }, + + helo: function(callback, domain) { + /* + * SMTP 'helo' command. + * Hostname to send for self command defaults to the FQDN of the local + * host. + */ + + var self = this, + + response = function(err, data) { + if (err) { + caller(callback, err); + } else { + self.parse_smtp_features(data); + caller(callback, err, data); + } + }; + + this.command("helo " + (domain || this.domain), response); + }, + + starttls: function(callback) { + var self = this, + + response = function(err, msg) { + if (err) { + err.message += " while establishing a starttls session"; + caller(callback, err); + } else { + var secured_socket = null; + var secured = function() { + self._secure = true; + self.sock = secured_socket; + + var error = function(err) { + self.close(true); + caller(callback, err); + }; + + SMTPResponse.monitor(self.sock, self.timeout, function() { + self.close(true); + }); + caller(callback, msg.data); + }; + + secured_socket = starttls.secure(self.sock, self.tls, secured); + } + }; + + this.command("starttls", response, [220]); + }, + + parse_smtp_features: function(data) { + var self = this; + + // According to RFC1869 some (badly written) + // MTA's will disconnect on an ehlo. Toss an exception if + // that happens -ddm + + data.split("\n").forEach(function(ext) { + var parse = ext.match(/^(?:\d+[\-=]?)\s*?([^\s]+)(?:\s+(.*)\s*?)?$/); + + // To be able to communicate with as many SMTP servers as possible, + // we have to take the old-style auth advertisement into account, + // because: + // 1) Else our SMTP feature parser gets confused. + // 2) There are some servers that only advertise the auth methods we + // support using the old style. + + if (parse) { + // RFC 1869 requires a space between ehlo keyword and parameters. + // It's actually stricter, in that only spaces are allowed between + // parameters, but were not going to check for that here. Note + // that the space isn't present if there are no parameters. + self.features[parse[1].toLowerCase()] = parse[2] || true; + } + }); + + return; + }, + + ehlo: function(callback, domain) { + var self = this, + + response = function(err, data) { + if (err) { + caller(callback, err); + } else { + self.parse_smtp_features(data); + + if (self.tls && !self._secure) { + self.starttls(function() { + self.ehlo(callback, domain); + }); + } else { + caller(callback, err, data); + } + } + }; + + this.features = {}; + this.command("ehlo " + (domain || this.domain), response); + }, + + has_extn: function(opt) { + return this.features[opt.toLowerCase()] === undefined; + }, + + help: function(callback, args) { + // SMTP 'help' command, returns text from the server + this.command(args ? "help " + args : "help", callback, [211, 214]); + }, + + rset: function(callback) { + this.command("rset", callback); + }, + + noop: function(callback) { + this.send("noop", callback); + }, + + mail: function(callback, from) { + this.command("mail FROM:" + from, callback); + }, + + rcpt: function(callback, to) { + this.command("RCPT TO:" + to, callback, [250, 251]); + }, + + data: function(callback) { + this.command("data", callback, [354]); + }, + + data_end: function(callback) { + this.command(CRLF + ".", callback); + }, + + message: function(data) { + log(data); + this.sock.write(data); + }, + + verify: function(address, callback) { + // SMTP 'verify' command -- checks for address validity.""" + this.command("vrfy " + address, callback, [250, 251, 252]); + }, + + expn: function(address, callback) { + // SMTP 'expn' command -- expands a mailing list. + this.command("expn " + address, callback); + }, + + ehlo_or_helo_if_needed: function(callback, domain) { + // Call self.ehlo() and/or self.helo() if needed. + // If there has been no previous EHLO or HELO command self session, self + // method tries ESMTP EHLO first. + var self = this; + + if (!this.features) { + var response = function(err, data) { + caller(callback, err, data); + }; + + var attempt = function(err, data) { + if (err) self.helo(response, domain); + else caller(callback, err, data); + }; + + self.ehlo(attempt, domain); + } + }, + + login: function(callback, user, password, options) { + var self = this, + + login = { + user: user ? function() { + return user; + } : self.user, + password: password ? function() { + return password; + } : self.password, + method: options && options.method ? options.method.toUpperCase() : '' + }, + + domain = options && options.domain ? options.domain : this.domain, + + initiate = function(err, data) { + if (err) { + caller(callback, err); + return; + } + + /* + * Log in on an SMTP server that requires authentication. + * + * The arguments are: + * - user: The user name to authenticate with. + * - password: The password for the authentication. + * + * If there has been no previous EHLO or HELO command self session, self + * method tries ESMTP EHLO first. + * + * This method will return normally if the authentication was successful. + */ + + var method = null, + + encode_cram_md5 = function(challenge) { + challenge = (new Buffer(challenge, "base64")).toString("ascii"); + + var hmac = crypto.createHmac('md5', login.password()); + hmac.update(challenge); + + return (new Buffer(login.user() + " " + hmac.digest('hex')).toString("base64")); + }, + + encode_plain = function() { + return (new Buffer("\0" + login.user() + "\0" + login.password())).toString("base64"); + }, + + encode_xoauth2 = function() { + // console.log("user=" + login.user() + "\1auth=Bearer " + login.password()+"\1\1"); + // see: https://developers.google.com/gmail/xoauth2_protocol + return (new Buffer("user=" + login.user() + "\1auth=Bearer " + login.password() + "\1\1")).toString("base64"); + }; + + // List of authentication methods we support: from preferred to + // less preferred methods. + if (!method) { + var preferred = [AUTH_METHODS.CRAM_MD5, AUTH_METHODS.LOGIN, AUTH_METHODS.PLAIN, AUTH_METHODS.XOAUTH2]; + + for (var i = 0; i < preferred.length; i++) { + if ((self.features.auth || "").indexOf(preferred[i]) != -1) { + method = preferred[i]; + break; + } + } + } + + // handle bad responses from command differently + var failed = function(err, data) { + self.loggedin = false; + self.close(); // if auth is bad, close the connection, it won't get better by itself + caller(callback, SMTPError('authorization.failed', SMTPError.AUTHFAILED, err, data)); + }; + + var response = function(err, data) { + if (err) { + failed(err, data); + } else { + self.loggedin = true; + caller(callback, err, data); + } + }; + + var attempt = function(err, data, msg) { + if (err) { + failed(err, data); + } else { + if (method == AUTH_METHODS.CRAM_MD5) { + self.command(encode_cram_md5(msg), response, [235, 503]); + } else if (method == AUTH_METHODS.LOGIN) { + self.command((new Buffer(login.password())).toString("base64"), response, [235, 503]); + } + } + }; + + var attempt_user = function(err, data, msg) { + if (err) { + failed(err, data); + } else { + if (method == AUTH_METHODS.LOGIN) { + self.command((new Buffer(login.user())).toString("base64"), attempt, [334]); + } + } + }; + + if (method == AUTH_METHODS.CRAM_MD5) self.command("AUTH " + AUTH_METHODS.CRAM_MD5, attempt, [334]); + + else if (method == AUTH_METHODS.LOGIN) self.command("AUTH " + AUTH_METHODS.LOGIN, attempt_user, [334]); + + else if (method == AUTH_METHODS.PLAIN) self.command("AUTH " + AUTH_METHODS.PLAIN + " " + encode_plain(login.user(), login.password()), response, [235, 503]); + + else if (method == AUTH_METHODS.XOAUTH2) self.command("AUTH " + AUTH_METHODS.XOAUTH2 + " " + encode_xoauth2(login.user(), login.password()), response, [235, 503]); + + else if (!method) caller(callback, SMTPError('no form of authorization supported', SMTPError.AUTHNOTSUPPORTED, null, data)); + }; + + self.ehlo_or_helo_if_needed(initiate, domain); + }, + + close: function(force) { + if (this.sock) { + if (force) { + log("smtp connection destroyed!"); + this.sock.destroy(); + } else { + log("smtp connection closed."); + this.sock.end(); + } + } + + if (this.monitor) { + this.monitor.stop(); + this.monitor = null; + } + + this._state = SMTPState.NOTCONNECTED; + this._secure = false; + this.sock = null; + this.features = null; + this.loggedin = !(this.user() && this.password()); + }, + + quit: function(callback) { + var self = this, + response = function(err, data) { + caller(callback, err, data); + self.close(); + }; + + this.command("quit", response, [221, 250]); + } +}; + +for (var each in events.EventEmitter.prototype) { + SMTP.prototype[each] = events.EventEmitter.prototype[each]; +} + +exports.SMTP = SMTP; +exports.state = SMTPState; diff --git a/node_modules/emailjs/smtp/tls.js b/node_modules/emailjs/smtp/tls.js new file mode 100644 index 0000000..ee1ffd7 --- /dev/null +++ b/node_modules/emailjs/smtp/tls.js @@ -0,0 +1,64 @@ +var crypto = require('crypto'); +var tls = require('tls'); + +var secure = function(socket, options, cb) +{ + var sslcontext = crypto.createCredentials(options); + //sslcontext.context.setCiphers('RC4-SHA:AES128-SHA:AES256-SHA'); + + var pair = tls.createSecurePair(sslcontext, false); + + var cleartext = pipe(pair, socket); + + pair.on('secure', function() + { + var verifyError = (pair.ssl || pair._ssl).verifyError(); + + if(verifyError) + { + cleartext.authorized = false; + cleartext.authorizationError = verifyError; + } + else + { + cleartext.authorized = true; + } + + if (cb) cb(); + }); + + cleartext._controlReleased = true; + return cleartext; +}; + +var pipe = function(pair, socket) +{ + pair.encrypted.pipe(socket); + socket.pipe(pair.encrypted); + + var cleartext = pair.cleartext; + cleartext.socket = socket; + cleartext.encrypted = pair.encrypted; + cleartext.authorized = false; + + function onerror(e) + { + if (cleartext._controlReleased) + { + cleartext.emit('error', e); + } + } + + function onclose() + { + socket.removeListener('error', onerror); + socket.removeListener('close', onclose); + } + + socket.on('error', onerror); + socket.on('close', onclose); + + return cleartext; +}; + +exports.secure = secure; diff --git a/node_modules/express/.npmignore b/node_modules/express/.npmignore new file mode 100644 index 0000000..caf574d --- /dev/null +++ b/node_modules/express/.npmignore @@ -0,0 +1,9 @@ +.git* +docs/ +examples/ +support/ +test/ +testing.js +.DS_Store +coverage.html +lib-cov diff --git a/node_modules/express/.travis.yml b/node_modules/express/.travis.yml new file mode 100644 index 0000000..cc4dba2 --- /dev/null +++ b/node_modules/express/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/node_modules/express/History.md b/node_modules/express/History.md new file mode 100644 index 0000000..1166646 --- /dev/null +++ b/node_modules/express/History.md @@ -0,0 +1,1183 @@ + +3.3.4 / 2013-07-08 +================== + + * update send and connect + +3.3.3 / 2013-07-04 +================== + + * update connect + +3.3.2 / 2013-07-03 +================== + + * update connect + * update send + * remove .version export + +3.3.1 / 2013-06-27 +================== + + * update connect + +3.3.0 / 2013-06-26 +================== + + * update connect + * add support for multiple X-Forwarded-Proto values. Closes #1646 + * change: remove charset from json responses. Closes #1631 + * change: return actual booleans from req.accept* functions + * fix jsonp callback array throw + +3.2.6 / 2013-06-02 +================== + + * update connect + +3.2.5 / 2013-05-21 +================== + + * update connect + * update node-cookie + * add: throw a meaningful error when there is no default engine + * change generation of ETags with res.send() to GET requests only. Closes #1619 + +3.2.4 / 2013-05-09 +================== + + * fix `req.subdomains` when no Host is present + * fix `req.host` when no Host is present, return undefined + +3.2.3 / 2013-05-07 +================== + + * update connect / qs + +3.2.2 / 2013-05-03 +================== + + * update qs + +3.2.1 / 2013-04-29 +================== + + * add app.VERB() paths array deprecation warning + * update connect + * update qs and remove all ~ semver crap + * fix: accept number as value of Signed Cookie + +3.2.0 / 2013-04-15 +================== + + * add "view" constructor setting to override view behaviour + * add req.acceptsEncoding(name) + * add req.acceptedEncodings + * revert cookie signature change causing session race conditions + * fix sorting of Accept values of the same quality + +3.1.2 / 2013-04-12 +================== + + * add support for custom Accept parameters + * update cookie-signature + +3.1.1 / 2013-04-01 +================== + + * add X-Forwarded-Host support to `req.host` + * fix relative redirects + * update mkdirp + * update buffer-crc32 + * remove legacy app.configure() method from app template. + +3.1.0 / 2013-01-25 +================== + + * add support for leading "." in "view engine" setting + * add array support to `res.set()` + * add node 0.8.x to travis.yml + * add "subdomain offset" setting for tweaking `req.subdomains` + * add `res.location(url)` implementing `res.redirect()`-like setting of Location + * use app.get() for x-powered-by setting for inheritance + * fix colons in passwords for `req.auth` + +3.0.6 / 2013-01-04 +================== + + * add http verb methods to Router + * update connect + * fix mangling of the `res.cookie()` options object + * fix jsonp whitespace escape. Closes #1132 + +3.0.5 / 2012-12-19 +================== + + * add throwing when a non-function is passed to a route + * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses + * revert "add 'etag' option" + +3.0.4 / 2012-12-05 +================== + + * add 'etag' option to disable `res.send()` Etags + * add escaping of urls in text/plain in `res.redirect()` + for old browsers interpreting as html + * change crc32 module for a more liberal license + * update connect + +3.0.3 / 2012-11-13 +================== + + * update connect + * update cookie module + * fix cookie max-age + +3.0.2 / 2012-11-08 +================== + + * add OPTIONS to cors example. Closes #1398 + * fix route chaining regression. Closes #1397 + +3.0.1 / 2012-11-01 +================== + + * update connect + +3.0.0 / 2012-10-23 +================== + + * add `make clean` + * add "Basic" check to req.auth + * add `req.auth` test coverage + * add cb && cb(payload) to `res.jsonp()`. Closes #1374 + * add backwards compat for `res.redirect()` status. Closes #1336 + * add support for `res.json()` to retain previously defined Content-Types. Closes #1349 + * update connect + * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382 + * remove non-primitive string support for `res.send()` + * fix view-locals example. Closes #1370 + * fix route-separation example + +3.0.0rc5 / 2012-09-18 +================== + + * update connect + * add redis search example + * add static-files example + * add "x-powered-by" setting (`app.disable('x-powered-by')`) + * add "application/octet-stream" redirect Accept test case. Closes #1317 + +3.0.0rc4 / 2012-08-30 +================== + + * add `res.jsonp()`. Closes #1307 + * add "verbose errors" option to error-pages example + * add another route example to express(1) so people are not so confused + * add redis online user activity tracking example + * update connect dep + * fix etag quoting. Closes #1310 + * fix error-pages 404 status + * fix jsonp callback char restrictions + * remove old OPTIONS default response + +3.0.0rc3 / 2012-08-13 +================== + + * update connect dep + * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds] + * fix `res.render()` clobbering of "locals" + +3.0.0rc2 / 2012-08-03 +================== + + * add CORS example + * update connect dep + * deprecate `.createServer()` & remove old stale examples + * fix: escape `res.redirect()` link + * fix vhost example + +3.0.0rc1 / 2012-07-24 +================== + + * add more examples to view-locals + * add scheme-relative redirects (`res.redirect("//foo.com")`) support + * update cookie dep + * update connect dep + * update send dep + * fix `express(1)` -h flag, use -H for hogan. Closes #1245 + * fix `res.sendfile()` socket error handling regression + +3.0.0beta7 / 2012-07-16 +================== + + * update connect dep for `send()` root normalization regression + +3.0.0beta6 / 2012-07-13 +================== + + * add `err.view` property for view errors. Closes #1226 + * add "jsonp callback name" setting + * add support for "/foo/:bar*" non-greedy matches + * change `res.sendfile()` to use `send()` module + * change `res.send` to use "response-send" module + * remove `app.locals.use` and `res.locals.use`, use regular middleware + +3.0.0beta5 / 2012-07-03 +================== + + * add "make check" support + * add route-map example + * add `res.json(obj, status)` support back for BC + * add "methods" dep, remove internal methods module + * update connect dep + * update auth example to utilize cores pbkdf2 + * updated tests to use "supertest" + +3.0.0beta4 / 2012-06-25 +================== + + * Added `req.auth` + * Added `req.range(size)` + * Added `res.links(obj)` + * Added `res.send(body, status)` support back for backwards compat + * Added `.default()` support to `res.format()` + * Added 2xx / 304 check to `req.fresh` + * Revert "Added + support to the router" + * Fixed `res.send()` freshness check, respect res.statusCode + +3.0.0beta3 / 2012-06-15 +================== + + * Added hogan `--hjs` to express(1) [nullfirm] + * Added another example to content-negotiation + * Added `fresh` dep + * Changed: `res.send()` always checks freshness + * Fixed: expose connects mime module. Cloases #1165 + +3.0.0beta2 / 2012-06-06 +================== + + * Added `+` support to the router + * Added `req.host` + * Changed `req.param()` to check route first + * Update connect dep + +3.0.0beta1 / 2012-06-01 +================== + + * Added `res.format()` callback to override default 406 behaviour + * Fixed `res.redirect()` 406. Closes #1154 + +3.0.0alpha5 / 2012-05-30 +================== + + * Added `req.ip` + * Added `{ signed: true }` option to `res.cookie()` + * Removed `res.signedCookie()` + * Changed: dont reverse `req.ips` + * Fixed "trust proxy" setting check for `req.ips` + +3.0.0alpha4 / 2012-05-09 +================== + + * Added: allow `[]` in jsonp callback. Closes #1128 + * Added `PORT` env var support in generated template. Closes #1118 [benatkin] + * Updated: connect 2.2.2 + +3.0.0alpha3 / 2012-05-04 +================== + + * Added public `app.routes`. Closes #887 + * Added _view-locals_ example + * Added _mvc_ example + * Added `res.locals.use()`. Closes #1120 + * Added conditional-GET support to `res.send()` + * Added: coerce `res.set()` values to strings + * Changed: moved `static()` in generated apps below router + * Changed: `res.send()` only set ETag when not previously set + * Changed connect 2.2.1 dep + * Changed: `make test` now runs unit / acceptance tests + * Fixed req/res proto inheritance + +3.0.0alpha2 / 2012-04-26 +================== + + * Added `make benchmark` back + * Added `res.send()` support for `String` objects + * Added client-side data exposing example + * Added `res.header()` and `req.header()` aliases for BC + * Added `express.createServer()` for BC + * Perf: memoize parsed urls + * Perf: connect 2.2.0 dep + * Changed: make `expressInit()` middleware self-aware + * Fixed: use app.get() for all core settings + * Fixed redis session example + * Fixed session example. Closes #1105 + * Fixed generated express dep. Closes #1078 + +3.0.0alpha1 / 2012-04-15 +================== + + * Added `app.locals.use(callback)` + * Added `app.locals` object + * Added `app.locals(obj)` + * Added `res.locals` object + * Added `res.locals(obj)` + * Added `res.format()` for content-negotiation + * Added `app.engine()` + * Added `res.cookie()` JSON cookie support + * Added "trust proxy" setting + * Added `req.subdomains` + * Added `req.protocol` + * Added `req.secure` + * Added `req.path` + * Added `req.ips` + * Added `req.fresh` + * Added `req.stale` + * Added comma-delmited / array support for `req.accepts()` + * Added debug instrumentation + * Added `res.set(obj)` + * Added `res.set(field, value)` + * Added `res.get(field)` + * Added `app.get(setting)`. Closes #842 + * Added `req.acceptsLanguage()` + * Added `req.acceptsCharset()` + * Added `req.accepted` + * Added `req.acceptedLanguages` + * Added `req.acceptedCharsets` + * Added "json replacer" setting + * Added "json spaces" setting + * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92 + * Added `--less` support to express(1) + * Added `express.response` prototype + * Added `express.request` prototype + * Added `express.application` prototype + * Added `app.path()` + * Added `app.render()` + * Added `res.type()` to replace `res.contentType()` + * Changed: `res.redirect()` to add relative support + * Changed: enable "jsonp callback" by default + * Changed: renamed "case sensitive routes" to "case sensitive routing" + * Rewrite of all tests with mocha + * Removed "root" setting + * Removed `res.redirect('home')` support + * Removed `req.notify()` + * Removed `app.register()` + * Removed `app.redirect()` + * Removed `app.is()` + * Removed `app.helpers()` + * Removed `app.dynamicHelpers()` + * Fixed `res.sendfile()` with non-GET. Closes #723 + * Fixed express(1) public dir for windows. Closes #866 + +2.5.9/ 2012-04-02 +================== + + * Added support for PURGE request method [pbuyle] + * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki] + +2.5.8 / 2012-02-08 +================== + + * Update mkdirp dep. Closes #991 + +2.5.7 / 2012-02-06 +================== + + * Fixed `app.all` duplicate DELETE requests [mscdex] + +2.5.6 / 2012-01-13 +================== + + * Updated hamljs dev dep. Closes #953 + +2.5.5 / 2012-01-08 +================== + + * Fixed: set `filename` on cached templates [matthewleon] + +2.5.4 / 2012-01-02 +================== + + * Fixed `express(1)` eol on 0.4.x. Closes #947 + +2.5.3 / 2011-12-30 +================== + + * Fixed `req.is()` when a charset is present + +2.5.2 / 2011-12-10 +================== + + * Fixed: express(1) LF -> CRLF for windows + +2.5.1 / 2011-11-17 +================== + + * Changed: updated connect to 1.8.x + * Removed sass.js support from express(1) + +2.5.0 / 2011-10-24 +================== + + * Added ./routes dir for generated app by default + * Added npm install reminder to express(1) app gen + * Added 0.5.x support + * Removed `make test-cov` since it wont work with node 0.5.x + * Fixed express(1) public dir for windows. Closes #866 + +2.4.7 / 2011-10-05 +================== + + * Added mkdirp to express(1). Closes #795 + * Added simple _json-config_ example + * Added shorthand for the parsed request's pathname via `req.path` + * Changed connect dep to 1.7.x to fix npm issue... + * Fixed `res.redirect()` __HEAD__ support. [reported by xerox] + * Fixed `req.flash()`, only escape args + * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] + +2.4.6 / 2011-08-22 +================== + + * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] + +2.4.5 / 2011-08-19 +================== + + * Added support for routes to handle errors. Closes #809 + * Added `app.routes.all()`. Closes #803 + * Added "basepath" setting to work in conjunction with reverse proxies etc. + * Refactored `Route` to use a single array of callbacks + * Added support for multiple callbacks for `app.param()`. Closes #801 +Closes #805 + * Changed: removed .call(self) for route callbacks + * Dependency: `qs >= 0.3.1` + * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808 + +2.4.4 / 2011-08-05 +================== + + * Fixed `res.header()` intention of a set, even when `undefined` + * Fixed `*`, value no longer required + * Fixed `res.send(204)` support. Closes #771 + +2.4.3 / 2011-07-14 +================== + + * Added docs for `status` option special-case. Closes #739 + * Fixed `options.filename`, exposing the view path to template engines + +2.4.2. / 2011-07-06 +================== + + * Revert "removed jsonp stripping" for XSS + +2.4.1 / 2011-07-06 +================== + + * Added `res.json()` JSONP support. Closes #737 + * Added _extending-templates_ example. Closes #730 + * Added "strict routing" setting for trailing slashes + * Added support for multiple envs in `app.configure()` calls. Closes #735 + * Changed: `res.send()` using `res.json()` + * Changed: when cookie `path === null` don't default it + * Changed; default cookie path to "home" setting. Closes #731 + * Removed _pids/logs_ creation from express(1) + +2.4.0 / 2011-06-28 +================== + + * Added chainable `res.status(code)` + * Added `res.json()`, an explicit version of `res.send(obj)` + * Added simple web-service example + +2.3.12 / 2011-06-22 +================== + + * \#express is now on freenode! come join! + * Added `req.get(field, param)` + * Added links to Japanese documentation, thanks @hideyukisaito! + * Added; the `express(1)` generated app outputs the env + * Added `content-negotiation` example + * Dependency: connect >= 1.5.1 < 2.0.0 + * Fixed view layout bug. Closes #720 + * Fixed; ignore body on 304. Closes #701 + +2.3.11 / 2011-06-04 +================== + + * Added `npm test` + * Removed generation of dummy test file from `express(1)` + * Fixed; `express(1)` adds express as a dep + * Fixed; prune on `prepublish` + +2.3.10 / 2011-05-27 +================== + + * Added `req.route`, exposing the current route + * Added _package.json_ generation support to `express(1)` + * Fixed call to `app.param()` function for optional params. Closes #682 + +2.3.9 / 2011-05-25 +================== + + * Fixed bug-ish with `../' in `res.partial()` calls + +2.3.8 / 2011-05-24 +================== + + * Fixed `app.options()` + +2.3.7 / 2011-05-23 +================== + + * Added route `Collection`, ex: `app.get('/user/:id').remove();` + * Added support for `app.param(fn)` to define param logic + * Removed `app.param()` support for callback with return value + * Removed module.parent check from express(1) generated app. Closes #670 + * Refactored router. Closes #639 + +2.3.6 / 2011-05-20 +================== + + * Changed; using devDependencies instead of git submodules + * Fixed redis session example + * Fixed markdown example + * Fixed view caching, should not be enabled in development + +2.3.5 / 2011-05-20 +================== + + * Added export `.view` as alias for `.View` + +2.3.4 / 2011-05-08 +================== + + * Added `./examples/say` + * Fixed `res.sendfile()` bug preventing the transfer of files with spaces + +2.3.3 / 2011-05-03 +================== + + * Added "case sensitive routes" option. + * Changed; split methods supported per rfc [slaskis] + * Fixed route-specific middleware when using the same callback function several times + +2.3.2 / 2011-04-27 +================== + + * Fixed view hints + +2.3.1 / 2011-04-26 +================== + + * Added `app.match()` as `app.match.all()` + * Added `app.lookup()` as `app.lookup.all()` + * Added `app.remove()` for `app.remove.all()` + * Added `app.remove.VERB()` + * Fixed template caching collision issue. Closes #644 + * Moved router over from connect and started refactor + +2.3.0 / 2011-04-25 +================== + + * Added options support to `res.clearCookie()` + * Added `res.helpers()` as alias of `res.locals()` + * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0` + * Changed; auto set Content-Type in res.attachement [Aaron Heckmann] + * Renamed "cache views" to "view cache". Closes #628 + * Fixed caching of views when using several apps. Closes #637 + * Fixed gotcha invoking `app.param()` callbacks once per route middleware. +Closes #638 + * Fixed partial lookup precedence. Closes #631 +Shaw] + +2.2.2 / 2011-04-12 +================== + + * Added second callback support for `res.download()` connection errors + * Fixed `filename` option passing to template engine + +2.2.1 / 2011-04-04 +================== + + * Added `layout(path)` helper to change the layout within a view. Closes #610 + * Fixed `partial()` collection object support. + Previously only anything with `.length` would work. + When `.length` is present one must still be aware of holes, + however now `{ collection: {foo: 'bar'}}` is valid, exposes + `keyInCollection` and `keysInCollection`. + + * Performance improved with better view caching + * Removed `request` and `response` locals + * Changed; errorHandler page title is now `Express` instead of `Connect` + +2.2.0 / 2011-03-30 +================== + + * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606 + * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606 + * Added `app.VERB(path)` as alias of `app.lookup.VERB()`. + * Dependency `connect >= 1.2.0` + +2.1.1 / 2011-03-29 +================== + + * Added; expose `err.view` object when failing to locate a view + * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann] + * Fixed; `res.send(undefined)` responds with 204 [aheckmann] + +2.1.0 / 2011-03-24 +================== + + * Added `/_?` partial lookup support. Closes #447 + * Added `request`, `response`, and `app` local variables + * Added `settings` local variable, containing the app's settings + * Added `req.flash()` exception if `req.session` is not available + * Added `res.send(bool)` support (json response) + * Fixed stylus example for latest version + * Fixed; wrap try/catch around `res.render()` + +2.0.0 / 2011-03-17 +================== + + * Fixed up index view path alternative. + * Changed; `res.locals()` without object returns the locals + +2.0.0rc3 / 2011-03-17 +================== + + * Added `res.locals(obj)` to compliment `res.local(key, val)` + * Added `res.partial()` callback support + * Fixed recursive error reporting issue in `res.render()` + +2.0.0rc2 / 2011-03-17 +================== + + * Changed; `partial()` "locals" are now optional + * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01] + * Fixed .filename view engine option [reported by drudge] + * Fixed blog example + * Fixed `{req,res}.app` reference when mounting [Ben Weaver] + +2.0.0rc / 2011-03-14 +================== + + * Fixed; expose `HTTPSServer` constructor + * Fixed express(1) default test charset. Closes #579 [reported by secoif] + * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP] + +2.0.0beta3 / 2011-03-09 +================== + + * Added support for `res.contentType()` literal + The original `res.contentType('.json')`, + `res.contentType('application/json')`, and `res.contentType('json')` + will work now. + * Added `res.render()` status option support back + * Added charset option for `res.render()` + * Added `.charset` support (via connect 1.0.4) + * Added view resolution hints when in development and a lookup fails + * Added layout lookup support relative to the page view. + For example while rendering `./views/user/index.jade` if you create + `./views/user/layout.jade` it will be used in favour of the root layout. + * Fixed `res.redirect()`. RFC states absolute url [reported by unlink] + * Fixed; default `res.send()` string charset to utf8 + * Removed `Partial` constructor (not currently used) + +2.0.0beta2 / 2011-03-07 +================== + + * Added res.render() `.locals` support back to aid in migration process + * Fixed flash example + +2.0.0beta / 2011-03-03 +================== + + * Added HTTPS support + * Added `res.cookie()` maxAge support + * Added `req.header()` _Referrer_ / _Referer_ special-case, either works + * Added mount support for `res.redirect()`, now respects the mount-point + * Added `union()` util, taking place of `merge(clone())` combo + * Added stylus support to express(1) generated app + * Added secret to session middleware used in examples and generated app + * Added `res.local(name, val)` for progressive view locals + * Added default param support to `req.param(name, default)` + * Added `app.disabled()` and `app.enabled()` + * Added `app.register()` support for omitting leading ".", either works + * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539 + * Added `app.param()` to map route params to async/sync logic + * Added; aliased `app.helpers()` as `app.locals()`. Closes #481 + * Added extname with no leading "." support to `res.contentType()` + * Added `cache views` setting, defaulting to enabled in "production" env + * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_. + * Added `req.accepts()` support for extensions + * Changed; `res.download()` and `res.sendfile()` now utilize Connect's + static file server `connect.static.send()`. + * Changed; replaced `connect.utils.mime()` with npm _mime_ module + * Changed; allow `req.query` to be pre-defined (via middleware or other parent + * Changed view partial resolution, now relative to parent view + * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`. + * Fixed `req.param()` bug returning Array.prototype methods. Closes #552 + * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()` + * Fixed; using _qs_ module instead of _querystring_ + * Fixed; strip unsafe chars from jsonp callbacks + * Removed "stream threshold" setting + +1.0.8 / 2011-03-01 +================== + + * Allow `req.query` to be pre-defined (via middleware or other parent app) + * "connect": ">= 0.5.0 < 1.0.0". Closes #547 + * Removed the long deprecated __EXPRESS_ENV__ support + +1.0.7 / 2011-02-07 +================== + + * Fixed `render()` setting inheritance. + Mounted apps would not inherit "view engine" + +1.0.6 / 2011-02-07 +================== + + * Fixed `view engine` setting bug when period is in dirname + +1.0.5 / 2011-02-05 +================== + + * Added secret to generated app `session()` call + +1.0.4 / 2011-02-05 +================== + + * Added `qs` dependency to _package.json_ + * Fixed namespaced `require()`s for latest connect support + +1.0.3 / 2011-01-13 +================== + + * Remove unsafe characters from JSONP callback names [Ryan Grove] + +1.0.2 / 2011-01-10 +================== + + * Removed nested require, using `connect.router` + +1.0.1 / 2010-12-29 +================== + + * Fixed for middleware stacked via `createServer()` + previously the `foo` middleware passed to `createServer(foo)` + would not have access to Express methods such as `res.send()` + or props like `req.query` etc. + +1.0.0 / 2010-11-16 +================== + + * Added; deduce partial object names from the last segment. + For example by default `partial('forum/post', postObject)` will + give you the _post_ object, providing a meaningful default. + * Added http status code string representation to `res.redirect()` body + * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__. + * Added `req.is()` to aid in content negotiation + * Added partial local inheritance [suggested by masylum]. Closes #102 + providing access to parent template locals. + * Added _-s, --session[s]_ flag to express(1) to add session related middleware + * Added _--template_ flag to express(1) to specify the + template engine to use. + * Added _--css_ flag to express(1) to specify the + stylesheet engine to use (or just plain css by default). + * Added `app.all()` support [thanks aheckmann] + * Added partial direct object support. + You may now `partial('user', user)` providing the "user" local, + vs previously `partial('user', { object: user })`. + * Added _route-separation_ example since many people question ways + to do this with CommonJS modules. Also view the _blog_ example for + an alternative. + * Performance; caching view path derived partial object names + * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454 + * Fixed jsonp support; _text/javascript_ as per mailinglist discussion + +1.0.0rc4 / 2010-10-14 +================== + + * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0 + * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware)) + * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass] + * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass] + * Added `partial()` support for array-like collections. Closes #434 + * Added support for swappable querystring parsers + * Added session usage docs. Closes #443 + * Added dynamic helper caching. Closes #439 [suggested by maritz] + * Added authentication example + * Added basic Range support to `res.sendfile()` (and `res.download()` etc) + * Changed; `express(1)` generated app using 2 spaces instead of 4 + * Default env to "development" again [aheckmann] + * Removed _context_ option is no more, use "scope" + * Fixed; exposing _./support_ libs to examples so they can run without installs + * Fixed mvc example + +1.0.0rc3 / 2010-09-20 +================== + + * Added confirmation for `express(1)` app generation. Closes #391 + * Added extending of flash formatters via `app.flashFormatters` + * Added flash formatter support. Closes #411 + * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold" + * Added _stream threshold_ setting for `res.sendfile()` + * Added `res.send()` __HEAD__ support + * Added `res.clearCookie()` + * Added `res.cookie()` + * Added `res.render()` headers option + * Added `res.redirect()` response bodies + * Added `res.render()` status option support. Closes #425 [thanks aheckmann] + * Fixed `res.sendfile()` responding with 403 on malicious path + * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_ + * Fixed; mounted apps settings now inherit from parent app [aheckmann] + * Fixed; stripping Content-Length / Content-Type when 204 + * Fixed `res.send()` 204. Closes #419 + * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402 + * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo] + + +1.0.0rc2 / 2010-08-17 +================== + + * Added `app.register()` for template engine mapping. Closes #390 + * Added `res.render()` callback support as second argument (no options) + * Added callback support to `res.download()` + * Added callback support for `res.sendfile()` + * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()` + * Added "partials" setting to docs + * Added default expresso tests to `express(1)` generated app. Closes #384 + * Fixed `res.sendfile()` error handling, defer via `next()` + * Fixed `res.render()` callback when a layout is used [thanks guillermo] + * Fixed; `make install` creating ~/.node_libraries when not present + * Fixed issue preventing error handlers from being defined anywhere. Closes #387 + +1.0.0rc / 2010-07-28 +================== + + * Added mounted hook. Closes #369 + * Added connect dependency to _package.json_ + + * Removed "reload views" setting and support code + development env never caches, production always caches. + + * Removed _param_ in route callbacks, signature is now + simply (req, res, next), previously (req, res, params, next). + Use _req.params_ for path captures, _req.query_ for GET params. + + * Fixed "home" setting + * Fixed middleware/router precedence issue. Closes #366 + * Fixed; _configure()_ callbacks called immediately. Closes #368 + +1.0.0beta2 / 2010-07-23 +================== + + * Added more examples + * Added; exporting `Server` constructor + * Added `Server#helpers()` for view locals + * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349 + * Added support for absolute view paths + * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363 + * Added Guillermo Rauch to the contributor list + * Added support for "as" for non-collection partials. Closes #341 + * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf] + * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo] + * Fixed instanceof `Array` checks, now `Array.isArray()` + * Fixed express(1) expansion of public dirs. Closes #348 + * Fixed middleware precedence. Closes #345 + * Fixed view watcher, now async [thanks aheckmann] + +1.0.0beta / 2010-07-15 +================== + + * Re-write + - much faster + - much lighter + - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs + +0.14.0 / 2010-06-15 +================== + + * Utilize relative requires + * Added Static bufferSize option [aheckmann] + * Fixed caching of view and partial subdirectories [aheckmann] + * Fixed mime.type() comments now that ".ext" is not supported + * Updated haml submodule + * Updated class submodule + * Removed bin/express + +0.13.0 / 2010-06-01 +================== + + * Added node v0.1.97 compatibility + * Added support for deleting cookies via Request#cookie('key', null) + * Updated haml submodule + * Fixed not-found page, now using using charset utf-8 + * Fixed show-exceptions page, now using using charset utf-8 + * Fixed view support due to fs.readFile Buffers + * Changed; mime.type() no longer accepts ".type" due to node extname() changes + +0.12.0 / 2010-05-22 +================== + + * Added node v0.1.96 compatibility + * Added view `helpers` export which act as additional local variables + * Updated haml submodule + * Changed ETag; removed inode, modified time only + * Fixed LF to CRLF for setting multiple cookies + * Fixed cookie complation; values are now urlencoded + * Fixed cookies parsing; accepts quoted values and url escaped cookies + +0.11.0 / 2010-05-06 +================== + + * Added support for layouts using different engines + - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' }) + - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml' + - this.render('page.html.haml', { layout: false }) // no layout + * Updated ext submodule + * Updated haml submodule + * Fixed EJS partial support by passing along the context. Issue #307 + +0.10.1 / 2010-05-03 +================== + + * Fixed binary uploads. + +0.10.0 / 2010-04-30 +================== + + * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s + encoding is set to 'utf8' or 'utf-8'. + * Added "encoding" option to Request#render(). Closes #299 + * Added "dump exceptions" setting, which is enabled by default. + * Added simple ejs template engine support + * Added error reponse support for text/plain, application/json. Closes #297 + * Added callback function param to Request#error() + * Added Request#sendHead() + * Added Request#stream() + * Added support for Request#respond(304, null) for empty response bodies + * Added ETag support to Request#sendfile() + * Added options to Request#sendfile(), passed to fs.createReadStream() + * Added filename arg to Request#download() + * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request + * Performance enhanced by preventing several calls to toLowerCase() in Router#match() + * Changed; Request#sendfile() now streams + * Changed; Renamed Request#halt() to Request#respond(). Closes #289 + * Changed; Using sys.inspect() instead of JSON.encode() for error output + * Changed; run() returns the http.Server instance. Closes #298 + * Changed; Defaulting Server#host to null (INADDR_ANY) + * Changed; Logger "common" format scale of 0.4f + * Removed Logger "request" format + * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found + * Fixed several issues with http client + * Fixed Logger Content-Length output + * Fixed bug preventing Opera from retaining the generated session id. Closes #292 + +0.9.0 / 2010-04-14 +================== + + * Added DSL level error() route support + * Added DSL level notFound() route support + * Added Request#error() + * Added Request#notFound() + * Added Request#render() callback function. Closes #258 + * Added "max upload size" setting + * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254 + * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js + * Added callback function support to Request#halt() as 3rd/4th arg + * Added preprocessing of route param wildcards using param(). Closes #251 + * Added view partial support (with collections etc) + * Fixed bug preventing falsey params (such as ?page=0). Closes #286 + * Fixed setting of multiple cookies. Closes #199 + * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml) + * Changed; session cookie is now httpOnly + * Changed; Request is no longer global + * Changed; Event is no longer global + * Changed; "sys" module is no longer global + * Changed; moved Request#download to Static plugin where it belongs + * Changed; Request instance created before body parsing. Closes #262 + * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253 + * Changed; Pre-caching view partials in memory when "cache view partials" is enabled + * Updated support to node --version 0.1.90 + * Updated dependencies + * Removed set("session cookie") in favour of use(Session, { cookie: { ... }}) + * Removed utils.mixin(); use Object#mergeDeep() + +0.8.0 / 2010-03-19 +================== + + * Added coffeescript example app. Closes #242 + * Changed; cache api now async friendly. Closes #240 + * Removed deprecated 'express/static' support. Use 'express/plugins/static' + +0.7.6 / 2010-03-19 +================== + + * Added Request#isXHR. Closes #229 + * Added `make install` (for the executable) + * Added `express` executable for setting up simple app templates + * Added "GET /public/*" to Static plugin, defaulting to /public + * Added Static plugin + * Fixed; Request#render() only calls cache.get() once + * Fixed; Namespacing View caches with "view:" + * Fixed; Namespacing Static caches with "static:" + * Fixed; Both example apps now use the Static plugin + * Fixed set("views"). Closes #239 + * Fixed missing space for combined log format + * Deprecated Request#sendfile() and 'express/static' + * Removed Server#running + +0.7.5 / 2010-03-16 +================== + + * Added Request#flash() support without args, now returns all flashes + * Updated ext submodule + +0.7.4 / 2010-03-16 +================== + + * Fixed session reaper + * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft) + +0.7.3 / 2010-03-16 +================== + + * Added package.json + * Fixed requiring of haml / sass due to kiwi removal + +0.7.2 / 2010-03-16 +================== + + * Fixed GIT submodules (HAH!) + +0.7.1 / 2010-03-16 +================== + + * Changed; Express now using submodules again until a PM is adopted + * Changed; chat example using millisecond conversions from ext + +0.7.0 / 2010-03-15 +================== + + * Added Request#pass() support (finds the next matching route, or the given path) + * Added Logger plugin (default "common" format replaces CommonLogger) + * Removed Profiler plugin + * Removed CommonLogger plugin + +0.6.0 / 2010-03-11 +================== + + * Added seed.yml for kiwi package management support + * Added HTTP client query string support when method is GET. Closes #205 + + * Added support for arbitrary view engines. + For example "foo.engine.html" will now require('engine'), + the exports from this module are cached after the first require(). + + * Added async plugin support + + * Removed usage of RESTful route funcs as http client + get() etc, use http.get() and friends + + * Removed custom exceptions + +0.5.0 / 2010-03-10 +================== + + * Added ext dependency (library of js extensions) + * Removed extname() / basename() utils. Use path module + * Removed toArray() util. Use arguments.values + * Removed escapeRegexp() util. Use RegExp.escape() + * Removed process.mixin() dependency. Use utils.mixin() + * Removed Collection + * Removed ElementCollection + * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;) + +0.4.0 / 2010-02-11 +================== + + * Added flash() example to sample upload app + * Added high level restful http client module (express/http) + * Changed; RESTful route functions double as HTTP clients. Closes #69 + * Changed; throwing error when routes are added at runtime + * Changed; defaulting render() context to the current Request. Closes #197 + * Updated haml submodule + +0.3.0 / 2010-02-11 +================== + + * Updated haml / sass submodules. Closes #200 + * Added flash message support. Closes #64 + * Added accepts() now allows multiple args. fixes #117 + * Added support for plugins to halt. Closes #189 + * Added alternate layout support. Closes #119 + * Removed Route#run(). Closes #188 + * Fixed broken specs due to use(Cookie) missing + +0.2.1 / 2010-02-05 +================== + + * Added "plot" format option for Profiler (for gnuplot processing) + * Added request number to Profiler plugin + * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8 + * Fixed issue with routes not firing when not files are present. Closes #184 + * Fixed process.Promise -> events.Promise + +0.2.0 / 2010-02-03 +================== + + * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180 + * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174 + * Added expiration support to cache api with reaper. Closes #133 + * Added cache Store.Memory#reap() + * Added Cache; cache api now uses first class Cache instances + * Added abstract session Store. Closes #172 + * Changed; cache Memory.Store#get() utilizing Collection + * Renamed MemoryStore -> Store.Memory + * Fixed use() of the same plugin several time will always use latest options. Closes #176 + +0.1.0 / 2010-02-03 +================== + + * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context + * Updated node support to 0.1.27 Closes #169 + * Updated dirname(__filename) -> __dirname + * Updated libxmljs support to v0.2.0 + * Added session support with memory store / reaping + * Added quick uid() helper + * Added multi-part upload support + * Added Sass.js support / submodule + * Added production env caching view contents and static files + * Added static file caching. Closes #136 + * Added cache plugin with memory stores + * Added support to StaticFile so that it works with non-textual files. + * Removed dirname() helper + * Removed several globals (now their modules must be required) + +0.0.2 / 2010-01-10 +================== + + * Added view benchmarks; currently haml vs ejs + * Added Request#attachment() specs. Closes #116 + * Added use of node's parseQuery() util. Closes #123 + * Added `make init` for submodules + * Updated Haml + * Updated sample chat app to show messages on load + * Updated libxmljs parseString -> parseHtmlString + * Fixed `make init` to work with older versions of git + * Fixed specs can now run independant specs for those who cant build deps. Closes #127 + * Fixed issues introduced by the node url module changes. Closes 126. + * Fixed two assertions failing due to Collection#keys() returning strings + * Fixed faulty Collection#toArray() spec due to keys() returning strings + * Fixed `make test` now builds libxmljs.node before testing + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/LICENSE b/node_modules/express/LICENSE new file mode 100644 index 0000000..36075a3 --- /dev/null +++ b/node_modules/express/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2009-2011 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/express/Makefile b/node_modules/express/Makefile new file mode 100644 index 0000000..228f299 --- /dev/null +++ b/node_modules/express/Makefile @@ -0,0 +1,33 @@ + +MOCHA_OPTS= --check-leaks +REPORTER = dot + +check: test + +test: test-unit test-acceptance + +test-unit: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + $(MOCHA_OPTS) + +test-acceptance: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + --bail \ + test/acceptance/*.js + +test-cov: lib-cov + @EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html + +lib-cov: + @jscoverage lib lib-cov + +benchmark: + @./support/bench + +clean: + rm -f coverage.html + rm -fr lib-cov + +.PHONY: test test-unit test-acceptance benchmark clean diff --git a/node_modules/express/Readme.md b/node_modules/express/Readme.md new file mode 100644 index 0000000..00158b8 --- /dev/null +++ b/node_modules/express/Readme.md @@ -0,0 +1,179 @@ +![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png) + + Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) [![Dependency Status](https://gemnasium.com/visionmedia/express.png)](https://gemnasium.com/visionmedia/express) + +```js +var express = require('express'); +var app = express(); + +app.get('/', function(req, res){ + res.send('Hello World'); +}); + +app.listen(3000); +``` + +## Installation + + $ npm install -g express + +## Quick Start + + The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below: + + Create the app: + + $ npm install -g express + $ express /tmp/foo && cd /tmp/foo + + Install dependencies: + + $ npm install + + Start the server: + + $ node app + +## Features + + * Built on [Connect](http://github.com/senchalabs/connect) + * Robust routing + * HTTP helpers (redirection, caching, etc) + * View system supporting 14+ template engines + * Content negotiation + * Focus on high performance + * Environment based configuration + * Executable for generating applications quickly + * High test coverage + +## Philosophy + + The Express philosophy is to provide small, robust tooling for HTTP servers. Making + it a great solution for single page applications, web sites, hybrids, or public + HTTP APIs. + + Built on Connect you can use _only_ what you need, and nothing more, applications + can be as big or as small as you like, even a single file. Express does + not force you to use any specific ORM or template engine. With support for over + 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js) + you can quickly craft your perfect framework. + +## More Information + + * Join #express on freenode + * [Google Group](http://groups.google.com/group/express-js) for discussion + * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates + * Visit the [Wiki](http://github.com/visionmedia/express/wiki) + * [Русскоязычная документация](http://jsman.ru/express/) + * Run express examples [online](https://runnable.com/express) + +## Viewing Examples + +Clone the Express repo, then install the dev dependencies to install all the example / test suite deps: + + $ git clone git://github.com/visionmedia/express.git --depth 1 + $ cd express + $ npm install + +then run whichever tests you want: + + $ node examples/content-negotiation + +## Running Tests + +To run the test suite first invoke the following command within the repo, installing the development dependencies: + + $ npm install + +then run the tests: + + $ make test + +## Contributors + +``` +project: express +commits: 3559 +active : 468 days +files : 237 +authors: + 1891 Tj Holowaychuk 53.1% + 1285 visionmedia 36.1% + 182 TJ Holowaychuk 5.1% + 54 Aaron Heckmann 1.5% + 34 csausdev 1.0% + 26 ciaranj 0.7% + 21 Robert Sköld 0.6% + 6 Guillermo Rauch 0.2% + 3 Dav Glass 0.1% + 3 Nick Poulden 0.1% + 2 Randy Merrill 0.1% + 2 Benny Wong 0.1% + 2 Hunter Loftis 0.1% + 2 Jake Gordon 0.1% + 2 Brian McKinney 0.1% + 2 Roman Shtylman 0.1% + 2 Ben Weaver 0.1% + 2 Dave Hoover 0.1% + 2 Eivind Fjeldstad 0.1% + 2 Daniel Shaw 0.1% + 1 Matt Colyer 0.0% + 1 Pau Ramon 0.0% + 1 Pero Pejovic 0.0% + 1 Peter Rekdal Sunde 0.0% + 1 Raynos 0.0% + 1 Teng Siong Ong 0.0% + 1 Viktor Kelemen 0.0% + 1 ctide 0.0% + 1 8bitDesigner 0.0% + 1 isaacs 0.0% + 1 mgutz 0.0% + 1 pikeas 0.0% + 1 shuwatto 0.0% + 1 tstrimple 0.0% + 1 ewoudj 0.0% + 1 Adam Sanderson 0.0% + 1 Andrii Kostenko 0.0% + 1 Andy Hiew 0.0% + 1 Arpad Borsos 0.0% + 1 Ashwin Purohit 0.0% + 1 Benjen 0.0% + 1 Darren Torpey 0.0% + 1 Greg Ritter 0.0% + 1 Gregory Ritter 0.0% + 1 James Herdman 0.0% + 1 Jim Snodgrass 0.0% + 1 Joe McCann 0.0% + 1 Jonathan Dumaine 0.0% + 1 Jonathan Palardy 0.0% + 1 Jonathan Zacsh 0.0% + 1 Justin Lilly 0.0% + 1 Ken Sato 0.0% + 1 Maciej Małecki 0.0% + 1 Masahiro Hayashi 0.0% +``` + +## License + +(The MIT License) + +Copyright (c) 2009-2012 TJ Holowaychuk <tj@vision-media.ca> + +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/express/bin/express b/node_modules/express/bin/express new file mode 100755 index 0000000..b2b98c8 --- /dev/null +++ b/node_modules/express/bin/express @@ -0,0 +1,422 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var exec = require('child_process').exec + , program = require('commander') + , mkdirp = require('mkdirp') + , pkg = require('../package.json') + , version = pkg.version + , os = require('os') + , fs = require('fs'); + +// CLI + +program + .version(version) + .option('-s, --sessions', 'add session support') + .option('-e, --ejs', 'add ejs engine support (defaults to jade)') + .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)') + .option('-H, --hogan', 'add hogan.js engine support') + .option('-c, --css ', 'add stylesheet support (less|stylus) (defaults to plain css)') + .option('-f, --force', 'force on non-empty directory') + .parse(process.argv); + +// Path + +var path = program.args.shift() || '.'; + +// end-of-line code + +var eol = os.EOL + +// Template engine + +program.template = 'jade'; +if (program.ejs) program.template = 'ejs'; +if (program.jshtml) program.template = 'jshtml'; +if (program.hogan) program.template = 'hjs'; + +/** + * Routes index template. + */ + +var index = [ + '' + , '/*' + , ' * GET home page.' + , ' */' + , '' + , 'exports.index = function(req, res){' + , ' res.render(\'index\', { title: \'Express\' });' + , '};' +].join(eol); + +/** + * Routes users template. + */ + +var users = [ + '' + , '/*' + , ' * GET users listing.' + , ' */' + , '' + , 'exports.list = function(req, res){' + , ' res.send("respond with a resource");' + , '};' +].join(eol); + +/** + * Jade layout template. + */ + +var jadeLayout = [ + 'doctype 5' + , 'html' + , ' head' + , ' title= title' + , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')' + , ' body' + , ' block content' +].join(eol); + +/** + * Jade index template. + */ + +var jadeIndex = [ + 'extends layout' + , '' + , 'block content' + , ' h1= title' + , ' p Welcome to #{title}' +].join(eol); + +/** + * EJS index template. + */ + +var ejsIndex = [ + '' + , '' + , ' ' + , ' <%= title %>' + , ' ' + , ' ' + , ' ' + , '

<%= title %>

' + , '

Welcome to <%= title %>

' + , ' ' + , '' +].join(eol); + +/** + * JSHTML layout template. + */ + +var jshtmlLayout = [ + '' + , '' + , ' ' + , ' @write(title) ' + , ' ' + , ' ' + , ' ' + , ' @write(body)' + , ' ' + , '' +].join(eol); + +/** + * JSHTML index template. + */ + +var jshtmlIndex = [ + '

@write(title)

' + , '

Welcome to @write(title)

' +].join(eol); + +/** + * Hogan.js index template. + */ +var hoganIndex = [ + '' + , '' + , ' ' + , ' {{ title }}' + , ' ' + , ' ' + , ' ' + , '

{{ title }}

' + , '

Welcome to {{ title }}

' + , ' ' + , '' +].join(eol); + +/** + * Default css template. + */ + +var css = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default less template. + */ + +var less = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default stylus template. + */ + +var stylus = [ + 'body' + , ' padding: 50px' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif' + , 'a' + , ' color: #00B7FF' +].join(eol); + +/** + * App template. + */ + +var app = [ + '' + , '/**' + , ' * Module dependencies.' + , ' */' + , '' + , 'var express = require(\'express\')' + , ' , routes = require(\'./routes\')' + , ' , user = require(\'./routes/user\')' + , ' , http = require(\'http\')' + , ' , path = require(\'path\');' + , '' + , 'var app = express();' + , '' + , '// all environments' + , 'app.set(\'port\', process.env.PORT || 3000);' + , 'app.set(\'views\', __dirname + \'/views\');' + , 'app.set(\'view engine\', \':TEMPLATE\');' + , 'app.use(express.favicon());' + , 'app.use(express.logger(\'dev\'));' + , 'app.use(express.bodyParser());' + , 'app.use(express.methodOverride());{sess}' + , 'app.use(app.router);{css}' + , 'app.use(express.static(path.join(__dirname, \'public\')));' + , '' + , '// development only' + , 'if (\'development\' == app.get(\'env\')) {' + , ' app.use(express.errorHandler());' + , '}' + , '' + , 'app.get(\'/\', routes.index);' + , 'app.get(\'/users\', user.list);' + , '' + , 'http.createServer(app).listen(app.get(\'port\'), function(){' + , ' console.log(\'Express server listening on port \' + app.get(\'port\'));' + , '});' + , '' +].join(eol); + +// Generate application + +(function createApplication(path) { + emptyDirectory(path, function(empty){ + if (empty || program.force) { + createApplicationAt(path); + } else { + program.confirm('destination is not empty, continue? ', function(ok){ + if (ok) { + process.stdin.destroy(); + createApplicationAt(path); + } else { + abort('aborting'); + } + }); + } + }); +})(path); + +/** + * Create application at the given directory `path`. + * + * @param {String} path + */ + +function createApplicationAt(path) { + console.log(); + process.on('exit', function(){ + console.log(); + console.log(' install dependencies:'); + console.log(' $ cd %s && npm install', path); + console.log(); + console.log(' run the app:'); + console.log(' $ node app'); + console.log(); + }); + + mkdir(path, function(){ + mkdir(path + '/public'); + mkdir(path + '/public/javascripts'); + mkdir(path + '/public/images'); + mkdir(path + '/public/stylesheets', function(){ + switch (program.css) { + case 'less': + write(path + '/public/stylesheets/style.less', less); + break; + case 'stylus': + write(path + '/public/stylesheets/style.styl', stylus); + break; + default: + write(path + '/public/stylesheets/style.css', css); + } + }); + + mkdir(path + '/routes', function(){ + write(path + '/routes/index.js', index); + write(path + '/routes/user.js', users); + }); + + mkdir(path + '/views', function(){ + switch (program.template) { + case 'ejs': + write(path + '/views/index.ejs', ejsIndex); + break; + case 'jade': + write(path + '/views/layout.jade', jadeLayout); + write(path + '/views/index.jade', jadeIndex); + break; + case 'jshtml': + write(path + '/views/layout.jshtml', jshtmlLayout); + write(path + '/views/index.jshtml', jshtmlIndex); + break; + case 'hjs': + write(path + '/views/index.hjs', hoganIndex); + break; + + } + }); + + // CSS Engine support + switch (program.css) { + case 'less': + app = app.replace('{css}', eol + 'app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));'); + break; + case 'stylus': + app = app.replace('{css}', eol + 'app.use(require(\'stylus\').middleware(__dirname + \'/public\'));'); + break; + default: + app = app.replace('{css}', ''); + } + + // Session support + app = app.replace('{sess}', program.sessions + ? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());' + : ''); + + // Template support + app = app.replace(':TEMPLATE', program.template); + + // package.json + var pkg = { + name: 'application-name' + , version: '0.0.1' + , private: true + , scripts: { start: 'node app.js' } + , dependencies: { + express: version + } + } + + if (program.template) pkg.dependencies[program.template] = '*'; + + // CSS Engine support + switch (program.css) { + case 'less': + pkg.dependencies['less-middleware'] = '*'; + break; + default: + if (program.css) { + pkg.dependencies[program.css] = '*'; + } + } + + write(path + '/package.json', JSON.stringify(pkg, null, 2)); + write(path + '/app.js', app); + }); +} + +/** + * Check if the given directory `path` is empty. + * + * @param {String} path + * @param {Function} fn + */ + +function emptyDirectory(path, fn) { + fs.readdir(path, function(err, files){ + if (err && 'ENOENT' != err.code) throw err; + fn(!files || !files.length); + }); +} + +/** + * echo str > path. + * + * @param {String} path + * @param {String} str + */ + +function write(path, str) { + fs.writeFile(path, str); + console.log(' \x1b[36mcreate\x1b[0m : ' + path); +} + +/** + * Mkdir -p. + * + * @param {String} path + * @param {Function} fn + */ + +function mkdir(path, fn) { + mkdirp(path, 0755, function(err){ + if (err) throw err; + console.log(' \033[36mcreate\033[0m : ' + path); + fn && fn(); + }); +} + +/** + * Exit with the given `str`. + * + * @param {String} str + */ + +function abort(str) { + console.error(str); + process.exit(1); +} diff --git a/node_modules/express/index.js b/node_modules/express/index.js new file mode 100644 index 0000000..bfe9934 --- /dev/null +++ b/node_modules/express/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.EXPRESS_COV + ? require('./lib-cov/express') + : require('./lib/express'); \ No newline at end of file diff --git a/node_modules/express/lib/application.js b/node_modules/express/lib/application.js new file mode 100644 index 0000000..5500655 --- /dev/null +++ b/node_modules/express/lib/application.js @@ -0,0 +1,535 @@ +/** + * Module dependencies. + */ + +var connect = require('connect') + , Router = require('./router') + , methods = require('methods') + , middleware = require('./middleware') + , debug = require('debug')('express:application') + , locals = require('./utils').locals + , View = require('./view') + , utils = connect.utils + , path = require('path') + , http = require('http') + , join = path.join; + +/** + * Application prototype. + */ + +var app = exports = module.exports = {}; + +/** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + * + * @api private + */ + +app.init = function(){ + this.cache = {}; + this.settings = {}; + this.engines = {}; + this.defaultConfiguration(); +}; + +/** + * Initialize application configuration. + * + * @api private + */ + +app.defaultConfiguration = function(){ + // default settings + this.enable('x-powered-by'); + this.set('env', process.env.NODE_ENV || 'development'); + this.set('subdomain offset', 2); + debug('booting in %s mode', this.get('env')); + + // implicit middleware + this.use(connect.query()); + this.use(middleware.init(this)); + + // inherit protos + this.on('mount', function(parent){ + this.request.__proto__ = parent.request; + this.response.__proto__ = parent.response; + this.engines.__proto__ = parent.engines; + this.settings.__proto__ = parent.settings; + }); + + // router + this._router = new Router(this); + this.routes = this._router.map; + this.__defineGetter__('router', function(){ + this._usedRouter = true; + this._router.caseSensitive = this.enabled('case sensitive routing'); + this._router.strict = this.enabled('strict routing'); + return this._router.middleware; + }); + + // setup locals + this.locals = locals(this); + + // default locals + this.locals.settings = this.settings; + + // default configuration + this.set('view', View); + this.set('views', process.cwd() + '/views'); + this.set('jsonp callback name', 'callback'); + + this.configure('development', function(){ + this.set('json spaces', 2); + }); + + this.configure('production', function(){ + this.enable('view cache'); + }); +}; + +/** + * Proxy `connect#use()` to apply settings to + * mounted applications. + * + * @param {String|Function|Server} route + * @param {Function|Server} fn + * @return {app} for chaining + * @api public + */ + +app.use = function(route, fn){ + var app; + + // default route to '/' + if ('string' != typeof route) fn = route, route = '/'; + + // express app + if (fn.handle && fn.set) app = fn; + + // restore .app property on req and res + if (app) { + app.route = route; + fn = function(req, res, next) { + var orig = req.app; + app.handle(req, res, function(err){ + req.__proto__ = orig.request; + res.__proto__ = orig.response; + next(err); + }); + }; + } + + connect.proto.use.call(this, route, fn); + + // mounted an app + if (app) { + app.parent = this; + app.emit('mount', this); + } + + return this; +}; + +/** + * Register the given template engine callback `fn` + * as `ext`. + * + * By default will `require()` the engine based on the + * file extension. For example if you try to render + * a "foo.jade" file Express will invoke the following internally: + * + * app.engine('jade', require('jade').__express); + * + * For engines that do not provide `.__express` out of the box, + * or if you wish to "map" a different extension to the template engine + * you may use this method. For example mapping the EJS template engine to + * ".html" files: + * + * app.engine('html', require('ejs').renderFile); + * + * In this case EJS provides a `.renderFile()` method with + * the same signature that Express expects: `(path, options, callback)`, + * though note that it aliases this method as `ejs.__express` internally + * so if you're using ".ejs" extensions you dont need to do anything. + * + * Some template engines do not follow this convention, the + * [Consolidate.js](https://github.com/visionmedia/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seamlessly within Express. + * + * @param {String} ext + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.engine = function(ext, fn){ + if ('function' != typeof fn) throw new Error('callback function required'); + if ('.' != ext[0]) ext = '.' + ext; + this.engines[ext] = fn; + return this; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback(s). + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the samesignature as middleware, the only differencing + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * next(err); + * } else if (user) { + * req.user = user; + * next(); + * } else { + * next(new Error('failed to load user')); + * } + * }); + * }); + * + * @param {String|Array} name + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.param = function(name, fn){ + var self = this + , fns = [].slice.call(arguments, 1); + + // array + if (Array.isArray(name)) { + name.forEach(function(name){ + fns.forEach(function(fn){ + self.param(name, fn); + }); + }); + // param logic + } else if ('function' == typeof name) { + this._router.param(name); + // single + } else { + if (':' == name[0]) name = name.substr(1); + fns.forEach(function(fn){ + self._router.param(name, fn); + }); + } + + return this; +}; + +/** + * Assign `setting` to `val`, or return `setting`'s value. + * + * app.set('foo', 'bar'); + * app.get('foo'); + * // => "bar" + * + * Mounted servers inherit their parent server's settings. + * + * @param {String} setting + * @param {String} val + * @return {Server} for chaining + * @api public + */ + +app.set = function(setting, val){ + if (1 == arguments.length) { + return this.settings[setting]; + } else { + this.settings[setting] = val; + return this; + } +}; + +/** + * Return the app's absolute pathname + * based on the parent(s) that have + * mounted it. + * + * For example if the application was + * mounted as "/admin", which itself + * was mounted as "/blog" then the + * return value would be "/blog/admin". + * + * @return {String} + * @api private + */ + +app.path = function(){ + return this.parent + ? this.parent.path() + this.route + : ''; +}; + +/** + * Check if `setting` is enabled (truthy). + * + * app.enabled('foo') + * // => false + * + * app.enable('foo') + * app.enabled('foo') + * // => true + * + * @param {String} setting + * @return {Boolean} + * @api public + */ + +app.enabled = function(setting){ + return !!this.set(setting); +}; + +/** + * Check if `setting` is disabled. + * + * app.disabled('foo') + * // => true + * + * app.enable('foo') + * app.disabled('foo') + * // => false + * + * @param {String} setting + * @return {Boolean} + * @api public + */ + +app.disabled = function(setting){ + return !this.set(setting); +}; + +/** + * Enable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @api public + */ + +app.enable = function(setting){ + return this.set(setting, true); +}; + +/** + * Disable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @api public + */ + +app.disable = function(setting){ + return this.set(setting, false); +}; + +/** + * Configure callback for zero or more envs, + * when no `env` is specified that callback will + * be invoked for all environments. Any combination + * can be used multiple times, in any order desired. + * + * Examples: + * + * app.configure(function(){ + * // executed for all envs + * }); + * + * app.configure('stage', function(){ + * // executed staging env + * }); + * + * app.configure('stage', 'production', function(){ + * // executed for stage and production + * }); + * + * Note: + * + * These callbacks are invoked immediately, and + * are effectively sugar for the following: + * + * var env = process.env.NODE_ENV || 'development'; + * + * switch (env) { + * case 'development': + * ... + * break; + * case 'stage': + * ... + * break; + * case 'production': + * ... + * break; + * } + * + * @param {String} env... + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.configure = function(env, fn){ + var envs = 'all' + , args = [].slice.call(arguments); + fn = args.pop(); + if (args.length) envs = args; + if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this); + return this; +}; + +/** + * Delegate `.VERB(...)` calls to `router.VERB(...)`. + */ + +methods.forEach(function(method){ + app[method] = function(path){ + if ('get' == method && 1 == arguments.length) return this.set(path); + + // deprecated + if (Array.isArray(path)) { + console.trace('passing an array to app.VERB() is deprecated and will be removed in 4.0'); + } + + // if no router attached yet, attach the router + if (!this._usedRouter) this.use(this.router); + + // setup route + this._router[method].apply(this._router, arguments); + return this; + }; +}); + +/** + * Special-cased "all" method, applying the given route `path`, + * middleware, and callback to _every_ HTTP method. + * + * @param {String} path + * @param {Function} ... + * @return {app} for chaining + * @api public + */ + +app.all = function(path){ + var args = arguments; + methods.forEach(function(method){ + app[method].apply(this, args); + }, this); + return this; +}; + +// del -> delete alias + +app.del = app.delete; + +/** + * Render the given view `name` name with `options` + * and a callback accepting an error and the + * rendered template string. + * + * Example: + * + * app.render('email', { name: 'Tobi' }, function(err, html){ + * // ... + * }) + * + * @param {String} name + * @param {String|Function} options or fn + * @param {Function} fn + * @api public + */ + +app.render = function(name, options, fn){ + var opts = {} + , cache = this.cache + , engines = this.engines + , view; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge app.locals + utils.merge(opts, this.locals); + + // merge options._locals + if (options._locals) utils.merge(opts, options._locals); + + // merge options + utils.merge(opts, options); + + // set .cache unless explicitly provided + opts.cache = null == opts.cache + ? this.enabled('view cache') + : opts.cache; + + // primed cache + if (opts.cache) view = cache[name]; + + // view + if (!view) { + view = new (this.get('view'))(name, { + defaultEngine: this.get('view engine'), + root: this.get('views'), + engines: engines + }); + + if (!view.path) { + var err = new Error('Failed to lookup view "' + name + '"'); + err.view = view; + return fn(err); + } + + // prime the cache + if (opts.cache) cache[name] = view; + } + + // render + try { + view.render(opts, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Listen for connections. + * + * A node `http.Server` is returned, with this + * application (which is a `Function`) as its + * callback. If you wish to create both an HTTP + * and HTTPS server you may do so with the "http" + * and "https" modules as shown here: + * + * var http = require('http') + * , https = require('https') + * , express = require('express') + * , app = express(); + * + * http.createServer(app).listen(80); + * https.createServer({ ... }, app).listen(443); + * + * @return {http.Server} + * @api public + */ + +app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; diff --git a/node_modules/express/lib/express.js b/node_modules/express/lib/express.js new file mode 100644 index 0000000..c204849 --- /dev/null +++ b/node_modules/express/lib/express.js @@ -0,0 +1,86 @@ +/** + * Module dependencies. + */ + +var connect = require('connect') + , proto = require('./application') + , Route = require('./router/route') + , Router = require('./router') + , req = require('./request') + , res = require('./response') + , utils = connect.utils; + +/** + * Expose `createApplication()`. + */ + +exports = module.exports = createApplication; + +/** + * Expose mime. + */ + +exports.mime = connect.mime; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + +function createApplication() { + var app = connect(); + utils.merge(app, proto); + app.request = { __proto__: req, app: app }; + app.response = { __proto__: res, app: app }; + app.init(); + return app; +} + +/** + * Expose connect.middleware as express.* + * for example `express.logger` etc. + */ + +for (var key in connect.middleware) { + Object.defineProperty( + exports + , key + , Object.getOwnPropertyDescriptor(connect.middleware, key)); +} + +/** + * Error on createServer(). + */ + +exports.createServer = function(){ + console.warn('Warning: express.createServer() is deprecated, express'); + console.warn('applications no longer inherit from http.Server,'); + console.warn('please use:'); + console.warn(''); + console.warn(' var express = require("express");'); + console.warn(' var app = express();'); + console.warn(''); + return createApplication(); +}; + +/** + * Expose the prototypes. + */ + +exports.application = proto; +exports.request = req; +exports.response = res; + +/** + * Expose constructors. + */ + +exports.Route = Route; +exports.Router = Router; + +// Error handler title + +exports.errorHandler.title = 'Express'; + diff --git a/node_modules/express/lib/middleware.js b/node_modules/express/lib/middleware.js new file mode 100644 index 0000000..e07dd4c --- /dev/null +++ b/node_modules/express/lib/middleware.js @@ -0,0 +1,32 @@ + +/** + * Module dependencies. + */ + +var utils = require('./utils'); + +/** + * Initialization middleware, exposing the + * request and response to eachother, as well + * as defaulting the X-Powered-By header field. + * + * @param {Function} app + * @return {Function} + * @api private + */ + +exports.init = function(app){ + return function expressInit(req, res, next){ + if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); + req.res = res; + res.req = req; + req.next = next; + + req.__proto__ = app.request; + res.__proto__ = app.response; + + res.locals = res.locals || utils.locals(res); + + next(); + } +}; diff --git a/node_modules/express/lib/request.js b/node_modules/express/lib/request.js new file mode 100644 index 0000000..6fc09ee --- /dev/null +++ b/node_modules/express/lib/request.js @@ -0,0 +1,526 @@ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('./utils') + , connect = require('connect') + , fresh = require('fresh') + , parseRange = require('range-parser') + , parse = connect.utils.parseUrl + , mime = connect.mime; + +/** + * Request prototype. + */ + +var req = exports = module.exports = { + __proto__: http.IncomingMessage.prototype +}; + +/** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param {String} name + * @return {String} + * @api public + */ + +req.get = +req.header = function(name){ + switch (name = name.toLowerCase()) { + case 'referer': + case 'referrer': + return this.headers.referrer + || this.headers.referer; + default: + return this.headers[name]; + } +}; + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json", a comma-delimted list such as "json, html, text/plain", + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html, json'); + * // => "json" + * + * @param {String|Array} type(s) + * @return {String} + * @api public + */ + +req.accepts = function(type){ + return utils.accepts(type, this.get('Accept')); +}; + +/** + * Check if the given `encoding` is accepted. + * + * @param {String} encoding + * @return {Boolean} + * @api public + */ + +req.acceptsEncoding = function(encoding){ + return !! ~this.acceptedEncodings.indexOf(encoding); +}; + +/** + * Check if the given `charset` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} charset + * @return {Boolean} + * @api public + */ + +req.acceptsCharset = function(charset){ + var accepted = this.acceptedCharsets; + return accepted.length + ? !! ~accepted.indexOf(charset) + : true; +}; + +/** + * Check if the given `lang` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} lang + * @return {Boolean} + * @api public + */ + +req.acceptsLanguage = function(lang){ + var accepted = this.acceptedLanguages; + return accepted.length + ? !! ~accepted.indexOf(lang) + : true; +}; + +/** + * Parse Range header field, + * capping to the given `size`. + * + * Unspecified ranges such as "0-" require + * knowledge of your resource length. In + * the case of a byte range this is of course + * the total number of bytes. If the Range + * header field is not given `null` is returned, + * `-1` when unsatisfiable, `-2` when syntactically invalid. + * + * NOTE: remember that ranges are inclusive, so + * for example "Range: users=0-3" should respond + * with 4 users when available, not 3. + * + * @param {Number} size + * @return {Array} + * @api public + */ + +req.range = function(size){ + var range = this.get('Range'); + if (!range) return; + return parseRange(size, range); +}; + +/** + * Return an array of encodings. + * + * Examples: + * + * ['gzip', 'deflate'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedEncodings', function(){ + var accept = this.get('Accept-Encoding'); + return accept + ? accept.trim().split(/ *, */) + : []; +}); + +/** + * Return an array of Accepted media types + * ordered from highest quality to lowest. + * + * Examples: + * + * [ { value: 'application/json', + * quality: 1, + * type: 'application', + * subtype: 'json' }, + * { value: 'text/html', + * quality: 0.5, + * type: 'text', + * subtype: 'html' } ] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('accepted', function(){ + var accept = this.get('Accept'); + return accept + ? utils.parseAccept(accept) + : []; +}); + +/** + * Return an array of Accepted languages + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Language: en;q=.5, en-us + * ['en-us', 'en'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedLanguages', function(){ + var accept = this.get('Accept-Language'); + return accept + ? utils + .parseParams(accept) + .map(function(obj){ + return obj.value; + }) + : []; +}); + +/** + * Return an array of Accepted charsets + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8 + * ['unicode-1-1', 'iso-8859-5'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedCharsets', function(){ + var accept = this.get('Accept-Charset'); + return accept + ? utils + .parseParams(accept) + .map(function(obj){ + return obj.value; + }) + : []; +}); + +/** + * Return the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `connect.bodyParser()` middleware. + * + * @param {String} name + * @param {Mixed} [defaultValue] + * @return {String} + * @api public + */ + +req.param = function(name, defaultValue){ + var params = this.params || {}; + var body = this.body || {}; + var query = this.query || {}; + if (null != params[name] && params.hasOwnProperty(name)) return params[name]; + if (null != body[name]) return body[name]; + if (null != query[name]) return query[name]; + return defaultValue; +}; + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param {String} type + * @return {Boolean} + * @api public + */ + +req.is = function(type){ + var ct = this.get('Content-Type'); + if (!ct) return false; + ct = ct.split(';')[0]; + if (!~type.indexOf('/')) type = mime.lookup(type); + if (~type.indexOf('*')) { + type = type.split('/'); + ct = ct.split('/'); + if ('*' == type[0] && type[1] == ct[1]) return true; + if ('*' == type[1] && type[0] == ct[0]) return true; + return false; + } + return !! ~ct.indexOf(type); +}; + +/** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting is enabled the "X-Forwarded-Proto" header + * field will be trusted. If you're running behind + * a reverse proxy that supplies https for you this + * may be enabled. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('protocol', function(){ + var trustProxy = this.app.get('trust proxy'); + if (this.connection.encrypted) return 'https'; + if (!trustProxy) return 'http'; + var proto = this.get('X-Forwarded-Proto') || 'http'; + return proto.split(/\s*,\s*/)[0]; +}); + +/** + * Short-hand for: + * + * req.protocol == 'https' + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('secure', function(){ + return 'https' == this.protocol; +}); + +/** + * Return the remote address, or when + * "trust proxy" is `true` return + * the upstream addr. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('ip', function(){ + return this.ips[0] || this.connection.remoteAddress; +}); + +/** + * When "trust proxy" is `true`, parse + * the "X-Forwarded-For" ip address list. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream. + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('ips', function(){ + var trustProxy = this.app.get('trust proxy'); + var val = this.get('X-Forwarded-For'); + return trustProxy && val + ? val.split(/ *, */) + : []; +}); + +/** + * Return basic auth credentials. + * + * Examples: + * + * // http://tobi:hello@example.com + * req.auth + * // => { username: 'tobi', password: 'hello' } + * + * @return {Object} or undefined + * @api public + */ + +req.__defineGetter__('auth', function(){ + // missing + var auth = this.get('Authorization'); + if (!auth) return; + + // malformed + var parts = auth.split(' '); + if ('basic' != parts[0].toLowerCase()) return; + if (!parts[1]) return; + auth = parts[1]; + + // credentials + auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/); + if (!auth) return; + return { username: auth[1], password: auth[2] }; +}); + +/** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('subdomains', function(){ + var offset = this.app.get('subdomain offset'); + return (this.host || '') + .split('.') + .reverse() + .slice(offset); +}); + +/** + * Short-hand for `url.parse(req.url).pathname`. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('path', function(){ + return parse(this).pathname; +}); + +/** + * Parse the "Host" header field hostname. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('host', function(){ + var trustProxy = this.app.get('trust proxy'); + var host = trustProxy && this.get('X-Forwarded-Host'); + host = host || this.get('Host'); + if (!host) return; + return host.split(':')[0]; +}); + +/** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('fresh', function(){ + var method = this.method; + var s = this.res.statusCode; + + // GET or HEAD for weak freshness validation only + if ('GET' != method && 'HEAD' != method) return false; + + // 2xx or 304 as per rfc2616 14.26 + if ((s >= 200 && s < 300) || 304 == s) { + return fresh(this.headers, this.res._headers); + } + + return false; +}); + +/** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('stale', function(){ + return !this.fresh; +}); + +/** + * Check if the request was an _XMLHttpRequest_. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('xhr', function(){ + var val = this.get('X-Requested-With') || ''; + return 'xmlhttprequest' == val.toLowerCase(); +}); diff --git a/node_modules/express/lib/response.js b/node_modules/express/lib/response.js new file mode 100644 index 0000000..f6b7144 --- /dev/null +++ b/node_modules/express/lib/response.js @@ -0,0 +1,757 @@ +/** + * Module dependencies. + */ + +var http = require('http') + , path = require('path') + , connect = require('connect') + , utils = connect.utils + , sign = require('cookie-signature').sign + , normalizeType = require('./utils').normalizeType + , normalizeTypes = require('./utils').normalizeTypes + , etag = require('./utils').etag + , statusCodes = http.STATUS_CODES + , cookie = require('cookie') + , send = require('send') + , mime = connect.mime + , basename = path.basename + , extname = path.extname + , join = path.join; + +/** + * Response prototype. + */ + +var res = module.exports = { + __proto__: http.ServerResponse.prototype +}; + +/** + * Set status `code`. + * + * @param {Number} code + * @return {ServerResponse} + * @api public + */ + +res.status = function(code){ + this.statusCode = code; + return this; +}; + +/** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param {Object} links + * @return {ServerResponse} + * @api public + */ + +res.links = function(links){ + return this.set('Link', Object.keys(links).map(function(rel){ + return '<' + links[rel] + '>; rel="' + rel + '"'; + }).join(', ')); +}; + +/** + * Send a response. + * + * Examples: + * + * res.send(new Buffer('wahoo')); + * res.send({ some: 'json' }); + * res.send('

some html

'); + * res.send(404, 'Sorry, cant find that'); + * res.send(404); + * + * @param {Mixed} body or status + * @param {Mixed} body + * @return {ServerResponse} + * @api public + */ + +res.send = function(body){ + var req = this.req; + var head = 'HEAD' == req.method; + var len; + + // allow status / body + if (2 == arguments.length) { + // res.send(body, status) backwards compat + if ('number' != typeof body && 'number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = body; + body = arguments[1]; + } + } + + switch (typeof body) { + // response status + case 'number': + this.get('Content-Type') || this.type('txt'); + this.statusCode = body; + body = http.STATUS_CODES[body]; + break; + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.charset = this.charset || 'utf-8'; + this.type('html'); + } + break; + case 'boolean': + case 'object': + if (null == body) { + body = ''; + } else if (Buffer.isBuffer(body)) { + this.get('Content-Type') || this.type('bin'); + } else { + return this.json(body); + } + break; + } + + // populate Content-Length + if (undefined !== body && !this.get('Content-Length')) { + this.set('Content-Length', len = Buffer.isBuffer(body) + ? body.length + : Buffer.byteLength(body)); + } + + // ETag support + // TODO: W/ support + if (len > 1024 && 'GET' == req.method) { + if (!this.get('ETag')) { + this.set('ETag', etag(body)); + } + } + + // freshness + if (req.fresh) this.statusCode = 304; + + // strip irrelevant headers + if (204 == this.statusCode || 304 == this.statusCode) { + this.removeHeader('Content-Type'); + this.removeHeader('Content-Length'); + this.removeHeader('Transfer-Encoding'); + body = ''; + } + + // respond + this.end(head ? null : body); + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * res.json(500, 'oh noes!'); + * res.json(404, 'I dont have that'); + * + * @param {Mixed} obj or status + * @param {Mixed} obj + * @return {ServerResponse} + * @api public + */ + +res.json = function(obj){ + // allow status / body + if (2 == arguments.length) { + // res.json(body, status) backwards compat + if ('number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = obj; + obj = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(obj, replacer, spaces); + + // content-type + this.get('Content-Type') || this.set('Content-Type', 'application/json'); + + return this.send(body); +}; + +/** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * res.jsonp(500, 'oh noes!'); + * res.jsonp(404, 'I dont have that'); + * + * @param {Mixed} obj or status + * @param {Mixed} obj + * @return {ServerResponse} + * @api public + */ + +res.jsonp = function(obj){ + // allow status / body + if (2 == arguments.length) { + // res.json(body, status) backwards compat + if ('number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = obj; + obj = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(obj, replacer, spaces) + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + this.charset = this.charset || 'utf-8'; + this.set('Content-Type', 'application/json'); + + // jsonp + if (callback) { + if (callback instanceof Array) callback = callback[0]; + this.set('Content-Type', 'text/javascript'); + var cb = callback.replace(/[^\[\]\w$.]/g, ''); + body = cb + ' && ' + cb + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `fn(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 + * - `root` root directory for relative filenames + * + * Examples: + * + * The following example illustrates how `res.sendfile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendfile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendfile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @param {String} path + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +res.sendfile = function(path, options, fn){ + var self = this + , req = self.req + , next = this.req.next + , options = options || {} + , done; + + // support function as second arg + if ('function' == typeof options) { + fn = options; + options = {}; + } + + // socket errors + req.socket.on('error', error); + + // errors + function error(err) { + if (done) return; + done = true; + + // clean up + cleanup(); + if (!self.headerSent) self.removeHeader('Content-Disposition'); + + // callback available + if (fn) return fn(err); + + // list in limbo if there's no callback + if (self.headerSent) return; + + // delegate + next(err); + } + + // streaming + function stream() { + if (done) return; + cleanup(); + if (fn) self.on('finish', fn); + } + + // cleanup + function cleanup() { + req.socket.removeListener('error', error); + } + + // transfer + var file = send(req, path); + if (options.root) file.root(options.root); + file.maxage(options.maxAge || 0); + file.on('error', error); + file.on('directory', next); + file.on('stream', stream); + file.pipe(this); + this.on('finish', cleanup); +}; + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `fn(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headerSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + * + * @param {String} path + * @param {String|Function} filename or fn + * @param {Function} fn + * @api public + */ + +res.download = function(path, filename, fn){ + // support function as second arg + if ('function' == typeof filename) { + fn = filename; + filename = null; + } + + filename = filename || path; + this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"'); + return this.sendfile(path, fn); +}; + +/** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param {String} type + * @return {ServerResponse} for chaining + * @api public + */ + +res.contentType = +res.type = function(type){ + return this.set('Content-Type', ~type.indexOf('/') + ? type + : mime.lookup(type)); +}; + +/** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('

hey

'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('

hey

'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param {Object} obj + * @return {ServerResponse} for chaining + * @api public + */ + +res.format = function(obj){ + var req = this.req + , next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = req.accepts(keys); + + this.set('Vary', 'Accept'); + + if (key) { + this.set('Content-Type', normalizeType(key).value); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = 406; + err.types = normalizeTypes(keys).map(function(o){ return o.value }); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @api public + */ + +res.attachment = function(filename){ + if (filename) this.type(extname(filename)); + this.set('Content-Disposition', filename + ? 'attachment; filename="' + basename(filename) + '"' + : 'attachment'); + return this; +}; + +/** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + * + * @param {String|Object|Array} field + * @param {String} val + * @return {ServerResponse} for chaining + * @api public + */ + +res.set = +res.header = function(field, val){ + if (2 == arguments.length) { + if (Array.isArray(val)) val = val.map(String); + else val = String(val); + this.setHeader(field, val); + } else { + for (var key in field) { + this.set(key, field[key]); + } + } + return this; +}; + +/** + * Get value for header `field`. + * + * @param {String} field + * @return {String} + * @api public + */ + +res.get = function(field){ + return this.getHeader(field); +}; + +/** + * Clear cookie `name`. + * + * @param {String} name + * @param {Object} options + * @param {ServerResponse} for chaining + * @api public + */ + +res.clearCookie = function(name, options){ + var opts = { expires: new Date(1), path: '/' }; + return this.cookie(name, '', options + ? utils.merge(opts, options) + : opts); +}; + +/** + * Set cookie `name` to `val`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + * + * @param {String} name + * @param {String|Object} val + * @param {Options} options + * @api public + */ + +res.cookie = function(name, val, options){ + options = utils.merge({}, options); + var secret = this.req.secret; + var signed = options.signed; + if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies'); + if ('number' == typeof val) val = val.toString(); + if ('object' == typeof val) val = 'j:' + JSON.stringify(val); + if (signed) val = 's:' + sign(val, secret); + if ('maxAge' in options) { + options.expires = new Date(Date.now() + options.maxAge); + options.maxAge /= 1000; + } + if (null == options.path) options.path = '/'; + this.set('Set-Cookie', cookie.serialize(name, String(val), options)); + return this; +}; + + +/** + * Set the location header to `url`. + * + * The given `url` can also be the name of a mapped url, for + * example by default express supports "back" which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com'); + * res.location('../login'); // /blog/post/1 -> /blog/login + * + * Mounting: + * + * When an application is mounted and `res.location()` + * is given a path that does _not_ lead with "/" it becomes + * relative to the mount-point. For example if the application + * is mounted at "/blog", the following would become "/blog/login". + * + * res.location('login'); + * + * While the leading slash would result in a location of "/login": + * + * res.location('/login'); + * + * @param {String} url + * @api public + */ + +res.location = function(url){ + var app = this.app + , req = this.req; + + // setup redirect map + var map = { back: req.get('Referrer') || '/' }; + + // perform redirect + url = map[url] || url; + + // relative + if (!~url.indexOf('://') && 0 != url.indexOf('//')) { + var path + + // relative to path + if ('.' == url[0]) { + path = req.originalUrl.split('?')[0] + url = path + ('/' == path[path.length - 1] ? '' : '/') + url; + // relative to mount-point + } else if ('/' != url[0]) { + path = app.path(); + url = path + '/' + url; + } + } + + // Respond + this.set('Location', url); + return this; +}; + +/** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com'); + * res.redirect(301, 'http://example.com'); + * res.redirect('http://example.com', 301); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + * + * @param {String} url + * @param {Number} code + * @api public + */ + +res.redirect = function(url){ + var app = this.app + , head = 'HEAD' == this.req.method + , status = 302 + , body; + + // allow status / url + if (2 == arguments.length) { + if ('number' == typeof url) { + status = url; + url = arguments[1]; + } else { + status = arguments[1]; + } + } + + // Set location header + this.location(url); + url = this.get('Location'); + + // Support text/{plain,html} by default + this.format({ + text: function(){ + body = statusCodes[status] + '. Redirecting to ' + encodeURI(url); + }, + + html: function(){ + var u = utils.escape(url); + body = '

' + statusCodes[status] + '. Redirecting to ' + u + '

'; + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + this.end(head ? null : body); +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @param {String} view + * @param {Object|Function} options or callback function + * @param {Function} fn + * @api public + */ + +res.render = function(view, options, fn){ + var self = this + , options = options || {} + , req = this.req + , app = req.app; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge res.locals + options._locals = self.locals; + + // default callback to respond + fn = fn || function(err, str){ + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, options, fn); +}; diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..662dc29 --- /dev/null +++ b/node_modules/express/lib/router/index.js @@ -0,0 +1,273 @@ +/** + * Module dependencies. + */ + +var Route = require('./route') + , utils = require('../utils') + , methods = require('methods') + , debug = require('debug')('express:router') + , parse = require('connect').utils.parseUrl; + +/** + * Expose `Router` constructor. + */ + +exports = module.exports = Router; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @api private + */ + +function Router(options) { + options = options || {}; + var self = this; + this.map = {}; + this.params = {}; + this._params = []; + this.caseSensitive = options.caseSensitive; + this.strict = options.strict; + this.middleware = function router(req, res, next){ + self._dispatch(req, res, next); + }; +} + +/** + * Register a param callback `fn` for the given `name`. + * + * @param {String|Function} name + * @param {Function} fn + * @return {Router} for chaining + * @api public + */ + +Router.prototype.param = function(name, fn){ + // param logic + if ('function' == typeof name) { + this._params.push(name); + return; + } + + // apply param functions + var params = this._params + , len = params.length + , ret; + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' != typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Route dispatcher aka the route "middleware". + * + * @param {IncomingMessage} req + * @param {ServerResponse} res + * @param {Function} next + * @api private + */ + +Router.prototype._dispatch = function(req, res, next){ + var params = this.params + , self = this; + + debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl); + + // route dispatch + (function pass(i, err){ + var paramCallbacks + , paramIndex = 0 + , paramVal + , route + , keys + , key; + + // match next route + function nextRoute(err) { + pass(req._route_index + 1, err); + } + + // match route + req.route = route = self.matchRequest(req, i); + + // no route + if (!route) return next(err); + debug('matched %s %s', route.method, route.path); + + // we have a route + // start at param 0 + req.params = route.params; + keys = route.keys; + i = 0; + + // param callbacks + function param(err) { + paramIndex = 0; + key = keys[i++]; + paramVal = key && req.params[key.name]; + paramCallbacks = key && params[key.name]; + + try { + if ('route' == err) { + nextRoute(); + } else if (err) { + i = 0; + callbacks(err); + } else if (paramCallbacks && undefined !== paramVal) { + paramCallback(); + } else if (key) { + param(); + } else { + i = 0; + callbacks(); + } + } catch (err) { + param(err); + } + }; + + param(err); + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + if (err || !fn) return param(err); + fn(req, res, paramCallback, paramVal, key.name); + } + + // invoke route callbacks + function callbacks(err) { + var fn = route.callbacks[i++]; + try { + if ('route' == err) { + nextRoute(); + } else if (err && fn) { + if (fn.length < 4) return callbacks(err); + fn(err, req, res, callbacks); + } else if (fn) { + if (fn.length < 4) return fn(req, res, callbacks); + callbacks(); + } else { + nextRoute(err); + } + } catch (err) { + callbacks(err); + } + } + })(0); +}; + +/** + * Attempt to match a route for `req` + * with optional starting index of `i` + * defaulting to 0. + * + * @param {IncomingMessage} req + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.matchRequest = function(req, i, head){ + var method = req.method.toLowerCase() + , url = parse(req) + , path = url.pathname + , routes = this.map + , i = i || 0 + , route; + + // HEAD support + if (!head && 'head' == method) { + route = this.matchRequest(req, i, true); + if (route) return route; + method = 'get'; + } + + // routes for this method + if (routes = routes[method]) { + + // matching routes + for (var len = routes.length; i < len; ++i) { + route = routes[i]; + if (route.match(path)) { + req._route_index = i; + return route; + } + } + } +}; + +/** + * Attempt to match a route for `method` + * and `url` with optional starting + * index of `i` defaulting to 0. + * + * @param {String} method + * @param {String} url + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.match = function(method, url, i, head){ + var req = { method: method, url: url }; + return this.matchRequest(req, i, head); +}; + +/** + * Route `method`, `path`, and one or more callbacks. + * + * @param {String} method + * @param {String} path + * @param {Function} callback... + * @return {Router} for chaining + * @api private + */ + +Router.prototype.route = function(method, path, callbacks){ + var method = method.toLowerCase() + , callbacks = utils.flatten([].slice.call(arguments, 2)); + + // ensure path was given + if (!path) throw new Error('Router#' + method + '() requires a path'); + + // ensure all callbacks are functions + callbacks.forEach(function(fn, i){ + if ('function' == typeof fn) return; + var type = {}.toString.call(fn); + var msg = '.' + method + '() requires callback functions but got a ' + type; + throw new Error(msg); + }); + + // create the route + debug('defined %s %s', method, path); + var route = new Route(method, path, callbacks, { + sensitive: this.caseSensitive, + strict: this.strict + }); + + // add it + (this.map[method] = this.map[method] || []).push(route); + return this; +}; + +methods.forEach(function(method){ + Router.prototype[method] = function(path){ + var args = [method].concat([].slice.call(arguments)); + this.route.apply(this, args); + return this; + }; +}); diff --git a/node_modules/express/lib/router/route.js b/node_modules/express/lib/router/route.js new file mode 100644 index 0000000..c1a0b5e --- /dev/null +++ b/node_modules/express/lib/router/route.js @@ -0,0 +1,72 @@ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Expose `Route`. + */ + +module.exports = Route; + +/** + * Initialize `Route` with the given HTTP `method`, `path`, + * and an array of `callbacks` and `options`. + * + * Options: + * + * - `sensitive` enable case-sensitive routes + * - `strict` enable strict matching for trailing slashes + * + * @param {String} method + * @param {String} path + * @param {Array} callbacks + * @param {Object} options. + * @api private + */ + +function Route(method, path, callbacks, options) { + options = options || {}; + this.path = path; + this.method = method; + this.callbacks = callbacks; + this.regexp = utils.pathRegexp(path + , this.keys = [] + , options.sensitive + , options.strict); +} + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Route.prototype.match = function(path){ + var keys = this.keys + , params = this.params = [] + , m = this.regexp.exec(path); + + if (!m) return false; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = 'string' == typeof m[i] + ? decodeURIComponent(m[i]) + : m[i]; + + if (key) { + params[key.name] = val; + } else { + params.push(val); + } + } + + return true; +}; diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js new file mode 100644 index 0000000..fd245a8 --- /dev/null +++ b/node_modules/express/lib/utils.js @@ -0,0 +1,313 @@ + +/** + * Module dependencies. + */ + +var mime = require('connect').mime + , crc32 = require('buffer-crc32'); + +/** + * toString ref. + */ + +var toString = {}.toString; + +/** + * Return ETag for `body`. + * + * @param {String|Buffer} body + * @return {String} + * @api private + */ + +exports.etag = function(body){ + return '"' + crc32.signed(body) + '"'; +}; + +/** + * Make `locals()` bound to the given `obj`. + * + * This is used for `app.locals` and `res.locals`. + * + * @param {Object} obj + * @return {Function} + * @api private + */ + +exports.locals = function(obj){ + function locals(obj){ + for (var key in obj) locals[key] = obj[key]; + return obj; + }; + + return locals; +}; + +/** + * Check if `path` looks absolute. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +exports.isAbsolute = function(path){ + if ('/' == path[0]) return true; + if (':' == path[1] && '\\' == path[2]) return true; +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = function(arr, ret){ + var ret = ret || [] + , len = arr.length; + for (var i = 0; i < len; ++i) { + if (Array.isArray(arr[i])) { + exports.flatten(arr[i], ret); + } else { + ret.push(arr[i]); + } + } + return ret; +}; + +/** + * Normalize the given `type`, for example "html" becomes "text/html". + * + * @param {String} type + * @return {Object} + * @api private + */ + +exports.normalizeType = function(type){ + return ~type.indexOf('/') + ? acceptParams(type) + : { value: mime.lookup(type), params: {} }; +}; + +/** + * Normalize `types`, for example "html" becomes "text/html". + * + * @param {Array} types + * @return {Array} + * @api private + */ + +exports.normalizeTypes = function(types){ + var ret = []; + + for (var i = 0; i < types.length; ++i) { + ret.push(exports.normalizeType(types[i])); + } + + return ret; +}; + +/** + * Return the acceptable type in `types`, if any. + * + * @param {Array} types + * @param {String} str + * @return {String} + * @api private + */ + +exports.acceptsArray = function(types, str){ + // accept anything when Accept is not present + if (!str) return types[0]; + + // parse + var accepted = exports.parseAccept(str) + , normalized = exports.normalizeTypes(types) + , len = accepted.length; + + for (var i = 0; i < len; ++i) { + for (var j = 0, jlen = types.length; j < jlen; ++j) { + if (exports.accept(normalized[j], accepted[i])) { + return types[j]; + } + } + } +}; + +/** + * Check if `type(s)` are acceptable based on + * the given `str`. + * + * @param {String|Array} type(s) + * @param {String} str + * @return {Boolean|String} + * @api private + */ + +exports.accepts = function(type, str){ + if ('string' == typeof type) type = type.split(/ *, */); + return exports.acceptsArray(type, str); +}; + +/** + * Check if `type` array is acceptable for `other`. + * + * @param {Object} type + * @param {Object} other + * @return {Boolean} + * @api private + */ + +exports.accept = function(type, other){ + var t = type.value.split('/'); + return (t[0] == other.type || '*' == other.type) + && (t[1] == other.subtype || '*' == other.subtype) + && paramsEqual(type.params, other.params); +}; + +/** + * Check if accept params are equal. + * + * @param {Object} a + * @param {Object} b + * @return {Boolean} + * @api private + */ + +function paramsEqual(a, b){ + return !Object.keys(a).some(function(k) { + return a[k] != b[k]; + }); +} + +/** + * Parse accept `str`, returning + * an array objects containing + * `.type` and `.subtype` along + * with the values provided by + * `parseQuality()`. + * + * @param {Type} name + * @return {Type} + * @api private + */ + +exports.parseAccept = function(str){ + return exports + .parseParams(str) + .map(function(obj){ + var parts = obj.value.split('/'); + obj.type = parts[0]; + obj.subtype = parts[1]; + return obj; + }); +}; + +/** + * Parse quality `str`, returning an + * array of objects with `.value`, + * `.quality` and optional `.params` + * + * @param {String} str + * @return {Array} + * @api private + */ + +exports.parseParams = function(str){ + return str + .split(/ *, */) + .map(acceptParams) + .filter(function(obj){ + return obj.quality; + }) + .sort(function(a, b){ + if (a.quality === b.quality) { + return a.originalIndex - b.originalIndex; + } else { + return b.quality - a.quality; + } + }); +}; + +/** + * Parse accept params `str` returning an + * object with `.value`, `.quality` and `.params`. + * also includes `.originalIndex` for stable sorting + * + * @param {String} str + * @return {Object} + * @api private + */ + +function acceptParams(str, index) { + var parts = str.split(/ *; */); + var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; + + for (var i = 1; i < parts.length; ++i) { + var pms = parts[i].split(/ *= */); + if ('q' == pms[0]) { + ret.quality = parseFloat(pms[1]); + } else { + ret.params[pms[0]] = pms[1]; + } + } + + return ret; +} + +/** + * 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, '>'); +}; + +/** + * Normalize the given path string, + * returning a regular expression. + * + * An empty array should be passed, + * which will contain the placeholder + * key names. For example "/user/:id" will + * then contain ["id"]. + * + * @param {String|RegExp|Array} path + * @param {Array} keys + * @param {Boolean} sensitive + * @param {Boolean} strict + * @return {RegExp} + * @api private + */ + +exports.pathRegexp = function(path, keys, sensitive, strict) { + if (toString.call(path) == '[object RegExp]') return path; + if (Array.isArray(path)) path = '(' + path.join('|') + ')'; + path = path + .concat(strict ? '' : '/?') + .replace(/\/\(/g, '(?:/') + .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){ + keys.push({ name: key, optional: !! optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + + (optional || '') + + (star ? '(/*)?' : ''); + }) + .replace(/([\/.])/g, '\\$1') + .replace(/\*/g, '(.*)'); + return new RegExp('^' + path + '$', sensitive ? '' : 'i'); +} diff --git a/node_modules/express/lib/view.js b/node_modules/express/lib/view.js new file mode 100644 index 0000000..b9dc69e --- /dev/null +++ b/node_modules/express/lib/view.js @@ -0,0 +1,77 @@ +/** + * Module dependencies. + */ + +var path = require('path') + , fs = require('fs') + , utils = require('./utils') + , dirname = path.dirname + , basename = path.basename + , extname = path.extname + , exists = fs.existsSync || path.existsSync + , join = path.join; + +/** + * Expose `View`. + */ + +module.exports = View; + +/** + * Initialize a new `View` with the given `name`. + * + * Options: + * + * - `defaultEngine` the default template engine name + * - `engines` template engine require() cache + * - `root` root path for view lookup + * + * @param {String} name + * @param {Object} options + * @api private + */ + +function View(name, options) { + options = options || {}; + this.name = name; + this.root = options.root; + var engines = options.engines; + this.defaultEngine = options.defaultEngine; + var ext = this.ext = extname(name); + if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.'); + if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); + this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); + this.path = this.lookup(name); +} + +/** + * Lookup view by the given `path` + * + * @param {String} path + * @return {String} + * @api private + */ + +View.prototype.lookup = function(path){ + var ext = this.ext; + + // . + if (!utils.isAbsolute(path)) path = join(this.root, path); + if (exists(path)) return path; + + // /index. + path = join(dirname(path), basename(path, ext), 'index' + ext); + if (exists(path)) return path; +}; + +/** + * Render with the given `options` and callback `fn(err, str)`. + * + * @param {Object} options + * @param {Function} fn + * @api private + */ + +View.prototype.render = function(options, fn){ + this.engine(this.path, options, fn); +}; diff --git a/node_modules/express/node_modules/buffer-crc32/.npmignore b/node_modules/express/node_modules/buffer-crc32/.npmignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/express/node_modules/buffer-crc32/.travis.yml b/node_modules/express/node_modules/buffer-crc32/.travis.yml new file mode 100644 index 0000000..7a902e8 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - 0.6 + - 0.8 +notifications: + email: + recipients: + - brianloveswords@gmail.com \ No newline at end of file diff --git a/node_modules/express/node_modules/buffer-crc32/README.md b/node_modules/express/node_modules/buffer-crc32/README.md new file mode 100644 index 0000000..0d9d8b8 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/README.md @@ -0,0 +1,47 @@ +# buffer-crc32 + +[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32) + +crc32 that works with binary data and fancy character sets, outputs +buffer, signed or unsigned data and has tests. + +Derived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix + +# install +``` +npm install buffer-crc32 +``` + +# example +```js +var crc32 = require('buffer-crc32'); +// works with buffers +var buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00]) +crc32(buf) // -> + +// has convenience methods for getting signed or unsigned ints +crc32.signed(buf) // -> -1805997238 +crc32.unsigned(buf) // -> 2488970058 + +// will cast to buffer if given a string, so you can +// directly use foreign characters safely +crc32('自動販売機') // -> + +// and works in append mode too +var partialCrc = crc32('hey'); +var partialCrc = crc32(' ', partialCrc); +var partialCrc = crc32('sup', partialCrc); +var partialCrc = crc32(' ', partialCrc); +var finalCrc = crc32('bros', partialCrc); // -> +``` + +# tests +This was tested against the output of zlib's crc32 method. You can run +the tests with`npm test` (requires tap) + +# see also +https://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also +supports buffer inputs and return unsigned ints (thanks @tjholowaychuk). + +# license +MIT/X11 diff --git a/node_modules/express/node_modules/buffer-crc32/index.js b/node_modules/express/node_modules/buffer-crc32/index.js new file mode 100644 index 0000000..e29ce3e --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/index.js @@ -0,0 +1,88 @@ +var Buffer = require('buffer').Buffer; + +var CRC_TABLE = [ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d +]; + +function bufferizeInt(num) { + var tmp = Buffer(4); + tmp.writeInt32BE(num, 0); + return tmp; +} + +function _crc32(buf, previous) { + if (!Buffer.isBuffer(buf)) { + buf = Buffer(buf); + } + if (Buffer.isBuffer(previous)) { + previous = previous.readUInt32BE(0); + } + var crc = ~~previous ^ -1; + for (var n = 0; n < buf.length; n++) { + crc = CRC_TABLE[(crc ^ buf[n]) & 0xff] ^ (crc >>> 8); + } + return (crc ^ -1); +} + +function crc32() { + return bufferizeInt(_crc32.apply(null, arguments)); +} +crc32.signed = function () { + return _crc32.apply(null, arguments); +}; +crc32.unsigned = function () { + return _crc32.apply(null, arguments) >>> 0; +}; + +module.exports = crc32; diff --git a/node_modules/express/node_modules/buffer-crc32/package.json b/node_modules/express/node_modules/buffer-crc32/package.json new file mode 100644 index 0000000..b5ef500 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/package.json @@ -0,0 +1,40 @@ +{ + "author": { + "name": "Brian J. Brennan", + "email": "brianloveswords@gmail.com", + "url": "http://bjb.io" + }, + "name": "buffer-crc32", + "description": "A pure javascript CRC32 algorithm that plays nice with binary data", + "version": "0.2.1", + "contributors": [ + { + "name": "Vladimir Kuznetsov" + } + ], + "homepage": "https://github.com/brianloveswords/buffer-crc32", + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/buffer-crc32.git" + }, + "main": "index.js", + "scripts": { + "test": "./node_modules/.bin/tap tests/*.test.js" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.2.5" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# buffer-crc32\n\n[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)\n\ncrc32 that works with binary data and fancy character sets, outputs\nbuffer, signed or unsigned data and has tests.\n\nDerived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix\n\n# install\n```\nnpm install buffer-crc32\n```\n\n# example\n```js\nvar crc32 = require('buffer-crc32');\n// works with buffers\nvar buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])\ncrc32(buf) // -> \n\n// has convenience methods for getting signed or unsigned ints\ncrc32.signed(buf) // -> -1805997238\ncrc32.unsigned(buf) // -> 2488970058\n\n// will cast to buffer if given a string, so you can\n// directly use foreign characters safely\ncrc32('自動販売機') // -> \n\n// and works in append mode too\nvar partialCrc = crc32('hey');\nvar partialCrc = crc32(' ', partialCrc);\nvar partialCrc = crc32('sup', partialCrc);\nvar partialCrc = crc32(' ', partialCrc);\nvar finalCrc = crc32('bros', partialCrc); // -> \n```\n\n# tests\nThis was tested against the output of zlib's crc32 method. You can run\nthe tests with`npm test` (requires tap)\n\n# see also\nhttps://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also\nsupports buffer inputs and return unsigned ints (thanks @tjholowaychuk).\n\n# license\nMIT/X11\n", + "readmeFilename": "README.md", + "_id": "buffer-crc32@0.2.1", + "dist": { + "shasum": "fb992f30339ebd361473336c76f07614fd8d91cb" + }, + "_from": "buffer-crc32@0.2.1", + "_resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz" +} diff --git a/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js b/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js new file mode 100644 index 0000000..bb0f9ef --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js @@ -0,0 +1,89 @@ +var crc32 = require('..'); +var test = require('tap').test; + +test('simple crc32 is no problem', function (t) { + var input = Buffer('hey sup bros'); + var expected = Buffer([0x47, 0xfa, 0x55, 0x70]); + t.same(crc32(input), expected); + t.end(); +}); + +test('another simple one', function (t) { + var input = Buffer('IEND'); + var expected = Buffer([0xae, 0x42, 0x60, 0x82]); + t.same(crc32(input), expected); + t.end(); +}); + +test('slightly more complex', function (t) { + var input = Buffer([0x00, 0x00, 0x00]); + var expected = Buffer([0xff, 0x41, 0xd9, 0x12]); + t.same(crc32(input), expected); + t.end(); +}); + +test('complex crc32 gets calculated like a champ', function (t) { + var input = Buffer('शीर्षक'); + var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]); + t.same(crc32(input), expected); + t.end(); +}); + +test('casts to buffer if necessary', function (t) { + var input = 'शीर्षक'; + var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]); + t.same(crc32(input), expected); + t.end(); +}); + +test('can do signed', function (t) { + var input = 'ham sandwich'; + var expected = -1891873021; + t.same(crc32.signed(input), expected); + t.end(); +}); + +test('can do unsigned', function (t) { + var input = 'bear sandwich'; + var expected = 3711466352; + t.same(crc32.unsigned(input), expected); + t.end(); +}); + + +test('simple crc32 in append mode', function (t) { + var input = [Buffer('hey'), Buffer(' '), Buffer('sup'), Buffer(' '), Buffer('bros')]; + var expected = Buffer([0x47, 0xfa, 0x55, 0x70]); + for (var crc = 0, i = 0; i < input.length; i++) { + crc = crc32(input[i], crc); + } + t.same(crc, expected); + t.end(); +}); + + +test('can do signed in append mode', function (t) { + var input1 = 'ham'; + var input2 = ' '; + var input3 = 'sandwich'; + var expected = -1891873021; + + var crc = crc32.signed(input1); + crc = crc32.signed(input2, crc); + crc = crc32.signed(input3, crc); + + t.same(crc, expected); + t.end(); +}); + +test('can do unsigned in append mode', function (t) { + var input1 = 'bear san'; + var input2 = 'dwich'; + var expected = 3711466352; + + var crc = crc32.unsigned(input1); + crc = crc32.unsigned(input2, crc); + t.same(crc, expected); + t.end(); +}); + diff --git a/node_modules/express/node_modules/commander/History.md b/node_modules/express/node_modules/commander/History.md new file mode 100644 index 0000000..7cda70f --- /dev/null +++ b/node_modules/express/node_modules/commander/History.md @@ -0,0 +1,158 @@ + +1.2.0 / 2013-06-13 +================== + + * allow "-" hyphen as an option argument + * support for RegExp coercion + +1.1.1 / 2012-11-20 +================== + + * add more sub-command padding + * fix .usage() when args are present. Closes #106 + +1.1.0 / 2012-11-16 +================== + + * add git-style executable subcommand support. Closes #94 + +1.0.5 / 2012-10-09 +================== + + * fix `--name` clobbering. Closes #92 + * fix examples/help. Closes #89 + +1.0.4 / 2012-09-03 +================== + + * add `outputHelp()` method. + +1.0.3 / 2012-08-30 +================== + + * remove invalid .version() defaulting + +1.0.2 / 2012-08-24 +================== + + * add `--foo=bar` support [arv] + * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus] + +1.0.1 / 2012-08-03 +================== + + * fix issue #56 + * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode()) + +1.0.0 / 2012-07-05 +================== + + * add support for optional option descriptions + * add defaulting of `.version()` to package.json's version + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/commander/Readme.md b/node_modules/express/node_modules/commander/Readme.md new file mode 100644 index 0000000..107932a --- /dev/null +++ b/node_modules/express/node_modules/commander/Readme.md @@ -0,0 +1,276 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +```js +program.prompt('Email: ', /^.+@.+\..+$/, function(email){ + console.log('email: %j', email); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## .outputHelp() + + Output help information without exiting. + +## .help() + + Output help information and exit immediately. + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/express/node_modules/commander/index.js b/node_modules/express/node_modules/commander/index.js new file mode 100644 index 0000000..0ceaf18 --- /dev/null +++ b/node_modules/express/node_modules/commander/index.js @@ -0,0 +1,1152 @@ +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , spawn = require('child_process').spawn + , keypress = require('keypress') + , fs = require('fs') + , exists = fs.existsSync + , path = require('path') + , tty = require('tty') + , dirname = path.dirname + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description || ''; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this._args = []; + this._name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @param {String} [desc] + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name, desc){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + if (desc) cmd.description(desc); + if (desc) this.executables = true; + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + if (desc) return this; + return cmd; +}; + +/** + * Add an implicit `help [cmd]` subcommand + * which invokes `--help` for the given command. + * + * @api private + */ + +Command.prototype.addImplicitHelpCommand = function() { + this.command('help [cmd]', 'display help for [cmd]'); +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self._args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self._args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this._name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + // Leftover arguments need to be pushed back. Fixes issue #56 + if (parsed.args.length) args = parsed.args.concat(args); + + self._args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self._args.length) { + args[self._args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // implicit help + if (this.executables) this.addImplicitHelpCommand(); + + // store raw args + this.rawArgs = argv; + + // guess name + this._name = this._name || basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + var args = this.args = parsed.args; + + // executable sub-commands, skip .parseArgs() + if (this.executables) return this.executeSubCommand(argv, args, parsed.unknown); + + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Execute a sub-command executable. + * + * @param {Array} argv + * @param {Array} args + * @param {Array} unknown + * @api private + */ + +Command.prototype.executeSubCommand = function(argv, args, unknown) { + args = args.concat(unknown); + + if (!args.length) this.help(); + if ('help' == args[0] && 1 == args.length) this.help(); + + // --help + if ('help' == args[0]) { + args[0] = args[1]; + args[1] = '--help'; + } + + // executable + var dir = dirname(argv[1]); + var bin = basename(argv[1]) + '-' + args[0]; + + // check for ./ first + var local = path.join(dir, bin); + if (exists(local)) bin = local; + + // run it + args = args.slice(1); + var proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); + proc.on('exit', function(code){ + if (code == 127) { + console.error('\n %s(1) does not exist\n', bin); + } + }); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * This also normalizes equal sign and splits "--abc=def" into "--abc def". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg + , index; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) { + ret.push(arg.slice(0, index), arg.slice(index + 1)); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0] && '-' != arg) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || ('-' == arg[0] && '-' != arg)) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this._args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this._args.length ? ' ' + args : ''); + + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd._args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return pad(cmd._name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args, 22) + + (cmd.description() + ? ' ' + cmd.description() + : ''); + }).join('\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this._name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + + +/** + * Prompt for a `Regular Expression`. + * + * @param {String} str + * @param {Object} pattern regular expression object to test + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForRegexp = function(str, pattern, fn){ + var self = this; + this.promptSingleLine(str, function parseRegexp(val){ + if(!pattern.test(val)) return self.promptSingleLine(str + '(regular expression mismatch) ', parseRegexp); + fn(val); + }); +}; + + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + // determine if the 2nd argument is a regular expression + if (arguments[1].global !== undefined && arguments[1].multiline !== undefined) { + return this.promptForRegexp(str, arguments[1], arguments[2]); + } else if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + keypress(process.stdin); + + function setRawMode(mode) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(mode); + } else { + tty.setRawMode(mode); + } + }; + setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.pause(); + process.stdin.removeAllListeners('keypress'); + setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + + +/** + * Output help information for this command + * + * @api public + */ + +Command.prototype.outputHelp = function(){ + process.stdout.write(this.helpInformation()); + this.emit('--help'); +}; + +/** + * Output help information and exit. + * + * @api public + */ + +Command.prototype.help = function(){ + this.outputHelp(); + process.exit(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + cmd.outputHelp(); + process.exit(0); + } + } +} diff --git a/node_modules/express/node_modules/commander/node_modules/keypress/README.md b/node_modules/express/node_modules/commander/node_modules/keypress/README.md new file mode 100644 index 0000000..a768e8f --- /dev/null +++ b/node_modules/express/node_modules/commander/node_modules/keypress/README.md @@ -0,0 +1,101 @@ +keypress +======== +### Make any Node ReadableStream emit "keypress" events + + +Previous to Node `v0.8.x`, there was an undocumented `"keypress"` event that +`process.stdin` would emit when it was a TTY. Some people discovered this hidden +gem, and started using it in their own code. + +Now in Node `v0.8.x`, this `"keypress"` event does not get emitted by default, +but rather only when it is being used in conjuction with the `readline` (or by +extension, the `repl`) module. + +This module is the exact logic from the node `v0.8.x` releases ripped out into its +own module. + +__Bonus:__ Now with mouse support! + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install keypress +``` + +Or add it to the `"dependencies"` section of your _package.json_ file. + + +Example +------- + +#### Listening for "keypress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "keypress" events +keypress(process.stdin); + +// listen for the "keypress" event +process.stdin.on('keypress', function (ch, key) { + console.log('got "keypress"', key); + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause(); + } +}); + +process.stdin.setRawMode(true); +process.stdin.resume(); +``` + +#### Listening for "mousepress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "mousepress" (and "keypress") events +keypress(process.stdin); + +// you must enable the mouse events before they will begin firing +keypress.enableMouse(process.stdout); + +process.stdin.on('mousepress', function (info) { + console.log('got "mousepress" event at %d x %d', info.x, info.y); +}); + +process.on('exit', function () { + // disable mouse on exit, so that the state + // is back to normal for the terminal + keypress.disableMouse(process.stdout); +}); +``` + + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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/express/node_modules/commander/node_modules/keypress/index.js b/node_modules/express/node_modules/commander/node_modules/keypress/index.js new file mode 100644 index 0000000..c2ba488 --- /dev/null +++ b/node_modules/express/node_modules/commander/node_modules/keypress/index.js @@ -0,0 +1,346 @@ + +/** + * This module offers the internal "keypress" functionality from node-core's + * `readline` module, for your own programs and modules to use. + * + * Usage: + * + * require('keypress')(process.stdin); + * + * process.stdin.on('keypress', function (ch, key) { + * console.log(ch, key); + * if (key.ctrl && key.name == 'c') { + * process.stdin.pause(); + * } + * }); + * proces.stdin.resume(); + */ +var exports = module.exports = keypress; + +exports.enableMouse = function (stream) { + stream.write('\x1b' +'[?1000h') +} + +exports.disableMouse = function (stream) { + stream.write('\x1b' +'[?1000l') +} + + +/** + * accepts a readable Stream instance and makes it emit "keypress" events + */ + +function keypress(stream) { + if (isEmittingKeypress(stream)) return; + stream._emitKeypress = true; + + function onData(b) { + if (stream.listeners('keypress').length > 0) { + emitKey(stream, b); + } else { + // Nobody's watching anyway + stream.removeListener('data', onData); + stream.on('newListener', onNewListener); + } + } + + function onNewListener(event) { + if (event == 'keypress') { + stream.on('data', onData); + stream.removeListener('newListener', onNewListener); + } + } + + if (stream.listeners('keypress').length > 0) { + stream.on('data', onData); + } else { + stream.on('newListener', onNewListener); + } +} + +/** + * Returns `true` if the stream is already emitting "keypress" events. + * `false` otherwise. + */ + +function isEmittingKeypress(stream) { + var rtn = stream._emitKeypress; + if (!rtn) { + // hack: check for the v0.6.x "data" event + stream.listeners('data').forEach(function (l) { + if (l.name == 'onData' && /emitKey/.test(l.toString())) { + rtn = true; + stream._emitKeypress = true; + } + }); + } + if (!rtn) { + // hack: check for the v0.6.x "newListener" event + stream.listeners('newListener').forEach(function (l) { + if (l.name == 'onNewListener' && /keypress/.test(l.toString())) { + rtn = true; + stream._emitKeypress = true; + } + }); + } + return rtn; +} + + +/* + Some patterns seen in terminal key escape codes, derived from combos seen + at http://www.midnight-commander.org/browser/lib/tty/key.c + + ESC letter + ESC [ letter + ESC [ modifier letter + ESC [ 1 ; modifier letter + ESC [ num char + ESC [ num ; modifier char + ESC O letter + ESC O modifier letter + ESC O 1 ; modifier letter + ESC N letter + ESC [ [ num ; modifier char + ESC [ [ 1 ; modifier letter + ESC ESC [ num char + ESC ESC O letter + + - char is usually ~ but $ and ^ also happen with rxvt + - modifier is 1 + + (shift * 1) + + (left_alt * 2) + + (ctrl * 4) + + (right_alt * 8) + - two leading ESCs apparently mean the same as one leading ESC +*/ + +// Regexes used for ansi escape code splitting +var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; +var functionKeyCodeRe = + /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; + +function emitKey(stream, s) { + var ch, + key = { + name: undefined, + ctrl: false, + meta: false, + shift: false + }, + parts; + + if (Buffer.isBuffer(s)) { + if (s[0] > 127 && s[1] === undefined) { + s[0] -= 128; + s = '\x1b' + s.toString(stream.encoding || 'utf-8'); + } else { + s = s.toString(stream.encoding || 'utf-8'); + } + } + + key.sequence = s; + + if (s === '\r' || s === '\n') { + // enter + key.name = 'enter'; + + } else if (s === '\t') { + // tab + key.name = 'tab'; + + } else if (s === '\b' || s === '\x7f' || + s === '\x1b\x7f' || s === '\x1b\b') { + // backspace or ctrl+h + key.name = 'backspace'; + key.meta = (s.charAt(0) === '\x1b'); + + } else if (s === '\x1b' || s === '\x1b\x1b') { + // escape key + key.name = 'escape'; + key.meta = (s.length === 2); + + } else if (s === ' ' || s === '\x1b ') { + key.name = 'space'; + key.meta = (s.length === 2); + + } else if (s <= '\x1a') { + // ctrl+letter + key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); + key.ctrl = true; + + } else if (s.length === 1 && s >= 'a' && s <= 'z') { + // lowercase letter + key.name = s; + + } else if (s.length === 1 && s >= 'A' && s <= 'Z') { + // shift+letter + key.name = s.toLowerCase(); + key.shift = true; + + } else if (parts = metaKeyCodeRe.exec(s)) { + // meta+character key + key.name = parts[1].toLowerCase(); + key.meta = true; + key.shift = /^[A-Z]$/.test(parts[1]); + + } else if (parts = functionKeyCodeRe.exec(s)) { + // ansi escape sequence + + // reassemble the key code leaving out leading \x1b's, + // the modifier key bitflag and any meaningless "1;" sequence + var code = (parts[1] || '') + (parts[2] || '') + + (parts[4] || '') + (parts[6] || ''), + modifier = (parts[3] || parts[5] || 1) - 1; + + // Parse the key modifier + key.ctrl = !!(modifier & 4); + key.meta = !!(modifier & 10); + key.shift = !!(modifier & 1); + key.code = code; + + // Parse the key itself + switch (code) { + /* xterm/gnome ESC O letter */ + case 'OP': key.name = 'f1'; break; + case 'OQ': key.name = 'f2'; break; + case 'OR': key.name = 'f3'; break; + case 'OS': key.name = 'f4'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[11~': key.name = 'f1'; break; + case '[12~': key.name = 'f2'; break; + case '[13~': key.name = 'f3'; break; + case '[14~': key.name = 'f4'; break; + + /* from Cygwin and used in libuv */ + case '[[A': key.name = 'f1'; break; + case '[[B': key.name = 'f2'; break; + case '[[C': key.name = 'f3'; break; + case '[[D': key.name = 'f4'; break; + case '[[E': key.name = 'f5'; break; + + /* common */ + case '[15~': key.name = 'f5'; break; + case '[17~': key.name = 'f6'; break; + case '[18~': key.name = 'f7'; break; + case '[19~': key.name = 'f8'; break; + case '[20~': key.name = 'f9'; break; + case '[21~': key.name = 'f10'; break; + case '[23~': key.name = 'f11'; break; + case '[24~': key.name = 'f12'; break; + + /* xterm ESC [ letter */ + case '[A': key.name = 'up'; break; + case '[B': key.name = 'down'; break; + case '[C': key.name = 'right'; break; + case '[D': key.name = 'left'; break; + case '[E': key.name = 'clear'; break; + case '[F': key.name = 'end'; break; + case '[H': key.name = 'home'; break; + + /* xterm/gnome ESC O letter */ + case 'OA': key.name = 'up'; break; + case 'OB': key.name = 'down'; break; + case 'OC': key.name = 'right'; break; + case 'OD': key.name = 'left'; break; + case 'OE': key.name = 'clear'; break; + case 'OF': key.name = 'end'; break; + case 'OH': key.name = 'home'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[1~': key.name = 'home'; break; + case '[2~': key.name = 'insert'; break; + case '[3~': key.name = 'delete'; break; + case '[4~': key.name = 'end'; break; + case '[5~': key.name = 'pageup'; break; + case '[6~': key.name = 'pagedown'; break; + + /* putty */ + case '[[5~': key.name = 'pageup'; break; + case '[[6~': key.name = 'pagedown'; break; + + /* rxvt */ + case '[7~': key.name = 'home'; break; + case '[8~': key.name = 'end'; break; + + /* rxvt keys with modifiers */ + case '[a': key.name = 'up'; key.shift = true; break; + case '[b': key.name = 'down'; key.shift = true; break; + case '[c': key.name = 'right'; key.shift = true; break; + case '[d': key.name = 'left'; key.shift = true; break; + case '[e': key.name = 'clear'; key.shift = true; break; + + case '[2$': key.name = 'insert'; key.shift = true; break; + case '[3$': key.name = 'delete'; key.shift = true; break; + case '[5$': key.name = 'pageup'; key.shift = true; break; + case '[6$': key.name = 'pagedown'; key.shift = true; break; + case '[7$': key.name = 'home'; key.shift = true; break; + case '[8$': key.name = 'end'; key.shift = true; break; + + case 'Oa': key.name = 'up'; key.ctrl = true; break; + case 'Ob': key.name = 'down'; key.ctrl = true; break; + case 'Oc': key.name = 'right'; key.ctrl = true; break; + case 'Od': key.name = 'left'; key.ctrl = true; break; + case 'Oe': key.name = 'clear'; key.ctrl = true; break; + + case '[2^': key.name = 'insert'; key.ctrl = true; break; + case '[3^': key.name = 'delete'; key.ctrl = true; break; + case '[5^': key.name = 'pageup'; key.ctrl = true; break; + case '[6^': key.name = 'pagedown'; key.ctrl = true; break; + case '[7^': key.name = 'home'; key.ctrl = true; break; + case '[8^': key.name = 'end'; key.ctrl = true; break; + + /* misc. */ + case '[Z': key.name = 'tab'; key.shift = true; break; + default: key.name = 'undefined'; break; + + } + } else if (s.length > 1 && s[0] !== '\x1b') { + // Got a longer-than-one string of characters. + // Probably a paste, since it wasn't a control sequence. + Array.prototype.forEach.call(s, function(c) { + emitKey(stream, c); + }); + return; + } + + if (key.code == '[M') { + key.name = 'mouse'; + var s = key.sequence; + var b = s.charCodeAt(3); + key.x = s.charCodeAt(4) - 040; + key.y = s.charCodeAt(5) - 040; + + key.scroll = 0; + + key.ctrl = !!(1<<4 & b); + key.meta = !!(1<<3 & b); + key.shift = !!(1<<2 & b); + + key.release = (3 & b) === 3; + + if (1<<6 & b) { //scroll + key.scroll = 1 & b ? 1 : -1; + } + + if (!key.release && !key.scroll) { + key.button = b & 3; + } + } + + // Don't emit a key if no name was found + if (key.name === undefined) { + key = undefined; + } + + if (s.length === 1) { + ch = s; + } + + if (key && key.name == 'mouse') { + stream.emit('mousepress', key) + } else if (key || ch) { + stream.emit('keypress', ch, key); + } +} diff --git a/node_modules/express/node_modules/commander/node_modules/keypress/package.json b/node_modules/express/node_modules/commander/node_modules/keypress/package.json new file mode 100644 index 0000000..ed9993f --- /dev/null +++ b/node_modules/express/node_modules/commander/node_modules/keypress/package.json @@ -0,0 +1,32 @@ +{ + "name": "keypress", + "version": "0.1.0", + "description": "Make any Node ReadableStream emit \"keypress\" events", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://tootallnate.net" + }, + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/keypress.git" + }, + "keywords": [ + "keypress", + "readline", + "core" + ], + "license": "MIT", + "readme": "keypress\n========\n### Make any Node ReadableStream emit \"keypress\" events\n\n\nPrevious to Node `v0.8.x`, there was an undocumented `\"keypress\"` event that\n`process.stdin` would emit when it was a TTY. Some people discovered this hidden\ngem, and started using it in their own code.\n\nNow in Node `v0.8.x`, this `\"keypress\"` event does not get emitted by default,\nbut rather only when it is being used in conjuction with the `readline` (or by\nextension, the `repl`) module.\n\nThis module is the exact logic from the node `v0.8.x` releases ripped out into its\nown module.\n\n__Bonus:__ Now with mouse support!\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install keypress\n```\n\nOr add it to the `\"dependencies\"` section of your _package.json_ file.\n\n\nExample\n-------\n\n#### Listening for \"keypress\" events\n\n``` js\nvar keypress = require('keypress');\n\n// make `process.stdin` begin emitting \"keypress\" events\nkeypress(process.stdin);\n\n// listen for the \"keypress\" event\nprocess.stdin.on('keypress', function (ch, key) {\n console.log('got \"keypress\"', key);\n if (key && key.ctrl && key.name == 'c') {\n process.stdin.pause();\n }\n});\n\nprocess.stdin.setRawMode(true);\nprocess.stdin.resume();\n```\n\n#### Listening for \"mousepress\" events\n\n``` js\nvar keypress = require('keypress');\n\n// make `process.stdin` begin emitting \"mousepress\" (and \"keypress\") events\nkeypress(process.stdin);\n\n// you must enable the mouse events before they will begin firing\nkeypress.enableMouse(process.stdout);\n\nprocess.stdin.on('mousepress', function (info) {\n console.log('got \"mousepress\" event at %d x %d', info.x, info.y);\n});\n\nprocess.on('exit', function () {\n // disable mouse on exit, so that the state\n // is back to normal for the terminal\n keypress.disableMouse(process.stdout);\n});\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "_id": "keypress@0.1.0", + "dist": { + "shasum": "6f5825a04f3bbf70b0410fc184a29b6e423651a4" + }, + "_from": "keypress@0.1.x", + "_resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz" +} diff --git a/node_modules/express/node_modules/commander/node_modules/keypress/test.js b/node_modules/express/node_modules/commander/node_modules/keypress/test.js new file mode 100644 index 0000000..c3f61d7 --- /dev/null +++ b/node_modules/express/node_modules/commander/node_modules/keypress/test.js @@ -0,0 +1,28 @@ + +var keypress = require('./') +keypress(process.stdin) + +if (process.stdin.setRawMode) + process.stdin.setRawMode(true) +else + require('tty').setRawMode(true) + +process.stdin.on('keypress', function (c, key) { + console.log(0, c, key) + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause() + } +}) +process.stdin.on('mousepress', function (mouse) { + console.log(mouse) +}) + +keypress.enableMouse(process.stdout) +process.on('exit', function () { + //disable mouse on exit, so that the state is back to normal + //for the terminal. + keypress.disableMouse(process.stdout) +}) + +process.stdin.resume() + diff --git a/node_modules/express/node_modules/commander/package.json b/node_modules/express/node_modules/commander/package.json new file mode 100644 index 0000000..e688ad8 --- /dev/null +++ b/node_modules/express/node_modules/commander/package.json @@ -0,0 +1,41 @@ +{ + "name": "commander", + "version": "1.2.0", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": { + "keypress": "0.1.x" + }, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.6.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n```js\nprogram.prompt('Email: ', /^.+@.+\\..+$/, function(email){\n console.log('email: %j', email);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## .outputHelp()\n\n Output help information without exiting.\n\n## .help()\n\n Output help information and exit immediately.\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "commander@1.2.0", + "dist": { + "shasum": "eddb75cdba2992e7ed1690f4803a249bf51117ef" + }, + "_from": "commander@1.2.0", + "_resolved": "https://registry.npmjs.org/commander/-/commander-1.2.0.tgz" +} diff --git a/node_modules/express/node_modules/connect/.npmignore b/node_modules/express/node_modules/connect/.npmignore new file mode 100644 index 0000000..9046dde --- /dev/null +++ b/node_modules/express/node_modules/connect/.npmignore @@ -0,0 +1,12 @@ +*.markdown +*.md +.git* +Makefile +benchmarks/ +docs/ +examples/ +install.sh +support/ +test/ +.DS_Store +coverage.html diff --git a/node_modules/express/node_modules/connect/.travis.yml b/node_modules/express/node_modules/connect/.travis.yml new file mode 100644 index 0000000..a12e3f0 --- /dev/null +++ b/node_modules/express/node_modules/connect/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/LICENSE b/node_modules/express/node_modules/connect/LICENSE new file mode 100644 index 0000000..0c5d22d --- /dev/null +++ b/node_modules/express/node_modules/connect/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/Readme.md b/node_modules/express/node_modules/connect/Readme.md new file mode 100644 index 0000000..7d65f9c --- /dev/null +++ b/node_modules/express/node_modules/connect/Readme.md @@ -0,0 +1,133 @@ +[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect) +# Connect + + Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance "plugins" known as _middleware_. + + Connect is bundled with over _20_ commonly used middleware, including + a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/). + +```js +var connect = require('connect') + , http = require('http'); + +var app = connect() + .use(connect.favicon()) + .use(connect.logger('dev')) + .use(connect.static('public')) + .use(connect.directory('public')) + .use(connect.cookieParser()) + .use(connect.session({ secret: 'my secret here' })) + .use(function(req, res){ + res.end('Hello from Connect!\n'); + }); + +http.createServer(app).listen(3000); +``` + +## Middleware + + - [csrf](http://www.senchalabs.org/connect/csrf.html) + - [basicAuth](http://www.senchalabs.org/connect/basicAuth.html) + - [bodyParser](http://www.senchalabs.org/connect/bodyParser.html) + - [json](http://www.senchalabs.org/connect/json.html) + - [multipart](http://www.senchalabs.org/connect/multipart.html) + - [urlencoded](http://www.senchalabs.org/connect/urlencoded.html) + - [cookieParser](http://www.senchalabs.org/connect/cookieParser.html) + - [directory](http://www.senchalabs.org/connect/directory.html) + - [compress](http://www.senchalabs.org/connect/compress.html) + - [errorHandler](http://www.senchalabs.org/connect/errorHandler.html) + - [favicon](http://www.senchalabs.org/connect/favicon.html) + - [limit](http://www.senchalabs.org/connect/limit.html) + - [logger](http://www.senchalabs.org/connect/logger.html) + - [methodOverride](http://www.senchalabs.org/connect/methodOverride.html) + - [query](http://www.senchalabs.org/connect/query.html) + - [responseTime](http://www.senchalabs.org/connect/responseTime.html) + - [session](http://www.senchalabs.org/connect/session.html) + - [static](http://www.senchalabs.org/connect/static.html) + - [staticCache](http://www.senchalabs.org/connect/staticCache.html) + - [vhost](http://www.senchalabs.org/connect/vhost.html) + - [subdomains](http://www.senchalabs.org/connect/subdomains.html) + - [cookieSession](http://www.senchalabs.org/connect/cookieSession.html) + +## Running Tests + +first: + + $ npm install -d + +then: + + $ make test + +## Authors + + Below is the output from [git-summary](http://github.com/visionmedia/git-extras). + + + project: connect + commits: 2033 + active : 301 days + files : 171 + authors: + 1414 Tj Holowaychuk 69.6% + 298 visionmedia 14.7% + 191 Tim Caswell 9.4% + 51 TJ Holowaychuk 2.5% + 10 Ryan Olds 0.5% + 8 Astro 0.4% + 5 Nathan Rajlich 0.2% + 5 Jakub Nešetřil 0.2% + 3 Daniel Dickison 0.1% + 3 David Rio Deiros 0.1% + 3 Alexander Simmerl 0.1% + 3 Andreas Lind Petersen 0.1% + 2 Aaron Heckmann 0.1% + 2 Jacques Crocker 0.1% + 2 Fabian Jakobs 0.1% + 2 Brian J Brennan 0.1% + 2 Adam Malcontenti-Wilson 0.1% + 2 Glen Mailer 0.1% + 2 James Campos 0.1% + 1 Trent Mick 0.0% + 1 Troy Kruthoff 0.0% + 1 Wei Zhu 0.0% + 1 comerc 0.0% + 1 darobin 0.0% + 1 nateps 0.0% + 1 Marco Sanson 0.0% + 1 Arthur Taylor 0.0% + 1 Aseem Kishore 0.0% + 1 Bart Teeuwisse 0.0% + 1 Cameron Howey 0.0% + 1 Chad Weider 0.0% + 1 Craig Barnes 0.0% + 1 Eran Hammer-Lahav 0.0% + 1 Gregory McWhirter 0.0% + 1 Guillermo Rauch 0.0% + 1 Jae Kwon 0.0% + 1 Jakub Nesetril 0.0% + 1 Joshua Peek 0.0% + 1 Jxck 0.0% + 1 AJ ONeal 0.0% + 1 Michael Hemesath 0.0% + 1 Morten Siebuhr 0.0% + 1 Samori Gorse 0.0% + 1 Tom Jensen 0.0% + +## Node Compatibility + + Connect `< 1.x` is compatible with node 0.2.x + + + Connect `1.x` is compatible with node 0.4.x + + + Connect (_master_) `2.x` is compatible with node 0.6.x + +## CLA + + [http://sencha.com/cla](http://sencha.com/cla) + +## License + +View the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/). diff --git a/node_modules/express/node_modules/connect/index.js b/node_modules/express/node_modules/connect/index.js new file mode 100644 index 0000000..23240ee --- /dev/null +++ b/node_modules/express/node_modules/connect/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.CONNECT_COV + ? require('./lib-cov/connect') + : require('./lib/connect'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/cache.js b/node_modules/express/node_modules/connect/lib/cache.js new file mode 100644 index 0000000..052fcdb --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/cache.js @@ -0,0 +1,81 @@ + +/*! + * Connect - Cache + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Expose `Cache`. + */ + +module.exports = Cache; + +/** + * LRU cache store. + * + * @param {Number} limit + * @api private + */ + +function Cache(limit) { + this.store = {}; + this.keys = []; + this.limit = limit; +} + +/** + * Touch `key`, promoting the object. + * + * @param {String} key + * @param {Number} i + * @api private + */ + +Cache.prototype.touch = function(key, i){ + this.keys.splice(i,1); + this.keys.push(key); +}; + +/** + * Remove `key`. + * + * @param {String} key + * @api private + */ + +Cache.prototype.remove = function(key){ + delete this.store[key]; +}; + +/** + * Get the object stored for `key`. + * + * @param {String} key + * @return {Array} + * @api private + */ + +Cache.prototype.get = function(key){ + return this.store[key]; +}; + +/** + * Add a cache `key`. + * + * @param {String} key + * @return {Array} + * @api private + */ + +Cache.prototype.add = function(key){ + // initialize store + var len = this.keys.push(key); + + // limit reached, invalidate LRU + if (len > this.limit) this.remove(this.keys.shift()); + + var arr = this.store[key] = []; + arr.createdAt = new Date; + return arr; +}; diff --git a/node_modules/express/node_modules/connect/lib/connect.js b/node_modules/express/node_modules/connect/lib/connect.js new file mode 100644 index 0000000..72961dc --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/connect.js @@ -0,0 +1,92 @@ +/*! + * Connect + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , proto = require('./proto') + , utils = require('./utils') + , path = require('path') + , basename = path.basename + , fs = require('fs'); + +// node patches + +require('./patch'); + +// expose createServer() as the module + +exports = module.exports = createServer; + +/** + * Framework version. + */ + +exports.version = '2.7.11'; + +/** + * Expose mime module. + */ + +exports.mime = require('./middleware/static').mime; + +/** + * Expose the prototype. + */ + +exports.proto = proto; + +/** + * Auto-load middleware getters. + */ + +exports.middleware = {}; + +/** + * Expose utilities. + */ + +exports.utils = utils; + +/** + * Create a new connect server. + * + * @return {Function} + * @api public + */ + +function createServer() { + function app(req, res, next){ app.handle(req, res, next); } + utils.merge(app, proto); + utils.merge(app, EventEmitter.prototype); + app.route = '/'; + app.stack = []; + for (var i = 0; i < arguments.length; ++i) { + app.use(arguments[i]); + } + return app; +}; + +/** + * Support old `.createServer()` method. + */ + +createServer.createServer = createServer; + +/** + * Auto-load bundled middleware with getters. + */ + +fs.readdirSync(__dirname + '/middleware').forEach(function(filename){ + if (!/\.js$/.test(filename)) return; + var name = basename(filename, '.js'); + function load(){ return require('./middleware/' + name); } + exports.middleware.__defineGetter__(name, load); + exports.__defineGetter__(name, load); +}); diff --git a/node_modules/express/node_modules/connect/lib/index.js b/node_modules/express/node_modules/connect/lib/index.js new file mode 100644 index 0000000..2618ddc --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/index.js @@ -0,0 +1,50 @@ + +/** + * Connect is a middleware framework for node, + * shipping with over 18 bundled middleware and a rich selection of + * 3rd-party middleware. + * + * var app = connect() + * .use(connect.logger('dev')) + * .use(connect.static('public')) + * .use(function(req, res){ + * res.end('hello world\n'); + * }) + * .listen(3000); + * + * Installation: + * + * $ npm install connect + * + * Middleware: + * + * - [logger](logger.html) request logger with custom format support + * - [csrf](csrf.html) Cross-site request forgery protection + * - [compress](compress.html) Gzip compression middleware + * - [basicAuth](basicAuth.html) basic http authentication + * - [bodyParser](bodyParser.html) extensible request body parser + * - [json](json.html) application/json parser + * - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser + * - [multipart](multipart.html) multipart/form-data parser + * - [timeout](timeout.html) request timeouts + * - [cookieParser](cookieParser.html) cookie parser + * - [session](session.html) session management support with bundled MemoryStore + * - [cookieSession](cookieSession.html) cookie-based session support + * - [methodOverride](methodOverride.html) faux HTTP method support + * - [responseTime](responseTime.html) calculates response-time and exposes via X-Response-Time + * - [staticCache](staticCache.html) memory cache layer for the static() middleware + * - [static](static.html) streaming static file server supporting `Range` and more + * - [directory](directory.html) directory listing middleware + * - [vhost](vhost.html) virtual host sub-domain mapping middleware + * - [favicon](favicon.html) efficient favicon server (with default icon) + * - [limit](limit.html) limit the bytesize of request bodies + * - [query](query.html) automatic querystring parser, populating `req.query` + * - [errorHandler](errorHandler.html) flexible error handler + * + * Links: + * + * - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware + * - GitHub [repository](http://github.com/senchalabs/connect) + * - [test documentation](https://github.com/senchalabs/connect/blob/gh-pages/tests.md) + * + */ \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js b/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js new file mode 100644 index 0000000..bc7ec97 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js @@ -0,0 +1,103 @@ + +/*! + * Connect - basicAuth + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , unauthorized = utils.unauthorized; + +/** + * Basic Auth: + * + * Enfore basic authentication by providing a `callback(user, pass)`, + * which must return `true` in order to gain access. Alternatively an async + * method is provided as well, invoking `callback(user, pass, callback)`. Populates + * `req.user`. The final alternative is simply passing username / password + * strings. + * + * Simple username and password + * + * connect(connect.basicAuth('username', 'password')); + * + * Callback verification + * + * connect() + * .use(connect.basicAuth(function(user, pass){ + * return 'tj' == user & 'wahoo' == pass; + * })) + * + * Async callback verification, accepting `fn(err, user)`. + * + * connect() + * .use(connect.basicAuth(function(user, pass, fn){ + * User.authenticate({ user: user, pass: pass }, fn); + * })) + * + * @param {Function|String} callback or username + * @param {String} realm + * @api public + */ + +module.exports = function basicAuth(callback, realm) { + var username, password; + + // user / pass strings + if ('string' == typeof callback) { + username = callback; + password = realm; + if ('string' != typeof password) throw new Error('password argument required'); + realm = arguments[2]; + callback = function(user, pass){ + return user == username && pass == password; + } + } + + realm = realm || 'Authorization Required'; + + return function(req, res, next) { + var authorization = req.headers.authorization; + + if (req.user) return next(); + if (!authorization) return unauthorized(res, realm); + + var parts = authorization.split(' '); + + if (parts.length !== 2) return next(utils.error(400)); + + var scheme = parts[0] + , credentials = new Buffer(parts[1], 'base64').toString() + , index = credentials.indexOf(':'); + + if ('Basic' != scheme || index < 0) return next(utils.error(400)); + + var user = credentials.slice(0, index) + , pass = credentials.slice(index + 1); + + // async + if (callback.length >= 3) { + var pause = utils.pause(req); + callback(user, pass, function(err, user){ + if (err || !user) return unauthorized(res, realm); + req.user = req.remoteUser = user; + next(); + pause.resume(); + }); + // sync + } else { + if (callback(user, pass)) { + req.user = req.remoteUser = user; + next(); + } else { + unauthorized(res, realm); + } + } + } +}; + diff --git a/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js b/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js new file mode 100644 index 0000000..9f692cd --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js @@ -0,0 +1,61 @@ + +/*! + * Connect - bodyParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var multipart = require('./multipart') + , urlencoded = require('./urlencoded') + , json = require('./json'); + +/** + * Body parser: + * + * Parse request bodies, supports _application/json_, + * _application/x-www-form-urlencoded_, and _multipart/form-data_. + * + * This is equivalent to: + * + * app.use(connect.json()); + * app.use(connect.urlencoded()); + * app.use(connect.multipart()); + * + * Examples: + * + * connect() + * .use(connect.bodyParser()) + * .use(function(req, res) { + * res.end('viewing user ' + req.body.user.name); + * }); + * + * $ curl -d 'user[name]=tj' http://local/ + * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://local/ + * + * View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function bodyParser(options){ + var _urlencoded = urlencoded(options) + , _multipart = multipart(options) + , _json = json(options); + + return function bodyParser(req, res, next) { + _json(req, res, function(err){ + if (err) return next(err); + _urlencoded(req, res, function(err){ + if (err) return next(err); + _multipart(req, res, next); + }); + }); + } +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/middleware/compress.js b/node_modules/express/node_modules/connect/lib/middleware/compress.js new file mode 100644 index 0000000..db60af5 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/compress.js @@ -0,0 +1,189 @@ +/*! + * Connect - compress + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var zlib = require('zlib'); +var utils = require('../utils'); + +/** + * Supported content-encoding methods. + */ + +exports.methods = { + gzip: zlib.createGzip + , deflate: zlib.createDeflate +}; + +/** + * Default filter function. + */ + +exports.filter = function(req, res){ + return /json|text|javascript/.test(res.getHeader('Content-Type')); +}; + +/** + * Compress: + * + * Compress response data with gzip/deflate. + * + * Filter: + * + * A `filter` callback function may be passed to + * replace the default logic of: + * + * exports.filter = function(req, res){ + * return /json|text|javascript/.test(res.getHeader('Content-Type')); + * }; + * + * Threshold: + * + * Only compress the response if the byte size is at or above a threshold. + * Always compress while streaming. + * + * - `threshold` - string representation of size or bytes as an integer. + * + * Options: + * + * All remaining options are passed to the gzip/deflate + * creation functions. Consult node's docs for additional details. + * + * - `chunkSize` (default: 16*1024) + * - `windowBits` + * - `level`: 0-9 where 0 is no compression, and 9 is slow but best compression + * - `memLevel`: 1-9 low is slower but uses less memory, high is fast but uses more + * - `strategy`: compression strategy + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function compress(options) { + options = options || {}; + var names = Object.keys(exports.methods) + , filter = options.filter || exports.filter + , threshold; + + if (false === options.threshold || 0 === options.threshold) { + threshold = 0 + } else if ('string' === typeof options.threshold) { + threshold = utils.parseBytes(options.threshold) + } else { + threshold = options.threshold || 1024 + } + + return function compress(req, res, next){ + var accept = req.headers['accept-encoding'] + , vary = res.getHeader('Vary') + , write = res.write + , end = res.end + , compress = true + , stream + , method; + + // vary + if (!vary) { + res.setHeader('Vary', 'Accept-Encoding'); + } else if (!~vary.indexOf('Accept-Encoding')) { + res.setHeader('Vary', vary + ', Accept-Encoding'); + } + + // see #724 + req.on('close', function(){ + res.write = res.end = function(){}; + }); + + // proxy + + res.write = function(chunk, encoding){ + if (!this.headerSent) this._implicitHeader(); + return stream + ? stream.write(new Buffer(chunk, encoding)) + : write.call(res, chunk, encoding); + }; + + res.end = function(chunk, encoding){ + if (chunk) { + if (!this.headerSent && getSize(chunk) < threshold) compress = false; + this.write(chunk, encoding); + } else if (!this.headerSent) { + // response size === 0 + compress = false; + } + return stream + ? stream.end() + : end.call(res); + }; + + res.on('header', function(){ + if (!compress) return; + + var encoding = res.getHeader('Content-Encoding') || 'identity'; + + // already encoded + if ('identity' != encoding) return; + + // default request filter + if (!filter(req, res)) return; + + // SHOULD use identity + if (!accept) return; + + // head + if ('HEAD' == req.method) return; + + // default to gzip + if ('*' == accept.trim()) method = 'gzip'; + + // compression method + if (!method) { + for (var i = 0, len = names.length; i < len; ++i) { + if (~accept.indexOf(names[i])) { + method = names[i]; + break; + } + } + } + + // compression method + if (!method) return; + + // compression stream + stream = exports.methods[method](options); + + // header fields + res.setHeader('Content-Encoding', method); + res.removeHeader('Content-Length'); + + // compression + + stream.on('data', function(chunk){ + write.call(res, chunk); + }); + + stream.on('end', function(){ + end.call(res); + }); + + stream.on('drain', function() { + res.emit('drain'); + }); + }); + + next(); + }; +}; + +function getSize(chunk) { + return Buffer.isBuffer(chunk) + ? chunk.length + : Buffer.byteLength(chunk); +} \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js b/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js new file mode 100644 index 0000000..5da23f2 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js @@ -0,0 +1,62 @@ + +/*! + * Connect - cookieParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./../utils') + , cookie = require('cookie'); + +/** + * Cookie parser: + * + * Parse _Cookie_ header and populate `req.cookies` + * with an object keyed by the cookie names. Optionally + * you may enabled signed cookie support by passing + * a `secret` string, which assigns `req.secret` so + * it may be used by other middleware. + * + * Examples: + * + * connect() + * .use(connect.cookieParser('optional secret string')) + * .use(function(req, res, next){ + * res.end(JSON.stringify(req.cookies)); + * }) + * + * @param {String} secret + * @return {Function} + * @api public + */ + +module.exports = function cookieParser(secret){ + return function cookieParser(req, res, next) { + if (req.cookies) return next(); + var cookies = req.headers.cookie; + + req.secret = secret; + req.cookies = {}; + req.signedCookies = {}; + + if (cookies) { + try { + req.cookies = cookie.parse(cookies); + if (secret) { + req.signedCookies = utils.parseSignedCookies(req.cookies, secret); + req.signedCookies = utils.parseJSONCookies(req.signedCookies); + } + req.cookies = utils.parseJSONCookies(req.cookies); + } catch (err) { + err.status = 400; + return next(err); + } + } + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js b/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js new file mode 100644 index 0000000..21011b8 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js @@ -0,0 +1,115 @@ +/*! + * Connect - cookieSession + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./../utils') + , Cookie = require('./session/cookie') + , debug = require('debug')('connect:cookieSession') + , signature = require('cookie-signature') + , crc32 = require('buffer-crc32'); + +/** + * Cookie Session: + * + * Cookie session middleware. + * + * var app = connect(); + * app.use(connect.cookieParser()); + * app.use(connect.cookieSession({ secret: 'tobo!', cookie: { maxAge: 60 * 60 * 1000 }})); + * + * Options: + * + * - `key` cookie name defaulting to `connect.sess` + * - `secret` prevents cookie tampering + * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` + * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") + * + * Clearing sessions: + * + * To clear the session simply set its value to `null`, + * `cookieSession()` will then respond with a 1970 Set-Cookie. + * + * req.session = null; + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function cookieSession(options){ + // TODO: utilize Session/Cookie to unify API + options = options || {}; + var key = options.key || 'connect.sess' + , trustProxy = options.proxy; + + return function cookieSession(req, res, next) { + + // req.secret is for backwards compatibility + var secret = options.secret || req.secret; + if (!secret) throw new Error('`secret` option required for cookie sessions'); + + // default session + req.session = {}; + var cookie = req.session.cookie = new Cookie(options.cookie); + + // pathname mismatch + if (0 != req.originalUrl.indexOf(cookie.path)) return next(); + + // cookieParser secret + if (!options.secret && req.secret) { + req.session = req.signedCookies[key] || {}; + req.session.cookie = cookie; + } else { + // TODO: refactor + var rawCookie = req.cookies[key]; + if (rawCookie) { + var unsigned = utils.parseSignedCookie(rawCookie, secret); + if (unsigned) { + var originalHash = crc32.signed(unsigned); + req.session = utils.parseJSONCookie(unsigned) || {}; + req.session.cookie = cookie; + } + } + } + + res.on('header', function(){ + // removed + if (!req.session) { + debug('clear session'); + cookie.expires = new Date(0); + res.setHeader('Set-Cookie', cookie.serialize(key, '')); + return; + } + + delete req.session.cookie; + + // check security + var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() + , tls = req.connection.encrypted || (trustProxy && 'https' == proto.split(/\s*,\s*/)[0]); + + // only send secure cookies via https + if (cookie.secure && !tls) return debug('not secured'); + + // serialize + debug('serializing %j', req.session); + var val = 'j:' + JSON.stringify(req.session); + + // compare hashes, no need to set-cookie if unchanged + if (originalHash == crc32.signed(val)) return debug('unmodified session'); + + // set-cookie + val = 's:' + signature.sign(val, secret); + val = cookie.serialize(key, val); + debug('set-cookie %j', cookie); + res.setHeader('Set-Cookie', val); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/csrf.js b/node_modules/express/node_modules/connect/lib/middleware/csrf.js new file mode 100644 index 0000000..a815444 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/csrf.js @@ -0,0 +1,75 @@ +/*! + * Connect - csrf + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); +var uid = require('uid2'); + +/** + * Anti CSRF: + * + * CRSF protection middleware. + * + * By default this middleware generates a token named "_csrf" + * which should be added to requests which mutate + * state, within a hidden form field, query-string etc. This + * token is validated against the visitor's `req.session._csrf` + * property. + * + * The default `value` function checks `req.body` generated + * by the `bodyParser()` middleware, `req.query` generated + * by `query()`, and the "X-CSRF-Token" header field. + * + * This middleware requires session support, thus should be added + * somewhere _below_ `session()` and `cookieParser()`. + * + * Options: + * + * - `value` a function accepting the request, returning the token + * + * @param {Object} options + * @api public + */ + +module.exports = function csrf(options) { + options = options || {}; + var value = options.value || defaultValue; + + return function(req, res, next){ + // generate CSRF token + var token = req.session._csrf || (req.session._csrf = uid(24)); + + // ignore these methods + if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next(); + + // determine value + var val = value(req); + + // check + if (val != token) return next(utils.error(403)); + + next(); + } +}; + +/** + * Default value function, checking the `req.body` + * and `req.query` for the CSRF token. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +function defaultValue(req) { + return (req.body && req.body._csrf) + || (req.query && req.query._csrf) + || (req.headers['x-csrf-token']) + || (req.headers['x-xsrf-token']); +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/directory.js b/node_modules/express/node_modules/connect/lib/middleware/directory.js new file mode 100644 index 0000000..1c925a7 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/directory.js @@ -0,0 +1,229 @@ + +/*! + * Connect - directory + * Copyright(c) 2011 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +// TODO: icon / style for directories +// TODO: arrow key navigation +// TODO: make icons extensible + +/** + * Module dependencies. + */ + +var fs = require('fs') + , parse = require('url').parse + , utils = require('../utils') + , path = require('path') + , normalize = path.normalize + , extname = path.extname + , join = path.join; + +/*! + * Icon cache. + */ + +var cache = {}; + +/** + * Directory: + * + * Serve directory listings with the given `root` path. + * + * Options: + * + * - `hidden` display hidden (dot) files. Defaults to false. + * - `icons` display icons. Defaults to false. + * - `filter` Apply this filter function to files. Defaults to false. + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function directory(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('directory() root path required'); + var hidden = options.hidden + , icons = options.icons + , filter = options.filter + , root = normalize(root); + + return function directory(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + + var accept = req.headers.accept || 'text/plain' + , url = parse(req.url) + , dir = decodeURIComponent(url.pathname) + , path = normalize(join(root, dir)) + , originalUrl = parse(req.originalUrl) + , originalDir = decodeURIComponent(originalUrl.pathname) + , showUp = path != root && path != root + '/'; + + // null byte(s), bad request + if (~path.indexOf('\0')) return next(utils.error(400)); + + // malicious path, forbidden + if (0 != path.indexOf(root)) return next(utils.error(403)); + + // check if we have a directory + fs.stat(path, function(err, stat){ + if (err) return 'ENOENT' == err.code + ? next() + : next(err); + + if (!stat.isDirectory()) return next(); + + // fetch files + fs.readdir(path, function(err, files){ + if (err) return next(err); + if (!hidden) files = removeHidden(files); + if (filter) files = files.filter(filter); + files.sort(); + + // content-negotiation + for (var key in exports) { + if (~accept.indexOf(key) || ~accept.indexOf('*/*')) { + exports[key](req, res, files, next, originalDir, showUp, icons); + return; + } + } + + // not acceptable + next(utils.error(406)); + }); + }); + }; +}; + +/** + * Respond with text/html. + */ + +exports.html = function(req, res, files, next, dir, showUp, icons){ + fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){ + if (err) return next(err); + fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){ + if (err) return next(err); + if (showUp) files.unshift('..'); + str = str + .replace('{style}', style) + .replace('{files}', html(files, dir, icons)) + .replace('{directory}', dir) + .replace('{linked-path}', htmlPath(dir)); + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Content-Length', str.length); + res.end(str); + }); + }); +}; + +/** + * Respond with application/json. + */ + +exports.json = function(req, res, files){ + files = JSON.stringify(files); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Respond with text/plain. + */ + +exports.plain = function(req, res, files){ + files = files.join('\n') + '\n'; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Map html `dir`, returning a linked path. + */ + +function htmlPath(dir) { + var curr = []; + return dir.split('/').map(function(part){ + curr.push(part); + return '' + part + ''; + }).join(' / '); +} + +/** + * Map html `files`, returning an html unordered list. + */ + +function html(files, dir, useIcons) { + return '
    ' + files.map(function(file){ + var icon = '' + , classes = []; + + if (useIcons && '..' != file) { + icon = icons[extname(file)] || icons.default; + icon = ''; + classes.push('icon'); + } + + return '
  • ' + + icon + file + '
  • '; + + }).join('\n') + '
'; +} + +/** + * Load and cache the given `icon`. + * + * @param {String} icon + * @return {String} + * @api private + */ + +function load(icon) { + if (cache[icon]) return cache[icon]; + return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64'); +} + +/** + * Filter "hidden" `files`, aka files + * beginning with a `.`. + * + * @param {Array} files + * @return {Array} + * @api private + */ + +function removeHidden(files) { + return files.filter(function(file){ + return '.' != file[0]; + }); +} + +/** + * Icon map. + */ + +var icons = { + '.js': 'page_white_code_red.png' + , '.c': 'page_white_c.png' + , '.h': 'page_white_h.png' + , '.cc': 'page_white_cplusplus.png' + , '.php': 'page_white_php.png' + , '.rb': 'page_white_ruby.png' + , '.cpp': 'page_white_cplusplus.png' + , '.swf': 'page_white_flash.png' + , '.pdf': 'page_white_acrobat.png' + , 'default': 'page_white.png' +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js new file mode 100644 index 0000000..4a84edc --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js @@ -0,0 +1,86 @@ +/*! + * Connect - errorHandler + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , fs = require('fs'); + +// environment + +var env = process.env.NODE_ENV || 'development'; + +/** + * Error handler: + * + * Development error handler, providing stack traces + * and error message responses for requests accepting text, html, + * or json. + * + * Text: + * + * By default, and when _text/plain_ is accepted a simple stack trace + * or error message will be returned. + * + * JSON: + * + * When _application/json_ is accepted, connect will respond with + * an object in the form of `{ "error": error }`. + * + * HTML: + * + * When accepted connect will output a nice html stack trace. + * + * @return {Function} + * @api public + */ + +exports = module.exports = function errorHandler(){ + return function errorHandler(err, req, res, next){ + if (err.status) res.statusCode = err.status; + if (res.statusCode < 400) res.statusCode = 500; + if ('test' != env) console.error(err.stack); + var accept = req.headers.accept || ''; + // html + if (~accept.indexOf('html')) { + fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){ + fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){ + var stack = (err.stack || '') + .split('\n').slice(1) + .map(function(v){ return '
  • ' + v + '
  • '; }).join(''); + html = html + .replace('{style}', style) + .replace('{stack}', stack) + .replace('{title}', exports.title) + .replace('{statusCode}', res.statusCode) + .replace(/\{error\}/g, utils.escape(err.toString())); + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end(html); + }); + }); + // json + } else if (~accept.indexOf('json')) { + var error = { message: err.message, stack: err.stack }; + for (var prop in err) error[prop] = err[prop]; + var json = JSON.stringify({ error: error }); + res.setHeader('Content-Type', 'application/json'); + res.end(json); + // plain text + } else { + res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' }); + res.end(err.stack); + } + }; +}; + +/** + * Template title, framework authors may override this value. + */ + +exports.title = 'Connect'; diff --git a/node_modules/express/node_modules/connect/lib/middleware/favicon.js b/node_modules/express/node_modules/connect/lib/middleware/favicon.js new file mode 100644 index 0000000..ef54354 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/favicon.js @@ -0,0 +1,80 @@ +/*! + * Connect - favicon + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , utils = require('../utils'); + +/** + * Favicon: + * + * By default serves the connect favicon, or the favicon + * located by the given `path`. + * + * Options: + * + * - `maxAge` cache-control max-age directive, defaulting to 1 day + * + * Examples: + * + * Serve default favicon: + * + * connect() + * .use(connect.favicon()) + * + * Serve favicon before logging for brevity: + * + * connect() + * .use(connect.favicon()) + * .use(connect.logger('dev')) + * + * Serve custom favicon: + * + * connect() + * .use(connect.favicon('public/favicon.ico')) + * + * @param {String} path + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function favicon(path, options){ + var options = options || {} + , path = path || __dirname + '/../public/favicon.ico' + , maxAge = options.maxAge || 86400000 + , icon; // favicon cache + + return function favicon(req, res, next){ + if ('/favicon.ico' == req.url) { + if (icon) { + res.writeHead(200, icon.headers); + res.end(icon.body); + } else { + fs.readFile(path, function(err, buf){ + if (err) return next(err); + icon = { + headers: { + 'Content-Type': 'image/x-icon' + , 'Content-Length': buf.length + , 'ETag': '"' + utils.md5(buf) + '"' + , 'Cache-Control': 'public, max-age=' + (maxAge / 1000) + }, + body: buf + }; + res.writeHead(200, icon.headers); + res.end(icon.body); + }); + } + } else { + next(); + } + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/json.js b/node_modules/express/node_modules/connect/lib/middleware/json.js new file mode 100644 index 0000000..29878d2 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/json.js @@ -0,0 +1,89 @@ + +/*! + * Connect - json + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , _limit = require('./limit'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * JSON: + * + * Parse JSON request bodies, providing the + * parsed object as `req.body`. + * + * Options: + * + * - `strict` when `false` anything `JSON.parse()` accepts will be parsed + * - `reviver` used as the second "reviver" argument for JSON.parse + * - `limit` byte limit disabled by default + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + var options = options || {} + , strict = options.strict !== false; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function json(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + + if (!utils.hasBody(req)) return next(); + + // check Content-Type + if (!exports.regexp.test(utils.mime(req))) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk }); + req.on('end', function(){ + var first = buf.trim()[0]; + + if (0 == buf.length) { + return next(utils.error(400, 'invalid json, empty body')); + } + + if (strict && '{' != first && '[' != first) return next(utils.error(400, 'invalid json')); + try { + req.body = JSON.parse(buf, options.reviver); + } catch (err){ + err.body = buf; + err.status = 400; + return next(err); + } + next(); + }); + }); + }; +}; + +exports.regexp = /^application\/([\w!#\$%&\*`\-\.\^~]*\+)?json$/i; + diff --git a/node_modules/express/node_modules/connect/lib/middleware/limit.js b/node_modules/express/node_modules/connect/lib/middleware/limit.js new file mode 100644 index 0000000..09bd1c4 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/limit.js @@ -0,0 +1,78 @@ + +/*! + * Connect - limit + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils'), + brokenPause = utils.brokenPause; + +/** + * Limit: + * + * Limit request bodies to the given size in `bytes`. + * + * A string representation of the bytesize may also be passed, + * for example "5mb", "200kb", "1gb", etc. + * + * connect() + * .use(connect.limit('5.5mb')) + * .use(handleImageUpload) + * + * @param {Number|String} bytes + * @return {Function} + * @api public + */ + +module.exports = function limit(bytes){ + if ('string' == typeof bytes) bytes = utils.parseBytes(bytes); + if ('number' != typeof bytes) throw new Error('limit() bytes required'); + return function limit(req, res, next){ + var received = 0 + , len = req.headers['content-length'] + ? parseInt(req.headers['content-length'], 10) + : null; + + // self-awareness + if (req._limit) return next(); + req._limit = true; + + // limit by content-length + if (len && len > bytes) return next(utils.error(413)); + + // limit + if (brokenPause) { + listen(); + } else { + req.on('newListener', function handler(event) { + if (event !== 'data') return; + + req.removeListener('newListener', handler); + // Start listening at the end of the current loop + // otherwise the request will be consumed too early. + // Sideaffect is `limit` will miss the first chunk, + // but that's not a big deal. + // Unfortunately, the tests don't have large enough + // request bodies to test this. + process.nextTick(listen); + }); + }; + + next(); + + function listen() { + req.on('data', function(chunk) { + received += Buffer.isBuffer(chunk) + ? chunk.length : + Buffer.byteLength(chunk); + + if (received > bytes) req.destroy(); + }); + }; + }; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/middleware/logger.js b/node_modules/express/node_modules/connect/lib/middleware/logger.js new file mode 100644 index 0000000..7e88248 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/logger.js @@ -0,0 +1,339 @@ +/*! + * Connect - logger + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var bytes = require('bytes'); + +/*! + * Log buffer. + */ + +var buf = []; + +/*! + * Default log buffer duration. + */ + +var defaultBufferDuration = 1000; + +/** + * Logger: + * + * Log requests with the given `options` or a `format` string. + * + * Options: + * + * - `format` Format string, see below for tokens + * - `stream` Output stream, defaults to _stdout_ + * - `buffer` Buffer duration, defaults to 1000ms when _true_ + * - `immediate` Write log line on request instead of response (for response times) + * + * Tokens: + * + * - `:req[header]` ex: `:req[Accept]` + * - `:res[header]` ex: `:res[Content-Length]` + * - `:http-version` + * - `:response-time` + * - `:remote-addr` + * - `:date` + * - `:method` + * - `:url` + * - `:referrer` + * - `:user-agent` + * - `:status` + * + * Formats: + * + * Pre-defined formats that ship with connect: + * + * - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"' + * - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms' + * - `tiny` ':method :url :status :res[content-length] - :response-time ms' + * - `dev` concise output colored by response status for development use + * + * Examples: + * + * connect.logger() // default + * connect.logger('short') + * connect.logger('tiny') + * connect.logger({ immediate: true, format: 'dev' }) + * connect.logger(':method :url - :referrer') + * connect.logger(':req[content-type] -> :res[content-type]') + * connect.logger(function(tokens, req, res){ return 'some format string' }) + * + * Defining Tokens: + * + * To define a token, simply invoke `connect.logger.token()` with the + * name and a callback function. The value returned is then available + * as ":type" in this case. + * + * connect.logger.token('type', function(req, res){ return req.headers['content-type']; }) + * + * Defining Formats: + * + * All default formats are defined this way, however it's public API as well: + * + * connect.logger.format('name', 'string or function') + * + * @param {String|Function|Object} format or options + * @return {Function} + * @api public + */ + +exports = module.exports = function logger(options) { + if ('object' == typeof options) { + options = options || {}; + } else if (options) { + options = { format: options }; + } else { + options = {}; + } + + // output on request instead of response + var immediate = options.immediate; + + // format name + var fmt = exports[options.format] || options.format || exports.default; + + // compile format + if ('function' != typeof fmt) fmt = compile(fmt); + + // options + var stream = options.stream || process.stdout + , buffer = options.buffer; + + // buffering support + if (buffer) { + var realStream = stream + , interval = 'number' == typeof buffer + ? buffer + : defaultBufferDuration; + + // flush interval + setInterval(function(){ + if (buf.length) { + realStream.write(buf.join('')); + buf.length = 0; + } + }, interval); + + // swap the stream + stream = { + write: function(str){ + buf.push(str); + } + }; + } + + return function logger(req, res, next) { + req._startTime = new Date; + + // immediate + if (immediate) { + var line = fmt(exports, req, res); + if (null == line) return; + stream.write(line + '\n'); + // proxy end to output logging + } else { + var end = res.end; + res.end = function(chunk, encoding){ + res.end = end; + res.end(chunk, encoding); + var line = fmt(exports, req, res); + if (null == line) return; + stream.write(line + '\n'); + }; + } + + + next(); + }; +}; + +/** + * Compile `fmt` into a function. + * + * @param {String} fmt + * @return {Function} + * @api private + */ + +function compile(fmt) { + fmt = fmt.replace(/"/g, '\\"'); + var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){ + return '"\n + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "'; + }) + '";' + return new Function('tokens, req, res', js); +}; + +/** + * Define a token function with the given `name`, + * and callback `fn(req, res)`. + * + * @param {String} name + * @param {Function} fn + * @return {Object} exports for chaining + * @api public + */ + +exports.token = function(name, fn) { + exports[name] = fn; + return this; +}; + +/** + * Define a `fmt` with the given `name`. + * + * @param {String} name + * @param {String|Function} fmt + * @return {Object} exports for chaining + * @api public + */ + +exports.format = function(name, str){ + exports[name] = str; + return this; +}; + +/** + * Default format. + */ + +exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'); + +/** + * Short format. + */ + +exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'); + +/** + * Tiny format. + */ + +exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms'); + +/** + * dev (colored) + */ + +exports.format('dev', function(tokens, req, res){ + var status = res.statusCode + , len = parseInt(res.getHeader('Content-Length'), 10) + , color = 32; + + if (status >= 500) color = 31 + else if (status >= 400) color = 33 + else if (status >= 300) color = 36; + + len = isNaN(len) + ? '' + : len = ' - ' + bytes(len); + + return '\x1b[90m' + req.method + + ' ' + req.originalUrl + ' ' + + '\x1b[' + color + 'm' + res.statusCode + + ' \x1b[90m' + + (new Date - req._startTime) + + 'ms' + len + + '\x1b[0m'; +}); + +/** + * request url + */ + +exports.token('url', function(req){ + return req.originalUrl || req.url; +}); + +/** + * request method + */ + +exports.token('method', function(req){ + return req.method; +}); + +/** + * response time in milliseconds + */ + +exports.token('response-time', function(req){ + return new Date - req._startTime; +}); + +/** + * UTC date + */ + +exports.token('date', function(){ + return new Date().toUTCString(); +}); + +/** + * response status code + */ + +exports.token('status', function(req, res){ + return res.statusCode; +}); + +/** + * normalized referrer + */ + +exports.token('referrer', function(req){ + return req.headers['referer'] || req.headers['referrer']; +}); + +/** + * remote address + */ + +exports.token('remote-addr', function(req){ + if (req.ip) return req.ip; + var sock = req.socket; + if (sock.socket) return sock.socket.remoteAddress; + return sock.remoteAddress; +}); + +/** + * HTTP version + */ + +exports.token('http-version', function(req){ + return req.httpVersionMajor + '.' + req.httpVersionMinor; +}); + +/** + * UA string + */ + +exports.token('user-agent', function(req){ + return req.headers['user-agent']; +}); + +/** + * request header + */ + +exports.token('req', function(req, res, field){ + return req.headers[field.toLowerCase()]; +}); + +/** + * response header + */ + +exports.token('res', function(req, res, field){ + return (res._headers || {})[field.toLowerCase()]; +}); + diff --git a/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js b/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js new file mode 100644 index 0000000..9ce4939 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js @@ -0,0 +1,59 @@ + +/*! + * Connect - methodOverride + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var methods = require('methods'); + +/** + * Method Override: + * + * Provides faux HTTP method support. + * + * Pass an optional `key` to use when checking for + * a method override, othewise defaults to _\_method_. + * The original method is available via `req.originalMethod`. + * + * @param {String} key + * @return {Function} + * @api public + */ + +module.exports = function methodOverride(key){ + key = key || "_method"; + return function methodOverride(req, res, next) { + var method; + req.originalMethod = req.originalMethod || req.method; + + // req.body + if (req.body && key in req.body) { + method = req.body[key].toLowerCase(); + delete req.body[key]; + } + + // check X-HTTP-Method-Override + if (req.headers['x-http-method-override']) { + method = req.headers['x-http-method-override'].toLowerCase(); + } + + // replace + if (supports(method)) req.method = method.toUpperCase(); + + next(); + }; +}; + +/** + * Check if node supports `method`. + */ + +function supports(method) { + return ~methods.indexOf(method); +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/multipart.js b/node_modules/express/node_modules/connect/lib/middleware/multipart.js new file mode 100644 index 0000000..7b26fae --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/multipart.js @@ -0,0 +1,133 @@ +/*! + * Connect - multipart + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var formidable = require('formidable') + , _limit = require('./limit') + , utils = require('../utils') + , qs = require('qs'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * Multipart: + * + * Parse multipart/form-data request bodies, + * providing the parsed object as `req.body` + * and `req.files`. + * + * Configuration: + * + * The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s + * `IncomingForm` object, allowing you to configure the upload directory, + * size limits, etc. For example if you wish to change the upload dir do the following. + * + * app.use(connect.multipart({ uploadDir: path })); + * + * Options: + * + * - `limit` byte limit defaulting to none + * - `defer` defers processing and exposes the Formidable form object as `req.form`. + * `next()` is called without waiting for the form's "end" event. + * This option is useful if you need to bind to the "progress" event, for example. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + options = options || {}; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function multipart(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + req.files = req.files || {}; + + if (!utils.hasBody(req)) return next(); + + // ignore GET + if ('GET' == req.method || 'HEAD' == req.method) return next(); + + // check Content-Type + if ('multipart/form-data' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + + var form = new formidable.IncomingForm + , data = {} + , files = {} + , done; + + Object.keys(options).forEach(function(key){ + form[key] = options[key]; + }); + + function ondata(name, val, data){ + if (Array.isArray(data[name])) { + data[name].push(val); + } else if (data[name]) { + data[name] = [data[name], val]; + } else { + data[name] = val; + } + } + + form.on('field', function(name, val){ + ondata(name, val, data); + }); + + form.on('file', function(name, val){ + ondata(name, val, files); + }); + + form.on('error', function(err){ + if (!options.defer) { + err.status = 400; + next(err); + } + done = true; + }); + + form.on('end', function(){ + if (done) return; + try { + req.body = qs.parse(data); + req.files = qs.parse(files); + if (!options.defer) next(); + } catch (err) { + form.emit('error', err); + } + }); + + form.parse(req); + + if (options.defer) { + req.form = form; + next(); + } + }); + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/query.js b/node_modules/express/node_modules/connect/lib/middleware/query.js new file mode 100644 index 0000000..93fc5d3 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/query.js @@ -0,0 +1,46 @@ +/*! + * Connect - query + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var qs = require('qs') + , parse = require('../utils').parseUrl; + +/** + * Query: + * + * Automatically parse the query-string when available, + * populating the `req.query` object. + * + * Examples: + * + * connect() + * .use(connect.query()) + * .use(function(req, res){ + * res.end(JSON.stringify(req.query)); + * }); + * + * The `options` passed are provided to qs.parse function. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function query(options){ + return function query(req, res, next){ + if (!req.query) { + req.query = ~req.url.indexOf('?') + ? qs.parse(parse(req).query, options) + : {}; + } + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/responseTime.js b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js new file mode 100644 index 0000000..62abc04 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js @@ -0,0 +1,32 @@ + +/*! + * Connect - responseTime + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Reponse time: + * + * Adds the `X-Response-Time` header displaying the response + * duration in milliseconds. + * + * @return {Function} + * @api public + */ + +module.exports = function responseTime(){ + return function(req, res, next){ + var start = new Date; + + if (res._responseTime) return next(); + res._responseTime = true; + + res.on('header', function(){ + var duration = new Date - start; + res.setHeader('X-Response-Time', duration + 'ms'); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session.js b/node_modules/express/node_modules/connect/lib/middleware/session.js new file mode 100644 index 0000000..a107295 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session.js @@ -0,0 +1,355 @@ +/*! + * Connect - session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Session = require('./session/session') + , debug = require('debug')('connect:session') + , MemoryStore = require('./session/memory') + , signature = require('cookie-signature') + , Cookie = require('./session/cookie') + , Store = require('./session/store') + , utils = require('./../utils') + , uid = require('uid2') + , parse = utils.parseUrl + , crc32 = require('buffer-crc32'); + +// environment + +var env = process.env.NODE_ENV; + +/** + * Expose the middleware. + */ + +exports = module.exports = session; + +/** + * Expose constructors. + */ + +exports.Store = Store; +exports.Cookie = Cookie; +exports.Session = Session; +exports.MemoryStore = MemoryStore; + +/** + * Warning message for `MemoryStore` usage in production. + */ + +var warning = 'Warning: connection.session() MemoryStore is not\n' + + 'designed for a production environment, as it will leak\n' + + 'memory, and will not scale past a single process.'; + +/** + * Session: + * + * Setup session store with the given `options`. + * + * Session data is _not_ saved in the cookie itself, however + * cookies are used, so we must use the [cookieParser()](cookieParser.html) + * middleware _before_ `session()`. + * + * Examples: + * + * connect() + * .use(connect.cookieParser()) + * .use(connect.session({ secret: 'keyboard cat', key: 'sid', cookie: { secure: true }})) + * + * Options: + * + * - `key` cookie name defaulting to `connect.sid` + * - `store` session store instance + * - `secret` session cookie is signed with this secret to prevent tampering + * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` + * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") + * + * Cookie option: + * + * By default `cookie.maxAge` is `null`, meaning no "expires" parameter is set + * so the cookie becomes a browser-session cookie. When the user closes the + * browser the cookie (and session) will be removed. + * + * ## req.session + * + * To store or access session data, simply use the request property `req.session`, + * which is (generally) serialized as JSON by the store, so nested objects + * are typically fine. For example below is a user-specific view counter: + * + * connect() + * .use(connect.favicon()) + * .use(connect.cookieParser()) + * .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})) + * .use(function(req, res, next){ + * var sess = req.session; + * if (sess.views) { + * res.setHeader('Content-Type', 'text/html'); + * res.write('

    views: ' + sess.views + '

    '); + * res.write('

    expires in: ' + (sess.cookie.maxAge / 1000) + 's

    '); + * res.end(); + * sess.views++; + * } else { + * sess.views = 1; + * res.end('welcome to the session demo. refresh!'); + * } + * } + * )).listen(3000); + * + * ## Session#regenerate() + * + * To regenerate the session simply invoke the method, once complete + * a new SID and `Session` instance will be initialized at `req.session`. + * + * req.session.regenerate(function(err){ + * // will have a new session here + * }); + * + * ## Session#destroy() + * + * Destroys the session, removing `req.session`, will be re-generated next request. + * + * req.session.destroy(function(err){ + * // cannot access session here + * }); + * + * ## Session#reload() + * + * Reloads the session data. + * + * req.session.reload(function(err){ + * // session updated + * }); + * + * ## Session#save() + * + * Save the session. + * + * req.session.save(function(err){ + * // session saved + * }); + * + * ## Session#touch() + * + * Updates the `.maxAge` property. Typically this is + * not necessary to call, as the session middleware does this for you. + * + * ## Session#cookie + * + * Each session has a unique cookie object accompany it. This allows + * you to alter the session cookie per visitor. For example we can + * set `req.session.cookie.expires` to `false` to enable the cookie + * to remain for only the duration of the user-agent. + * + * ## Session#maxAge + * + * Alternatively `req.session.cookie.maxAge` will return the time + * remaining in milliseconds, which we may also re-assign a new value + * to adjust the `.expires` property appropriately. The following + * are essentially equivalent + * + * var hour = 3600000; + * req.session.cookie.expires = new Date(Date.now() + hour); + * req.session.cookie.maxAge = hour; + * + * For example when `maxAge` is set to `60000` (one minute), and 30 seconds + * has elapsed it will return `30000` until the current request has completed, + * at which time `req.session.touch()` is called to reset `req.session.maxAge` + * to its original value. + * + * req.session.cookie.maxAge; + * // => 30000 + * + * Session Store Implementation: + * + * Every session store _must_ implement the following methods + * + * - `.get(sid, callback)` + * - `.set(sid, session, callback)` + * - `.destroy(sid, callback)` + * + * Recommended methods include, but are not limited to: + * + * - `.length(callback)` + * - `.clear(callback)` + * + * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +function session(options){ + var options = options || {} + , key = options.key || 'connect.sid' + , store = options.store || new MemoryStore + , cookie = options.cookie || {} + , trustProxy = options.proxy + , storeReady = true; + + // notify user that this store is not + // meant for a production environment + if ('production' == env && store instanceof MemoryStore) { + console.warn(warning); + } + + // generates the new session + store.generate = function(req){ + req.sessionID = uid(24); + req.session = new Session(req); + req.session.cookie = new Cookie(cookie); + }; + + store.on('disconnect', function(){ storeReady = false; }); + store.on('connect', function(){ storeReady = true; }); + + return function session(req, res, next) { + // self-awareness + if (req.session) return next(); + + // Handle connection as if there is no session if + // the store has temporarily disconnected etc + if (!storeReady) return debug('store is disconnected'), next(); + + // pathname mismatch + if (0 != req.originalUrl.indexOf(cookie.path || '/')) return next(); + + // backwards compatibility for signed cookies + // req.secret is passed from the cookie parser middleware + var secret = options.secret || req.secret; + + // ensure secret is available or bail + if (!secret) throw new Error('`secret` option required for sessions'); + + // parse url + var originalHash + , originalId; + + // expose store + req.sessionStore = store; + + // grab the session cookie value and check the signature + var rawCookie = req.cookies[key]; + + // get signedCookies for backwards compat with signed cookies + var unsignedCookie = req.signedCookies[key]; + + if (!unsignedCookie && rawCookie) { + unsignedCookie = utils.parseSignedCookie(rawCookie, secret); + } + + // set-cookie + res.on('header', function(){ + if (!req.session) return; + var cookie = req.session.cookie + , proto = (req.headers['x-forwarded-proto'] || '').split(',')[0].toLowerCase().trim() + , tls = req.connection.encrypted || (trustProxy && 'https' == proto) + , isNew = unsignedCookie != req.sessionID; + + // only send secure cookies via https + if (cookie.secure && !tls) return debug('not secured'); + + // long expires, handle expiry server-side + if (!isNew && cookie.hasLongExpires) return debug('already set cookie'); + + // browser-session length cookie + if (null == cookie.expires) { + if (!isNew) return debug('already set browser-session cookie'); + // compare hashes and ids + } else if (originalHash == hash(req.session) && originalId == req.session.id) { + return debug('unmodified session'); + } + + var val = 's:' + signature.sign(req.sessionID, secret); + val = cookie.serialize(key, val); + debug('set-cookie %s', val); + res.setHeader('Set-Cookie', val); + }); + + // proxy end() to commit the session + var end = res.end; + res.end = function(data, encoding){ + res.end = end; + if (!req.session) return res.end(data, encoding); + debug('saving'); + req.session.resetMaxAge(); + req.session.save(function(err){ + if (err) console.error(err.stack); + debug('saved'); + res.end(data, encoding); + }); + }; + + // generate the session + function generate() { + store.generate(req); + } + + // get the sessionID from the cookie + req.sessionID = unsignedCookie; + + // generate a session if the browser doesn't send a sessionID + if (!req.sessionID) { + debug('no SID sent, generating session'); + generate(); + next(); + return; + } + + // generate the session object + var pause = utils.pause(req); + debug('fetching %s', req.sessionID); + store.get(req.sessionID, function(err, sess){ + // proxy to resume() events + var _next = next; + next = function(err){ + _next(err); + pause.resume(); + }; + + // error handling + if (err) { + debug('error %j', err); + if ('ENOENT' == err.code) { + generate(); + next(); + } else { + next(err); + } + // no session + } else if (!sess) { + debug('no session found'); + generate(); + next(); + // populate req.session + } else { + debug('session found'); + store.createSession(req, sess); + originalId = req.sessionID; + originalHash = hash(sess); + next(); + } + }); + }; +}; + +/** + * Hash the given `sess` object omitting changes + * to `.cookie`. + * + * @param {Object} sess + * @return {String} + * @api private + */ + +function hash(sess) { + return crc32.signed(JSON.stringify(sess, function(key, val){ + if ('cookie' != key) return val; + })); +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js b/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js new file mode 100644 index 0000000..cdce2a5 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js @@ -0,0 +1,140 @@ + +/*! + * Connect - session - Cookie + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../../utils') + , cookie = require('cookie'); + +/** + * Initialize a new `Cookie` with the given `options`. + * + * @param {IncomingMessage} req + * @param {Object} options + * @api private + */ + +var Cookie = module.exports = function Cookie(options) { + this.path = '/'; + this.maxAge = null; + this.httpOnly = true; + if (options) utils.merge(this, options); + this.originalMaxAge = undefined == this.originalMaxAge + ? this.maxAge + : this.originalMaxAge; +}; + +/*! + * Prototype. + */ + +Cookie.prototype = { + + /** + * Set expires `date`. + * + * @param {Date} date + * @api public + */ + + set expires(date) { + this._expires = date; + this.originalMaxAge = this.maxAge; + }, + + /** + * Get expires `date`. + * + * @return {Date} + * @api public + */ + + get expires() { + return this._expires; + }, + + /** + * Set expires via max-age in `ms`. + * + * @param {Number} ms + * @api public + */ + + set maxAge(ms) { + this.expires = 'number' == typeof ms + ? new Date(Date.now() + ms) + : ms; + }, + + /** + * Get expires max-age in `ms`. + * + * @return {Number} + * @api public + */ + + get maxAge() { + return this.expires instanceof Date + ? this.expires.valueOf() - Date.now() + : this.expires; + }, + + /** + * Return cookie data object. + * + * @return {Object} + * @api private + */ + + get data() { + return { + originalMaxAge: this.originalMaxAge + , expires: this._expires + , secure: this.secure + , httpOnly: this.httpOnly + , domain: this.domain + , path: this.path + } + }, + + /** + * Check if the cookie has a reasonably large max-age. + * + * @return {Boolean} + * @api private + */ + + get hasLongExpires() { + var week = 604800000; + return this.maxAge > (4 * week); + }, + + /** + * Return a serialized cookie string. + * + * @return {String} + * @api public + */ + + serialize: function(name, val){ + return cookie.serialize(name, val, this.data); + }, + + /** + * Return JSON representation of this cookie. + * + * @return {Object} + * @api private + */ + + toJSON: function(){ + return this.data; + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/memory.js b/node_modules/express/node_modules/connect/lib/middleware/session/memory.js new file mode 100644 index 0000000..fb93939 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/memory.js @@ -0,0 +1,129 @@ + +/*! + * Connect - session - MemoryStore + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Store = require('./store'); + +/** + * Initialize a new `MemoryStore`. + * + * @api public + */ + +var MemoryStore = module.exports = function MemoryStore() { + this.sessions = {}; +}; + +/** + * Inherit from `Store.prototype`. + */ + +MemoryStore.prototype.__proto__ = Store.prototype; + +/** + * Attempt to fetch session by the given `sid`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.get = function(sid, fn){ + var self = this; + process.nextTick(function(){ + var expires + , sess = self.sessions[sid]; + if (sess) { + sess = JSON.parse(sess); + expires = 'string' == typeof sess.cookie.expires + ? new Date(sess.cookie.expires) + : sess.cookie.expires; + if (!expires || new Date < expires) { + fn(null, sess); + } else { + self.destroy(sid, fn); + } + } else { + fn(); + } + }); +}; + +/** + * Commit the given `sess` object associated with the given `sid`. + * + * @param {String} sid + * @param {Session} sess + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.set = function(sid, sess, fn){ + var self = this; + process.nextTick(function(){ + self.sessions[sid] = JSON.stringify(sess); + fn && fn(); + }); +}; + +/** + * Destroy the session associated with the given `sid`. + * + * @param {String} sid + * @api public + */ + +MemoryStore.prototype.destroy = function(sid, fn){ + var self = this; + process.nextTick(function(){ + delete self.sessions[sid]; + fn && fn(); + }); +}; + +/** + * Invoke the given callback `fn` with all active sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.all = function(fn){ + var arr = [] + , keys = Object.keys(this.sessions); + for (var i = 0, len = keys.length; i < len; ++i) { + arr.push(this.sessions[keys[i]]); + } + fn(null, arr); +}; + +/** + * Clear all sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.clear = function(fn){ + this.sessions = {}; + fn && fn(); +}; + +/** + * Fetch number of sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.length = function(fn){ + fn(null, Object.keys(this.sessions).length); +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/session.js b/node_modules/express/node_modules/connect/lib/middleware/session/session.js new file mode 100644 index 0000000..0dd4b40 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/session.js @@ -0,0 +1,116 @@ + +/*! + * Connect - session - Session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../../utils'); + +/** + * Create a new `Session` with the given request and `data`. + * + * @param {IncomingRequest} req + * @param {Object} data + * @api private + */ + +var Session = module.exports = function Session(req, data) { + Object.defineProperty(this, 'req', { value: req }); + Object.defineProperty(this, 'id', { value: req.sessionID }); + if ('object' == typeof data) utils.merge(this, data); +}; + +/** + * Update reset `.cookie.maxAge` to prevent + * the cookie from expiring when the + * session is still active. + * + * @return {Session} for chaining + * @api public + */ + +Session.prototype.touch = function(){ + return this.resetMaxAge(); +}; + +/** + * Reset `.maxAge` to `.originalMaxAge`. + * + * @return {Session} for chaining + * @api public + */ + +Session.prototype.resetMaxAge = function(){ + this.cookie.maxAge = this.cookie.originalMaxAge; + return this; +}; + +/** + * Save the session data with optional callback `fn(err)`. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.save = function(fn){ + this.req.sessionStore.set(this.id, this, fn || function(){}); + return this; +}; + +/** + * Re-loads the session data _without_ altering + * the maxAge properties. Invokes the callback `fn(err)`, + * after which time if no exception has occurred the + * `req.session` property will be a new `Session` object, + * although representing the same session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.reload = function(fn){ + var req = this.req + , store = this.req.sessionStore; + store.get(this.id, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(new Error('failed to load session')); + store.createSession(req, sess); + fn(); + }); + return this; +}; + +/** + * Destroy `this` session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.destroy = function(fn){ + delete this.req.session; + this.req.sessionStore.destroy(this.id, fn); + return this; +}; + +/** + * Regenerate this request's session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.regenerate = function(fn){ + this.req.sessionStore.regenerate(this.req, fn); + return this; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/store.js b/node_modules/express/node_modules/connect/lib/middleware/session/store.js new file mode 100644 index 0000000..54294cb --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/store.js @@ -0,0 +1,84 @@ + +/*! + * Connect - session - Store + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , Session = require('./session') + , Cookie = require('./cookie'); + +/** + * Initialize abstract `Store`. + * + * @api private + */ + +var Store = module.exports = function Store(options){}; + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Store.prototype.__proto__ = EventEmitter.prototype; + +/** + * Re-generate the given requests's session. + * + * @param {IncomingRequest} req + * @return {Function} fn + * @api public + */ + +Store.prototype.regenerate = function(req, fn){ + var self = this; + this.destroy(req.sessionID, function(err){ + self.generate(req); + fn(err); + }); +}; + +/** + * Load a `Session` instance via the given `sid` + * and invoke the callback `fn(err, sess)`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +Store.prototype.load = function(sid, fn){ + var self = this; + this.get(sid, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(); + var req = { sessionID: sid, sessionStore: self }; + sess = self.createSession(req, sess); + fn(null, sess); + }); +}; + +/** + * Create session from JSON `sess` data. + * + * @param {IncomingRequest} req + * @param {Object} sess + * @return {Session} + * @api private + */ + +Store.prototype.createSession = function(req, sess){ + var expires = sess.cookie.expires + , orig = sess.cookie.originalMaxAge; + sess.cookie = new Cookie(sess.cookie); + if ('string' == typeof expires) sess.cookie.expires = new Date(expires); + sess.cookie.originalMaxAge = orig; + req.session = new Session(req, sess); + return req.session; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/static.js b/node_modules/express/node_modules/connect/lib/middleware/static.js new file mode 100644 index 0000000..7762ac1 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/static.js @@ -0,0 +1,95 @@ +/*! + * Connect - static + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var send = require('send') + , utils = require('../utils') + , parse = utils.parseUrl + , url = require('url'); + +/** + * Static: + * + * Static file server with the given `root` path. + * + * Examples: + * + * var oneDay = 86400000; + * + * connect() + * .use(connect.static(__dirname + '/public')) + * + * connect() + * .use(connect.static(__dirname + '/public', { maxAge: oneDay })) + * + * Options: + * + * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0 + * - `hidden` Allow transfer of hidden files. defaults to false + * - `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to true + * - `index` Default file name, defaults to 'index.html' + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('static() root path required'); + + // default redirect + var redirect = false !== options.redirect; + + return function staticMiddleware(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + var path = parse(req).pathname; + var pause = utils.pause(req); + + function resume() { + next(); + pause.resume(); + } + + function directory() { + if (!redirect) return resume(); + var pathname = url.parse(req.originalUrl).pathname; + res.statusCode = 303; + res.setHeader('Location', pathname + '/'); + res.end('Redirecting to ' + utils.escape(pathname) + '/'); + } + + function error(err) { + if (404 == err.status) return resume(); + next(err); + } + + send(req, path) + .maxage(options.maxAge || 0) + .root(root) + .index(options.index || 'index.html') + .hidden(options.hidden) + .on('error', error) + .on('directory', directory) + .pipe(res); + }; +}; + +/** + * Expose mime module. + * + * If you wish to extend the mime table use this + * reference to the "mime" module in the npm registry. + */ + +exports.mime = send.mime; diff --git a/node_modules/express/node_modules/connect/lib/middleware/staticCache.js b/node_modules/express/node_modules/connect/lib/middleware/staticCache.js new file mode 100644 index 0000000..7354a8f --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/staticCache.js @@ -0,0 +1,231 @@ + +/*! + * Connect - staticCache + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , Cache = require('../cache') + , fresh = require('fresh'); + +/** + * Static cache: + * + * Enables a memory cache layer on top of + * the `static()` middleware, serving popular + * static files. + * + * By default a maximum of 128 objects are + * held in cache, with a max of 256k each, + * totalling ~32mb. + * + * A Least-Recently-Used (LRU) cache algo + * is implemented through the `Cache` object, + * simply rotating cache objects as they are + * hit. This means that increasingly popular + * objects maintain their positions while + * others get shoved out of the stack and + * garbage collected. + * + * Benchmarks: + * + * static(): 2700 rps + * node-static: 5300 rps + * static() + staticCache(): 7500 rps + * + * Options: + * + * - `maxObjects` max cache objects [128] + * - `maxLength` max cache object length 256kb + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function staticCache(options){ + var options = options || {} + , cache = new Cache(options.maxObjects || 128) + , maxlen = options.maxLength || 1024 * 256; + + console.warn('connect.staticCache() is deprecated and will be removed in 3.0'); + console.warn('use varnish or similar reverse proxy caches.'); + + return function staticCache(req, res, next){ + var key = cacheKey(req) + , ranges = req.headers.range + , hasCookies = req.headers.cookie + , hit = cache.get(key); + + // cache static + // TODO: change from staticCache() -> cache() + // and make this work for any request + req.on('static', function(stream){ + var headers = res._headers + , cc = utils.parseCacheControl(headers['cache-control'] || '') + , contentLength = headers['content-length'] + , hit; + + // dont cache set-cookie responses + if (headers['set-cookie']) return hasCookies = true; + + // dont cache when cookies are present + if (hasCookies) return; + + // ignore larger files + if (!contentLength || contentLength > maxlen) return; + + // don't cache partial files + if (headers['content-range']) return; + + // dont cache items we shouldn't be + // TODO: real support for must-revalidate / no-cache + if ( cc['no-cache'] + || cc['no-store'] + || cc['private'] + || cc['must-revalidate']) return; + + // if already in cache then validate + if (hit = cache.get(key)){ + if (headers.etag == hit[0].etag) { + hit[0].date = new Date; + return; + } else { + cache.remove(key); + } + } + + // validation notifiactions don't contain a steam + if (null == stream) return; + + // add the cache object + var arr = []; + + // store the chunks + stream.on('data', function(chunk){ + arr.push(chunk); + }); + + // flag it as complete + stream.on('end', function(){ + var cacheEntry = cache.add(key); + delete headers['x-cache']; // Clean up (TODO: others) + cacheEntry.push(200); + cacheEntry.push(headers); + cacheEntry.push.apply(cacheEntry, arr); + }); + }); + + if (req.method == 'GET' || req.method == 'HEAD') { + if (ranges) { + next(); + } else if (!hasCookies && hit && !mustRevalidate(req, hit)) { + res.setHeader('X-Cache', 'HIT'); + respondFromCache(req, res, hit); + } else { + res.setHeader('X-Cache', 'MISS'); + next(); + } + } else { + next(); + } + } +}; + +/** + * Respond with the provided cached value. + * TODO: Assume 200 code, that's iffy. + * + * @param {Object} req + * @param {Object} res + * @param {Object} cacheEntry + * @return {String} + * @api private + */ + +function respondFromCache(req, res, cacheEntry) { + var status = cacheEntry[0] + , headers = utils.merge({}, cacheEntry[1]) + , content = cacheEntry.slice(2); + + headers.age = (new Date - new Date(headers.date)) / 1000 || 0; + + switch (req.method) { + case 'HEAD': + res.writeHead(status, headers); + res.end(); + break; + case 'GET': + if (utils.conditionalGET(req) && fresh(req.headers, headers)) { + headers['content-length'] = 0; + res.writeHead(304, headers); + res.end(); + } else { + res.writeHead(status, headers); + + function write() { + while (content.length) { + if (false === res.write(content.shift())) { + res.once('drain', write); + return; + } + } + res.end(); + } + + write(); + } + break; + default: + // This should never happen. + res.writeHead(500, ''); + res.end(); + } +} + +/** + * Determine whether or not a cached value must be revalidated. + * + * @param {Object} req + * @param {Object} cacheEntry + * @return {String} + * @api private + */ + +function mustRevalidate(req, cacheEntry) { + var cacheHeaders = cacheEntry[1] + , reqCC = utils.parseCacheControl(req.headers['cache-control'] || '') + , cacheCC = utils.parseCacheControl(cacheHeaders['cache-control'] || '') + , cacheAge = (new Date - new Date(cacheHeaders.date)) / 1000 || 0; + + if ( cacheCC['no-cache'] + || cacheCC['must-revalidate'] + || cacheCC['proxy-revalidate']) return true; + + if (reqCC['no-cache']) return true; + + if (null != reqCC['max-age']) return reqCC['max-age'] < cacheAge; + + if (null != cacheCC['max-age']) return cacheCC['max-age'] < cacheAge; + + return false; +} + +/** + * The key to use in the cache. For now, this is the URL path and query. + * + * 'http://example.com?key=value' -> '/?key=value' + * + * @param {Object} req + * @return {String} + * @api private + */ + +function cacheKey(req) { + return utils.parseUrl(req).path; +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/timeout.js b/node_modules/express/node_modules/connect/lib/middleware/timeout.js new file mode 100644 index 0000000..5496c02 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/timeout.js @@ -0,0 +1,55 @@ +/*! + * Connect - timeout + * Ported from https://github.com/LearnBoost/connect-timeout + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var debug = require('debug')('connect:timeout'); + +/** + * Timeout: + * + * Times out the request in `ms`, defaulting to `5000`. The + * method `req.clearTimeout()` is added to revert this behaviour + * programmatically within your application's middleware, routes, etc. + * + * The timeout error is passed to `next()` so that you may customize + * the response behaviour. This error has the `.timeout` property as + * well as `.status == 503`. + * + * @param {Number} ms + * @return {Function} + * @api public + */ + +module.exports = function timeout(ms) { + ms = ms || 5000; + + return function(req, res, next) { + var id = setTimeout(function(){ + req.emit('timeout', ms); + }, ms); + + req.on('timeout', function(){ + if (res.headerSent) return debug('response started, cannot timeout'); + var err = new Error('Response timeout'); + err.timeout = ms; + err.status = 503; + next(err); + }); + + req.clearTimeout = function(){ + clearTimeout(id); + }; + + res.on('header', function(){ + clearTimeout(id); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js b/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js new file mode 100644 index 0000000..cceafc0 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js @@ -0,0 +1,78 @@ + +/*! + * Connect - urlencoded + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , _limit = require('./limit') + , qs = require('qs'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * Urlencoded: + * + * Parse x-ww-form-urlencoded request bodies, + * providing the parsed object as `req.body`. + * + * Options: + * + * - `limit` byte limit disabled by default + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + options = options || {}; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function urlencoded(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + + if (!utils.hasBody(req)) return next(); + + // check Content-Type + if ('application/x-www-form-urlencoded' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk }); + req.on('end', function(){ + try { + req.body = buf.length + ? qs.parse(buf, options) + : {}; + next(); + } catch (err){ + err.body = buf; + next(err); + } + }); + }); + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/vhost.js b/node_modules/express/node_modules/connect/lib/middleware/vhost.js new file mode 100644 index 0000000..abbb050 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/vhost.js @@ -0,0 +1,40 @@ + +/*! + * Connect - vhost + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Vhost: + * + * Setup vhost for the given `hostname` and `server`. + * + * connect() + * .use(connect.vhost('foo.com', fooApp)) + * .use(connect.vhost('bar.com', barApp)) + * .use(connect.vhost('*.com', mainApp)) + * + * The `server` may be a Connect server or + * a regular Node `http.Server`. + * + * @param {String} hostname + * @param {Server} server + * @return {Function} + * @api public + */ + +module.exports = function vhost(hostname, server){ + if (!hostname) throw new Error('vhost hostname required'); + if (!server) throw new Error('vhost server required'); + var regexp = new RegExp('^' + hostname.replace(/[^*\w]/g, '\\$&').replace(/[*]/g, '(?:.*?)') + '$', 'i'); + if (server.onvhost) server.onvhost(hostname); + return function vhost(req, res, next){ + if (!req.headers.host) return next(); + var host = req.headers.host.split(':')[0]; + if (!regexp.test(host)) return next(); + if ('function' == typeof server) return server(req, res, next); + server.emit('request', req, res); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/patch.js b/node_modules/express/node_modules/connect/lib/patch.js new file mode 100644 index 0000000..7cf0012 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/patch.js @@ -0,0 +1,79 @@ + +/*! + * Connect + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , res = http.ServerResponse.prototype + , setHeader = res.setHeader + , _renderHeaders = res._renderHeaders + , writeHead = res.writeHead; + +// apply only once + +if (!res._hasConnectPatch) { + + /** + * Provide a public "header sent" flag + * until node does. + * + * @return {Boolean} + * @api public + */ + + res.__defineGetter__('headerSent', function(){ + return this._header; + }); + + /** + * Set header `field` to `val`, special-casing + * the `Set-Cookie` field for multiple support. + * + * @param {String} field + * @param {String} val + * @api public + */ + + res.setHeader = function(field, val){ + var key = field.toLowerCase() + , prev; + + // special-case Set-Cookie + if (this._headers && 'set-cookie' == key) { + if (prev = this.getHeader(field)) { + val = Array.isArray(prev) + ? prev.concat(val) + : [prev, val]; + } + // charset + } else if ('content-type' == key && this.charset) { + val += '; charset=' + this.charset; + } + + return setHeader.call(this, field, val); + }; + + /** + * Proxy to emit "header" event. + */ + + res._renderHeaders = function(){ + if (!this._emittedHeader) this.emit('header'); + this._emittedHeader = true; + return _renderHeaders.call(this); + }; + + res.writeHead = function(){ + if (!this._emittedHeader) this.emit('header'); + this._emittedHeader = true; + return writeHead.apply(this, arguments); + }; + + res._hasConnectPatch = true; +} diff --git a/node_modules/express/node_modules/connect/lib/proto.js b/node_modules/express/node_modules/connect/lib/proto.js new file mode 100644 index 0000000..6fadf8f --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/proto.js @@ -0,0 +1,230 @@ + +/*! + * Connect - HTTPServer + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('./utils') + , debug = require('debug')('connect:dispatcher'); + +// prototype + +var app = module.exports = {}; + +// environment + +var env = process.env.NODE_ENV || 'development'; + +/** + * Utilize the given middleware `handle` to the given `route`, + * defaulting to _/_. This "route" is the mount-point for the + * middleware, when given a value other than _/_ the middleware + * is only effective when that segment is present in the request's + * pathname. + * + * For example if we were to mount a function at _/admin_, it would + * be invoked on _/admin_, and _/admin/settings_, however it would + * not be invoked for _/_, or _/posts_. + * + * Examples: + * + * var app = connect(); + * app.use(connect.favicon()); + * app.use(connect.logger()); + * app.use(connect.static(__dirname + '/public')); + * + * If we wanted to prefix static files with _/public_, we could + * "mount" the `static()` middleware: + * + * app.use('/public', connect.static(__dirname + '/public')); + * + * This api is chainable, so the following is valid: + * + * connect() + * .use(connect.favicon()) + * .use(connect.logger()) + * .use(connect.static(__dirname + '/public')) + * .listen(3000); + * + * @param {String|Function|Server} route, callback or server + * @param {Function|Server} callback or server + * @return {Server} for chaining + * @api public + */ + +app.use = function(route, fn){ + // default route to '/' + if ('string' != typeof route) { + fn = route; + route = '/'; + } + + // wrap sub-apps + if ('function' == typeof fn.handle) { + var server = fn; + fn.route = route; + fn = function(req, res, next){ + server.handle(req, res, next); + }; + } + + // wrap vanilla http.Servers + if (fn instanceof http.Server) { + fn = fn.listeners('request')[0]; + } + + // strip trailing slash + if ('/' == route[route.length - 1]) { + route = route.slice(0, -1); + } + + // add the middleware + debug('use %s %s', route || '/', fn.name || 'anonymous'); + this.stack.push({ route: route, handle: fn }); + + return this; +}; + +/** + * Handle server requests, punting them down + * the middleware stack. + * + * @api private + */ + +app.handle = function(req, res, out) { + var stack = this.stack + , fqdn = ~req.url.indexOf('://') + , removed = '' + , slashAdded = false + , index = 0; + + function next(err) { + var layer, path, status, c; + + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + req.url = removed + req.url; + req.originalUrl = req.originalUrl || req.url; + removed = ''; + + // next callback + layer = stack[index++]; + + // all done + if (!layer || res.headerSent) { + // delegate to parent + if (out) return out(err); + + // unhandled error + if (err) { + // default to 500 + if (res.statusCode < 400) res.statusCode = 500; + debug('default %s', res.statusCode); + + // respect err.status + if (err.status) res.statusCode = err.status; + + // production gets a basic error message + var msg = 'production' == env + ? http.STATUS_CODES[res.statusCode] + : err.stack || err.toString(); + + // log to stderr in a non-test env + if ('test' != env) console.error(err.stack || err.toString()); + if (res.headerSent) return req.socket.destroy(); + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', Buffer.byteLength(msg)); + if ('HEAD' == req.method) return res.end(); + res.end(msg); + } else { + debug('default 404'); + res.statusCode = 404; + res.setHeader('Content-Type', 'text/plain'); + if ('HEAD' == req.method) return res.end(); + res.end('Cannot ' + utils.escape(req.method) + ' ' + utils.escape(req.originalUrl)); + } + return; + } + + try { + path = utils.parseUrl(req).pathname; + if (undefined == path) path = '/'; + + // skip this layer if the route doesn't match. + if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err); + + c = path[layer.route.length]; + if (c && '/' != c && '.' != c) return next(err); + + // Call the layer handler + // Trim off the part of the url that matches the route + removed = layer.route; + req.url = req.url.substr(removed.length); + + // Ensure leading slash + if (!fqdn && '/' != req.url[0]) { + req.url = '/' + req.url; + slashAdded = true; + } + + debug('%s %s : %s', layer.handle.name || 'anonymous', layer.route, req.originalUrl); + var arity = layer.handle.length; + if (err) { + if (arity === 4) { + layer.handle(err, req, res, next); + } else { + next(err); + } + } else if (arity < 4) { + layer.handle(req, res, next); + } else { + next(); + } + } catch (e) { + next(e); + } + } + next(); +}; + +/** + * Listen for connections. + * + * This method takes the same arguments + * as node's `http.Server#listen()`. + * + * HTTP and HTTPS: + * + * If you run your application both as HTTP + * and HTTPS you may wrap them individually, + * since your Connect "server" is really just + * a JavaScript `Function`. + * + * var connect = require('connect') + * , http = require('http') + * , https = require('https'); + * + * var app = connect(); + * + * http.createServer(app).listen(80); + * https.createServer(options, app).listen(443); + * + * @return {http.Server} + * @api public + */ + +app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; diff --git a/node_modules/express/node_modules/connect/lib/public/directory.html b/node_modules/express/node_modules/connect/lib/public/directory.html new file mode 100644 index 0000000..2d63704 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/directory.html @@ -0,0 +1,81 @@ + + + + + listing directory {directory} + + + + + +
    +

    {linked-path}

    + {files} +
    + + \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/public/error.html b/node_modules/express/node_modules/connect/lib/public/error.html new file mode 100644 index 0000000..a6d3faf --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/error.html @@ -0,0 +1,14 @@ + + + + {error} + + + +
    +

    {title}

    +

    {statusCode} {error}

    +
      {stack}
    +
    + + diff --git a/node_modules/express/node_modules/connect/lib/public/favicon.ico b/node_modules/express/node_modules/connect/lib/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..895fc96a76b68b4924f1c51d022e1b82fa0f461f GIT binary patch literal 1406 zcmZQzU<5(|0R}M0U}azs1F|%L7$l?s#Ec9aKoZP=&}i&OouUjIY8@C}uZw4x5z5N2 zvEG^C^vXtt_xtJ?p3O32c(KTx;lsgZhW%5M85Sf}k-mf`L80)|7ga~M{a znlL=>m1Q`#uoPkbC~GtXMnhnDh5$DU1D6mx+;2QAKt3ZQFH}H~1y~00GcqzVg9QXw z_<%(a7y$V|wJgF=E>MgE#Aid|14}IyCM5MhEnxFF;pTzOK(>#80puP=gnOXwAd33` mpMe2}f66m3eB@_fcnmb^7!b1nO#opK8zcsj1F30)+jEP);68^d)m`eN0o>(5%D`Q(1;j>g@G;xlf`0VBQ`PFY?6)!N&f?*K}$p; zB!U=NBn{eB8${1}&-2_L*HuZp@ZP1@clS@cHp)4iM1ewzw59vko7eMM{e9z|%NNdX z0V;`?KKSzTCvTm5bc{L^CIKLUxc2X{i{ISz$8Sgf{q)1nXTP{`{s?9mQ$4&hPiKC- zY8q7(Y1Xu5iCf33=O4Vy(+|zQ?rW#gkKB0f%}?+6{G*qT22|DQB-73`YzA{N4W^=s zq0kQYcbtFfz zLz)H<&|z(Y4kBG67=JY6c|L1R-#TR>fC$3^Y%QEnYO1xHsf)+GU`3F<{J0kR(;pbF3)zyg$H+idfnl-wl5Wkh!vUH z4Z32YP=l_}1rZd1W_D&^$A($A+&a0e&P?xx0!ctY2}*<#p+qPVN*B(YzvAWXa*%bzq z7Fz41LKILT(GWohi9|LgIzSZBhb*Zf6R6O}WYQ4GOi&71s9lmll0x6;8&ILOl$j(c z0Z1T(6Tg09{?wd{moFHNN6PS?$|e>1MxSJ(0Z7o2)J-Zv|>acY@f`(Y@g7GwsEj5NLQo+q|HsxQ5}XSX_d@*^A9ZT9=A{W~j+$GyI1 zc4oqTHx@1FlRjw4XWyPN5i2~l_F3@aBk!0yu^aoRDvXy}8@HCjUVQUsuSH4$T5|r< zzZOn^?Wfa6y|Q($Hx4{ws+)wX6-HP4zo!S?4KJ@7PG@G3G{CjXs(p*kIrj6rHs7_y z+=<-=Q62s9FuWa^X~WKgJIAAZJR&XBB002ovPDHLkV1jCMPILeO literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png b/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png new file mode 100644 index 0000000000000000000000000000000000000000..89ee2da0753040d1ba0a3487473a715a8fe89322 GIT binary patch literal 794 zcmV+#1LgdQP)i_t#ewV_0K6;=bl;e_Jt7$~$sQ)q$+ia<4Ec+jeaGt9oWH@O|2`W6&O0t!k{B9sUvLWxkCaPsd9W(`fa z;j-|^ZI^2XnzhgZWYRW-kP&J>DWPo`%;JaBX}or79k=+Jo@h%4Eo72tqev+cB?PjP zO<|ByL#>Tehyq$jR74O$B9WDW1`tK`LzYyL3A9iAcRxLkJ`I)n}v%Od-3H>j$OTBtk>(k-9o?8PqI=0 zB&f-+KOXVnjyKJlf4iHOtnuiE_4+ZVJ$dHjU<^o^YCjQ-wt^!;rPpBv(@pFO{9rdw98 z_s@3+yta93oyfL>7AD5}r=|`zS3Gm$_|(iSl8XBd9k%=91J0j2=ivT5cJ18ZmDjh{ z$-RMd{jQ#X79#Sc literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_code.png b/node_modules/express/node_modules/connect/lib/public/icons/page_code.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ea90419d950f9e69d977a1f5847456d96a5f0b GIT binary patch literal 818 zcmV-21I_%2P)@LCln44|RX7Ti z0HI3&7jPq){odH{?_{%nYVq_;n_c4WbUpvU(&Cvnj!vq|kVC-vpF6vp^;;e0mm6HW z+WPzA`AZ|;pPp$&dNjzrc??4rt`k%Q1l*u-BPD0MQ}Fbm8jnsyezNt7+u{23>t7Em zJtETY?ja9KrVs^!LJ$xEMF3-bAZO;-IQJavE60KA7fO$VY_%N)R6s>g5mW>fL4&aR z*EVgKKTBXm!=L?S0?xM zYqL@C$|EDF2q*3zWW7;PDZ}SK*IE8;i!3U62=qn80C&*I1Le7WwNP5EcX;_oh2dJn zf#HgBe4@r$GcjHjmj2vAfT%(YN?}kK=(*+1*DkNNc1H5R++vfBMhACi<5uFUU+N4+ z<&U*CPmWi}REa7C6-t>2im1CWv5Jkefxa6>)dEj-CAW wWa{_}BJ!}~75?MkfaCnj>Dn=~vkLS70Pk`;z)@TQj{pDw07*qoM6N<$f@imYHUIzs literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png b/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png new file mode 100644 index 0000000000000000000000000000000000000000..195dc6d6c365d298e466026b37c1959d96119ea7 GIT binary patch literal 663 zcmV;I0%-k-P)^@R5;6Z z(>-WZK@^7J_sq=QY_e{46@P+~LNG}sRzZsxQHvCsN*h5ir6^j7pq-$xu$N#V1gx}9 zClV7;5)7zih-s3DB)G=7|99>ji@So7-P24n=VQ(@GctDX!^_@$bj%oviY6e4Dh;od zooe%Wvs8LEKQ&&bL&@bwi=STIAI@!-gB2jC5+?y?VR~VkrNxam-`6*8&po|RZ5LpS zNKdJ%c4bTX`XjKsnecf%W>1%6WT?pKNdLLq{=(f(Col?P1+oq@R>)W(n=x!|*BIIh z6DJGw_w`)u6yN|vAhMteYK5#b%r5^v+VCFl1IGssaclZZMS{vs-LJ2$)n7DAr6==K z<29#%AXsBsDoO}SBaXR#_Ap!JKx)(1)3O2pj0_dYWz5By*X74fRT01$Fk%P_RzOMDtV?GU{nsYq#K8iy zb6qzLYDj`_f5$BwC*WE(t0m#xYJ*=jC2|HQYHh=pf#QG7oowi`h!L!{DB$8|qY{~X zu8@sU1tWq;n$XThR0%;45mdqXM892|{CJ@0DS*}>?ami06Q_^tvM~Y3K(_-`#m!8f z8f!QIrH4y#61;0Ym0cCoLl8{IPombPHtnn7%SbTdI&G-d>ZQo!_wBMF9nzX!g8HVY xYTJPGciz9XMh3w2fmZ(7v{)r*QZD48?mrio{~IaoqP z|1Ep}yDQG09bP~E^Dk?@JiKQJ z6-pO(3~IOP)IYisL6D6;oAEd;E%zR}{U$rMRNuD6nQV7nesKS>)yLo7JuDCrD>Abi zbj3uW23?^GA}9jQ{M^8v?ejL?HaT7AX5WPZNkBmfN`w-jL?{tT7ykZt$%Yln?p_m~ z-?>&d(LD(jAd}h=LPltPQbO$*Wbyl@G-_k5jXbb#qffHY03>M1jfEqoPJQ6Mr=Byp=^jfzePZV1 zLjCmNi31hdIJHa%e;5g=1(`u3BRzfeExY%=VCu{loOr{`%2hUR*x>tL^W_TTaj);0 zpPR6CUD1+0>4TQ6zVfH3TQ;%l6#(_%yspK@3gcmG#Q4!WCPyLU93nMKk7E2pcA=l45({2jNho>sdF*A~bA zxX?-cp~y_z_kFf+yqu3m#QiB}03?Z&9vvR5TNgj<)($Vm)xq5G>|o2sFMag&6aNF+ WAT1?sQBYt20000iHtsh1EzPArg^Q zIZrOk#rNsfjaSbMAL;<4h;Z=jvu8dzyz8N&Nb7=z03ZUw?9z%8KQEa6yM5=kUnka& z3?FJk2}L7q>na=T#;<7U*P91xfF`;`6%pVgWgRy0?1ZryL@%z52=-!fGXWGEn4M351L4<+7eDgwo|moqXT+s1&Kmn>-uQQ8mL7XY)w5Zk*(g+<3Y3tmkR!bL zOUKaUtj_pX26sH+=Iorwu}MGd`_%O-_sS}8VpG#fJA)Fcs#ezwtZf?q?Ac70mDv`rVs{$od?VPKeqf<-kUjNtS6ecB*mq<&M97K^6IVsDO zt2$Ru!b+>2S<}_H>$RcInusU_8PMNdf(W{sNlJ3FkrwMJPeBPO#d}Y^a{9TH(#{Y) l0D?dWAV4eUJX#h`!2gmISk&ZKd4B)^002ovPDHLkV1g&sd|Lnj literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_error.png b/node_modules/express/node_modules/connect/lib/public/icons/page_error.png new file mode 100644 index 0000000000000000000000000000000000000000..f07f449a44ff2761bfc7b752db3d08d0e1238b02 GIT binary patch literal 793 zcmV+!1LpjRP)lHwhvrAu0-@MQwt}+5~MQTtu}C0%;W( z1<{R?aHBz*g;pk%AyQVBR_Zu5m~;ES_vxI-O!vIF|H*|T{l`n#garr?$RMk>)?Y48 z(ZF2yTneKb};DNWF+jK)IF`6_IfJ{i|F3o%Q+l&4_HGBD|ACE8na_6>L z=s{^>-C(a7J$6=8A_%h5W!1K6dcL!D?XX+Ndk)oei?UundDpX_E&1Y&`)3P8#Ny0s z2Ag7_&ZPhyGj%)g&S6V2LNun1;iBQm#Fwlfv zgyESZR$X}2P;=RW!2zid1r$hBL{K7>2qi*f7>pT1=RdT3@-anEoH{ z={KFOO;Dh#bV*jaN>}M>RZqQd`S=6O9C3KpI~I>l%QFYfo;jqQYe5fcn`)+)zMm6P z4X&L(>gnN0!%J4^rhX->?$S5bY<=GEU%jc!KLL8sww-Eg;h z`H-yBHa)yfojYT}&G*GFc$<(Yja_q=lZvj66DC^O5%$B)|Z(CeD=n`|eM04SP; z>-=-l+xdJjA~vR6^xB#o{ehf~tSM`iwaQv$O<8NIHA}W_WOw*~ XD^gE}t;YAo00000NkvXXu0mjfl6ZQ> literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png b/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6158eb5ca9c4b64c81e70e0fd894dbc8e2bed9 GIT binary patch literal 817 zcmV-11J3-3P)hdKqhFO_H1|Vn1E?(=|cjAh_&P}y{{^`u< zcYD@PK?$)4i~7o9*6F_$F$4lR(d4AAvrez^(88Hk+)+B7E)M3jc=Ewl4$S^`_qwSF zA%qz@=c2EOsz@0qB1IqsqJU)HaG&+}%`-OM8YqW{K85hqj@4&V9vz!Cm_n0-W#f;# zeEpJde%vdgRn5?(+PY=W*z~|lT2-mtown({ll8&3S5+lWz5K}LTRW{k{eJn3Qz!SU zQ`@qI_n2;K?RG~pYJ9=dj-RWgG;P&wEuoAxL~Q)<>x0b=dED^Outj&xQ^rA;u3pw| zca_ClTh_d9cxXg_U!lLRl0`xU@$=UXO|_dRdtXfKwPawmnf(LC7u}-U>8k6}3u|{8 zs9LHr>MIJZGD^r9h|q2yF24Wuh+PM^yMN9GP1$khlDkdyCY}D{kg}jEf-(kW5jBY> z0rB29ZhG-r=i_R{;+1k0?A-sBM;AP6(k1i9ZuixR4?MqXOvphQgCYj~RnXKKL~J9Q zIDNz~XMfO{ZhUg&BTtMyXJqDVqc<x643?SvKHx004lTvR=0a5$dUw z>Xb470000$S;ka1sfH4I-R8njUol7M4dtApOahDylptpYswf1hD#CwFoz6oEA>(SIECU&IQ%a}GXdnC!9$70`0uH1B00000NkvXXu0mjf!8w72 literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_find.png b/node_modules/express/node_modules/connect/lib/public/icons/page_find.png new file mode 100644 index 0000000000000000000000000000000000000000..2f193889f7ea091c292acdd684c595dcb206b5c4 GIT binary patch literal 879 zcmV-#1CacQP)@+1&aazfGU7ezSm^v zpACwO+tu0su66!(dT=`e05DeeCnCFJW(8|RKtKa{4LGONnx2V85A4m%PEQ?MEtR-esdM$pB-`H542D0)N2zSC6Imf)4L8?>%ZrW+H>xCKi$unm zvGZq-*Q%Aahx;C*=l+K%-?>XB)6TB$-L$r*`RUvlA`xP1NG2?)ge8@TQ4EN|Jks0u zcDg;oFC#-#R`YbWB`D?Q`1#y7l$LXhjSLf8AvQuB84}i#j0^!#g{VE#(K7h@5pFHy zSenl=@XBEdxp`h2Ji>CR%=qXJ7!e|?paKet-~;#ok#jETyeB(5&Bkhp;!+;51~G=) zH?L7xmDUu_h+a$+xuWom;AWW!mS$%%+436Rjc@}y?l1134kgD0AOf$OmjOR zstUlshZk$ZC!bAyIg{Y29z#&@3SJ;6D4+_eFume9^#TmMccC5u0J!ZCTnO6m$lnD| z5JeFHf`Xs~1vP>RLKI1GKDY<~pjr2&bi(fX;6Nj-ss@Ds0CcoO0H{JsEQkm{q03skAA);_bv3q{k31qwVo&s-q`Z?_e+j^w(WL? zl+uETs5+~xBU2};OqEE9ETLGwsMGe1%iTRNue)9}|0~E4B*@5#oRXZ9oRXZ9TqRep zPrGZuoOON4n@=uPbyP1y4G=+HktC6l(gZoFD>@_lXDrN?wo+zozGt3P=Qh+3L7+}q z2!WK7geXLnO3Vw;o12Skp%_E#+N#9;DDWP?Q-VS3B$v~Ha)dDzWn0zG~O(^_1!n0HYp-( z+;wPIdoFgQlpYV!10V>5@a)1LyGBMvoa}miyp(bxbMTM-FYNyx;V@TfYddyT00000 LNkvXXu0mjf90!wr literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_go.png b/node_modules/express/node_modules/connect/lib/public/icons/page_go.png new file mode 100644 index 0000000000000000000000000000000000000000..80fe1ed0cc75fbb67e9398ae686641f8fb287238 GIT binary patch literal 779 zcmV+m1N8ifP)JNR2Ufr z!Apo%Wf%b9=l#x^8AolrB&K9H?Pg_|78WA8(M3toqE%3B#7*srcF`i*xhupr27%Nr ziguah1+mN)U5GNmyEfQ3-e%_i&-vb-Co#(>FJ+EhQEwjRYVQ(&UYy{U@%vbY||>@4x=B^vIqabI?L* z;-S&DS^V3-ni4^fl|HMkOEbgX)(390>A}|VIypb5Xee4g;7ck zwKh^A3Mi1Mh@eC$5lV!}Fw%sP623U`g3pd_Hr5sunLvTskx4}&Gm%Q6L}(l4x}jCe z*81q1_4-O*ffi~_nMslo?EQ8t*&Ec(pzEw$vc}pKn_Qp0>D7Jr>ATNC3w@9f|Y+U&+)#!t7l&wKp+nP{PQsb+fb=Yf!Fu&5j8vpRj{FT>jD z>d>$sx;A&+`n$HcF}&sYKSyR;=(=9tvvOj@hUG;~4qTYk^_@E=?$*^_pVh_bGnOt~ z;pEw)j{SK$XVc;qy181rT655gW9NG{(yeablViIL>cDI_ux8m>Pp{tY$J0lgo4#ax za?j0EA3s0S!f>{~ykN9h_RhM&g3K(E`q(dE(Rd49+%xMeR9{qlWnmd{s#(SQ>PmFtSQqUjAtB;_Vvt6}AS_5YgM`Uqu`yva+H8^=4U$e4gHb}u zAQ2N{V3A%pO|?Pv?tb6z=jC}SiRa$G^v3q?*6XcYz$p|cq{uLj@#~Fi`J(>5{@&&N zy%T^+;>8cXx%|o77anP?&W1?1A(>-T49z9pyeCl@7YI+Si zKti7=B~``}TImz(G{0PnlQA3P#MAd}sorMjkP!50B7$nAkU^%#nl{Q9lW0@}9fE-> zN(q7tRuiC_T1r|BBtVBTlQ2+70$Rf;eF`Z;lx46Cpu-rEgb)EBKq(b^W8l<^We(`D z43?0=01z<3G6+UUv6`CsWCk6^93!#+<;ws7007{zS3k2k9-zZKFO~(k`>s0y006+1 zgF_jyIhsL-`FMf~JL~C=cV75(CrJ|q;MVO961G=O zm9d)YpJg5g(4i_HKL75eSE}mq$Y}r}hyVdcV~p>6a}oXr80q`oj%+s700000NkvXX Hu0mjfPs|!l literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_key.png b/node_modules/express/node_modules/connect/lib/public/icons/page_key.png new file mode 100644 index 0000000000000000000000000000000000000000..d6626cb09eb11a298b90a8a27b0d8eab41f49a82 GIT binary patch literal 801 zcmV++1K#|JP)$lC4gU2-`f*>nhR-;k6IP7e>YO!0^w)WK%3$w02v-#>5Ep64PCP| zJihT#O|N+nT7XR2h7dAB?UEAOhJF^mol1i`QtQB`HSY}RE7=r! z)zaVIHr5?>v2Gz&fdYw&2ug$!p+txby(aWZ7(4QT)l2`jX7eMQ{>)lG6ev(fWKxmH zOr%mM5$6B%u~qGtCf40#`mbGj3s!n+^%wnJ&#rl>g<4Z)lB5J6f!?|AP275)Zswr* z%T}4~{;_(?waU!#?JabbF3Cy-kf0{R{z}6$e=5yMQKt3BPcl2>zoTPMqMwF;3!_n|>sT?~bK_-2O_m+o>GJ6h zt=+g$4n7y%1qVJI7*5Yw(hqM=JusY{d}*?U(Oj*gT655eZ>Ksn(qrd7v3}DX1}C>` z+X+8@+4-pVq_fxG zlU}~Ye!0+%>J+pPk+0wV{GM$QaYM?5ux)w2z59=S&H2+K?;gH$bZGzL&g5>G ft+noNiyiPkP9r@8gT|RZ00000NkvXXu0mjfuqTIu literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png b/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png new file mode 100644 index 0000000000000000000000000000000000000000..7e568703d6432c530224e443771a04fc1e2e59c6 GIT binary patch literal 839 zcmV-N1GxN&P)73{`^;G#xwAtHz%LU)4b zqTRU=ve1RNa3QT=ZM7C`iJ~QFQ*9t7<~pX$d^7W%^M8FFCkcQj-~0ZRTBCB(J0^iD z-~e!d9LR`f3#|=(>$bPvx_D-~2jC%pJ=n_e_OK zeJ_2b-KdDDh@@UlzBSMC;EPygH_MwjWBnPGQegihBV73D?-x9PlHL9A=(Vg=8^d<4 z<9r=UkxuIm)*CO=9e###7PztDxUv}e?$0)rQicmYhV`pQ%S!g@;K(?TVfhM#E?bM| z=B0gfb6h@a8bf5FVT-SV~6}?X}9lK@@Yynoty&1zdZP@?RfODsl=2XzzU% zS8gIN43How+9%bK2S@Xbc`O>`z5`%^;pXGy8^4f>9^3!Sp@|O&)m;dOa3q6d;4P-l zca|=H_{G&m?D_+&-}r{u-J$5T=(X4R&)q|O^gN8cgv;s#@5sEPT5_Z)oFo9Ac>l+I zc4ng5zHpps|9)<_Rw>5bKzE(M1j)dFWI_%OH$BJSz0?T+02W0)_a>#vFqb!*d|5wB zzBUN|M&ty51O@=i?kiDrjQ{{}e|^rU?OS|RdxxP1p5mAw36cX72#`R6UsoeCQFI~! z0ATITp!vfeYyQ?Dr=^5BAshfEa0nB~JG?nUa2Aur006MC*<9`)86SPS(W^`H2n+xi ztOWohsFfVfVWrI7PSKW}BmkyPoj(-|J?ES|BGd-}fIxr{00@ANnO*ZR`#)pee4I5T Rmm>fG002ovPDHLkV1i|Hc$okI literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_link.png b/node_modules/express/node_modules/connect/lib/public/icons/page_link.png new file mode 100644 index 0000000000000000000000000000000000000000..312eab0914ab59271384686255d1be913a6b3add GIT binary patch literal 830 zcmV-E1Ht@>P)VWgGzD=Y79#JI$lhEn`|2MpRa?Bt#-nSD~P0P(mbVe{KrOBoKnSsk>m|ML{6l zBosu@om4j#WzNLRAk+{k1JRvL(MfE&vvbb->v>W{*z*1_uMP}0cIRX*?mz+wk%*#O z%0D-+$B*g1nRkvI+_3E8Pr1NC6@5M&4vWaLCnNlr;lNlr4i91z&)eBGqL{L{GNu;Fof}GS9{gM5BJuH;2QWk8yuOZdB3pGR#s8bd~ zAmt<>3Q=YH$t5YJ5;7@+8Uh6=ktBgY6#6Pa%2F?h910?U8cLT43KAj$Z1*==ra&gILO{WkHfs(--F=bly9l~${z@AT>V$oat!YAD@M zBE0v_F{`g#^wOSP-u~!wvlmXdd*uqFqoZ0^{&nEMDU+=!>({S0wrQhFmoB}Yq1)~0 z^{A)L8Xjzdr(W4_exYO6u3a{4*kIeXZMJUR>Q=ksjW_p!rAwDKYUs90>6Q|C>56o@ zbrSq^Xk7Gq#>dAsn@un`Hz$?w$;Ss`%jV7L%9ShgHFV~C)6M>B`Tp%|nqPc&G*A3| z)Qe+}vT4-x^t1~XE@(6wR;^lPWMo9n*~E!cy~)YRsT2{`?fqeIw-e7N@mOA%UcCIq z_kH(_EK7|>pM*1Wt2^DaDAp|cvp*@(ZZDKpYkKC^?97(`0sb&XTXy7N#sB~S07*qo IM6N<$f;YmCWB>pF literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png b/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png new file mode 100644 index 0000000000000000000000000000000000000000..246a2f0b426faa0c7f5ba009e32b1deaf88d1288 GIT binary patch literal 813 zcmV+|1JeA7P)otxGRZMDZ!_a~nK|b_-`n%VosaL{KDuPV10`(1LIen8kX2Xff$3BE zah#djvFGJ&eE^89Pk*-O^+&d>FC~^GjRYVQ(uuPJyS|-v?9lxA-+tM5>1Qu*n+Ir1 z6KhA>X4$XDH6?-|E5oe1E?pQ5-M;2xw_ex!x}I2+b=}mPFW$U%^;o(Zg*LP!K^1kP%8ynsD^= z1y^6xD1#GLjO{VLdh@0GKY7;d$+NGukV)GRLPn^=q=dF%B#XaJrNP`0E6=}e&Gj3d zKJbQre*WXt!60_DnIzgMQc6S#fvjXxsE1v7;T;njHkdy2miIqAS(nX~o%cO+q+b#h z5tIleLWvL=dQE8OC#{%y*Tnku&K`Tuub&_ELI0t_ea{@3f>Jv&sYqld(%}3_GY3Dm z;O{3*Y?v^A`a|D;^qrM=ykI)U6QHd%WhO~VF!SGjGn0GOZrc3mGZudNl9{Q#X5&-F zuGwVReFLBjE5jr!!^-5*L%!I%PkYH#Hs5rMrEBl^)9)9XTD;xjHFxVZMc3~Dw6#k$ z(-S}RE$bgMHv6Z`mS5|u$$78sp4G-8b@lVkl`HtEv+MGn!F&bKcHPi$$oP_;=BrPf z$(~b3&p3CsuQxhoV$%jIR;`lB-s7FDX)xCTXuJ7ZyIQk96uIR=HBt%-P?N*bp`)EF zq14c}QM+O70NTOa@V~_)&GMZ$^cQDlkyOCa(H3Mf+6xhCuZh`VSN{cQBl5Ys9{cp( rh`2H3A^=GuC6HjQ*7|*0>;m{7QlnX3z3MSD00000NkvXXu0mjfR5FYo literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png b/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png new file mode 100644 index 0000000000000000000000000000000000000000..968f073fdddc1cc0f0800b1ac4001cd9a55f053d GIT binary patch literal 703 zcmV;w0zmzVP)AVs!l4K}n~L(tL`6d4Up4iSWnZ3Qg~4n+_J zDGk-qQdogO5JUtO-d5pRp7Nd7_r1^a|M&Zq%mn9Oe((|e0sw%Ur!K7T1pojj=U#f? zQM`qbQrM^DPkwa?DK_be^~z<~RgSMIa<`xP_4P7gg2jCwJ{9^k!fsU=#Ti|%I3p;>90Qd+7|~0h&mIklA#nb>ATL2+v$&u)OBgB z;nsHb)I&QRKeX40H~~cIZxCd}5C} z=79lXoXK%6YlyLtsV$~bSm?Upq|DJh#{|*a7XMm`4QJWZ>s6nL2R1|&J z0VPEwJ9?!n`o5PKAjc->P1Gi8BY*%!5&FVp=#)$mMJYul1Jton}gujiUf??eOy!x&!tsjxy;=Q3_DdcXx=a^OBhW0N~`A@4xB0a*%F? l+@c^sQA%W+?pa#c`9H5UNfS6T{e=Jk002ovPDHLkV1grvM=byV literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_red.png b/node_modules/express/node_modules/connect/lib/public/icons/page_red.png new file mode 100644 index 0000000000000000000000000000000000000000..0b18247da5850f3c2486373a3e179acd2772e8aa GIT binary patch literal 641 zcmV-{0)G98P);68^@7JE5sw#jpE*579S@TLkU(6yap1yN*Zuy>-hV%Q_v4Ar&!63c8OBr(ZRhFu z_kWs36-AmgZCT>x!RqM;Zu9tqvoHI~k@UmYo_g(*J3c%2{N8}7I+|qKPQzv}7t>%W zsu&9G)UmCzkDYSw{fBnuW4j;1fKV_nicw`$8C6D=F_qu`zUiK$2Oc?5UVY+D(`I@R zW`KlwqLftWHH3Z2_XVNfKn>VgT~k=@- z+N>c>0|@A_HbI9Jn`v0~7cfIF(TS69zaomDS1QtgvaBBfGEPLHccO2~3jc>n^6}^HAEh-2#VxC7YYcDXv!L9X= z-R*SOUvIs;n`8(LxP4~^2|JsiN^hq6cU}5dn4v1~Kl{eT7pm&f$PoY`hyVe%y8G*S bxB&kH@RuR86sIAS00000NkvXXu0mjfZBi!% literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png b/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..cf347c7d4685128a4a447abb9fb8e939417644f4 GIT binary patch literal 858 zcmV-g1Eu_lP)`6pHR2Ufr z!EI=jWf;Km|8+n2IrHqe<9xxFVk)&(Nh?w$Xk`TAyvb=#e=0aySC z00NkRDM597_LiNIJ2M^qhuTvB004REvvU8@of{r?P8tmo3;+Pk0F0@*jAMhdOkS&1 zhJPPfQa;pP0|4+Yk%#j>X}o-s#EF1_DMV93FsfPP`G*>Ks>L&)Q}w2g%slu0kBfW1 z+*$*0BC^oTl6>OGIq(9BgG4|C90Dk-N_mPazGrQ7uHZ|>BLD!-KmZ)z1e^#?1Sf(M z!6m}K(^b|i%$TcA5bC}r$tAA?0C)g1@CgWliJ;NAk&ZF+-w#}$`-3nZ32C6IVKrHp zr+(!L2hRfF&AsTw>_@ z1y23;E%Oz}?q^Q2d($ayO;-sON2t7$w(Z|o0Pw1YnSp^}0PI+I5HnDNsFCA?oorkG z5sUIGIq=FSyxcj+xlhkm0en=52Bx3@02o12gdAU$_i?v6iyFMuc7P9#zQ-Hf; zVuV$t9P5`m)F2w1?t6{<8%wk{w-PP#Sj#%1MbsjrSI6n;D_@8q9`~W98dNQf$j=iI z6~hpgww&be%X_HI50Hhx@W==u4TLPB;ei-J-1}G8wH}|{i#Lk-WZAyfv}k4y0|fvU zZTy^$u6L>2nWo(NDSV2@MRD}JQ4(c%G%=dG@_vxH?>gcH#*Ue2HC}9sapf8X?R$Z;XEnm&g zW99mh)5jNw008mK8)r^`_{yH0rNn%u1|SpC(tjf#om=+r#lh+?Kb>DVb9`|C0Bvbv zN3U(>f4-tAC1hosRoA7p(b(hL*V}(j>ug<`&U)|l$6o$)!>PBQ9RQSwn9asj2p*|xhU*R^vq?*Twb0t!lm5}`yW5lRy-U0ZYK?8to!;o!r!XeOE$ z0HB3T+6EEoI4PlR=wonwqJ+TvCoWh&$?CAPVYcU= zD{DS0?AkOtb@-hh^ZLq~FMjxYf19X?pa_YqtgZGvv2TaxcF#KT?O%=_*a-kW_;N|D zakkWsOe!)HsT5WRBiC+p;N-c>0Qwy(1D2MDBC595oXSiR07)sKNk-%9*rDBOO^HUD zZW#;)R&EZpqha<(HK$(tZYU#V29<@0qCXgU{gXeGpc_|pTqQD-WO|}%yKZbeX7k*H z2W~CK$v8NBAq~czrc5A(v51g0Wma7`G8}f=ZcuAiYYxZan@gP(;Ku66M6?bquGiHe z3Q0ya)%Lvk@kLixZfZyU@#UFbv+>pYhcj8TRKSr_sWG8i^X~UA**LvbD3(_Lba3xm ziYcpup*A9qJ$?AA=Og05lndxfwr`!C+O~h|B~4 z01q8H`StcY);%&mId7_+)76ovRpeNWRp&4M?#jx@|E-)x%P*A6t^fc407*qoM6N<$ Ef@ddc(f|Me literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white.png new file mode 100644 index 0000000000000000000000000000000000000000..8b8b1ca0000bc8fa8d0379926736029f8fabe364 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-&H;pyTSqH(@-Vl>|&1p(LP>kg~E zYiz5X^`c$+%8#zC{u)yfe-5 zmgid={Z3k(ERKCKrE7DF;=x4^O+ pzO8rLO8p|Ip=x)jHOtWj`bJBmKdh_V<`47(gQu&X%Q~loCIFbEay|e6 literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8095e46fa4965700afe1f9d065d8a37b101676 GIT binary patch literal 591 zcmV-V0~O9lw>B8WRlD)Gm}Jrz31u-X&&gn2lvjs=i{7nIaL6v2==uw+8Lcs(8j27 z;|c`rmSv@Lx!heopGP^^Ieb3f=R!%Lpp$}iMS-&P3EJ)s48wrJ_Ni0~k|c47D2nj= z{jS6bt|kFpFf|p5cM`_&0Zh|`rfEp0(}=}lT#(6RpzAsUfxv^LSYX>WlAaN$>)*J5 z0#sE+JRUD8iT9*fz{)_^7@6P&!sEjTcD+I9Z4YjT1`wH@fV{cEvneYGFU%maIEU2s55&K(LixD|{p-uiS@?KNj zk-Go8G$hH6g002ovPDHLkV1hVj1#|!a literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png new file mode 100644 index 0000000000000000000000000000000000000000..159b24075191fc259cfd80c797a1b0d74c168422 GIT binary patch literal 664 zcmV;J0%!e+P)7Z7t2}reCh0o`+ zAlt$F2tW%oO@m<=(B8a-_VgLl#~yUMUDWG!0qFPppd^03e+x1WpkO1NhIaKD2A)-@ z=Py8(Wi%R%JtYZG#sTKH@6Z+&!S3Edf8jFJJNKuva#KJQD3X^7;H^fd2di znEN&c58aUG>`>P{Vqq$kLb+TP{?I!d4(|o59X_%|nVEZq2Rk60n7072SWJ{64CV?3 zgS!EB=eYxwQ>P2&$}(iT6UMvuFgHHIEdNA29!EBtg=v~X!DxxEH~}L2zn|52%xalaq@DTdhh{EVwv0IaQ=!?daer zTKp4I`l8SDt;d{8Q`5Ko;BXUi&oAG1l4}59P-{|^S(Rmord5s6qsh<&m@Ab^wqCD) zHyRD}lKLDzpYN&@q5&*47mGzGiqcXpmqR9#K|CH8kXS4RNs`(iEF%HjP%f8ItyaZK z6$%Apvsok(2>~dTO5jTZfq;N?0ch4l01f$k9?4{~Youl-#x{UDMr#AFIkz@SDwPtQ z$gQ^$2|*(Ps9LQiav_8o8Ne<=Zx1*M*syo80sEO1tB%>5 zfdHB`1z+!R@?ghPRKmL)hWEvZE$=*54ose*0JiUNTM_)cMDXhxEKg(?-pD=y<)L4J zT0dSyD0&NhJ$^_8Ko9uom%-ZM4BTM{Tw$9qyPj=-9W;N(Wi@3*-Q4pq`Gcp}^vvNr zyd&PsmG>fpCSZz?K}UIEd;HGgG%0MG>ymxKPwy{>wy(m*Atq7)0000~7 zMNw2LQirBVQoa8G3P(rY+l;L4iy+JwSqmy$9JlSkk z&*$^Eg+c)@!R|v4gdc8+TTn&eWHO0VD&>$!B%o;;WLf4CNs=Inq9d`xA4otCWHK38 zmc{pkX`0Y=9g3oGK{}lVy~OYL|C5lQ&U^l;wrg|7w=BcA9L4-r411?K7f`@348&rw zXD#uW)DK;H`hxO}u%=@Cj{;#u#_;bb1_KgUOT2Hp6;)MvC6P$vQP3=g1O5#aU%I!K zZ1dc@f}YvG&*Spnplm2rIp^VdA^HydZ0X1axdms2!RKi5x-SFA4p@ zC@N|PI$ryHL@t-(!zBsf2-+sYAukhDHU7Lxm88-p zDk^c;sHj}OKUc4lGZU}6umlGVNAJx0%sKDOFwQx|V2pVvxhYKe|L9TNk!~md3BVrm zYPDL8Hk*yU-ER3~LGwJ7N`0ZV&nOhBI{~~A;@ND*=kxg?#^W&`4u`zk?Mg_e)8XlK z`T#M+OaR1!<#Nf_>$S`xrqd}OjYhoJ>q)?3vEX8pY&I()ERjfjrXM$k7e+-Qs3Ihj zNyOuEQ2EGYG7ro!o6VOBQEwuV2z)*tR8>WxP{616FY)p1Pn1d}#9}cxolZC$4n(6- z35hJq0;FlHC{ zp*iF(lgUK(E`($(s9pJ8Kn?(M734H_63WHtf}6SQQ_MXEP!#0|&@>J8dL5TfG&tBw z#tYn{TCGZvAr>cca%YYn^!t73tg8OOJ2FvJ(`YpCyVZi*?Ur+1uUA$hAg8-aK)c;e zQ<)!XwHh|n&ND=$@^)>aF-`~n}#*WMkD*M|f8r$i*z7+W! qF|A!t*4fE(R`<_YIkN&?Jng?3oQ|aAqClPi0000t>5xmo{nArfL4CJwMMm+N`pQ3p^Le$?rMud6Rbxz!-yG7bz2z$^USP5(;udf(gfQ zG~f68y^)EvcNWp#bUoDt2=h+^%o-?-|mo~iieWqLNP<0m@2PTB7ftyb= z@H`K$>v9Pr5X`L|rw&CEN2(9SB7A2SE;d|j9@*F}sd(@*2l|P*fWfK>1drZUrtUA7 zNXO~pKn1cjf~~TLbje1g>EPPzN2GH#UIBxJ{}S9=E`{zs-w#hO?vcH+hJxroI5v?j zD!4lP0WXq8zUx3RAP@|Gq$}6wXCjFLZY^YSWBxN9#&g)ro$%5}aYn#y=tJ_aIT%4d z5d4u`rlp!};XGmbZkJE*kYJoi&N0pd*yxY{0${xD;;Q1h^8f$<07*qoM6N<$f(}t7 Ae*gdg literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png new file mode 100644 index 0000000000000000000000000000000000000000..0c76bd1297751b66230f74719504b2adb02b1615 GIT binary patch literal 603 zcmV-h0;K(kP)^~*-1fljz_B$LUvK}k?BNXe#Y!m=zM!!V#}8bncK5m;8VP zw86G*RI63?Cd%b9bX|ueNlZ|wR6rj|r_)VIP@r2imh3?SN+^{|kY%~8B{maJ@F*OK z&VH9LwOeGt#DRjj0~v~8`>iO7!Ybi;zE$va`A^T#yW`y44;k^#O~K5*jD=qcUhPSc zvyy~q;5H_1WT1l~cqje9yfa+l!hu6xjdOJ8s;8E^+=QQ$tw p?%p!Hy#YapB=@+^9(46X{{RQg%9y;OKjr`c002ovPDHLkV1g7l326WT literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png new file mode 100644 index 0000000000000000000000000000000000000000..87a69145075afd8f8fd8b391c5da1249ec8b2889 GIT binary patch literal 587 zcmV-R0<`^!P)LWh{^|hy<@Q*xw+qo|KpY<+vaXbbW{L4q( zTsjXEJvb}e%bgb=o%W0h?4u1;^bWTqH8}5Th002ovPDHLkV1nrS0P+9; literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000000000000000000000000000000000000..c66011fb0fbdcbf210483d676b7131542a0e282b GIT binary patch literal 592 zcmV-W0k7R5;6x zlV4BMP#DI+Z{WQcKZBTk0lfkj5F$ztWhP#lcuyb@0@rA^#Kpu5KLA&Rgc}o#aSmis zrZC__xY^&#cI&!!{c|4Q_tcec*#b>|Y15wPcY2=o3;-Bl=(t4;6Ok*pL)-{*A;GX^ zS(@WGp6j~k1wBVR9)BB_gar`}HyRBXh7nM!)u5^>N~MyN6bc0-5{W?44iB<`2biXb zR;wk?jIQg@G!5l)SqhrXCU}x$GU-dY1sra}0uCq@153FUULT=jNwSk}0WBjKz}Jdu z<5gB*<^XtpAmp3m^ZEXQZWd1krhft}CoYaF4cSMvTJ01}X3X37KYdx-D0$c{doUe8 ztY{vlGr-e*;N!WAV%_hgUawyYrhegW>^F)pv%uUTFslHn; zvJ)l{%w(~{!O4`KTmK{Q{zCYltLfs&4?nz|6IdlqHCvX;|HGv~!QW?8P~_d#e0$v$ z)5XHEz{3>qMiH`1+qNYf?huS+@L`J9_$cjJF)Hf?@pu;)`9}BXwGUM{2!{y-4|Z{L zG>z?O%Cp8P5T#j1DID7u_*(Jg?7iss8AZQ+&;u_J{FmILf((9eoiL5nGUe>Fgq*U$z0000 zJ3A|*qoWOonz+4ZQ0KNhDB07SX1?#FrNy8%K)_l}y&kh`*KYdy`Y99&tgNgMLSSrc z?B?+B@HO@P-jS~z2Rgc6yy~Y~%>oJpBxsb$5<&nRLqiuR7K=@0SZj~jTs|sv_jWVX zGe?WflejOaq|Vec=s9+ahmXbyJ|T)Sl*?s82sr2H?Ce~HD5WI+Sz&tmWrN()wI2}+ zKqg92t*l^-#ae~;9%KFlWkmwnY=-UK`_|%ICZ#P1gdjK<2n38VXsuC7{WiU!fZFmm zW~Sda9(Qi@pxO}$ARY+;t##Ao27usOqNt7Hwq6K7G1il@xitj=LIM&{N&#SuX;x4x zmG6FhCg-$PI;hQ=;1iZ>F>^~@)IPi;l}fX?SZ!QiO=X<|pSVkNpJuLHzW(FT_~W-v z?vFpkyE>8ee4d=7wKauH5~dd_M7d2Aa=ICC{Nj7Blqv&DQEP#j_VeWV&WXL>c=LLK zsmYg^_JiDb;%U!UxO%qjFAvsDFj-kzT2$GbV(ZopPM$i$z`!7jvEk07BcC=6FMt4` z*0u3Sy`0b~%#(0000K literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png new file mode 100644 index 0000000000000000000000000000000000000000..a9f31a278e17993d8d4e13beac2f9d5f7b42d08f GIT binary patch literal 309 zcmV-50m}Y~P)sF~CC`eaI+m%Y8jfzomMvZQaNUIT3LIrJ$h)_W{ zwF|LDNlB-g`Hb_G$;>3F$9JF3WYR|3fy2C+_wH}*xp!_4fF2UN4lt#d26oXwru}hT z0+0%Vz-l&|Tdh_L-Ng1G2*RBtBncRx;99K)&+}s0whhxXp{go}$g&Jk6k|vfypI5M z!1sNGVaV?!*L7i87Bo%cfO@?S`bajL{R<($@$|PtgBRcCGIJ_2a|&kO>G-s2aR3E4 zjssoScUa;zIdOeGHBnH13G)W-zt$kUQgNfG;96b=v&4NzRt&@7nN%v3HsG`<<+F$cumMs448N!W3r&2Z*b~D5^$^d6Jxn@SFK5Q8*uKSR7x{I|H-_N1f+AD zSYC5@2K4OKL$==F9U@CH;ONNL(W}oZICHn;d?~pw?GRIsH*x-68Oy6SuK`)`{E)46 z9^3(-HXa#X89SBv?u_YP)WjsQrp;}0X?Bxrvf12IKW8>3t`e~W9|JS<{btTNbNT@EQIWBSNJTX8AMGXD z-SsH|s#>j9Xf~VMtyT-YMD}5^SWHTY5->o`k|d#AE_YQd79j`%GMS7FNvG3b7^Vy9 zn0HYCJy5MyQLoqKnW|JOp-?D*<2V^msZ>BOv0ANd2n7t@{=V;sZrQ>3c})5_%ms4z z7!qXwHHe~!QFj8aR~&*-3F?O|;#(ESIXP~Os%|~y^7c15*q5`gz2-5ol!fU92NIGT z_ves+>+Tf3gfcL?!nimYmR}cw*|BGULzI^7!;k#3K^YO#;!+vM@N~(99+<;fdqr zYPJm+pXYFYk;neQyXXEcTQDNQx57i`Okp9A#n?<7!{#tnKJdsF>utb@JH7dU01gfL zEK2hoPZAnO5+je3&^i*hWM`qCW^vLK!O*?U-#IvXV?#6koWqrwnD{j&K`7N>^tR3G z8zr1(qVOzcF#nF1&0MZ5C$l8*E^Uth0000zE0Ay_3@1Z_7#f-XWL#E{8Al7>L$ z0Rx7lnddoqAyfT%&#`$;v0@*5YdW3w z7mLNoa=FAshK% zDiy@zakyMAxr-H?iQDZi^!t5;Eno2A=?>mMx`Vg(Z!?<53LHLvfTPa`$mjDcX*Qdv zR;ylN4OH+m)fVX&Z#yZpUae;ss@a$K&})gHovkhr@w#xyPVlfVgXti1_357y%I-UHDvRWYvPEX+#g+j4Q9ayba zh7uQN1j%HQgA=Fp9DfODAU^*3*FCs^6IpO7xg`RUXyP)(;=d!ly=#I^l3e0Cub`{H Z`5PU3+D2e&<<>s`J(VpX#y^kqzQ;#=2x({YMw9Q&ndHT&`BD$#%Ql?{+)-OuSA`r}MWJ zVg+2Gc(GW}a=BERPNy^;kEz$|38dTYlFQ{%5S!g@|8f8D_!Nu9_Ni2glF1}xG8xi! zorc39&F6EPOeWOt_XS`W2H_Bo$MXugy}SEctJQj=(TLXTHL(jRXfzs>NF=0SHk;94 zF!&HjdZNX(3U3;LY64IMX__Xv%_wjLC!J2`0Jw?X=zPK$C$`&dYPDKaC={e16bcE@ zgun^<0k;ak*=xLE)@(Lqu~MmsFoMCLY&0Qog`NO(h@kyxaA%EbwJLy8sU*Vi`~52K zX0wrqW;_LmMq@evX4iAM9Od(Q0eHP$1%L|xAh@vrqB`HPQLon}f3aAka=9!3hr=O- z5F9`#J_7Jhah=U(4RjaRhkS4Xkk98kDz-`i!r|~~AQ1TFcDw(@<8g{aBE)l)PNxNE zI(RPyc>9e{@WGSMU%i7*v{!&P$WLz25)0oc=Dl-yy%xYZAm4b-rttL7UjR#%`#j_F R;_m(?iiXTHIMmcoLoO94I8;j@ zv^2DJ5#orqydFJX|Gm$_Bi_vyew+j6{r}$Qc@D1%fQqeAhJj)1!z4pP83k2MV2~s! zSt^w(<#HLFVBg_#xz1W8ioi(WY&Hu~6zil?DI^jJgu`K35(hkP)H%@Imesbg#5!Ps_$Ni*SiR8&sKb9?M`0-mH)gtg&YgRX#*TXz@Z+| z;|2H@xzE0TfuORhuO2k6#K8#sW^J`mQ0+E@$K`QkFV+DTlI$w{GJ;zid{*v9xeIe_ z$|Bp`@iKkgoFK3{4Z)#DWKV~W4K@5WZN+Ql_7%YxNqSx7%cWud&cX>)_PvD*UzxZg a%Kia9Rjz_59@~-t0000)l$0ECbfb-0$}>7z|u>IvuoHEmW&j4lzv=KA+EpIObc7e7{sGA)QVmnM@*^ z%|h38^m;wC+ilpk%>l#V5LCqP_y2_Cayd^XlX;j*r54R*lW!zbqtSpQNyz8(JVmWm zyV4S$2{Uhyc{Cb0QQbf{ZGT{Kr zvJi{K_&f+q^Pv4MK$hhS4TgFj_FD*rLOePdE-E^T7ZzTFCRUB`*?9&h(a#C!-v8lWG#k3AOJQaUey6Oasked^kDPe=Khg@7s584 zg`XfS1)&u*_c;I76#%`kkBfiZgKKo@0)9d6vZw=ExQUtV?eW{Y1Xv}=4X(2zy85d> Y0C^(qLv?Ui{{R3007*qoM6N<$f-gW7od5s; literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..b93e77600def75c9a144d3d0a5088a62c02cbb0b GIT binary patch literal 618 zcmV-w0+s!VP)$>5Y&axjp2O=VLu>*f>1L;s0)kkvKC!*u?s6CVL=HJ6oP~pNfZc; zsKr=bq;7MITw8NXw{SZm%59TId2x_9BQ zV86`NuvGI!>o^V!Na!=$7GJE{Cq`b+XwknM{UcGHFTTfmuS+ zm-zYC!P3+zmY;SG$?!fYkOih`QYaLxyF}A86h$GGN}kFj)_o*0e zjPMP%zTG7FYMAfO2Nn1D`D0Cj?Wl>5q%@CE10nX)KxpNmwk+!IWkzywiYD( zqUXiYYIq3qcRyMGJ;IY`(Gz~E$J$zu2+R{)xGlE*88b3WK6V*J>}2iPY1HH|tER0W z_+^^FdppY?o)Gt5M2`%xwRDH@R3G}^i1l4|6uchm0X0f!@&YdVLB5K&dd7Rv{)DXX zt^&vP;}kqj3f>94j+4xd93>s|Q!Ezi>?r8(Il$P}PFxSqu{d*!Y%*#cX(R0f|Juz# z3o0_xI14Al->1uky@W-rCI_%l&>PK^TXNSN{byMk2AI5vbwp!K-%-@!-vPR3iikL1L7HA!^!~ChCFU#lnGzp88=I z67V8PHBo4(l$u?-AKmT8?#_0rKW9dUNRbpLc`}piywAM9$xZ-3fR1C75T(BjCn-l* zjUcci2oXXo-}iqun@#)+`W@kL_-U&|2>MxZy~3IdmRm&8b)9!2%ksg3R)nNnT*TJOC=6{2hG86Dz+<^p6qfG5$i^UNUh+u)CD7O2 zK>Ioazn;U|+X0x$=feveYZL1W*Fm%e5P1sajd#eW#^5(ddx76*pt$^)b}$Q4oPabL zLc^HF>Z{8za;f$LtN0P$6C?1{X*jtXkRJ8IEeyiSzencvH3Ux_y>y^}wfJrRCQN#9 z?&e+C>sSAfrE%mZD5RfZ`gSndD)=P?+nG5Oq$zmY&-v+gc7R6c0u8^Ke#|XOq?gF@othF3zFpM8Il<8BJrWqBtF>b#_ye4{0)Xbu6j&@UIhRE002ov JPDHLkV1nWI9dZBw literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png new file mode 100644 index 0000000000000000000000000000000000000000..b977d7e52e2446ea01201c5c7209ac3a05f12c9f GIT binary patch literal 663 zcmV;I0%-k-P)^@R5;6x zlTS!gQ5431_q{u#M2 zg&W%y6a}>qj1Z|7Vu&-DW6d~k-n;jnHsjb-q#u0C^W!_5^C=MlKq<8oNCQ6qS00!X z5eI;XP=g!^f}j{hku}E1zZ?XCjE;`p19k(Rh%^AQQ54xysU+ocx$c#f61Z4HnT#3u~FR(3>BnZniMIF4DouI8Hi4u>cAK%EN)5PO(ip3(% zIgBx+QYirR){Z8QwV$9Z(Mpt=L-Or3#bf-G@66}txq0yc*T(zNTBDT0T8rO^JeNbSI-Tzf5!pBioy4NwAN^?iN#{;fH1Jke4Xa`^fR8m z%h6dq%xX)S?7`zae))(Xst^Scp6B8FejQW?RLTM8@0=vnnntuRGBM2dpo>gbCnTD= z^<;=JuqdSf@O>Z8^XdR?s+KEfhDdB_#ahFj^giCtzT(s8kA$AViyTqaAR;KGaLzUU z<=GqA4bRwpX|IG~*x>pZ!@zLr`XQ`od>m(`;jz|M_*1GDO#$7;n74ppb8=eiqh760 x0yt}J1#p`gw$`o!R{d7zU9~!Un@nJV{4bstt4Au+Up@c;002ovPDHLkV1kWhGjjj{ literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png new file mode 100644 index 0000000000000000000000000000000000000000..581843637079359a6a58fcdccf0763690c67b063 GIT binary patch literal 676 zcmV;V0$crwP)_k3`4d{s8lK_6bi^@vq&To98fNoK}7)fx$e2^Y&@<^jR_Ee+8}KG;X`@ z@bCyiolqX>bb1ZIs%QGnjzFU~L8H~d?e;*XP(h(S262}XyZ3a0h07r{KV?E70l+e- zE`%3x|M5#q+;HOC(h@A^M)7Rn13dm0&>K$j%k_F4wOWlsNCIH+!c_#{eS&TL8v4yc zcpnPEY`cQzZ$ILq{U-MA6Z6Z|1p!FZjQ}tXSb25J@HphEqX-6Hqo?-_Zn@{d#>2Ml zJGhxTAd&emK$lV-QK&VM&ix0Xy{GyS3Wp(+E1^8BhD3T0a)m-Lw@Lu4zQRrP)9(3F z^>$hh@N>OAXrmPYunLi|fJ$_*5i`46;M>~*5D{bp>-OL3{+!MJa`3kv~Q#QfQ%c z)1s}QE<_XaYBG;IuRF=td#+}fi4h(6HgoUyJLi0t(*dA^B)%@8kkG&bdM5P5^Z5WF z%d%>m^SbN0XeV)wbUOXn5Ag#A$gJx+7-OCkMM1S%MWIlTkbFLmOeW(&n&wUd&;`>p zVcRy$Z{K0=?SpNnP^;BYEEXleFbq(UY&LrXX$6qkJ~)8+b{=jj3HEXds;Z(?D%}}L zX3`39&dy=Zyar!ehA}e>w)(*vrCct{PI9^2Jpj&OZS8<3-@{0(gNv%1{)zAiLY+_^ zl}e>Ofd4&#Irj#7>=o=Uhv5IJ@?sN0^J|(WL2Uun$4}si6}TG-s3T#p&6GE<<2W)O zf{^Y2HlO#*QDvTp3v&d@;8*}aUC4lisG9(w7@d5Y8y)}U#FwCkqp*Mcgme4{&gGRf zlBfd`nF9cQBKB2_L{F8G2)7pAf$i)Ds`|}-c>pc^LRW{w4SQ)3N^BbZx)6BlCZts! zKph%`(m#xg-q3I7=(us;9<)*2%iuQ1J`oV3gU6V~T}^JU5714JN33&GwEEru0d}Uo U{MPL+lmGw#07*qoM6N<$f^vibe*gdg literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png new file mode 100644 index 0000000000000000000000000000000000000000..8d719df5205f7415ce657e5c277db4533c82f346 GIT binary patch literal 639 zcmV-_0)YLAP)p{{sC7)XB-g4w*W1a1)XtvxrMYa1o?wn&v~3 zHnC|#(>B_M1d`_7gfzLiHy=0c<2kQQdXu*33(xYN_xYW39(cz9jEVT%VokB8|DoF~ z8u%Q5sdl@4VB7X#uh+v_;yOGY&pRi?378ghv)P1cngiAAb<}D#l*?rWDV0j_dc6Zk z-|P~AJZQCA=yWcQjG8fYnimzj*3KqTfN0Cy!G^$7)+bQ$+mHVd1J zvwOR^5Lm<|R+uyB1Nu4vL?d4qa3tn?9H7SZH@~u=fFHEDfSH|bHU6kh0O3%cLdyny z{`9S2Sw~WMy0MPy!64i`jdk4Z3>^+KIL_fN2V_d&ywBt`^IJpxUI$=YAph~5`;xCe Z{s%Y0vkUXDnO6V+002ovPDHLkV1loX8z=w( literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png new file mode 100644 index 0000000000000000000000000000000000000000..106f5aa3611a4807ec8c21701c631730275089a4 GIT binary patch literal 402 zcmV;D0d4+?P)<@FR}JvtGRKa0_WfK^c7uXaFH3q@Y!Hnl8VySc`OtkPN3;#l*y*l23+99h*9JzA00}rAC!#M1dZ#v9YOBH|eC*${MmzzYjBu!!-< zK8tujf&(6i)1biy*F>4{f*Kd(IU-JsG&#b_@NgTnx@40)2@2%c;*=?-2Za=}O}7&( w%_K#(S>e1j&gfY?mR})n>>0+8p`iTe2d1K2h8#$+)&Kwi07*qoM6N<$f(2cptN;K2 literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a1ecba1b60e54f3777717ed105cdde745b7184 GIT binary patch literal 516 zcmV+f0{i`mP)o)wchR-92qq~y6`XqbKmElbB3z{pkZs0VPF`CFvS?7jDn^mFo>d9Y&06* z&1MsS!M-CH3ee+h_sy)Ms%B*ec3R0RpVi9?*mU84yoq(Bw8 z<4(999dJJE!V%pWT~HGRIAb;(#O%2K3?uRpz}AfgE8e9q&OSdr^e^}lC$QXZz;S2A z)w>^oHy>?v)q--`!pmuBe96PxP0u*inQvyFW(llfv9 zXV1s*Jh`y2H%B3ZTA(AzpsQ?hb6_PyZ=c1?_B4fbl>G%!@ubJln=!)x0000#DY{xaiib^#X=YT4@yE_&2#eBulEdzjE`u&@G%2(&u{J-<}d(^uY4W_kMfEX z@!X)AR9F&FL?RJyJRUzvBoeqN{5kY`z3wcM0+du73~_0|*lac! z42Dw(Eg1o{Ash}P8jXrqN+1w`*XxDD;ShmPCZC7#4;wWbHoMvBl$=zF-`?*9j*Nbjd=v@OWt_BgKxP-3wd zy37?ATx&$b+&zRM!K;BD%Okw`Sb@&Pak8$KRX19jWZmC0&n*Ggv%j8nvSPDFw zEkV65AGOoBQ8kf`R|}Px*&INNS%osq9b{Fq2I(x6@xM>tg=vRLF?I`0rWzHyRc>}g~)F_Qn`A>)C_iwK%Z zrIJ;xR)UI1Y4Ozts|-Nho;q zVk9-bX)%F~!;63iu$Fk=VJn3~fmb5S@@)ZqjBT2{f`vT`b2}zxb0$o;EF@G3&BHK^ zc)`1kUzo^Qkk$?KFKHNBD?nP-MJ3b@&4fg;g5l2wMi^g?9qj+~@b;62o_U1_S1J`g z7m^UMg25FX1MJ5AQxAJ5F5WDt=$=-@JV-!LHA2vuxl9kN>PS8x??^AINH6LjF*#nbk4}=n3gfWp$kEX5IpHS zYiQ{@d7Nl&d$#+7-TckP&Q}N91e-C#5QQ<|d}62BjvZR2H60wE-&H<>}%WqH(_V;zPbB1rgSSSC(0? zWlQ#?N3UgnJ9m2C29w!SwoOo5_2Iq!<8vCyEoDoj@#oV($oJEg6Bj@;nD|2g8 s%L|>IZ381yx9RvPhV4J)*SeoEV4lyr#k*`nfWBbxboFyt=akR{0DpOPi2wiq literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png new file mode 100644 index 0000000000000000000000000000000000000000..d61648452284da1bc28b10385f95b5d2bf027901 GIT binary patch literal 616 zcmV-u0+;=XP)-tZUVHjYHp;RjQ0M0pRlXN=mLv{hk9Ebp9&~+Wj-T9IkpzWPWd#fZ)d=zV^~S`;LE*!&u-?g42^wwN&Xr1~#d5ifl_2*B1OoS}CDno^8a50ArfE8;stQF>AP54J@H~%T zFz84s;dO!QJKD36(~!QOg!t_^gfFcSKDU4yK0+Ypg$NT^mIYcQ6bk*3P(lBLh7Df_ zTu=2xC#+-_%)|{Cv8zz0t|0y4D5M`xAc{gwOKc`ou<*&VjUREFHs1qd<_xSkKeTBt zgyCi=@jj;&Ns^GsWWaIUl0Y2azcDlF@u{(P*!+EH;lnU~b|Lv{4|4Hdkh!qoQHiE$ zY#y>KFA0QEw=4Z|uV{0A^`Y=D}hB$GP&<$bi8q(u;p^0(my3Rz7fP}|# zGZ&#uor4@c3q9r|f?H6-UZmfgKx(iV(MQ`MPWB>iC~SxnN5H*zb*A3#zWwgu&c|}3 zn^g87H{pdeasl%Lhmab&jC?lES}7C?4BFDNA<}20hoY@w_IU%i*T;}}wh!589}7~7 z#Ug`-R~4j&+K_y4kW@X7qLr-)S5qVKU)tO;+kXJ++{vPI@{hVK|PhMVVx_`)vx~zUs}c9O-Ok{00000NkvXXu0mjf DS5_-g literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7bd1c9bfd78d689c73ba67cf914182933ee68c GIT binary patch literal 614 zcmV-s0-61ZP)OOAS;jTeL{ZSdz-%)SMH9tDF;N4B6%j=d15J&5qy`F#vB?Ar zqS1nH@%ny_XSI*Y>) z1f5QYdmzT>YciP<3WehS<{GovEaLGv27>{*-7f0&I$yJ^L%ZGPv1YT$V|u;*+ZCWz ztHI~CDVsuy($SfR6-`N~K?9GTB#l%%0h7 z-q`K-y~E)+s8lMyTrPL8^_pUo)9G|SluG5pPqw6!LJB_PzyJUM07*qoM6N<$f^=yZ AYybcN literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b74cc40f82fc83e4dfa6e9647ccc1b34e6ed7e GIT binary patch literal 554 zcmV+_0@eMAP)Vb2f>2}Fa82O3m(Ob=t*sniin`NpInLyMJgI`saru@YOPfh zy4g0#G*cV!#N%;Gq9_VH9?v%kjS3Rb1j8^;C={$Gp=lbj z*(?%?geA!5^Pok%UauwjA)v4g2`HedDw4_Mk4hhBQt?e7YJ5(hcj|3dNu^TOPGnjB zTTsqd3GIZ=Bb`n=7no)dflv&K(lsWw?lH6T1Yht0F9qgIuzh}ym0%n<3d3EBWB*pg z+G!I0lbAEXyd>k|QNuwr4=KX1D+tLPv)j@C1=N4sA4NF9A>HcO3G47*Y6!+SrUH-7 z1hb;^#S=r|`aMh>J#dWruAEf}gcR(DRUC`ZUev&$Sbh0SgLiTXeeHEU<$_YV;9281 zym`igIE%Sm8DpDw7@71Tv^EB5xSdUR*0$Mqp+Wq8OoaZtOg52&)zZ;;M=7#C1Yd6x svjx>8ad4e2x|*xHHwRjcjs6zA0XLDUqKT6dS^xk507*qoM6N<$f*wetruo^Ag2=LamM1T#~4RmC^m`_ zs}H7d&XJ}mg+hU?tu0noRvyjI&o2SRAeYZFesYkts79I^jJ7!A7%6nJwq8O?iT55M z1OQ` zbL{!Cp5o*IRmE9PInMCSPjTwfT~J+EYkz}tjxY=fg5Yf6EQ@DG$0kMJ9h^&$W}9BU zP1oj2;?MWVkKIEl)r=Y;L^Cx2q|>!)qJJ8zE7-V*-Cf7V8_2#1c0N975t~+&QUpQJ z5(uo(-O_`%Rj@U@t>JYAgd!>L?0Idxtd#oW2gc!jinsAEva8|kF4#Ic**mmml_{d^$s}Q5Q)KCys4sfck5bP1SyeHwh2`A<@N&t2j0^lgHC_^(pAAPCNjwl+>AN%C4Ll>_8Hjda%9 oS~i=#*e)>KsPlg0=2)Qg6BCqJ=F8HdGXMYp07*qoM6N<$f@i)wr~m)} literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png new file mode 100644 index 0000000000000000000000000000000000000000..a65bcb3e1e9613cd9e4950850db43d7025a5fdf9 GIT binary patch literal 779 zcmV+m1N8ifP)JNR5;6x zll@CmQ5eTZ^k*a#RQf}fVOdd`5NJh6S(>6Cf$wEW#f&JyAR#GAn9>Gml;nOf3WCDa z5({5&UB$(IF?G#$x4X@Ickg!Y-HU!Z_rzX=qAq-XI_LS^=lOCT0|0{#{kBkYDS7{3 zD`iu%E=`cDX_^#^#n$5SIQ|4Zhsk8>N|zXHXG@*41$i-7`Jr{8`3S_OEcmY|RF48wXkk?WpdVM4OePBSbfh z#4_=eXJg@3epx~gi>QbUmO}Bm(ENN3+@c?jWiKvSrm(o|W}Ud*?vy~fn1!V~Cl4kB zI-;c!8f~-v)jX82%EG($>?;KSD$64f2&4qQ#=Yyrcpy$57RAVuV#vKMP)0hT$r6m# zc^F^XaJ8R9Q|}x^NoJYIvYZkq-z}Tnj@UJK2l2H zG}p+VvtjP2Z%bsb$~7QLJ9#pC0dKi`ppOd^_V;ME6tdzC0PtV|r=@e@37O`%0k^=5^`%cf$eu00N17Ro!{^30krz>a%3j34C?*{Mt2^a4~ zK=P+Qq%|f;Tc&+9ps;@Mw`EE%rgs&#y=j6BUGg96oIqdwj9-fiy*N(|@o)eD002ov JPDHLkV1j#pUPb@_ literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png new file mode 100644 index 0000000000000000000000000000000000000000..23a37b891c2f5faa3b8128d45373ceab794ca609 GIT binary patch literal 688 zcmV;h0#E&kP)PK^TXt2QS_@2qt2T|9~baC-vaPn=ziepcfAwB$0!O2Q)E}1e8!q+9)KT5JVKU z7HNY}h##OS-BxWHWjD0wrPDeEfUClHs%Q6&2u@FTOJkKMQN|_Rlw6rQz$gPzqGNtj z#ruSeFeh835JJFiM6vp@6M5bXj%k7CMt%SIwfbF_fD-3*Os`9Ly_Q3WQ_SX33E{pX z9_WIeeTCGQ3wYALpBcK+P-iuw;3i&7xCua37k5# z`>c`M@sGeC7cdsdz`aE9lOz!hPholbyz%T85LYf6O*@SA+9&+^7k>+4M8$A8iNQq{ zQvn8k?-+dU`Z@gK0z$EtPV#+`^OH`R@cE-cuE&_!D)SZGxmQxeobP_Zwq zMEgi6ePN45N`|V1so0uE8^}1xw8s;VM%Ai@7} z2-&Cyvez_-O4?6uv{zTaj|YeYEk34i~K@`8YW2g{x* zc;7z3lItpVy_et{Z-ZZ)<@*%{l7Ao8mu@V7*gz<_1##mwW*%LEwCdzNsVLYx2*T-J z#HeQ*_a=R~KDdVNk$EVgAIRl$oQi_(`_IrdJciDpH|Xe{K-YsMtc!cRnFi$qzsr4z z5*$;ecov%3->1{YNy6-Gf(Ecy&_I$CjI#laeuE+S120^|Vjsf)W&i*H07*qoM6N<$ Ef)^4A_ab^avY?n0hpS-#mn_4{O$e%cm-@NH=3`90Wq+3`~HKArSdfX`&Z12 z(CY$VW-MNtXX4xy%yUeE?}*~0-|iByA@ZrwXgph4S*bhcc5{HB!DFVm_v}P*g7+Q~K}7K0lcp(^N@X>U zV`{ZpeIf${R6Hgg4FL^`X$Eu75k(PE6ycl$AW0Ic)#@rR7Z(7;V?i-dR1K935Jgcx zPfkwK>2wGokf!Nih^ARp6-6arYFG#(9Ta!x93nFEjoA==z(g?#sDg?Owk?Mg7K+>l zWYsf(<`#+$h9Sp6gFOg_dd+80SkUpk&xM7h0`Sov9W73spU;GP073|VfZ&Gd$J$*0<~TV5aPS|qWH57|VJz+d0000vYep8SaFV10Q$h+;hIUPX_=v5b}%>Tm<(&j1&5;I!55C)oN0s(P%ZB zP3Q#ahfpXKWF@S?jm4U#fv)QovMhrriclyNs6-G12#3R##4PSZ0VY(dRWJ;Lwuq{# zAW0Gwi$yA^R4RZ!;W+L`f&%x{=D^VK#BBWL4Ys{;*!A7Q;!=dN<&D8*GzGaF4`hV4 zDbY0{NrMX>ZqF=0((gR5-zL$kC*b)!fwu{Euru|XrG<$^n#@)7i_>rCmRxnDq>$Y%gJaCkRd|tE*a2x05Pe!I^e13o69#&RQZ36s0 zB=O|K2Yi(jsMqThn}9t?f5E-)L^naZ+db$&%M$!bCdm=jv7?t_lB?3&%Ltq(>ESw? c;MI421LCcoDG!2@;{X5v07*qoM6N<$f`UZt7XSbN literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..134b6693687b2fa5fe36d48a9c0b8001f937c741 GIT binary patch literal 650 zcmV;50(Jd~P)VHAd+bMNh~)LLRqN>D)-jd9UvB%+hyKX5U|&4t0)fzgD-MPpQ$nHU%yoz=vI zMGb>1Xu!6Hw$NT~@Au<4P-+{9;Uw?&oj31uzH>xX0T7Xkz!(tn|Ed9-s_FqyReC13 z(ll)vW1O{Ck5ihay12Ob2ABc@RUI;zHpaMiyRDs0r>|D4rHw{ItJSJnYjt~jTbGuW z`X(~}?!&86q40R8<4zYw;$qi0^3ec=c&<&H;r`8W%H=Xymf^i;Wo6~<+}zx2UMzpC z*6MZN?(FMv`n|KO3(KFiUaucP0;Z!@LcUNa%8#vGK5aZ>wDgB0Gi=t*argWJcdlMQ z2#MpEX0wU+9&0U?N(F#OgpviU_Y{jYMsj65U3|PjwUOY}lUYj?MTiK_Il}NCVx-Eh zDx-TzMk7se+M#W_>?A1-x}ZXw3kkyz5kW)_hkjsi@RhKadN#H$Hq)$07*qoM6N<$f}lhwPXGV_ literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..c4eff0387d5888c638ba09473ba6d2369f7b56f0 GIT binary patch literal 588 zcmV-S0<-;zP)HU2HvUSp%6 z*n}iP63IK?dpo;h@sj9~pcxo;VVTc-XLiP@DgefqE#NE=@oyUd-&HjLpsLIuSFXV-EMck)oQ(A`s%*^&wf0(rNiNHsU%=0Rw;WC z(kbc37l6fo`-0uR!pYkYv8U^3?nsh^@pw!K0TH3uYyx1_2>|JbXPmfskJ|1YAw9w! z9`N)1^Aesr;y5Nr5-ODn)oOL|CGi}f9!&iVwpK$khlIX10X$H6^A_stBJqvLhU$?V`QXqKme*s~gVDJ4A;LTs_e15jhc1;By a82kqHEPVYFAD2!50000JNR5;6( zlS@kiVHAe7MZY2;Xi-5)WxDDgv@tCUl*&p14T@Z~3ThM5LP4tuQfLu@EnG;nXc<8S z6&3BN?fx-cv-Kp6>HRiNTHE>$X( zD&=w+?GWC>?RLAGC6Yix;an~UmSt)tSf}1VS6N1N2ONORdD? zaj}w6DAZZdOud9Ep?M?{iQWbE5^9HLLZZF|1kdy0Tu4InEuboP9@nvbZ-P0n4AZTy zyMRIxRDmUE#LdqYuD=-Qz4N^bC`_#S7vcLn1M}{J(Wl3#c4VWczu&)AjUlh(11>gp>f`wv{KnjF%!aA*Jk N002ovPDHLkV1kkt*XsZP literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png new file mode 100644 index 0000000000000000000000000000000000000000..f59b7c4365fa1720af1aa04eb47167ddaa6eeed4 GIT binary patch literal 626 zcmV-&0*(ENP)ZS(e|#C2>JN4>y}l*tQ*E7zP@R2CCJnkW?xa6bgk%(hgtZ z0=~d?U3i`+Mvi4!&~+WPT1^NX#{u6&QIx+DE(oR{&T5&-ovF?@wGw)P&AtpHZa|G%V*GUUqL@@!d4V$`8=##4)ytY959JG zdc&Kho)&AL70^i z!PEmeeDWCB-UbK(*4JST44^tV2z_J(dn~+vBMJT97_7rzFio=~XczIv?PQ5$v%u~y zu(bteXb5I1h2zCV{Jc2~V{{yzZipgsP6;k264$*#5q?GzCm|CPa9CKqm4b116h3Pu z?+%Cm52plC8|5P0@igf2GV1KkCfk{Zecu=G@VNrf>s%g9c5D%@cfxVb6$nY`1IW=4 zt10QqSps_2JLp0f3I0j0u>#qA;v!+T))KEbCg|mo3q0pG{OR}p0fPds8+K~d>Hq)$ M07*qoM6N<$g1S2e3jhEB literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png new file mode 100644 index 0000000000000000000000000000000000000000..44084add79b9a0fc3354d16bbd4b4b5ff8095da7 GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$R@9E+gqH(@-qA%AW0|7U8+xDRI z0k`B18}ImRw2g{jTGP$Pmx3yI6F_2s&$|`cJ!i0UN zB3H;=r{#{FwLaNVJ&hZl9+MTHGx1T^-A=Q0?hRb#8a~x50X%;`b6ik3cw=#XdxWy= zgrpBoDjpwP&g9<9h3x!k_B!?vuTJVkmIJ-U N;OXk;vd$@?2>|rNdMN+^ literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png new file mode 100644 index 0000000000000000000000000000000000000000..3a1441c9a12062a4bb3d706000d3ca14399aebca GIT binary patch literal 565 zcmV-50?Pe~P)SCZIX8XZzY2l?gCw6LlgWJ5Avz#QX4|&mI8LN)w~J1vgL=KLAhlWz*=#m~gyvxa z&;iC6gb?aZvMdXxX`<0+D1hs_pqJ!wxqlEH;CJ)je~uL(gpi@v>!I0f_Kl=E(E+Tq z26na*9gribxx-Oft(HnstyXUUy!39&E-cI%J5Rsy;(PGZH{g{ty!HVC&yGPT3H8x# zw{^gBPW)O0FMoh{k%l<`1a|To_Wl&u&-GXm8izU|&<&utILc4wc6s@u1bmTz6x{qg zTw@7=FQRcg&r`h+gcR$*Jbv+*DPk7v)B@e0o2 z6IlBXW&8xh@9)YKiV~2>+z&XKd24JT55YWz&JtfvCg4r^~bLP79-yS@n$OW00000NkvXXu0mjf DStt2z literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png new file mode 100644 index 0000000000000000000000000000000000000000..e7708292adabf4821612bfca032cbd019c63180b GIT binary patch literal 634 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 literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png new file mode 100644 index 0000000000000000000000000000000000000000..1eb880947ddf3e745c29e8d9dc90f09c7e6e323c GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$R?&;zfqH(@;q9b3Efq-lM(nr^( z=EYR73-9e)UYMWsXy%?aZsD68Yyv^2$~6QgEcljw%kx>O(f-gQ?@fOOx3A-0+Qw?O zRx~W)kn~Qe2d6f9nMG#g9Q04Mk==M~N!Dglvxk!fgVh#w@ZV$IY1+Xc`d{d2UcaP~ zfWp)_Ivqj}l2SPy^9ZWy6rG9Yx4v67_uA&&9|XA~5-#3)W3%em1peD8RWH^#O%XoM zxMPud%}GTj#~*+7JMxTd!`{^Q+>(D3*|@KV`*G2;{QnANOxu1$r2xIe;OXk;vd$@? F2>@zac~<}c literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png new file mode 100644 index 0000000000000000000000000000000000000000..ae8ecbf47672a874c0958d0d113a56162c2bd364 GIT binary patch literal 651 zcmV;60(AX}P)hkjP zNW|QGv-YFNLN^qH@tJycPNG5ti6B7;r4mEr#lr@*T8*M85D`{ZR^BWwF23T<%MYIh zdC)S*p=|xk^!~H=+HSZ183~y8v4|mYmZxt&)5{{~>J`>E223Q5>T$=~mtA71q-jdG z+eJhOAyBW^0k9Gk1+rX8)zFx((CG^&tDY>6XaS~Fy!WJON|Gdujg5^~Vzt@o%BcYLiNiTQSD`zL^ociBz_>bDlpw3kriQ@Z`bVsGz-_6N>$&gTDiKDTKR^ z-hB*tHa^>!oD~5TK^0UK5rZ}RBm50Bv}S-yA%s=Ha5RYb{)!z2N&$&64gfhybBu8p lh~_|?8^bu;BRYt{<}Yrwd83Y=s?Goa002ovPDHLkV1l%3CP4rI literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2490ed1432d5d667a76235360824a1088e928 GIT binary patch literal 734 zcmV<40wMj0P)JT{hN;C#tgf#9krG=I>5!<*aE1_(spcgF}<`n4i zJi-}^6UUeU4jUFwdCiVPDm%`Zx^UBa8J(mnR6wEgz^}o8;)M*Y(@l_!Kfv)}4+NuM zaPXE50z)r)9=D=SR|RIqfQ^j}Hu!fzMeQBo+@PZk1G8hOw|vBTvkx`HM)Xe9q3xao z@`p0`NO!2904FHSLA6E@Y-O6zH$DQzvq@aHsz}}<(!v(Z_+EodX%R&NZW75g+nENo zV0020rxE^;7d!067AN>6*+&YLp$9uH6F-=In`XC{Cn%+o|5)b&boEPr02w@|P*oGm QmjD0&07*qoM6N<$g78X0Q~&?~ literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png new file mode 100644 index 0000000000000000000000000000000000000000..fecadd08afed92536be91ab12d8e37b6bf410d5d GIT binary patch literal 613 zcmV-r0-F7aP)wK%m(L+9IV|s|#(WRl-O^4GvaQsnHq|OstfO zIJ3}3<01}YGARE4m!7=)QisvlHUo!Qymx-@-t*p_129Ko-#pVI)6#!*kLj-AGXWNR zyA_{wKii_amK7^YT-v z6#plaNm#8`-kz@OvjIt^4%IN{@J3bR zRI}ME1Mv85p|%;RK>ViR>APPLB4;;BpCtqE@P+*7!G>I4UjNx~e>r3HA^tWCQ@S)l z{BslcSwL-CxQ&_ZZSv_g0Tu{yi*X){Mt|W7)lbE`SQxFP00000NkvXXu0mjf;)M*S literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png new file mode 100644 index 0000000000000000000000000000000000000000..fd4bbccdf1643f4ff5022fbc59b82546e259317e GIT binary patch literal 386 zcmV-|0e$|7P)_QM!1S$Bhw4w+iRuFWf;tfR6D%SMJrb+tx zC9R6{2>Ou6#juIy6u(I?|;&Owi$sRB4^20apB5xE2 z#B9XekY66S6lzfCL!eEQRgo0LokTA55@Y#%_wN!TXPw^Q4IIXsG~v#u_4t;x_HM16EQ@QRY+rut&97&UefsPmLrQ5P zBC2kcbux9L%2bJz$P$XV$*zSxb2e@6_3O#;&!FD<&hLjGn%~%en;7)djE^d6!t$lW7GyIOKlQ46hr`Z zjLNuRDP_53dNoN?wd&HMgL^m1DXFU<5dQsrceN>fSz00000)O9XRTN^$%%`*Fg>ryDtc(lF@?b>dE!20r+y z#Q*>(wbV5H`-E4Do={CJp7=ERhw15hgZi)?jRG88 zzVz(5;g?Td1izJyO33bhjg2Qc7FVY@f9!o)Gu?DII~vm-Dc?}3M!fsgjP?F(7`rgg z+xOk8XD)e?Zl=5+un`5!7kr?F=eq)K-5uqr%yU$1hLv){Vlm=)*5~`lwMciiXFu*g z)*Jkz6AF>#zb(Vx`Iv{bdGZHtlW)v(y5k^|xgSUc9%0}S20nrYrO}78ofk?bV!5)4 z=Ngz@+$9N1>>mA%IWx`Fqa240bWkiW;2TZgd8CZS0U}@mknC;!2;wi$eI@`h0y2JS`Eae0CW}q(2(%!m8 zWq$`PDU>LT1_y*bBv#P5<@q0@ttz$hIH}YMDvAigCc=y*)jY-VOpTd;A8@3t7Xh4r z0KTWOk;N2Ox4!&&^4B*no$WtTX!BXB)rg!y8dvGgKBQKLJNXRRp0}Bsjd1|LNQX~c zbC~fjrk2iL@4dYF*vt;}dFn(%h)n_-vzEIHMOKRkdF%3Lq|zBgKm_h>TEq!))nWjq zzn;B!?!(dQcHu$#=JF`cS&W~C`WHFW^B!~MI#k)>1Vk&eQy8P1O`J6V04{D@|7d6^ zyBABnh-d^H0FX&L07M||E0n_dp4v&Q%PSE9p#R#Hq)`5I_(B5CE#q dxjPz0{s-<+c#AC!i7@~G002ovPDHLkV1iPlpuqqD literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/lib/public/style.css b/node_modules/express/node_modules/connect/lib/public/style.css new file mode 100644 index 0000000..32b6507 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/style.css @@ -0,0 +1,141 @@ +body { + margin: 0; + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + margin: 0; + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul { + margin: 0; + padding: 0; +} +ul li { + margin: 5px 0; + padding: 3px 8px; + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 500px; +} +ul#files li { + padding: 0; +} +ul#files li img { + position: absolute; + top: 5px; + left: 5px; +} +ul#files li a { + position: relative; + display: block; + margin: 1px; + width: 30%; + height: 25px; + line-height: 25px; + text-indent: 8px; + float: left; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + text-overflow: ellipsis; +} +ul#files li a.icon { + text-indent: 25px; +} +ul#files li a:focus, +ul#files li a:hover { + outline: none; + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} diff --git a/node_modules/express/node_modules/connect/lib/utils.js b/node_modules/express/node_modules/connect/lib/utils.js new file mode 100644 index 0000000..d52009a --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/utils.js @@ -0,0 +1,386 @@ + +/*! + * Connect - utils + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , crypto = require('crypto') + , parse = require('url').parse + , signature = require('cookie-signature') + , nodeVersion = process.versions.node.split('.'); + +// pause is broken in node < 0.10 +exports.brokenPause = parseInt(nodeVersion[0], 10) === 0 + && parseInt(nodeVersion[1], 10) < 10; + +/** + * Return `true` if the request has a body, otherwise return `false`. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.hasBody = function(req) { + var encoding = 'transfer-encoding' in req.headers; + var length = 'content-length' in req.headers && req.headers['content-length'] !== '0'; + return encoding || length; +}; + +/** + * Extract the mime type from the given request's + * _Content-Type_ header. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +exports.mime = function(req) { + var str = req.headers['content-type'] || ''; + return str.split(';')[0]; +}; + +/** + * Generate an `Error` from the given status `code` + * and optional `msg`. + * + * @param {Number} code + * @param {String} msg + * @return {Error} + * @api private + */ + +exports.error = function(code, msg){ + var err = new Error(msg || http.STATUS_CODES[code]); + err.status = code; + return err; +}; + +/** + * Return md5 hash of the given string and optional encoding, + * defaulting to hex. + * + * utils.md5('wahoo'); + * // => "e493298061761236c96b02ea6aa8a2ad" + * + * @param {String} str + * @param {String} encoding + * @return {String} + * @api private + */ + +exports.md5 = function(str, encoding){ + return crypto + .createHash('md5') + .update(str) + .digest(encoding || 'hex'); +}; + +/** + * Merge object b with object a. + * + * var a = { foo: 'bar' } + * , b = { bar: 'baz' }; + * + * utils.merge(a, b); + * // => { foo: 'bar', bar: 'baz' } + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api private + */ + +exports.merge = function(a, b){ + if (a && b) { + for (var key in b) { + a[key] = b[key]; + } + } + return a; +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature') + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature') + var str = val.slice(0, val.lastIndexOf('.')); + return exports.sign(str, secret) == val + ? str + : false; +}; + +/** + * Parse signed cookies, returning an object + * containing the decoded key/value pairs, + * while removing the signed key from `obj`. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseSignedCookies = function(obj, secret){ + var ret = {}; + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + if (0 == val.indexOf('s:')) { + val = signature.unsign(val.slice(2), secret); + if (val) { + ret[key] = val; + delete obj[key]; + } + } + }); + return ret; +}; + +/** + * Parse a signed cookie string, return the decoded value + * + * @param {String} str signed cookie string + * @param {String} secret + * @return {String} decoded value + * @api private + */ + +exports.parseSignedCookie = function(str, secret){ + return 0 == str.indexOf('s:') + ? signature.unsign(str.slice(2), secret) + : str; +}; + +/** + * Parse JSON cookies. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseJSONCookies = function(obj){ + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + var res = exports.parseJSONCookie(val); + if (res) obj[key] = res; + }); + return obj; +}; + +/** + * Parse JSON cookie string + * + * @param {String} str + * @return {Object} Parsed object or null if not json cookie + * @api private + */ + +exports.parseJSONCookie = function(str) { + if (0 == str.indexOf('j:')) { + try { + return JSON.parse(str.slice(2)); + } catch (err) { + // no op + } + } +}; + +/** + * Pause `data` and `end` events on the given `obj`. + * Middleware performing async tasks _should_ utilize + * this utility (or similar), to re-emit data once + * the async operation has completed, otherwise these + * events may be lost. Pause is only required for + * node versions less than 10, and is replaced with + * noop's otherwise. + * + * var pause = utils.pause(req); + * fs.readFile(path, function(){ + * next(); + * pause.resume(); + * }); + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.pause = exports.brokenPause + ? require('pause') + : function () { + return { + end: noop, + resume: noop + } + } + +/** + * Strip `Content-*` headers from `res`. + * + * @param {ServerResponse} res + * @api private + */ + +exports.removeContentHeaders = function(res){ + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Check if `req` is a conditional GET request. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.conditionalGET = function(req) { + return req.headers['if-modified-since'] + || req.headers['if-none-match']; +}; + +/** + * Respond with 401 "Unauthorized". + * + * @param {ServerResponse} res + * @param {String} realm + * @api private + */ + +exports.unauthorized = function(res, realm) { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); + res.end('Unauthorized'); +}; + +/** + * Respond with 304 "Not Modified". + * + * @param {ServerResponse} res + * @param {Object} headers + * @api private + */ + +exports.notModified = function(res) { + exports.removeContentHeaders(res); + res.statusCode = 304; + res.end(); +}; + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * Parse the given Cache-Control `str`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +exports.parseCacheControl = function(str){ + var directives = str.split(',') + , obj = {}; + + for(var i = 0, len = directives.length; i < len; i++) { + var parts = directives[i].split('=') + , key = parts.shift().trim() + , val = parseInt(parts.shift(), 10); + + obj[key] = isNaN(val) ? true : val; + } + + return obj; +}; + +/** + * Parse the `req` url with memoization. + * + * @param {ServerRequest} req + * @return {Object} + * @api private + */ + +exports.parseUrl = function(req){ + var parsed = req._parsedUrl; + if (parsed && parsed.href == req.url) { + return parsed; + } else { + return req._parsedUrl = parse(req.url); + } +}; + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api private + */ + +exports.parseBytes = require('bytes'); + +function noop() {} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore b/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/History.md b/node_modules/express/node_modules/connect/node_modules/bytes/History.md new file mode 100644 index 0000000..1332808 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/History.md @@ -0,0 +1,10 @@ + +0.2.0 / 2012-10-28 +================== + + * bytes(200).should.eql('200b') + +0.1.0 / 2012-07-04 +================== + + * add bytes to string conversion [yields] diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/Makefile b/node_modules/express/node_modules/connect/node_modules/bytes/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md b/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md new file mode 100644 index 0000000..9325d5b --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md @@ -0,0 +1,51 @@ +# node-bytes + + Byte string parser / formatter. + +## Example: + +```js +bytes('1kb') +// => 1024 + +bytes('2mb') +// => 2097152 + +bytes('1gb') +// => 1073741824 + +bytes(1073741824) +// => 1gb +``` + +## Installation + +``` +$ npm install bytes +$ component install visionmedia/bytes.js +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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/express/node_modules/connect/node_modules/bytes/component.json b/node_modules/express/node_modules/connect/node_modules/bytes/component.json new file mode 100644 index 0000000..76a6057 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/component.json @@ -0,0 +1,7 @@ +{ + "name": "bytes", + "description": "byte size string parser / serializer", + "keywords": ["bytes", "utility"], + "version": "0.1.0", + "scripts": ["index.js"] +} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/index.js b/node_modules/express/node_modules/connect/node_modules/bytes/index.js new file mode 100644 index 0000000..70b2e01 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/index.js @@ -0,0 +1,39 @@ + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api public + */ + +module.exports = function(size) { + if ('number' == typeof size) return convert(size); + var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/) + , n = parseFloat(parts[1]) + , type = parts[2]; + + var map = { + kb: 1 << 10 + , mb: 1 << 20 + , gb: 1 << 30 + }; + + return map[type] * n; +}; + +/** + * convert bytes into string. + * + * @param {Number} b - bytes to convert + * @return {String} + * @api public + */ + +function convert (b) { + var gb = 1 << 30, mb = 1 << 20, kb = 1 << 10; + if (b >= gb) return (Math.round(b / gb * 100) / 100) + 'gb'; + if (b >= mb) return (Math.round(b / mb * 100) / 100) + 'mb'; + if (b >= kb) return (Math.round(b / kb * 100) / 100) + 'kb'; + return b + 'b'; +} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/package.json b/node_modules/express/node_modules/connect/node_modules/bytes/package.json new file mode 100644 index 0000000..d46a835 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/package.json @@ -0,0 +1,24 @@ +{ + "name": "bytes", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "byte size string parser / serializer", + "version": "0.2.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "# node-bytes\n\n Byte string parser / formatter.\n\n## Example:\n\n```js\nbytes('1kb')\n// => 1024\n\nbytes('2mb')\n// => 2097152\n\nbytes('1gb')\n// => 1073741824\n\nbytes(1073741824)\n// => 1gb\n```\n\n## Installation\n\n```\n$ npm install bytes\n$ component install visionmedia/bytes.js\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "Readme.md", + "_id": "bytes@0.2.0", + "dist": { + "shasum": "9a536ac4d524b28b7c968adc06908ca7116e4ad5" + }, + "_from": "bytes@0.2.0", + "_resolved": "https://registry.npmjs.org/bytes/-/bytes-0.2.0.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore new file mode 100644 index 0000000..4fbabb3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore @@ -0,0 +1,4 @@ +/test/tmp/ +*.upload +*.un~ +*.http diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml new file mode 100644 index 0000000..cb931cb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 + - 0.9 + - "0.10" diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE b/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE new file mode 100644 index 0000000..38d3c9c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE @@ -0,0 +1,7 @@ +Copyright (C) 2011 Felix Geisendörfer + +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/express/node_modules/connect/node_modules/formidable/Readme.md b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md new file mode 100644 index 0000000..08e9eca --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md @@ -0,0 +1,419 @@ +# Formidable + +[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable) + +## Purpose + +A node.js module for parsing form data, especially file uploads. + +## Current status + +This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading +and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from +a large variety of clients and is considered production-ready. + +## Features + +* Fast (~500mb/sec), non-buffering multipart parser +* Automatically writing file uploads to disk +* Low memory footprint +* Graceful error handling +* Very high test coverage + +## Installation + +Via [npm](http://github.com/isaacs/npm): +``` +npm install formidable@latest +``` +Manually: +``` +git clone git://github.com/felixge/node-formidable.git formidable +vim my.js +# var formidable = require('./formidable'); +``` + +Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library. + +## Example + +Parse an incoming file upload. +```javascript +var formidable = require('formidable'), + http = require('http'), + util = require('util'); + +http.createServer(function(req, res) { + if (req.url == '/upload' && req.method.toLowerCase() == 'post') { + // parse a file upload + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received upload:\n\n'); + res.end(util.inspect({fields: fields, files: files})); + }); + + return; + } + + // show a file upload form + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); +}).listen(8080); +``` +## API + +### Formidable.IncomingForm +```javascript +var form = new formidable.IncomingForm() +``` +Creates a new incoming form. + +```javascript +form.encoding = 'utf-8'; +``` +Sets encoding for incoming form fields. + +```javascript +form.uploadDir = process.env.TMP || process.env.TMPDIR || process.env.TEMP || '/tmp' || process.cwd(); +``` +The directory for placing file uploads in. You can move them later on using +`fs.rename()`. The default directory is picked at module load time depending on +the first existing directory from those listed above. + +```javascript +form.keepExtensions = false; +``` +If you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`. + +```javascript +form.type +``` +Either 'multipart' or 'urlencoded' depending on the incoming request. + +```javascript +form.maxFieldsSize = 2 * 1024 * 1024; +``` +Limits the amount of memory a field (not file) can allocate in bytes. +If this value is exceeded, an `'error'` event is emitted. The default +size is 2MB. + +```javascript +form.maxFields = 0; +``` +Limits the number of fields that the querystring parser will decode. Defaults +to 0 (unlimited). + +```javascript +form.hash = false; +``` +If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`. + +```javascript +form.bytesReceived +``` +The amount of bytes received for this form so far. + +```javascript +form.bytesExpected +``` +The expected number of bytes in this form. + +```javascript +form.parse(request, [cb]); +``` +Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback: + + +```javascript +form.parse(req, function(err, fields, files) { + // ... +}); + +form.onPart(part); +``` +You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing. + +```javascript +form.onPart = function(part) { + part.addListener('data', function() { + // ... + }); +} +``` +If you want to use formidable to only handle certain parts for you, you can do so: +```javascript +form.onPart = function(part) { + if (!part.filename) { + // let formidable handle all non-file parts + form.handlePart(part); + } +} +``` +Check the code in this method for further inspiration. + + +### Formidable.File +```javascript +file.size = 0 +``` +The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet. +```javascript +file.path = null +``` +The path this file is being written to. You can modify this in the `'fileBegin'` event in +case you are unhappy with the way formidable generates a temporary path for your files. +```javascript +file.name = null +``` +The name this file had according to the uploading client. +```javascript +file.type = null +``` +The mime type of this file, according to the uploading client. +```javascript +file.lastModifiedDate = null +``` +A date object (or `null`) containing the time this file was last written to. Mostly +here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). +```javascript +file.hash = null +``` +If hash calculation was set, you can read the hex digest out of this var. + +#### Formidable.File#toJSON() + + This method returns a JSON-representation of the file, allowing you to + `JSON.stringify()` the file which is useful for logging and responding + to requests. + +### Events + + +#### 'progress' +```javascript +form.on('progress', function(bytesReceived, bytesExpected) { +}); +``` +Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. + + + +#### 'field' +```javascript +form.on('field', function(name, value) { +}); +``` + +#### 'fileBegin' + +Emitted whenever a field / value pair has been received. +```javascript +form.on('fileBegin', function(name, file) { +}); +``` + +#### 'file' + +Emitted whenever a new file is detected in the upload stream. Use this even if +you want to stream the file to somewhere else while buffering the upload on +the file system. + +Emitted whenever a field / file pair has been received. `file` is an instance of `File`. +```javascript +form.on('file', function(name, file) { +}); +``` + +#### 'error' + +Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events. +```javascript +form.on('error', function(err) { +}); +``` + +#### 'aborted' + + +Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core). +```javascript +form.on('aborted', function() { +}); +``` + +##### 'end' +```javascript +form.on('end', function() { +}); +``` +Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response. + + + +## Changelog + +### v1.0.14 + +* Add failing hash tests. (Ben Trask) +* Enable hash calculation again (Eugene Girshov) +* Test for immediate data events (Tim Smart) +* Re-arrange IncomingForm#parse (Tim Smart) + +### v1.0.13 + +* Only update hash if update method exists (Sven Lito) +* According to travis v0.10 needs to go quoted (Sven Lito) +* Bumping build node versions (Sven Lito) +* Additional fix for empty requests (Eugene Girshov) +* Change the default to 1000, to match the new Node behaviour. (OrangeDog) +* Add ability to control maxKeys in the querystring parser. (OrangeDog) +* Adjust test case to work with node 0.9.x (Eugene Girshov) +* Update package.json (Sven Lito) +* Path adjustment according to eb4468b (Markus Ast) + +### v1.0.12 + +* Emit error on aborted connections (Eugene Girshov) +* Add support for empty requests (Eugene Girshov) +* Fix name/filename handling in Content-Disposition (jesperp) +* Tolerate malformed closing boundary in multipart (Eugene Girshov) +* Ignore preamble in multipart messages (Eugene Girshov) +* Add support for application/json (Mike Frey, Carlos Rodriguez) +* Add support for Base64 encoding (Elmer Bulthuis) +* Add File#toJSON (TJ Holowaychuk) +* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley) +* Documentation improvements (Sven Lito, Andre Azevedo) +* Add support for application/octet-stream (Ion Lupascu, Chris Scribner) +* Use os.tmpDir() to get tmp directory (Andrew Kelley) +* Improve package.json (Andrew Kelley, Sven Lito) +* Fix benchmark script (Andrew Kelley) +* Fix scope issue in incoming_forms (Sven Lito) +* Fix file handle leak on error (OrangeDog) + +### v1.0.11 + +* Calculate checksums for incoming files (sreuter) +* Add definition parameters to "IncomingForm" as an argument (Math-) + +### v1.0.10 + +* Make parts to be proper Streams (Matt Robenolt) + +### v1.0.9 + +* Emit progress when content length header parsed (Tim Koschützki) +* Fix Readme syntax due to GitHub changes (goob) +* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara) + +### v1.0.8 + +* Strip potentially unsafe characters when using `keepExtensions: true`. +* Switch to utest / urun for testing +* Add travis build + +### v1.0.7 + +* Remove file from package that was causing problems when installing on windows. (#102) +* Fix typos in Readme (Jason Davies). + +### v1.0.6 + +* Do not default to the default to the field name for file uploads where + filename="". + +### v1.0.5 + +* Support filename="" in multipart parts +* Explain unexpected end() errors in parser better + +**Note:** Starting with this version, formidable emits 'file' events for empty +file input fields. Previously those were incorrectly emitted as regular file +input fields with value = "". + +### v1.0.4 + +* Detect a good default tmp directory regardless of platform. (#88) + +### v1.0.3 + +* Fix problems with utf8 characters (#84) / semicolons in filenames (#58) +* Small performance improvements +* New test suite and fixture system + +### v1.0.2 + +* Exclude node\_modules folder from git +* Implement new `'aborted'` event +* Fix files in example folder to work with recent node versions +* Make gently a devDependency + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2) + +### v1.0.1 + +* Fix package.json to refer to proper main directory. (#68, Dean Landolt) + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1) + +### v1.0.0 + +* Add support for multipart boundaries that are quoted strings. (Jeff Craig) + +This marks the beginning of development on version 2.0 which will include +several architectural improvements. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0) + +### v0.9.11 + +* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki) +* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class + +**Important:** The old property names of the File class will be removed in a +future release. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11) + +### Older releases + +These releases were done before starting to maintain the above Changelog: + +* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10) +* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9) +* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8) +* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7) +* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6) +* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5) +* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4) +* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3) +* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2) +* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0) + +## License + +Formidable is licensed under the MIT license. + +## Ports + +* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable + +## Credits + +* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js new file mode 100644 index 0000000..49abc43 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js @@ -0,0 +1,71 @@ +var assert = require('assert'); +require('../test/common'); +var multipartParser = require('../lib/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + Buffer = require('buffer').Buffer, + boundary = '-----------------------------168072824752491622650073', + mb = 100, + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), + callbacks = + { partBegin: -1, + partEnd: -1, + headerField: -1, + headerValue: -1, + partData: -1, + end: -1, + }; + + +parser.initWithBoundary(boundary); +parser.onHeaderField = function() { + callbacks.headerField++; +}; + +parser.onHeaderValue = function() { + callbacks.headerValue++; +}; + +parser.onPartBegin = function() { + callbacks.partBegin++; +}; + +parser.onPartData = function() { + callbacks.partData++; +}; + +parser.onPartEnd = function() { + callbacks.partEnd++; +}; + +parser.onEnd = function() { + callbacks.end++; +}; + +var start = +new Date(), + nparsed = parser.write(buffer), + duration = +new Date - start, + mbPerSec = (mb / (duration / 1000)).toFixed(2); + +console.log(mbPerSec+' mb/sec'); + +assert.equal(nparsed, buffer.length); + +function createMultipartBuffer(boundary, size) { + var head = + '--'+boundary+'\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + , tail = '\r\n--'+boundary+'--\r\n' + , buffer = new Buffer(size); + + buffer.write(head, 'ascii', 0); + buffer.write(tail, 'ascii', buffer.length - tail.length); + return buffer; +} + +process.on('exit', function() { + for (var k in callbacks) { + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); + } +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js new file mode 100644 index 0000000..eb8a724 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js @@ -0,0 +1,67 @@ +var common = require('../test/common'), + http = require('http'), + util = require('util'), + formidable = common.formidable, + Buffer = require('buffer').Buffer, + port = common.port, + server; + +server = http.createServer(function(req, res) { + if (req.method !== 'POST') { + res.writeHead(200, {'content-type': 'text/plain'}) + res.end('Please POST a JSON payload to http://localhost:'+port+'/') + return; + } + + var form = new formidable.IncomingForm(), + fields = {}; + + form + .on('error', function(err) { + res.writeHead(500, {'content-type': 'text/plain'}); + res.end('error:\n\n'+util.inspect(err)); + console.error(err); + }) + .on('field', function(field, value) { + console.log(field, value); + fields[field] = value; + }) + .on('end', function() { + console.log('-> post done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('received fields:\n\n '+util.inspect(fields)); + }); + form.parse(req); +}); +server.listen(port); + +console.log('listening on http://localhost:'+port+'/'); + + +var request = http.request({ + host: 'localhost', + path: '/', + port: port, + method: 'POST', + headers: { 'content-type':'application/json', 'content-length':48 } +}, function(response) { + var data = ''; + console.log('\nServer responded with:'); + console.log('Status:', response.statusCode); + response.pipe(process.stdout); + response.on('end', function() { + console.log('\n') + process.exit(); + }); + // response.on('data', function(chunk) { + // data += chunk.toString('utf8'); + // }); + // response.on('end', function() { + // console.log('Response Data:') + // console.log(data); + // process.exit(); + // }); +}) + +request.write('{"numbers":[1,2,3,4,5],"nested":{"key":"value"}}'); +request.end(); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js new file mode 100644 index 0000000..f6c15a6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js @@ -0,0 +1,43 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + } else if (req.url == '/post') { + var form = new formidable.IncomingForm(), + fields = []; + + form + .on('error', function(err) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('error:\n\n'+util.inspect(err)); + }) + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('end', function() { + console.log('-> post done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('received fields:\n\n '+util.inspect(fields)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js new file mode 100644 index 0000000..050cdd9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js @@ -0,0 +1,48 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + } else if (req.url == '/upload') { + var form = new formidable.IncomingForm(), + files = [], + fields = []; + + form.uploadDir = TEST_TMP; + + form + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('file', function(field, file) { + console.log(field, file); + files.push([field, file]); + }) + .on('end', function() { + console.log('-> upload done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received fields:\n\n '+util.inspect(fields)); + res.write('\n\n'); + res.end('received files:\n\n '+util.inspect(files)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/index.js new file mode 100644 index 0000000..4cc88b3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/index.js @@ -0,0 +1 @@ +module.exports = require('./lib'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js new file mode 100644 index 0000000..e34c10e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js @@ -0,0 +1,72 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var util = require('util'), + WriteStream = require('fs').WriteStream, + EventEmitter = require('events').EventEmitter, + crypto = require('crypto'); + +function File(properties) { + EventEmitter.call(this); + + this.size = 0; + this.path = null; + this.name = null; + this.type = null; + this.hash = null; + this.lastModifiedDate = null; + + this._writeStream = null; + + for (var key in properties) { + this[key] = properties[key]; + } + + if(typeof this.hash === 'string') { + this.hash = crypto.createHash(properties.hash); + } else { + this.hash = null; + } +} +module.exports = File; +util.inherits(File, EventEmitter); + +File.prototype.open = function() { + this._writeStream = new WriteStream(this.path); +}; + +File.prototype.toJSON = function() { + return { + size: this.size, + path: this.path, + name: this.name, + type: this.type, + mtime: this.lastModifiedDate, + length: this.length, + filename: this.filename, + mime: this.mime + }; +}; + +File.prototype.write = function(buffer, cb) { + var self = this; + if (self.hash) { + self.hash.update(buffer); + } + this._writeStream.write(buffer, function() { + self.lastModifiedDate = new Date(); + self.size += buffer.length; + self.emit('progress', self.size); + cb(); + }); +}; + +File.prototype.end = function(cb) { + var self = this; + if (self.hash) { + self.hash = self.hash.digest('hex'); + } + this._writeStream.end(function() { + self.emit('end'); + cb(); + }); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js new file mode 100644 index 0000000..c2eeaf8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js @@ -0,0 +1,535 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var fs = require('fs'); +var util = require('util'), + path = require('path'), + File = require('./file'), + MultipartParser = require('./multipart_parser').MultipartParser, + QuerystringParser = require('./querystring_parser').QuerystringParser, + OctetParser = require('./octet_parser').OctetParser, + JSONParser = require('./json_parser').JSONParser, + StringDecoder = require('string_decoder').StringDecoder, + EventEmitter = require('events').EventEmitter, + Stream = require('stream').Stream, + os = require('os'); + +function IncomingForm(opts) { + if (!(this instanceof IncomingForm)) return new IncomingForm(opts); + EventEmitter.call(this); + + opts=opts||{}; + + this.error = null; + this.ended = false; + + this.maxFields = opts.maxFields || 1000; + this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024; + this.keepExtensions = opts.keepExtensions || false; + this.uploadDir = opts.uploadDir || os.tmpDir(); + this.encoding = opts.encoding || 'utf-8'; + this.headers = null; + this.type = null; + this.hash = false; + + this.bytesReceived = null; + this.bytesExpected = null; + + this._parser = null; + this._flushing = 0; + this._fieldsSize = 0; + this.openedFiles = []; + + return this; +}; +util.inherits(IncomingForm, EventEmitter); +exports.IncomingForm = IncomingForm; + +IncomingForm.prototype.parse = function(req, cb) { + this.pause = function() { + try { + req.pause(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + return true; + }; + + this.resume = function() { + try { + req.resume(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + + return true; + }; + + // Setup callback first, so we don't miss anything from data events emitted + // immediately. + if (cb) { + var fields = {}, files = {}; + this + .on('field', function(name, value) { + fields[name] = value; + }) + .on('file', function(name, file) { + files[name] = file; + }) + .on('error', function(err) { + cb(err, fields, files); + }) + .on('end', function() { + cb(null, fields, files); + }); + } + + // Parse headers and setup the parser, ready to start listening for data. + this.writeHeaders(req.headers); + + // Start listening for data. + var self = this; + req + .on('error', function(err) { + self._error(err); + }) + .on('aborted', function() { + self.emit('aborted'); + self._error(new Error('Request aborted')); + }) + .on('data', function(buffer) { + self.write(buffer); + }) + .on('end', function() { + if (self.error) { + return; + } + + var err = self._parser.end(); + if (err) { + self._error(err); + } + }); + + return this; +}; + +IncomingForm.prototype.writeHeaders = function(headers) { + this.headers = headers; + this._parseContentLength(); + this._parseContentType(); +}; + +IncomingForm.prototype.write = function(buffer) { + if (!this._parser) { + this._error(new Error('unintialized parser')); + return; + } + + this.bytesReceived += buffer.length; + this.emit('progress', this.bytesReceived, this.bytesExpected); + + var bytesParsed = this._parser.write(buffer); + if (bytesParsed !== buffer.length) { + this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); + } + + return bytesParsed; +}; + +IncomingForm.prototype.pause = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.resume = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.onPart = function(part) { + // this method can be overwritten by the user + this.handlePart(part); +}; + +IncomingForm.prototype.handlePart = function(part) { + var self = this; + + if (part.filename === undefined) { + var value = '' + , decoder = new StringDecoder(this.encoding); + + part.on('data', function(buffer) { + self._fieldsSize += buffer.length; + if (self._fieldsSize > self.maxFieldsSize) { + self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data')); + return; + } + value += decoder.write(buffer); + }); + + part.on('end', function() { + self.emit('field', part.name, value); + }); + return; + } + + this._flushing++; + + var file = new File({ + path: this._uploadPath(part.filename), + name: part.filename, + type: part.mime, + hash: self.hash + }); + + this.emit('fileBegin', part.name, file); + + file.open(); + this.openedFiles.push(file); + + part.on('data', function(buffer) { + self.pause(); + file.write(buffer, function() { + self.resume(); + }); + }); + + part.on('end', function() { + file.end(function() { + self._flushing--; + self.emit('file', part.name, file); + self._maybeEnd(); + }); + }); +}; + +function dummyParser(self) { + return { + end: function () { + self.ended = true; + self._maybeEnd(); + return null; + } + }; +} + +IncomingForm.prototype._parseContentType = function() { + if (this.bytesExpected === 0) { + this._parser = dummyParser(this); + return; + } + + if (!this.headers['content-type']) { + this._error(new Error('bad content-type header, no content-type')); + return; + } + + if (this.headers['content-type'].match(/octet-stream/i)) { + this._initOctetStream(); + return; + } + + if (this.headers['content-type'].match(/urlencoded/i)) { + this._initUrlencoded(); + return; + } + + if (this.headers['content-type'].match(/multipart/i)) { + var m; + if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) { + this._initMultipart(m[1] || m[2]); + } else { + this._error(new Error('bad content-type header, no multipart boundary')); + } + return; + } + + if (this.headers['content-type'].match(/json/i)) { + this._initJSONencoded(); + return; + } + + this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); +}; + +IncomingForm.prototype._error = function(err) { + if (this.error || this.ended) { + return; + } + + this.error = err; + this.pause(); + this.emit('error', err); + + if (Array.isArray(this.openedFiles)) { + this.openedFiles.forEach(function(file) { + file._writeStream.destroy(); + setTimeout(fs.unlink, 0, file.path); + }); + } +}; + +IncomingForm.prototype._parseContentLength = function() { + this.bytesReceived = 0; + if (this.headers['content-length']) { + this.bytesExpected = parseInt(this.headers['content-length'], 10); + } else if (this.headers['transfer-encoding'] === undefined) { + this.bytesExpected = 0; + } + + if (this.bytesExpected !== null) { + this.emit('progress', this.bytesReceived, this.bytesExpected); + } +}; + +IncomingForm.prototype._newParser = function() { + return new MultipartParser(); +}; + +IncomingForm.prototype._initMultipart = function(boundary) { + this.type = 'multipart'; + + var parser = new MultipartParser(), + self = this, + headerField, + headerValue, + part; + + parser.initWithBoundary(boundary); + + parser.onPartBegin = function() { + part = new Stream(); + part.readable = true; + part.headers = {}; + part.name = null; + part.filename = null; + part.mime = null; + + part.transferEncoding = 'binary'; + part.transferBuffer = ''; + + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString(self.encoding, start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString(self.encoding, start, end); + }; + + parser.onHeaderEnd = function() { + headerField = headerField.toLowerCase(); + part.headers[headerField] = headerValue; + + var m; + if (headerField == 'content-disposition') { + if (m = headerValue.match(/\bname="([^"]+)"/i)) { + part.name = m[1]; + } + + part.filename = self._fileName(headerValue); + } else if (headerField == 'content-type') { + part.mime = headerValue; + } else if (headerField == 'content-transfer-encoding') { + part.transferEncoding = headerValue.toLowerCase(); + } + + headerField = ''; + headerValue = ''; + }; + + parser.onHeadersEnd = function() { + switch(part.transferEncoding){ + case 'binary': + case '7bit': + case '8bit': + parser.onPartData = function(b, start, end) { + part.emit('data', b.slice(start, end)); + }; + + parser.onPartEnd = function() { + part.emit('end'); + }; + break; + + case 'base64': + parser.onPartData = function(b, start, end) { + part.transferBuffer += b.slice(start, end).toString('ascii'); + + /* + four bytes (chars) in base64 converts to three bytes in binary + encoding. So we should always work with a number of bytes that + can be divided by 4, it will result in a number of buytes that + can be divided vy 3. + */ + var offset = parseInt(part.transferBuffer.length / 4) * 4; + part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64')) + part.transferBuffer = part.transferBuffer.substring(offset); + }; + + parser.onPartEnd = function() { + part.emit('data', new Buffer(part.transferBuffer, 'base64')) + part.emit('end'); + }; + break; + + default: + return self._error(new Error('unknown transfer-encoding')); + } + + self.onPart(part); + }; + + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._fileName = function(headerValue) { + var m = headerValue.match(/\bfilename="(.*?)"($|; )/i); + if (!m) return; + + var filename = m[1].substr(m[1].lastIndexOf('\\') + 1); + filename = filename.replace(/%22/g, '"'); + filename = filename.replace(/&#([\d]{4});/g, function(m, code) { + return String.fromCharCode(code); + }); + return filename; +}; + +IncomingForm.prototype._initUrlencoded = function() { + this.type = 'urlencoded'; + + var parser = new QuerystringParser(this.maxFields) + , self = this; + + parser.onField = function(key, val) { + self.emit('field', key, val); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._initOctetStream = function() { + this.type = 'octet-stream'; + var filename = this.headers['x-file-name']; + var mime = this.headers['content-type']; + + var file = new File({ + path: this._uploadPath(filename), + name: filename, + type: mime + }); + + file.open(); + + this.emit('fileBegin', filename, file); + + this._flushing++; + + var self = this; + + self._parser = new OctetParser(); + + //Keep track of writes that haven't finished so we don't emit the file before it's done being written + var outstandingWrites = 0; + + self._parser.on('data', function(buffer){ + self.pause(); + outstandingWrites++; + + file.write(buffer, function() { + outstandingWrites--; + self.resume(); + + if(self.ended){ + self._parser.emit('doneWritingFile'); + } + }); + }); + + self._parser.on('end', function(){ + self._flushing--; + self.ended = true; + + var done = function(){ + self.emit('file', 'file', file); + self._maybeEnd(); + }; + + if(outstandingWrites === 0){ + done(); + } else { + self._parser.once('doneWritingFile', done); + } + }); +}; + +IncomingForm.prototype._initJSONencoded = function() { + this.type = 'json'; + + var parser = new JSONParser() + , self = this; + + if (this.bytesExpected) { + parser.initWithLength(this.bytesExpected); + } + + parser.onField = function(key, val) { + self.emit('field', key, val); + } + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._uploadPath = function(filename) { + var name = ''; + for (var i = 0; i < 32; i++) { + name += Math.floor(Math.random() * 16).toString(16); + } + + if (this.keepExtensions) { + var ext = path.extname(filename); + ext = ext.replace(/(\.[a-z0-9]+).*/, '$1'); + + name += ext; + } + + return path.join(this.uploadDir, name); +}; + +IncomingForm.prototype._maybeEnd = function() { + if (!this.ended || this._flushing || this.error) { + return; + } + + this.emit('end'); +}; + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js new file mode 100644 index 0000000..7a6e3e1 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js @@ -0,0 +1,3 @@ +var IncomingForm = require('./incoming_form').IncomingForm; +IncomingForm.IncomingForm = IncomingForm; +module.exports = IncomingForm; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js new file mode 100644 index 0000000..6ce966b --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js @@ -0,0 +1,35 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var Buffer = require('buffer').Buffer + +function JSONParser() { + this.data = new Buffer(''); + this.bytesWritten = 0; +}; +exports.JSONParser = JSONParser; + +JSONParser.prototype.initWithLength = function(length) { + this.data = new Buffer(length); +} + +JSONParser.prototype.write = function(buffer) { + if (this.data.length >= this.bytesWritten + buffer.length) { + buffer.copy(this.data, this.bytesWritten); + } else { + this.data = Buffer.concat([this.data, buffer]); + } + this.bytesWritten += buffer.length; + return buffer.length; +} + +JSONParser.prototype.end = function() { + try { + var fields = JSON.parse(this.data.toString('utf8')) + for (var field in fields) { + this.onField(field, fields[field]); + } + } catch (e) {} + this.data = null; + + this.onEnd(); +} \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js new file mode 100644 index 0000000..98a6856 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js @@ -0,0 +1,324 @@ +var Buffer = require('buffer').Buffer, + s = 0, + S = + { PARSER_UNINITIALIZED: s++, + START: s++, + START_BOUNDARY: s++, + HEADER_FIELD_START: s++, + HEADER_FIELD: s++, + HEADER_VALUE_START: s++, + HEADER_VALUE: s++, + HEADER_VALUE_ALMOST_DONE: s++, + HEADERS_ALMOST_DONE: s++, + PART_DATA_START: s++, + PART_DATA: s++, + PART_END: s++, + END: s++ + }, + + f = 1, + F = + { PART_BOUNDARY: f, + LAST_BOUNDARY: f *= 2 + }, + + LF = 10, + CR = 13, + SPACE = 32, + HYPHEN = 45, + COLON = 58, + A = 97, + Z = 122, + + lower = function(c) { + return c | 0x20; + }; + +for (s in S) { + exports[s] = S[s]; +} + +function MultipartParser() { + this.boundary = null; + this.boundaryChars = null; + this.lookbehind = null; + this.state = S.PARSER_UNINITIALIZED; + + this.index = null; + this.flags = 0; +}; +exports.MultipartParser = MultipartParser; + +MultipartParser.stateToString = function(stateNumber) { + for (var state in S) { + var number = S[state]; + if (number === stateNumber) return state; + } +}; + +MultipartParser.prototype.initWithBoundary = function(str) { + this.boundary = new Buffer(str.length+4); + this.boundary.write('\r\n--', 'ascii', 0); + this.boundary.write(str, 'ascii', 4); + this.lookbehind = new Buffer(this.boundary.length+8); + this.state = S.START; + + this.boundaryChars = {}; + for (var i = 0; i < this.boundary.length; i++) { + this.boundaryChars[this.boundary[i]] = true; + } +}; + +MultipartParser.prototype.write = function(buffer) { + var self = this, + i = 0, + len = buffer.length, + prevIndex = this.index, + index = this.index, + state = this.state, + flags = this.flags, + lookbehind = this.lookbehind, + boundary = this.boundary, + boundaryChars = this.boundaryChars, + boundaryLength = this.boundary.length, + boundaryEnd = boundaryLength - 1, + bufferLength = buffer.length, + c, + cl, + + mark = function(name) { + self[name+'Mark'] = i; + }, + clear = function(name) { + delete self[name+'Mark']; + }, + callback = function(name, buffer, start, end) { + if (start !== undefined && start === end) { + return; + } + + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](buffer, start, end); + } + }, + dataCallback = function(name, clear) { + var markSymbol = name+'Mark'; + if (!(markSymbol in self)) { + return; + } + + if (!clear) { + callback(name, buffer, self[markSymbol], buffer.length); + self[markSymbol] = 0; + } else { + callback(name, buffer, self[markSymbol], i); + delete self[markSymbol]; + } + }; + + for (i = 0; i < len; i++) { + c = buffer[i]; + switch (state) { + case S.PARSER_UNINITIALIZED: + return i; + case S.START: + index = 0; + state = S.START_BOUNDARY; + case S.START_BOUNDARY: + if (index == boundary.length - 2) { + if (c != CR) { + return i; + } + index++; + break; + } else if (index - 1 == boundary.length - 2) { + if (c != LF) { + return i; + } + index = 0; + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + + if (c != boundary[index+2]) { + index = -2; + } + if (c == boundary[index+2]) { + index++; + } + break; + case S.HEADER_FIELD_START: + state = S.HEADER_FIELD; + mark('headerField'); + index = 0; + case S.HEADER_FIELD: + if (c == CR) { + clear('headerField'); + state = S.HEADERS_ALMOST_DONE; + break; + } + + index++; + if (c == HYPHEN) { + break; + } + + if (c == COLON) { + if (index == 1) { + // empty header field + return i; + } + dataCallback('headerField', true); + state = S.HEADER_VALUE_START; + break; + } + + cl = lower(c); + if (cl < A || cl > Z) { + return i; + } + break; + case S.HEADER_VALUE_START: + if (c == SPACE) { + break; + } + + mark('headerValue'); + state = S.HEADER_VALUE; + case S.HEADER_VALUE: + if (c == CR) { + dataCallback('headerValue', true); + callback('headerEnd'); + state = S.HEADER_VALUE_ALMOST_DONE; + } + break; + case S.HEADER_VALUE_ALMOST_DONE: + if (c != LF) { + return i; + } + state = S.HEADER_FIELD_START; + break; + case S.HEADERS_ALMOST_DONE: + if (c != LF) { + return i; + } + + callback('headersEnd'); + state = S.PART_DATA_START; + break; + case S.PART_DATA_START: + state = S.PART_DATA; + mark('partData'); + case S.PART_DATA: + prevIndex = index; + + if (index == 0) { + // boyer-moore derrived algorithm to safely skip non-boundary data + i += boundaryEnd; + while (i < bufferLength && !(buffer[i] in boundaryChars)) { + i += boundaryLength; + } + i -= boundaryEnd; + c = buffer[i]; + } + + if (index < boundary.length) { + if (boundary[index] == c) { + if (index == 0) { + dataCallback('partData', true); + } + index++; + } else { + index = 0; + } + } else if (index == boundary.length) { + index++; + if (c == CR) { + // CR = part boundary + flags |= F.PART_BOUNDARY; + } else if (c == HYPHEN) { + // HYPHEN = end boundary + flags |= F.LAST_BOUNDARY; + } else { + index = 0; + } + } else if (index - 1 == boundary.length) { + if (flags & F.PART_BOUNDARY) { + index = 0; + if (c == LF) { + // unset the PART_BOUNDARY flag + flags &= ~F.PART_BOUNDARY; + callback('partEnd'); + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + } else if (flags & F.LAST_BOUNDARY) { + if (c == HYPHEN) { + callback('partEnd'); + callback('end'); + state = S.END; + } else { + index = 0; + } + } else { + index = 0; + } + } + + if (index > 0) { + // when matching a possible boundary, keep a lookbehind reference + // in case it turns out to be a false lead + lookbehind[index-1] = c; + } else if (prevIndex > 0) { + // if our boundary turned out to be rubbish, the captured lookbehind + // belongs to partData + callback('partData', lookbehind, 0, prevIndex); + prevIndex = 0; + mark('partData'); + + // reconsider the current character even so it interrupted the sequence + // it could be the beginning of a new sequence + i--; + } + + break; + case S.END: + break; + default: + return i; + } + } + + dataCallback('headerField'); + dataCallback('headerValue'); + dataCallback('partData'); + + this.index = index; + this.state = state; + this.flags = flags; + + return len; +}; + +MultipartParser.prototype.end = function() { + var callback = function(self, name) { + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](); + } + }; + if ((this.state == S.HEADER_FIELD_START && this.index == 0) || + (this.state == S.PART_DATA && this.index == this.boundary.length)) { + callback(this, 'partEnd'); + callback(this, 'end'); + } else if (this.state != S.END) { + return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain()); + } +}; + +MultipartParser.prototype.explain = function() { + return 'state = ' + MultipartParser.stateToString(this.state); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js new file mode 100644 index 0000000..6e8b551 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js @@ -0,0 +1,20 @@ +var EventEmitter = require('events').EventEmitter + , util = require('util'); + +function OctetParser(options){ + if(!(this instanceof OctetParser)) return new OctetParser(options); + EventEmitter.call(this); +} + +util.inherits(OctetParser, EventEmitter); + +exports.OctetParser = OctetParser; + +OctetParser.prototype.write = function(buffer) { + this.emit('data', buffer); + return buffer.length; +}; + +OctetParser.prototype.end = function() { + this.emit('end'); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js new file mode 100644 index 0000000..320ce5a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js @@ -0,0 +1,27 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +// This is a buffering parser, not quite as nice as the multipart one. +// If I find time I'll rewrite this to be fully streaming as well +var querystring = require('querystring'); + +function QuerystringParser(maxKeys) { + this.maxKeys = maxKeys; + this.buffer = ''; +}; +exports.QuerystringParser = QuerystringParser; + +QuerystringParser.prototype.write = function(buffer) { + this.buffer += buffer.toString('ascii'); + return buffer.length; +}; + +QuerystringParser.prototype.end = function() { + var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys }); + for (var field in fields) { + this.onField(field, fields[field]); + } + this.buffer = ''; + + this.onEnd(); +}; + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/package.json b/node_modules/express/node_modules/connect/node_modules/formidable/package.json new file mode 100644 index 0000000..cb57c12 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/package.json @@ -0,0 +1,42 @@ +{ + "name": "formidable", + "description": "A node.js module for parsing form data, especially file uploads.", + "homepage": "https://github.com/felixge/node-formidable", + "version": "1.0.14", + "devDependencies": { + "gently": "0.8.0", + "findit": "0.1.1", + "hashish": "0.0.4", + "urun": "~0.0.6", + "utest": "0.0.3", + "request": "~2.11.4" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/index", + "scripts": { + "test": "node test/run.js", + "clean": "rm test/tmp/*" + }, + "engines": { + "node": ">=0.8.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-formidable.git" + }, + "bugs": { + "url": "http://github.com/felixge/node-formidable/issues" + }, + "optionalDependencies": {}, + "readme": "# Formidable\n\n[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)\n\n## Purpose\n\nA node.js module for parsing form data, especially file uploads.\n\n## Current status\n\nThis module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading\nand encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from\na large variety of clients and is considered production-ready.\n\n## Features\n\n* Fast (~500mb/sec), non-buffering multipart parser\n* Automatically writing file uploads to disk\n* Low memory footprint\n* Graceful error handling\n* Very high test coverage\n\n## Installation\n\nVia [npm](http://github.com/isaacs/npm):\n```\nnpm install formidable@latest\n```\nManually:\n```\ngit clone git://github.com/felixge/node-formidable.git formidable\nvim my.js\n# var formidable = require('./formidable');\n```\n\nNote: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.\n\n## Example\n\nParse an incoming file upload.\n```javascript\nvar formidable = require('formidable'),\n http = require('http'),\n util = require('util');\n\nhttp.createServer(function(req, res) {\n if (req.url == '/upload' && req.method.toLowerCase() == 'post') {\n // parse a file upload\n var form = new formidable.IncomingForm();\n\n form.parse(req, function(err, fields, files) {\n res.writeHead(200, {'content-type': 'text/plain'});\n res.write('received upload:\\n\\n');\n res.end(util.inspect({fields: fields, files: files}));\n });\n\n return;\n }\n\n // show a file upload form\n res.writeHead(200, {'content-type': 'text/html'});\n res.end(\n '
    '+\n '
    '+\n '
    '+\n ''+\n '
    '\n );\n}).listen(8080);\n```\n## API\n\n### Formidable.IncomingForm\n```javascript\nvar form = new formidable.IncomingForm()\n```\nCreates a new incoming form.\n\n```javascript\nform.encoding = 'utf-8';\n```\nSets encoding for incoming form fields.\n\n```javascript\nform.uploadDir = process.env.TMP || process.env.TMPDIR || process.env.TEMP || '/tmp' || process.cwd();\n```\nThe directory for placing file uploads in. You can move them later on using\n`fs.rename()`. The default directory is picked at module load time depending on\nthe first existing directory from those listed above.\n\n```javascript\nform.keepExtensions = false;\n```\nIf you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`.\n\n```javascript\nform.type\n```\nEither 'multipart' or 'urlencoded' depending on the incoming request.\n\n```javascript\nform.maxFieldsSize = 2 * 1024 * 1024;\n```\nLimits the amount of memory a field (not file) can allocate in bytes.\nIf this value is exceeded, an `'error'` event is emitted. The default\nsize is 2MB.\n\n```javascript\nform.maxFields = 0;\n```\nLimits the number of fields that the querystring parser will decode. Defaults\nto 0 (unlimited).\n\n```javascript\nform.hash = false;\n```\nIf you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.\n\n```javascript\nform.bytesReceived\n```\nThe amount of bytes received for this form so far.\n\n```javascript\nform.bytesExpected\n```\nThe expected number of bytes in this form.\n\n```javascript\nform.parse(request, [cb]);\n```\nParses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:\n\n\n```javascript\nform.parse(req, function(err, fields, files) {\n // ...\n});\n\nform.onPart(part);\n```\nYou may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.\n\n```javascript\nform.onPart = function(part) {\n part.addListener('data', function() {\n // ...\n });\n}\n```\nIf you want to use formidable to only handle certain parts for you, you can do so:\n```javascript\nform.onPart = function(part) {\n if (!part.filename) {\n // let formidable handle all non-file parts\n form.handlePart(part);\n }\n}\n```\nCheck the code in this method for further inspiration.\n\n\n### Formidable.File\n```javascript\nfile.size = 0\n```\nThe size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.\n```javascript\nfile.path = null\n```\nThe path this file is being written to. You can modify this in the `'fileBegin'` event in\ncase you are unhappy with the way formidable generates a temporary path for your files.\n```javascript\nfile.name = null\n```\nThe name this file had according to the uploading client.\n```javascript\nfile.type = null\n```\nThe mime type of this file, according to the uploading client.\n```javascript\nfile.lastModifiedDate = null\n```\nA date object (or `null`) containing the time this file was last written to. Mostly\nhere for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).\n```javascript\nfile.hash = null\n```\nIf hash calculation was set, you can read the hex digest out of this var.\n\n#### Formidable.File#toJSON()\n\n This method returns a JSON-representation of the file, allowing you to\n `JSON.stringify()` the file which is useful for logging and responding\n to requests.\n\n### Events\n\n\n#### 'progress'\n```javascript\nform.on('progress', function(bytesReceived, bytesExpected) {\n});\n```\nEmitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.\n\n\n\n#### 'field'\n```javascript\nform.on('field', function(name, value) {\n});\n```\n\n#### 'fileBegin'\n\nEmitted whenever a field / value pair has been received.\n```javascript\nform.on('fileBegin', function(name, file) {\n});\n```\n\n#### 'file'\n\nEmitted whenever a new file is detected in the upload stream. Use this even if\nyou want to stream the file to somewhere else while buffering the upload on\nthe file system.\n\nEmitted whenever a field / file pair has been received. `file` is an instance of `File`.\n```javascript\nform.on('file', function(name, file) {\n});\n```\n\n#### 'error'\n\nEmitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.\n```javascript\nform.on('error', function(err) {\n});\n```\n\n#### 'aborted'\n\n\nEmitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).\n```javascript\nform.on('aborted', function() {\n});\n```\n\n##### 'end'\n```javascript\nform.on('end', function() {\n});\n```\nEmitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.\n\n\n\n## Changelog\n\n### v1.0.14\n\n* Add failing hash tests. (Ben Trask)\n* Enable hash calculation again (Eugene Girshov)\n* Test for immediate data events (Tim Smart)\n* Re-arrange IncomingForm#parse (Tim Smart)\n\n### v1.0.13\n\n* Only update hash if update method exists (Sven Lito)\n* According to travis v0.10 needs to go quoted (Sven Lito)\n* Bumping build node versions (Sven Lito)\n* Additional fix for empty requests (Eugene Girshov)\n* Change the default to 1000, to match the new Node behaviour. (OrangeDog)\n* Add ability to control maxKeys in the querystring parser. (OrangeDog)\n* Adjust test case to work with node 0.9.x (Eugene Girshov)\n* Update package.json (Sven Lito)\n* Path adjustment according to eb4468b (Markus Ast)\n\n### v1.0.12\n\n* Emit error on aborted connections (Eugene Girshov)\n* Add support for empty requests (Eugene Girshov)\n* Fix name/filename handling in Content-Disposition (jesperp)\n* Tolerate malformed closing boundary in multipart (Eugene Girshov)\n* Ignore preamble in multipart messages (Eugene Girshov)\n* Add support for application/json (Mike Frey, Carlos Rodriguez)\n* Add support for Base64 encoding (Elmer Bulthuis)\n* Add File#toJSON (TJ Holowaychuk)\n* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)\n* Documentation improvements (Sven Lito, Andre Azevedo)\n* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)\n* Use os.tmpDir() to get tmp directory (Andrew Kelley)\n* Improve package.json (Andrew Kelley, Sven Lito)\n* Fix benchmark script (Andrew Kelley)\n* Fix scope issue in incoming_forms (Sven Lito)\n* Fix file handle leak on error (OrangeDog)\n\n### v1.0.11\n\n* Calculate checksums for incoming files (sreuter)\n* Add definition parameters to \"IncomingForm\" as an argument (Math-)\n\n### v1.0.10\n\n* Make parts to be proper Streams (Matt Robenolt)\n\n### v1.0.9\n\n* Emit progress when content length header parsed (Tim Koschützki)\n* Fix Readme syntax due to GitHub changes (goob)\n* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)\n\n### v1.0.8\n\n* Strip potentially unsafe characters when using `keepExtensions: true`.\n* Switch to utest / urun for testing\n* Add travis build\n\n### v1.0.7\n\n* Remove file from package that was causing problems when installing on windows. (#102)\n* Fix typos in Readme (Jason Davies).\n\n### v1.0.6\n\n* Do not default to the default to the field name for file uploads where\n filename=\"\".\n\n### v1.0.5\n\n* Support filename=\"\" in multipart parts\n* Explain unexpected end() errors in parser better\n\n**Note:** Starting with this version, formidable emits 'file' events for empty\nfile input fields. Previously those were incorrectly emitted as regular file\ninput fields with value = \"\".\n\n### v1.0.4\n\n* Detect a good default tmp directory regardless of platform. (#88)\n\n### v1.0.3\n\n* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)\n* Small performance improvements\n* New test suite and fixture system\n\n### v1.0.2\n\n* Exclude node\\_modules folder from git\n* Implement new `'aborted'` event\n* Fix files in example folder to work with recent node versions\n* Make gently a devDependency\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)\n\n### v1.0.1\n\n* Fix package.json to refer to proper main directory. (#68, Dean Landolt)\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)\n\n### v1.0.0\n\n* Add support for multipart boundaries that are quoted strings. (Jeff Craig)\n\nThis marks the beginning of development on version 2.0 which will include\nseveral architectural improvements.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)\n\n### v0.9.11\n\n* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)\n* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class\n\n**Important:** The old property names of the File class will be removed in a\nfuture release.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)\n\n### Older releases\n\nThese releases were done before starting to maintain the above Changelog:\n\n* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)\n* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)\n* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)\n* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)\n* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)\n* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)\n* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)\n* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)\n* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)\n* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)\n\n## License\n\nFormidable is licensed under the MIT license.\n\n## Ports\n\n* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable\n\n## Credits\n\n* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js\n", + "readmeFilename": "Readme.md", + "_id": "formidable@1.0.14", + "dependencies": {}, + "dist": { + "shasum": "c3835ae29c5aa753bcda9ae763792a3f732cc588" + }, + "_from": "formidable@1.0.14", + "_resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js new file mode 100644 index 0000000..6a94295 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js @@ -0,0 +1,18 @@ +var path = require('path'); + +var root = path.join(__dirname, '../'); +exports.dir = { + root : root, + lib : root + '/lib', + fixture : root + '/test/fixture', + tmp : root + '/test/tmp', +}; + +exports.port = 13532; + +exports.formidable = require('..'); +exports.assert = require('assert'); + +exports.require = function(lib) { + return require(exports.dir.lib + '/' + lib); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/beta-sticker-1.png new file mode 100644 index 0000000000000000000000000000000000000000..20b1a7f177927900e120c24f97d9514d3325873f GIT binary patch literal 1660 zcmV-?27~#DP)3JV+!|TB%7InihJI zi%oiz5`4wPD(5TE#Clfmyz`#@W}LZ>>+E@k7CP{;vvaq*zx`hGeT&flY)Jpowfx+# zF#k`0B<>n%i|hRykUvy7X`3KSRI;Na0P)F={!qZAZGfn#s5xQh>_6;*UJByn#3z8; zG&CW=u!m}>XtDJ5^&Lz}N!jo9dR0E3PxAZM?>|01e)rh1V|QTc0daHUp~B#VJ|+c$ z;XyEjuBD}APenz=$*8EP!zz_ZPwq%T_@l?;Sy@U2uTeogKh9w7xlft=0P-+D;F|CAOxNsr& z`0?ZCqobn_OVT=js7E~Dx~$^j;{27BmEZ2&yJwd<{w80N12M-XFc&Xg%q=Y~?bYdY zN&Lft0f^SZ!or>{C@3g>^5ltWXlTgBMW0XZPildwh`-d<*2Xt9G@K6=Mg+yr!RK^& zd3iZzvw2{Ce%{GNpPz%;;6u!BbRdxv6BDh>XF~NCr8WNi!Gj0i6c!eK1gA?N%OI=N z*@-`?1R<_%ZEf8XA0J;AibjHIPri;vdU|?!Wo2awOe3&0sYL<_Rt`kMyt=yju_I%p$sD z`kl=G0ewW)@i_mv3EjOtMdtIfR`koyQ}ADh5N_YTed!cN!)Zv;$irT**FVQD#8H9g zEJ}JWo5}IBmhVyTjWsei^kRN0XkrrG{B9WOqasj7)-H4ow3Bym52`qt zi;9k9qM}za&N@qBK25$TUa5SX`58OVQ%hB65t z9_PADXnDzj%4>4a-N8u_jHtW`MAn8XZ*FexzEWu4F-@RyLpwRocwrZ+f4vYDANT|r zUiy^y5eEFAsUJO`m56=-v%UM~SLDCUk9Z$?`0(MBXg}lg5BB&Sr%#{GICJKVk-Y`f zI*8BK^2{6RxqPj@zP|4I_3PuX^e4^Qc;j{PKw6qTqhV(@X|>u!48v|9a`dN#vD@vB zp}2bumKLcj(bB}N;&xiL^SYsixeApaayT5wX0zcNAg9xb+-^6~7y}jMnNY^?@bFKv zVl7bKs%3eI)Iw8JQ1ngUVCbY;S>d$fmYYn} zefno-XPup$ohHzjF*`f^835ZI9v)7hu*NVH_AC5AwOWmfFh#RjtyT+E5of_vRtjU| zY9SAMrdpxnL|k9x85tQ_0yPgpaW#;ipP!bLl(Z9~FrY2$SET$@fSQ?^F;`VpogEt+ z`-6kwwc{0)ut=f%^s*icZfI?9Z@&q<^>|uZT4F*%!cGjsw1i=xQV2i+ti8X#|BI56 zk}qYNVZP(yVEn<_Aby|G(4?uOMHS9fkyx6WoA=k$)HFcdy&IblYYkv=s;~?U3|wt% zYr75FU8E1UbK>AyA>UR&q855X!$^y(2r4_ERVst%(?Ysffb2UlIy$;U-`+*d;^4%| z`Hfe!b%fg6t2vGFVBu7BoC~lv+QoIPYl39x52bTeYPWea@?Z>3!vXn%^!7d_nC*Ta zQUX)U3Uz)f^2ok~__q39^fX`4Bn9V}WI+C>`9Acw00RIQn|MJlIvG3w0000C3%>5t zidr%inNpJrrOWk}o?bo`LL3TPGX8LmGr|Nex)~wfXj5t5$CAq--YK`!ZrA66XG4Cp zNAorG(h%OxqAiuau^-NH&_!(J^LR0~)=HZ(o`*BhTmP2vf46?}{IFN8_QblI zaR`~MHq*UKQ*|Hoq3fAlfBP>300000000000000000000z<=}(t;CCo04M+egQt(w literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..75b945d2553848b8b6f41fe5e24599c0687b8472 GIT binary patch literal 49 zcmZ?wbhEHbWMp7unE0RJ|Ns9C3=9Vj8~~DvKUo+V7?>DzfNY>Fh|Ltj$Y2csQN9XW literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt new file mode 100644 index 0000000..e7a4785 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt @@ -0,0 +1 @@ +I am a text file with a funky name! diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/menu_separator.png new file mode 100644 index 0000000000000000000000000000000000000000..1c16a71ed41bb17dabbf11eeecc76f3ca03d3f24 GIT binary patch literal 931 zcmaJ=&u-H&9L|6Pnly1_aI&&1P3)vyR;ytuO~)cgRkamVTp&%{HtHN_iA&QS;e-U- zd5OKiBqk0Vcm-}q+!2BY!0wuk10|AU|E%x(et-R@-FmpQeRo??lpXij>4^QBSi3jn z|M`dW_hP%ln|T35jm!Y8(R8C2hEg9b|psA#Yhz#$%-Nz4mwc*Qk0a^)z{ zM0j>c8oeapQOYP-ri`P_vA~UbD{iV?FpJ7So=J zv7UUR7vf3WcAa`J|2jDR{`=RvpM!z&`qQJW8@tM_v#pO$-hO^2pN-pWIcE=Ey!r!8 CR~}#h literal 0 HcmV?d00001 diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt new file mode 100644 index 0000000..9b6903e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt @@ -0,0 +1 @@ +I am a plain text file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md new file mode 100644 index 0000000..3c9dbe3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md @@ -0,0 +1,3 @@ +* Opera does not allow submitting this file, it shows a warning to the + user that the file could not be found instead. Tested in 9.8, 11.51 on OSX. + Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com). diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js new file mode 100644 index 0000000..fc22026 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js @@ -0,0 +1,24 @@ +module.exports['menu_seperator.png.http'] = [ + {type: 'file', name: 'image', filename: 'menu_separator.png', fixture: 'menu_separator.png', + sha1: 'c845ca3ea794be298f2a1b79769b71939eaf4e54'} +]; + +module.exports['beta-sticker-1.png.http'] = [ + {type: 'file', name: 'sticker', filename: 'beta-sticker-1.png', fixture: 'beta-sticker-1.png', + sha1: '6abbcffd12b4ada5a6a084fe9e4584f846331bc4'} +]; + +module.exports['blank.gif.http'] = [ + {type: 'file', name: 'file', filename: 'blank.gif', fixture: 'blank.gif', + sha1: 'a1fdee122b95748d81cee426d717c05b5174fe96'} +]; + +module.exports['binaryfile.tar.gz.http'] = [ + {type: 'file', name: 'file', filename: 'binaryfile.tar.gz', fixture: 'binaryfile.tar.gz', + sha1: 'cfabe13b348e5e69287d677860880c52a69d2155'} +]; + +module.exports['plain.txt.http'] = [ + {type: 'file', name: 'file', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'} +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js new file mode 100644 index 0000000..4489176 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js @@ -0,0 +1,6 @@ +module.exports = { + 'empty.http': [], + 'empty-urlencoded.http': [], + 'empty-multipart.http': [], + 'minimal.http': [], +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js new file mode 100644 index 0000000..f03b4f0 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js @@ -0,0 +1,9 @@ +module.exports['generic.http'] = [ + {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; + +module.exports['filename-name.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js new file mode 100644 index 0000000..d2e4cfd --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js @@ -0,0 +1,9 @@ +module.exports['crlf.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; + +module.exports['preamble.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js new file mode 100644 index 0000000..eb76fdc --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js @@ -0,0 +1,21 @@ +var properFilename = 'funkyfilename.txt'; + +function expect(filename) { + return [ + {type: 'field', name: 'title', value: 'Weird filename'}, + {type: 'file', name: 'upload', filename: filename, fixture: properFilename}, + ]; +}; + +var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; +var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; + +module.exports = { + 'osx-chrome-13.http' : expect(webkit), + 'osx-firefox-3.6.http' : expect(ffOrIe), + 'osx-safari-5.http' : expect(webkit), + 'xp-chrome-12.http' : expect(webkit), + 'xp-ie-7.http' : expect(ffOrIe), + 'xp-ie-8.http' : expect(ffOrIe), + 'xp-safari-5.http' : expect(webkit), +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js new file mode 100644 index 0000000..e59c5b2 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js @@ -0,0 +1,8 @@ +module.exports['missing-hyphens1.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; +module.exports['missing-hyphens2.http'] = [ + {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js new file mode 100644 index 0000000..a476169 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js @@ -0,0 +1,72 @@ +exports['rfc1867'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['noTrailing\r\n'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['emptyHeader'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + ': foo\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + expectError: true, + }; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js new file mode 100644 index 0000000..8e10ac9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js @@ -0,0 +1,96 @@ +var hashish = require('hashish'); +var fs = require('fs'); +var findit = require('findit'); +var path = require('path'); +var http = require('http'); +var net = require('net'); +var assert = require('assert'); + +var common = require('../common'); +var formidable = common.formidable; + +var server = http.createServer(); +server.listen(common.port, findFixtures); + +function findFixtures() { + var fixtures = []; + findit + .sync(common.dir.fixture + '/js') + .forEach(function(jsPath) { + if (!/\.js$/.test(jsPath)) return; + + var group = path.basename(jsPath, '.js'); + hashish.forEach(require(jsPath), function(fixture, name) { + fixtures.push({ + name : group + '/' + name, + fixture : fixture, + }); + }); + }); + + testNext(fixtures); +} + +function testNext(fixtures) { + var fixture = fixtures.shift(); + if (!fixture) return server.close(); + + var name = fixture.name; + var fixture = fixture.fixture; + + uploadFixture(name, function(err, parts) { + if (err) throw err; + + fixture.forEach(function(expectedPart, i) { + var parsedPart = parts[i]; + assert.equal(parsedPart.type, expectedPart.type); + assert.equal(parsedPart.name, expectedPart.name); + + if (parsedPart.type === 'file') { + var file = parsedPart.value; + assert.equal(file.name, expectedPart.filename); + if(expectedPart.sha1) assert.equal(file.hash, expectedPart.sha1); + } + }); + + testNext(fixtures); + }); +}; + +function uploadFixture(name, cb) { + server.once('request', function(req, res) { + var form = new formidable.IncomingForm(); + form.uploadDir = common.dir.tmp; + form.hash = "sha1"; + form.parse(req); + + function callback() { + var realCallback = cb; + cb = function() {}; + realCallback.apply(null, arguments); + } + + var parts = []; + form + .on('error', callback) + .on('fileBegin', function(name, value) { + parts.push({type: 'file', name: name, value: value}); + }) + .on('field', function(name, value) { + parts.push({type: 'field', name: name, value: value}); + }) + .on('end', function() { + res.end('OK'); + callback(null, parts); + }); + }); + + var socket = net.createConnection(common.port); + var file = fs.createReadStream(common.dir.fixture + '/http/' + name); + + file.pipe(socket, {end: false}); + socket.on('data', function () { + socket.end(); + }); + +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js new file mode 100644 index 0000000..28e758e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var formidable = common.formidable; +var http = require('http'); +var assert = require('assert'); + +var testData = { + numbers: [1, 2, 3, 4, 5], + nested: { key: 'value' } +}; + +var server = http.createServer(function(req, res) { + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + assert.deepEqual(fields, testData); + + res.end(); + server.close(); + }); +}); + +var port = common.port; + +server.listen(port, function(err){ + assert.equal(err, null); + + var request = http.request({ + port: port, + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + + request.write(JSON.stringify(testData)); + request.end(); +}); + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js new file mode 100644 index 0000000..643d2c6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js @@ -0,0 +1,45 @@ +var common = require('../common'); +var formidable = common.formidable; +var http = require('http'); +var fs = require('fs'); +var path = require('path'); +var hashish = require('hashish'); +var assert = require('assert'); + +var testFilePath = path.join(__dirname, '../fixture/file/binaryfile.tar.gz'); + +var server = http.createServer(function(req, res) { + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + assert.equal(hashish(files).length, 1); + var file = files.file; + + assert.equal(file.size, 301); + + var uploaded = fs.readFileSync(file.path); + var original = fs.readFileSync(testFilePath); + + assert.deepEqual(uploaded, original); + + res.end(); + server.close(); + }); +}); + +var port = common.port; + +server.listen(port, function(err){ + assert.equal(err, null); + + var request = http.request({ + port: port, + method: 'POST', + headers: { + 'Content-Type': 'application/octet-stream' + } + }); + + fs.createReadStream(testFilePath).pipe(request); +}); + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js new file mode 100644 index 0000000..2b98598 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js @@ -0,0 +1,24 @@ +var path = require('path'), + fs = require('fs'); + +try { + global.Gently = require('gently'); +} catch (e) { + throw new Error('this test suite requires node-gently'); +} + +exports.lib = path.join(__dirname, '../../lib'); + +global.GENTLY = new Gently(); + +global.assert = require('assert'); +global.TEST_PORT = 13532; +global.TEST_FIXTURES = path.join(__dirname, '../fixture'); +global.TEST_TMP = path.join(__dirname, '../tmp'); + +// Stupid new feature in node that complains about gently attaching too many +// listeners to process 'exit'. This is a workaround until I can think of a +// better way to deal with this. +if (process.setMaxListeners) { + process.setMaxListeners(10000); +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js new file mode 100644 index 0000000..75232aa --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js @@ -0,0 +1,80 @@ +var common = require('../common'); +var CHUNK_LENGTH = 10, + multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + fixtures = require(TEST_FIXTURES + '/multipart'), + Buffer = require('buffer').Buffer; + +Object.keys(fixtures).forEach(function(name) { + var fixture = fixtures[name], + buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')), + offset = 0, + chunk, + nparsed, + + parts = [], + part = null, + headerField, + headerValue, + endCalled = ''; + + parser.initWithBoundary(fixture.boundary); + parser.onPartBegin = function() { + part = {headers: {}, data: ''}; + parts.push(part); + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString('ascii', start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString('ascii', start, end); + } + + parser.onHeaderEnd = function() { + part.headers[headerField] = headerValue; + headerField = ''; + headerValue = ''; + }; + + parser.onPartData = function(b, start, end) { + var str = b.toString('ascii', start, end); + part.data += b.slice(start, end); + } + + parser.onEnd = function() { + endCalled = true; + } + + buffer.write(fixture.raw, 'binary', 0); + + while (offset < buffer.length) { + if (offset + CHUNK_LENGTH < buffer.length) { + chunk = buffer.slice(offset, offset+CHUNK_LENGTH); + } else { + chunk = buffer.slice(offset, buffer.length); + } + offset = offset + CHUNK_LENGTH; + + nparsed = parser.write(chunk); + if (nparsed != chunk.length) { + if (fixture.expectError) { + return; + } + puts('-- ERROR --'); + p(chunk.toString('ascii')); + throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!'); + } + } + + if (fixture.expectError) { + throw new Error('expected parse error did not happen'); + } + + assert.ok(endCalled); + assert.deepEqual(parts, fixture.parts); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js new file mode 100644 index 0000000..52ceedb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js @@ -0,0 +1,104 @@ +var common = require('../common'); +var WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); + +var File = require(common.lib + '/file'), + EventEmitter = require('events').EventEmitter, + file, + gently; + +function test(test) { + gently = new Gently(); + file = new File(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.ok(file instanceof EventEmitter); + assert.strictEqual(file.size, 0); + assert.strictEqual(file.path, null); + assert.strictEqual(file.name, null); + assert.strictEqual(file.type, null); + assert.strictEqual(file.lastModifiedDate, null); + + assert.strictEqual(file._writeStream, null); + + (function testSetProperties() { + var file2 = new File({foo: 'bar'}); + assert.equal(file2.foo, 'bar'); + })(); +}); + +test(function open() { + var WRITE_STREAM; + file.path = '/foo'; + + gently.expect(WriteStreamStub, 'new', function (path) { + WRITE_STREAM = this; + assert.strictEqual(path, file.path); + }); + + file.open(); + assert.strictEqual(file._writeStream, WRITE_STREAM); +}); + +test(function write() { + var BUFFER = {length: 10}, + CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'write', function (buffer, cb) { + assert.strictEqual(buffer, BUFFER); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.ok(file.lastModifiedDate instanceof Date); + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 10); + }); + + cb(); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 20); + }); + + cb(); + }); + + file.write(BUFFER, CB); +}); + +test(function end() { + var CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'end', function (cb) { + gently.expect(file, 'emit', function (event) { + assert.equal(event, 'end'); + }); + + CB_STUB = gently.expect(function endCb() { + }); + + cb(); + }); + + file.end(CB); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js new file mode 100644 index 0000000..25bd887 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js @@ -0,0 +1,756 @@ +var common = require('../common'); +var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'), + QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'), + EventEmitterStub = GENTLY.stub('events', 'EventEmitter'), + StreamStub = GENTLY.stub('stream', 'Stream'), + FileStub = GENTLY.stub('./file'); + +var formidable = require(common.lib + '/index'), + IncomingForm = formidable.IncomingForm, + events = require('events'), + fs = require('fs'), + path = require('path'), + Buffer = require('buffer').Buffer, + fixtures = require(TEST_FIXTURES + '/multipart'), + form, + gently; + +function test(test) { + gently = new Gently(); + gently.expect(EventEmitterStub, 'call'); + form = new IncomingForm(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.strictEqual(form.error, null); + assert.strictEqual(form.ended, false); + assert.strictEqual(form.type, null); + assert.strictEqual(form.headers, null); + assert.strictEqual(form.keepExtensions, false); + // Can't assume dir === '/tmp' for portability + // assert.strictEqual(form.uploadDir, '/tmp'); + // Make sure it is a directory instead + assert.doesNotThrow(function () { + assert(fs.statSync(form.uploadDir).isDirectory()); + }); + assert.strictEqual(form.encoding, 'utf-8'); + assert.strictEqual(form.bytesReceived, null); + assert.strictEqual(form.bytesExpected, null); + assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024); + assert.strictEqual(form._parser, null); + assert.strictEqual(form._flushing, 0); + assert.strictEqual(form._fieldsSize, 0); + assert.ok(form instanceof EventEmitterStub); + assert.equal(form.constructor.name, 'IncomingForm'); + + (function testSimpleConstructor() { + gently.expect(EventEmitterStub, 'call'); + var form = IncomingForm(); + assert.ok(form instanceof IncomingForm); + })(); + + (function testSimpleConstructorShortcut() { + gently.expect(EventEmitterStub, 'call'); + var form = formidable(); + assert.ok(form instanceof IncomingForm); + })(); +}); + +test(function parse() { + var REQ = {headers: {}} + , emit = {}; + + gently.expect(form, 'writeHeaders', function(headers) { + assert.strictEqual(headers, REQ.headers); + }); + + var EVENTS = ['error', 'aborted', 'data', 'end']; + gently.expect(REQ, 'on', EVENTS.length, function(event, fn) { + assert.equal(event, EVENTS.shift()); + emit[event] = fn; + return this; + }); + + form.parse(REQ); + + (function testPause() { + gently.expect(REQ, 'pause'); + assert.strictEqual(form.pause(), true); + })(); + + (function testPauseCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testPauseHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testResume() { + gently.expect(REQ, 'resume'); + assert.strictEqual(form.resume(), true); + })(); + + (function testResumeCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testResumeHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testEmitError() { + var ERR = new Error('something bad happened'); + gently.expect(form, '_error',function(err) { + assert.strictEqual(err, ERR); + }); + emit.error(ERR); + })(); + + (function testEmitAborted() { + gently.expect(form, 'emit',function(event) { + assert.equal(event, 'aborted'); + }); + gently.expect(form, '_error'); + + emit.aborted(); + })(); + + + (function testEmitData() { + var BUFFER = [1, 2, 3]; + gently.expect(form, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + }); + emit.data(BUFFER); + })(); + + (function testEmitEnd() { + form._parser = {}; + + (function testWithError() { + var ERR = new Error('haha'); + gently.expect(form._parser, 'end', function() { + return ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + emit.end(); + })(); + + (function testWithoutError() { + gently.expect(form._parser, 'end'); + emit.end(); + })(); + + (function testAfterError() { + form.error = true; + emit.end(); + })(); + })(); + + (function testWithCallback() { + gently.expect(EventEmitterStub, 'call'); + var form = new IncomingForm(), + REQ = {headers: {}}, + parseCalled = 0; + + gently.expect(form, 'on', 4, function(event, fn) { + if (event == 'field') { + fn('field1', 'foo'); + fn('field1', 'bar'); + fn('field2', 'nice'); + } + + if (event == 'file') { + fn('file1', '1'); + fn('file1', '2'); + fn('file2', '3'); + } + + if (event == 'end') { + fn(); + } + return this; + }); + + gently.expect(form, 'writeHeaders'); + + gently.expect(REQ, 'on', 4, function() { + return this; + }); + + var parseCbOk = function (err, fields, files) { + assert.deepEqual(fields, {field1: 'bar', field2: 'nice'}); + assert.deepEqual(files, {file1: '2', file2: '3'}); + }; + form.parse(REQ, parseCbOk); + + var ERR = new Error('test'); + gently.expect(form, 'on', 3, function(event, fn) { + if (event == 'field') { + fn('foo', 'bar'); + } + + if (event == 'error') { + fn(ERR); + gently.expect(form, 'on'); + gently.expect(form, 'writeHeaders'); + gently.expect(REQ, 'on', 4, function() { + return this; + }); + } + return this; + }); + + form.parse(REQ, function parseCbErr(err, fields, files) { + assert.strictEqual(err, ERR); + assert.deepEqual(fields, {foo: 'bar'}); + }); + })(); + + (function testWriteOrder() { + gently.expect(EventEmitterStub, 'call'); + var form = new IncomingForm(); + var REQ = new events.EventEmitter(); + var BUF = {}; + var DATACB = null; + + REQ.on('newListener', function(event, fn) { + if ('data' === event) fn(BUF); + }); + + gently.expect(form, 'writeHeaders'); + gently.expect(form, 'write', function(buf) { + assert.strictEqual(buf, BUF); + }); + + form.parse(REQ); + })(); +}); + +test(function pause() { + assert.strictEqual(form.pause(), false); +}); + +test(function resume() { + assert.strictEqual(form.resume(), false); +}); + + +test(function writeHeaders() { + var HEADERS = {}; + gently.expect(form, '_parseContentLength'); + gently.expect(form, '_parseContentType'); + + form.writeHeaders(HEADERS); + assert.strictEqual(form.headers, HEADERS); +}); + +test(function write() { + var parser = {}, + BUFFER = [1, 2, 3]; + + form._parser = parser; + form.bytesExpected = 523423; + + (function testBasic() { + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, BUFFER.length); + assert.equal(bytesExpected, form.bytesExpected); + }); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length; + }); + + assert.equal(form.write(BUFFER), BUFFER.length); + assert.equal(form.bytesReceived, BUFFER.length); + })(); + + (function testParserError() { + gently.expect(form, 'emit'); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length - 1; + }); + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/parser error/i)); + }); + + assert.equal(form.write(BUFFER), BUFFER.length - 1); + assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length); + })(); + + (function testUninitialized() { + delete form._parser; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unintialized parser/i)); + }); + form.write(BUFFER); + })(); +}); + +test(function parseContentType() { + var HEADERS = {}; + + form.headers = {'content-type': 'application/x-www-form-urlencoded'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + // accept anything that has 'urlencoded' in it + form.headers = {'content-type': 'broken-client/urlencoded-stupid'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + var BOUNDARY = '---------------------------57814261102167618332366269'; + form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + + (function testQuotedBoundary() { + form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + })(); + + (function testNoBoundary() { + form.headers = {'content-type': 'multipart/form-data'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no multipart boundary/i)); + }); + form._parseContentType(); + })(); + + (function testNoContentType() { + form.headers = {}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no content-type/i)); + }); + form._parseContentType(); + })(); + + (function testUnknownContentType() { + form.headers = {'content-type': 'invalid'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unknown content-type/i)); + }); + form._parseContentType(); + })(); +}); + +test(function parseContentLength() { + var HEADERS = {}; + + form.headers = {}; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 0); + }); + form._parseContentLength(); + + form.headers['content-length'] = '8'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesReceived, 0); + assert.strictEqual(form.bytesExpected, 8); + + // JS can be evil, lets make sure we are not + form.headers['content-length'] = '08'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesExpected, 8); +}); + +test(function _initMultipart() { + var BOUNDARY = '123', + PARSER; + + gently.expect(MultipartParserStub, 'new', function() { + PARSER = this; + }); + + gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + + form._initMultipart(BOUNDARY); + assert.equal(form.type, 'multipart'); + assert.strictEqual(form._parser, PARSER); + + (function testRegularField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.strictEqual(part, PART); + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field1"' + , 'foo': 'bar' + } + ); + assert.equal(part.name, 'field1'); + + var strings = ['hello', ' world']; + gently.expect(part, 'emit', 2, function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), strings.shift()); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10); + PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('foo'), 0, 3); + PARSER.onHeaderValue(new Buffer('bar'), 0, 3); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('hello world'), 0, 5); + PARSER.onPartData(new Buffer('hello world'), 5, 11); + PARSER.onPartEnd(); + })(); + + (function testFileField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"' + , 'content-type': 'text/plain' + } + ); + assert.equal(part.name, 'field2'); + assert.equal(part.filename, 'Sun"et.jpg'); + assert.equal(part.mime, 'text/plain'); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), '... contents of file1.txt ...'); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12); + PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29); + PARSER.onPartEnd(); + })(); + + (function testEnd() { + gently.expect(form, '_maybeEnd'); + PARSER.onEnd(); + assert.ok(form.ended); + })(); +}); + +test(function _fileName() { + // TODO + return; +}); + +test(function _initUrlencoded() { + var PARSER; + + gently.expect(QuerystringParserStub, 'new', function() { + PARSER = this; + }); + + form._initUrlencoded(); + assert.equal(form.type, 'urlencoded'); + assert.strictEqual(form._parser, PARSER); + + (function testOnField() { + var KEY = 'KEY', VAL = 'VAL'; + gently.expect(form, 'emit', function(field, key, val) { + assert.equal(field, 'field'); + assert.equal(key, KEY); + assert.equal(val, VAL); + }); + + PARSER.onField(KEY, VAL); + })(); + + (function testOnEnd() { + gently.expect(form, '_maybeEnd'); + + PARSER.onEnd(); + assert.equal(form.ended, true); + })(); +}); + +test(function _error() { + var ERR = new Error('bla'); + + gently.expect(form, 'pause'); + gently.expect(form, 'emit', function(event, err) { + assert.equal(event, 'error'); + assert.strictEqual(err, ERR); + }); + + form._error(ERR); + assert.strictEqual(form.error, ERR); + + // make sure _error only does its thing once + form._error(ERR); +}); + +test(function onPart() { + var PART = {}; + gently.expect(form, 'handlePart', function(part) { + assert.strictEqual(part, PART); + }); + + form.onPart(PART); +}); + +test(function handlePart() { + (function testUtf8Field() { + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field'); + assert.equal(value, 'hello world: €'); + }); + + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testBinaryField() { + var PART = new events.EventEmitter(); + PART.name = 'my_field2'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field2'); + assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary')); + }); + + form.encoding = 'binary'; + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testFieldSize() { + form.maxFieldsSize = 8; + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, '_error', function(err) { + assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data'); + }); + + form.handlePart(PART); + form._fieldsSize = 1; + PART.emit('data', new Buffer(7)); + PART.emit('data', new Buffer(1)); + })(); + + (function testFilePart() { + var PART = new events.EventEmitter(), + FILE = new events.EventEmitter(), + PATH = '/foo/bar'; + + PART.name = 'my_file'; + PART.filename = 'sweet.txt'; + PART.mime = 'sweet.txt'; + + gently.expect(form, '_uploadPath', function(filename) { + assert.equal(filename, PART.filename); + return PATH; + }); + + gently.expect(FileStub, 'new', function(properties) { + assert.equal(properties.path, PATH); + assert.equal(properties.name, PART.filename); + assert.equal(properties.type, PART.mime); + FILE = this; + + gently.expect(form, 'emit', function (event, field, file) { + assert.equal(event, 'fileBegin'); + assert.strictEqual(field, PART.name); + assert.strictEqual(file, FILE); + }); + + gently.expect(FILE, 'open'); + }); + + form.handlePart(PART); + assert.equal(form._flushing, 1); + + var BUFFER; + gently.expect(form, 'pause'); + gently.expect(FILE, 'write', function(buffer, cb) { + assert.strictEqual(buffer, BUFFER); + gently.expect(form, 'resume'); + // @todo handle cb(new Err) + cb(); + }); + + PART.emit('data', BUFFER = new Buffer('test')); + + gently.expect(FILE, 'end', function(cb) { + gently.expect(form, 'emit', function(event, field, file) { + assert.equal(event, 'file'); + assert.strictEqual(file, FILE); + }); + + gently.expect(form, '_maybeEnd'); + + cb(); + assert.equal(form._flushing, 0); + }); + + PART.emit('end'); + })(); +}); + +test(function _uploadPath() { + (function testUniqueId() { + var UUID_A, UUID_B; + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + assert.equal(uploadDir, form.uploadDir); + UUID_A = uuid; + }); + form._uploadPath(); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + UUID_B = uuid; + }); + form._uploadPath(); + + assert.notEqual(UUID_A, UUID_B); + })(); + + (function testFileExtension() { + form.keepExtensions = true; + var FILENAME = 'foo.jpg', + EXT = '.bar'; + + gently.expect(GENTLY.hijacked.path, 'extname', function(filename) { + assert.equal(filename, FILENAME); + gently.restore(path, 'extname'); + + return EXT; + }); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) { + assert.equal(path.extname(name), EXT); + }); + form._uploadPath(FILENAME); + })(); +}); + +test(function _maybeEnd() { + gently.expect(form, 'emit', 0); + form._maybeEnd(); + + form.ended = true; + form._flushing = 1; + form._maybeEnd(); + + gently.expect(form, 'emit', function(event) { + assert.equal(event, 'end'); + }); + + form.ended = true; + form._flushing = 0; + form._maybeEnd(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js new file mode 100644 index 0000000..bf2cd5e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js @@ -0,0 +1,50 @@ +var common = require('../common'); +var multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + events = require('events'), + Buffer = require('buffer').Buffer, + parser; + +function test(test) { + parser = new MultipartParser(); + test(); +} + +test(function constructor() { + assert.equal(parser.boundary, null); + assert.equal(parser.state, 0); + assert.equal(parser.flags, 0); + assert.equal(parser.boundaryChars, null); + assert.equal(parser.index, null); + assert.equal(parser.lookbehind, null); + assert.equal(parser.constructor.name, 'MultipartParser'); +}); + +test(function initWithBoundary() { + var boundary = 'abc'; + parser.initWithBoundary(boundary); + assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]); + assert.equal(parser.state, multipartParser.START); + + assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true}); +}); + +test(function parserError() { + var boundary = 'abc', + buffer = new Buffer(5); + + parser.initWithBoundary(boundary); + buffer.write('--ad', 'ascii', 0); + assert.equal(parser.write(buffer), 5); +}); + +test(function end() { + (function testError() { + assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain()); + })(); + + (function testRegular() { + parser.state = multipartParser.END; + assert.strictEqual(parser.end(), undefined); + })(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js new file mode 100644 index 0000000..54d3e2d --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js @@ -0,0 +1,45 @@ +var common = require('../common'); +var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser, + Buffer = require('buffer').Buffer, + gently, + parser; + +function test(test) { + gently = new Gently(); + parser = new QuerystringParser(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.equal(parser.buffer, ''); + assert.equal(parser.constructor.name, 'QuerystringParser'); +}); + +test(function write() { + var a = new Buffer('a=1'); + assert.equal(parser.write(a), a.length); + + var b = new Buffer('&b=2'); + parser.write(b); + assert.equal(parser.buffer, a + b); +}); + +test(function end() { + var FIELDS = {a: ['b', {c: 'd'}], e: 'f'}; + + gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) { + assert.equal(str, parser.buffer); + return FIELDS; + }); + + gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) { + assert.deepEqual(FIELDS[key], val); + }); + + gently.expect(parser, 'onEnd'); + + parser.buffer = 'my buffer'; + parser.end(); + assert.equal(parser.buffer, ''); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js new file mode 100644 index 0000000..b35ffd6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js @@ -0,0 +1,71 @@ +var common = require('../common'); +var BOUNDARY = '---------------------------10102754414578508781458777923', + FIXTURE = TEST_FIXTURES+'/multi_video.upload', + fs = require('fs'), + http = require('http'), + formidable = require(common.lib + '/index'), + server = http.createServer(); + +server.on('request', function(req, res) { + var form = new formidable.IncomingForm(), + uploads = {}; + + form.uploadDir = TEST_TMP; + form.hash = 'sha1'; + form.parse(req); + + form + .on('fileBegin', function(field, file) { + assert.equal(field, 'upload'); + + var tracker = {file: file, progress: [], ended: false}; + uploads[file.name] = tracker; + file + .on('progress', function(bytesReceived) { + tracker.progress.push(bytesReceived); + assert.equal(bytesReceived, file.size); + }) + .on('end', function() { + tracker.ended = true; + }); + }) + .on('field', function(field, value) { + assert.equal(field, 'title'); + assert.equal(value, ''); + }) + .on('file', function(field, file) { + assert.equal(field, 'upload'); + assert.strictEqual(uploads[file.name].file, file); + }) + .on('end', function() { + assert.ok(uploads['shortest_video.flv']); + assert.ok(uploads['shortest_video.flv'].ended); + assert.ok(uploads['shortest_video.flv'].progress.length > 3); + assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a'); + assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.size); + assert.ok(uploads['shortest_video.mp4']); + assert.ok(uploads['shortest_video.mp4'].ended); + assert.ok(uploads['shortest_video.mp4'].progress.length > 3); + assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f'); + + server.close(); + res.writeHead(200); + res.end('good'); + }); +}); + +server.listen(TEST_PORT, function() { + var stat, headers, request, fixture; + + stat = fs.statSync(FIXTURE); + request = http.request({ + port: TEST_PORT, + path: '/', + method: 'POST', + headers: { + 'content-type': 'multipart/form-data; boundary='+BOUNDARY, + 'content-length': stat.size, + }, + }); + fs.createReadStream(FIXTURE).pipe(request); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js new file mode 100755 index 0000000..02d6d5c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js @@ -0,0 +1 @@ +require('urun')(__dirname) diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js new file mode 100644 index 0000000..4ea4431 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js @@ -0,0 +1,27 @@ +var assert = require('assert'); +var http = require('http'); +var net = require('net'); +var formidable = require('../../lib/index'); + +var server = http.createServer(function (req, res) { + var form = new formidable.IncomingForm(); + var aborted_received = false; + form.on('aborted', function () { + aborted_received = true; + }); + form.on('error', function () { + assert(aborted_received, 'Error event should follow aborted'); + server.close(); + }); + form.on('end', function () { + throw new Error('Unexpected "end" event'); + }); + form.parse(req); +}).listen(0, 'localhost', function () { + var client = net.connect(server.address().port); + client.write( + "POST / HTTP/1.1\r\n" + + "Content-Length: 70\r\n" + + "Content-Type: multipart/form-data; boundary=foo\r\n\r\n"); + client.end(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js new file mode 100644 index 0000000..165628a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js @@ -0,0 +1,48 @@ +var assert = require('assert'); +var common = require('../common'); +var formidable = require('../../lib/index'); +var http = require('http'); + +var server = http.createServer(function(req, res) { + var form = new formidable.IncomingForm(); + form.uploadDir = common.dir.tmp; + form.on('end', function () { + throw new Error('Unexpected "end" event'); + }); + form.on('error', function (e) { + res.writeHead(500); + res.end(e.message); + }); + form.parse(req); +}); + +server.listen(0, function() { + var body = + '--foo\r\n' + + 'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' + + 'Content-Type: application/octet-stream\r\n' + + '\r\nThis is the first file\r\n' + + '--foo\r\n' + + 'Content-Type: application/octet-stream\r\n' + + 'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' + + 'Content-Transfer-Encoding: unknown\r\n' + + '\r\nThis is the second file\r\n' + + '--foo--\r\n'; + + var req = http.request({ + method: 'POST', + port: server.address().port, + headers: { + 'Content-Length': body.length, + 'Content-Type': 'multipart/form-data; boundary=foo' + } + }); + req.on('response', function (res) { + assert.equal(res.statusCode, 500); + res.on('data', function () {}); + res.on('end', function () { + server.close(); + }); + }); + req.end(body); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js new file mode 100644 index 0000000..1939328 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js @@ -0,0 +1,49 @@ +var http = require('http'), + formidable = require('../../lib/index'), + request = require('request'), + assert = require('assert'); + +var host = 'localhost'; + +var index = [ + '
    ', + ' ', + ' ', + '
    ' +].join("\n"); + +var server = http.createServer(function(req, res) { + + // Show a form for testing purposes. + if (req.method == 'GET') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end(index); + return; + } + + // Parse form and write results to response. + var form = new formidable.IncomingForm(); + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write(JSON.stringify({err: err, fields: fields, files: files})); + res.end(); + }); + +}).listen(0, host, function() { + + console.log("Server up and running..."); + + var server = this, + url = 'http://' + host + ':' + server.address().port; + + var parts = [ + {'Content-Disposition': 'form-data; name="foo"', 'body': 'bar'} + ] + + var req = request({method: 'POST', url: url, multipart: parts}, function(e, res, body) { + var obj = JSON.parse(body); + assert.equal("bar", obj.fields.foo); + server.close(); + }); + +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html b/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html new file mode 100644 index 0000000..48ad92e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html @@ -0,0 +1,67 @@ + + + Convert a file to a base64 request + + + + + + + +
    +
    +
    +
    +
    +
    +

    +Don't forget to save the output with windows (CRLF) line endings! +

    + + + diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js new file mode 100644 index 0000000..fc8f36e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js @@ -0,0 +1,33 @@ +var common = require('../common'); +var test = require('utest'); +var assert = common.assert; +var File = common.require('file'); + +var file; +var now = new Date; +test('IncomingForm', { + before: function() { + file = new File({ + size: 1024, + path: '/tmp/cat.png', + name: 'cat.png', + type: 'image/png', + lastModifiedDate: now, + filename: 'cat.png', + mime: 'image/png' + }) + }, + + '#toJSON()': function() { + var obj = file.toJSON(); + var len = Object.keys(obj).length; + assert.equal(1024, obj.size); + assert.equal('/tmp/cat.png', obj.path); + assert.equal('cat.png', obj.name); + assert.equal('image/png', obj.type); + assert.equal('image/png', obj.mime); + assert.equal('cat.png', obj.filename); + assert.equal(now, obj.mtime); + assert.equal(len, 8); + } +}); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js new file mode 100644 index 0000000..fe2ac1c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js @@ -0,0 +1,63 @@ +var common = require('../common'); +var test = require('utest'); +var assert = common.assert; +var IncomingForm = common.require('incoming_form').IncomingForm; +var path = require('path'); + +var form; +test('IncomingForm', { + before: function() { + form = new IncomingForm(); + }, + + '#_fileName with regular characters': function() { + var filename = 'foo.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'foo.txt'); + }, + + '#_fileName with unescaped quote': function() { + var filename = 'my".txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with escaped quote': function() { + var filename = 'my%22.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with bad quote and additional sub-header': function() { + var filename = 'my".txt'; + var header = makeHeader(filename) + '; foo="bar"'; + assert.equal(form._fileName(header), filename); + }, + + '#_fileName with semicolon': function() { + var filename = 'my;.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my;.txt'); + }, + + '#_fileName with utf8 character': function() { + var filename = 'my☃.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt'); + }, + + '#_uploadPath strips harmful characters from extension when keepExtensions': function() { + form.keepExtensions = true; + + var ext = path.extname(form._uploadPath('fine.jpg?foo=bar')); + assert.equal(ext, '.jpg'); + + var ext = path.extname(form._uploadPath('fine?foo=bar')); + assert.equal(ext, ''); + + var ext = path.extname(form._uploadPath('super.cr2+dsad')); + assert.equal(ext, '.cr2'); + + var ext = path.extname(form._uploadPath('super.bar')); + assert.equal(ext, '.bar'); + }, +}); + +function makeHeader(filename) { + return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"'; +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js new file mode 100644 index 0000000..9f1cef8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js @@ -0,0 +1,47 @@ +var http = require('http'); +var fs = require('fs'); +var connections = 0; + +var server = http.createServer(function(req, res) { + var socket = req.socket; + console.log('Request: %s %s -> %s', req.method, req.url, socket.filename); + + req.on('end', function() { + if (req.url !== '/') { + res.end(JSON.stringify({ + method: req.method, + url: req.url, + filename: socket.filename, + })); + return; + } + + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + }); +}); + +server.on('connection', function(socket) { + connections++; + + socket.id = connections; + socket.filename = 'connection-' + socket.id + '.http'; + socket.file = fs.createWriteStream(socket.filename); + socket.pipe(socket.file); + + console.log('--> %s', socket.filename); + socket.on('close', function() { + console.log('<-- %s', socket.filename); + }); +}); + +var port = process.env.PORT || 8080; +server.listen(port, function() { + console.log('Recording connections on port %s', port); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/pause/.npmignore b/node_modules/express/node_modules/connect/node_modules/pause/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/connect/node_modules/pause/History.md b/node_modules/express/node_modules/connect/node_modules/pause/History.md new file mode 100644 index 0000000..c8aa68f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/History.md @@ -0,0 +1,5 @@ + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/connect/node_modules/pause/Makefile b/node_modules/express/node_modules/connect/node_modules/pause/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/Readme.md b/node_modules/express/node_modules/connect/node_modules/pause/Readme.md new file mode 100644 index 0000000..1cdd68a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/Readme.md @@ -0,0 +1,29 @@ + +# pause + + Pause streams... + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/index.js b/node_modules/express/node_modules/connect/node_modules/pause/index.js new file mode 100644 index 0000000..1b7b379 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/index.js @@ -0,0 +1,29 @@ + +module.exports = function(obj){ + var onData + , onEnd + , events = []; + + // buffer data + obj.on('data', onData = function(data, encoding){ + events.push(['data', data, encoding]); + }); + + // buffer end + obj.on('end', onEnd = function(data, encoding){ + events.push(['end', data, encoding]); + }); + + return { + end: function(){ + obj.removeListener('data', onData); + obj.removeListener('end', onEnd); + }, + resume: function(){ + this.end(); + for (var i = 0, len = events.length; i < len; ++i) { + obj.emit.apply(obj, events[i]); + } + } + }; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/package.json b/node_modules/express/node_modules/connect/node_modules/pause/package.json new file mode 100644 index 0000000..84221f9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/package.json @@ -0,0 +1,25 @@ +{ + "name": "pause", + "version": "0.0.1", + "description": "Pause streams...", + "keywords": [], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "index", + "readme": "\n# pause\n\n Pause streams...\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "pause@0.0.1", + "dist": { + "shasum": "e105f34d8354a6de38513898cbc178d85cb098e7" + }, + "_from": "pause@0.0.1", + "_resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "scripts": {} +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules b/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules new file mode 100644 index 0000000..49e31da --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.npmignore b/node_modules/express/node_modules/connect/node_modules/qs/.npmignore new file mode 100644 index 0000000..e85ce2a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.npmignore @@ -0,0 +1,7 @@ +test +.travis.yml +benchmark.js +component.json +examples.js +History.md +Makefile diff --git a/node_modules/express/node_modules/connect/node_modules/qs/Readme.md b/node_modules/express/node_modules/connect/node_modules/qs/Readme.md new file mode 100644 index 0000000..27e54a4 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/index.js b/node_modules/express/node_modules/connect/node_modules/qs/index.js new file mode 100644 index 0000000..590491e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/index.js @@ -0,0 +1,387 @@ +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Object#hasOwnProperty ref + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Array#indexOf shim. + */ + +var indexOf = typeof Array.prototype.indexOf === 'function' + ? function(arr, el) { return arr.indexOf(el); } + : function(arr, el) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === el) return i; + } + return -1; + }; + +/** + * Array.isArray shim. + */ + +var isArray = Array.isArray || function(arr) { + return toString.call(arr) == '[object Array]'; +}; + +/** + * Object.keys shim. + */ + +var objectKeys = Object.keys || function(obj) { + var ret = []; + for (var key in obj) ret.push(key); + return ret; +}; + +/** + * Array#forEach shim. + */ + +var forEach = typeof Array.prototype.forEach === 'function' + ? function(arr, fn) { return arr.forEach(fn); } + : function(arr, fn) { + for (var i = 0; i < arr.length; i++) fn(arr[i]); + }; + +/** + * Array#reduce shim. + */ + +var reduce = function(arr, fn, initial) { + if (typeof arr.reduce === 'function') return arr.reduce(fn, initial); + var res = initial; + for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]); + return res; +}; + +/** + * Create a nullary object if possible + */ + +function createObject() { + return Object.create + ? Object.create(null) + : {}; +} + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = createObject(); + var t = createObject(); + for (var i in parent[key]) { + if (hasOwnProperty.call(parent[key], i)) { + t[i] = parent[key][i]; + } + } + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[objectKeys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~indexOf(part, ']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~indexOf(key, ']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && isArray(parent.base)) { + var t = createObject(); + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Compact sparse arrays. + */ + +function compact(obj) { + if ('object' != typeof obj) return obj; + + if (isArray(obj)) { + var ret = []; + + for (var i in obj) { + if (hasOwnProperty.call(obj, i)) { + ret.push(obj[i]); + } + } + + return ret; + } + + for (var key in obj) { + obj[key] = compact(obj[key]); + } + + return obj; +} + +/** + * Restore Object.prototype. + * see pull-request #58 + */ + +function restoreProto(obj) { + if (!Object.create) return obj; + if (isArray(obj)) return obj; + if (obj && 'object' != typeof obj) return obj; + + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + obj[key] = restoreProto(obj[key]); + } + } + + obj.__proto__ = Object.prototype; + return obj; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + + forEach(objectKeys(obj), function(name){ + merge(ret, name, obj[name]); + }); + + return compact(ret.base); +} + +/** + * Parse the given str. + */ + +function parseString(str){ + var ret = reduce(String(str).split('&'), function(ret, pair){ + var eql = indexOf(pair, '=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(indexOf(val, '=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + if ('' == key) return ret; + + return merge(ret, decode(key), decode(val)); + }, { base: createObject() }).base; + + return restoreProto(compact(ret)); +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + encodeURIComponent(String(obj)); + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '[' + i + ']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = objectKeys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + if ('' == key) continue; + if (null == obj[key]) { + ret.push(encodeURIComponent(key) + '='); + } else { + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/package.json b/node_modules/express/node_modules/connect/node_modules/qs/package.json new file mode 100644 index 0000000..7ae39ca --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/package.json @@ -0,0 +1,38 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.6.5", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "scripts": { + "test": "make test" + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "qs@0.6.5", + "dist": { + "shasum": "ed0dd8b3d3ba67dafc839eaa1238de88f286333d" + }, + "_from": "qs@0.6.5", + "_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz" +} diff --git a/node_modules/express/node_modules/connect/node_modules/uid2/index.js b/node_modules/express/node_modules/connect/node_modules/uid2/index.js new file mode 100644 index 0000000..d665f51 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/uid2/index.js @@ -0,0 +1,49 @@ +/** + * Module dependencies + */ + +var crypto = require('crypto'); + +/** + * The size ratio between a base64 string and the equivalent byte buffer + */ + +var ratio = Math.log(64) / Math.log(256); + +/** + * Make a Base64 string ready for use in URLs + * + * @param {String} + * @returns {String} + * @api private + */ + +function urlReady(str) { + return str.replace(/\+/g, '_').replace(/\//g, '-'); +} + +/** + * Generate an Unique Id + * + * @param {Number} length The number of chars of the uid + * @param {Number} cb (optional) Callback for async uid generation + * @api public + */ + +function uid(length, cb) { + var numbytes = Math.ceil(length * ratio); + if (typeof cb === 'undefined') { + return urlReady(crypto.randomBytes(numbytes).toString('base64').slice(0, length)); + } else { + crypto.randomBytes(numbytes, function(err, bytes) { + if (err) return cb(err); + cb(null, urlReady(bytes.toString('base64').slice(0, length))); + }) + } +} + +/** + * Exports + */ + +module.exports = uid; diff --git a/node_modules/express/node_modules/connect/node_modules/uid2/package.json b/node_modules/express/node_modules/connect/node_modules/uid2/package.json new file mode 100644 index 0000000..851f66e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/uid2/package.json @@ -0,0 +1,16 @@ +{ + "name": "uid2", + "description": "strong uid", + "tags": [ + "uid" + ], + "version": "0.0.2", + "dependencies": {}, + "_id": "uid2@0.0.2", + "readme": "ERROR: No README.md file found!", + "dist": { + "shasum": "e422b8be7dd45ed1fc0cf6801d85f25efced9ab6" + }, + "_from": "uid2@0.0.2", + "_resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.2.tgz" +} diff --git a/node_modules/express/node_modules/connect/package.json b/node_modules/express/node_modules/connect/package.json new file mode 100644 index 0000000..b7621f2 --- /dev/null +++ b/node_modules/express/node_modules/connect/package.json @@ -0,0 +1,56 @@ +{ + "name": "connect", + "version": "2.8.4", + "description": "High performance middleware framework", + "keywords": [ + "framework", + "web", + "middleware", + "connect", + "rack" + ], + "repository": { + "type": "git", + "url": "git://github.com/senchalabs/connect.git" + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "dependencies": { + "qs": "0.6.5", + "formidable": "1.0.14", + "cookie-signature": "1.0.1", + "buffer-crc32": "0.2.1", + "cookie": "0.1.0", + "send": "0.1.3", + "bytes": "0.2.0", + "fresh": "0.1.0", + "pause": "0.0.1", + "uid2": "0.0.2", + "debug": "*", + "methods": "0.0.1" + }, + "devDependencies": { + "should": "*", + "mocha": "*", + "jade": "*", + "dox": "*" + }, + "main": "index", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "make" + }, + "readme": "[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect)\n# Connect\n\n Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance \"plugins\" known as _middleware_.\n\n Connect is bundled with over _20_ commonly used middleware, including\n a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/).\n\n```js\nvar connect = require('connect')\n , http = require('http');\n\nvar app = connect()\n .use(connect.favicon())\n .use(connect.logger('dev'))\n .use(connect.static('public'))\n .use(connect.directory('public'))\n .use(connect.cookieParser())\n .use(connect.session({ secret: 'my secret here' }))\n .use(function(req, res){\n res.end('Hello from Connect!\\n');\n });\n\nhttp.createServer(app).listen(3000);\n```\n\n## Middleware\n\n - [csrf](http://www.senchalabs.org/connect/csrf.html)\n - [basicAuth](http://www.senchalabs.org/connect/basicAuth.html)\n - [bodyParser](http://www.senchalabs.org/connect/bodyParser.html)\n - [json](http://www.senchalabs.org/connect/json.html)\n - [multipart](http://www.senchalabs.org/connect/multipart.html)\n - [urlencoded](http://www.senchalabs.org/connect/urlencoded.html)\n - [cookieParser](http://www.senchalabs.org/connect/cookieParser.html)\n - [directory](http://www.senchalabs.org/connect/directory.html)\n - [compress](http://www.senchalabs.org/connect/compress.html)\n - [errorHandler](http://www.senchalabs.org/connect/errorHandler.html)\n - [favicon](http://www.senchalabs.org/connect/favicon.html)\n - [limit](http://www.senchalabs.org/connect/limit.html)\n - [logger](http://www.senchalabs.org/connect/logger.html)\n - [methodOverride](http://www.senchalabs.org/connect/methodOverride.html)\n - [query](http://www.senchalabs.org/connect/query.html)\n - [responseTime](http://www.senchalabs.org/connect/responseTime.html)\n - [session](http://www.senchalabs.org/connect/session.html)\n - [static](http://www.senchalabs.org/connect/static.html)\n - [staticCache](http://www.senchalabs.org/connect/staticCache.html)\n - [vhost](http://www.senchalabs.org/connect/vhost.html)\n - [subdomains](http://www.senchalabs.org/connect/subdomains.html)\n - [cookieSession](http://www.senchalabs.org/connect/cookieSession.html)\n\n## Running Tests\n\nfirst:\n\n $ npm install -d\n\nthen:\n\n $ make test\n\n## Authors\n\n Below is the output from [git-summary](http://github.com/visionmedia/git-extras).\n\n\n project: connect\n commits: 2033\n active : 301 days\n files : 171\n authors: \n 1414\tTj Holowaychuk 69.6%\n 298\tvisionmedia 14.7%\n 191\tTim Caswell 9.4%\n 51\tTJ Holowaychuk 2.5%\n 10\tRyan Olds 0.5%\n 8\tAstro 0.4%\n 5\tNathan Rajlich 0.2%\n 5\tJakub Nešetřil 0.2%\n 3\tDaniel Dickison 0.1%\n 3\tDavid Rio Deiros 0.1%\n 3\tAlexander Simmerl 0.1%\n 3\tAndreas Lind Petersen 0.1%\n 2\tAaron Heckmann 0.1%\n 2\tJacques Crocker 0.1%\n 2\tFabian Jakobs 0.1%\n 2\tBrian J Brennan 0.1%\n 2\tAdam Malcontenti-Wilson 0.1%\n 2\tGlen Mailer 0.1%\n 2\tJames Campos 0.1%\n 1\tTrent Mick 0.0%\n 1\tTroy Kruthoff 0.0%\n 1\tWei Zhu 0.0%\n 1\tcomerc 0.0%\n 1\tdarobin 0.0%\n 1\tnateps 0.0%\n 1\tMarco Sanson 0.0%\n 1\tArthur Taylor 0.0%\n 1\tAseem Kishore 0.0%\n 1\tBart Teeuwisse 0.0%\n 1\tCameron Howey 0.0%\n 1\tChad Weider 0.0%\n 1\tCraig Barnes 0.0%\n 1\tEran Hammer-Lahav 0.0%\n 1\tGregory McWhirter 0.0%\n 1\tGuillermo Rauch 0.0%\n 1\tJae Kwon 0.0%\n 1\tJakub Nesetril 0.0%\n 1\tJoshua Peek 0.0%\n 1\tJxck 0.0%\n 1\tAJ ONeal 0.0%\n 1\tMichael Hemesath 0.0%\n 1\tMorten Siebuhr 0.0%\n 1\tSamori Gorse 0.0%\n 1\tTom Jensen 0.0%\n\n## Node Compatibility\n\n Connect `< 1.x` is compatible with node 0.2.x\n\n\n Connect `1.x` is compatible with node 0.4.x\n\n\n Connect (_master_) `2.x` is compatible with node 0.6.x\n\n## CLA\n\n [http://sencha.com/cla](http://sencha.com/cla)\n\n## License\n\nView the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/).\n", + "readmeFilename": "Readme.md", + "_id": "connect@2.8.4", + "dist": { + "shasum": "506f31b57e4335e8be0213c6bb3be72ae168bd35" + }, + "_from": "connect@2.8.4", + "_resolved": "https://registry.npmjs.org/connect/-/connect-2.8.4.tgz" +} diff --git a/node_modules/express/node_modules/connect/test.js b/node_modules/express/node_modules/connect/test.js new file mode 100644 index 0000000..ef743f2 --- /dev/null +++ b/node_modules/express/node_modules/connect/test.js @@ -0,0 +1,8 @@ +var crypto = require('crypto') + +exports.uid = function(len) { + return crypto.randomBytes(Math.ceil(len * 3 / 4)) + .toString('hex') +}; + +console.log(exports.uid(10)); diff --git a/node_modules/express/node_modules/cookie-signature/.npmignore b/node_modules/express/node_modules/cookie-signature/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/cookie-signature/History.md b/node_modules/express/node_modules/cookie-signature/History.md new file mode 100644 index 0000000..9e30179 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/History.md @@ -0,0 +1,11 @@ + +1.0.1 / 2013-04-15 +================== + + * Revert "Changed underlying HMAC algo. to sha512." + * Revert "Fix for timing attacks on MAC verification." + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/cookie-signature/Makefile b/node_modules/express/node_modules/cookie-signature/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/cookie-signature/Readme.md b/node_modules/express/node_modules/cookie-signature/Readme.md new file mode 100644 index 0000000..2559e84 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/Readme.md @@ -0,0 +1,42 @@ + +# cookie-signature + + Sign and unsign cookies. + +## Example + +```js +var cookie = require('cookie-signature'); + +var val = cookie.sign('hello', 'tobiiscool'); +val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI'); + +var val = cookie.sign('hello', 'tobiiscool'); +cookie.unsign(val, 'tobiiscool').should.equal('hello'); +cookie.unsign(val, 'luna').should.be.false; +``` + +## License + +(The MIT License) + +Copyright (c) 2012 LearnBoost <tj@learnboost.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. \ No newline at end of file diff --git a/node_modules/express/node_modules/cookie-signature/index.js b/node_modules/express/node_modules/cookie-signature/index.js new file mode 100644 index 0000000..ed62814 --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/index.js @@ -0,0 +1,42 @@ + +/** + * Module dependencies. + */ + +var crypto = require('crypto'); + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + if ('string' != typeof val) throw new TypeError('cookie required'); + if ('string' != typeof secret) throw new TypeError('secret required'); + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/\=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + if ('string' != typeof val) throw new TypeError('cookie required'); + if ('string' != typeof secret) throw new TypeError('secret required'); + var str = val.slice(0, val.lastIndexOf('.')); + return exports.sign(str, secret) == val ? str : false; +}; diff --git a/node_modules/express/node_modules/cookie-signature/package.json b/node_modules/express/node_modules/cookie-signature/package.json new file mode 100644 index 0000000..5f0730e --- /dev/null +++ b/node_modules/express/node_modules/cookie-signature/package.json @@ -0,0 +1,28 @@ +{ + "name": "cookie-signature", + "version": "1.0.1", + "description": "Sign and unsign cookies", + "keywords": [ + "cookie", + "sign", + "unsign" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@learnboost.com" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "index", + "readme": "\n# cookie-signature\n\n Sign and unsign cookies.\n\n## Example\n\n```js\nvar cookie = require('cookie-signature');\n\nvar val = cookie.sign('hello', 'tobiiscool');\nval.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');\n\nvar val = cookie.sign('hello', 'tobiiscool');\ncookie.unsign(val, 'tobiiscool').should.equal('hello');\ncookie.unsign(val, 'luna').should.be.false;\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 LearnBoost <tj@learnboost.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "cookie-signature@1.0.1", + "dist": { + "shasum": "50ccf312d91c329294a55a5cda765857946f86e2" + }, + "_from": "cookie-signature@1.0.1", + "_resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz" +} diff --git a/node_modules/express/node_modules/cookie/.npmignore b/node_modules/express/node_modules/cookie/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/express/node_modules/cookie/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/express/node_modules/cookie/.travis.yml b/node_modules/express/node_modules/cookie/.travis.yml new file mode 100644 index 0000000..9400c11 --- /dev/null +++ b/node_modules/express/node_modules/cookie/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.6" + - "0.8" + - "0.10" diff --git a/node_modules/express/node_modules/cookie/LICENSE b/node_modules/express/node_modules/cookie/LICENSE new file mode 100644 index 0000000..249d9de --- /dev/null +++ b/node_modules/express/node_modules/cookie/LICENSE @@ -0,0 +1,9 @@ +// MIT License + +Copyright (C) Roman Shtylman + +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/express/node_modules/cookie/README.md b/node_modules/express/node_modules/cookie/README.md new file mode 100644 index 0000000..5187ed1 --- /dev/null +++ b/node_modules/express/node_modules/cookie/README.md @@ -0,0 +1,44 @@ +# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) # + +cookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers. + +See [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies. + +## how? + +``` +npm install cookie +``` + +```javascript +var cookie = require('cookie'); + +var hdr = cookie.serialize('foo', 'bar'); +// hdr = 'foo=bar'; + +var cookies = cookie.parse('foo=bar; cat=meow; dog=ruff'); +// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' }; +``` + +## more + +The serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values. + +### path +> cookie path + +### expires +> absolute expiration date for the cookie (Date object) + +### maxAge +> relative max age of the cookie from when the client receives it (seconds) + +### domain +> domain for the cookie + +### secure +> true or false + +### httpOnly +> true or false + diff --git a/node_modules/express/node_modules/cookie/index.js b/node_modules/express/node_modules/cookie/index.js new file mode 100644 index 0000000..16bdb65 --- /dev/null +++ b/node_modules/express/node_modules/cookie/index.js @@ -0,0 +1,70 @@ + +/// Serialize the a name value pair into a cookie string suitable for +/// http headers. An optional options object specified cookie parameters +/// +/// serialize('foo', 'bar', { httpOnly: true }) +/// => "foo=bar; httpOnly" +/// +/// @param {String} name +/// @param {String} val +/// @param {Object} options +/// @return {String} +var serialize = function(name, val, opt){ + opt = opt || {}; + var enc = opt.encode || encode; + var pairs = [name + '=' + enc(val)]; + + if (opt.maxAge) pairs.push('Max-Age=' + opt.maxAge); + if (opt.domain) pairs.push('Domain=' + opt.domain); + if (opt.path) pairs.push('Path=' + opt.path); + if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString()); + if (opt.httpOnly) pairs.push('HttpOnly'); + if (opt.secure) pairs.push('Secure'); + + return pairs.join('; '); +}; + +/// Parse the given cookie header string into an object +/// The object has the various cookies as keys(names) => values +/// @param {String} str +/// @return {Object} +var parse = function(str, opt) { + opt = opt || {}; + var obj = {} + var pairs = str.split(/[;,] */); + var dec = opt.decode || decode; + + pairs.forEach(function(pair) { + var eq_idx = pair.indexOf('=') + + // skip things that don't look like key=value + if (eq_idx < 0) { + return; + } + + var key = pair.substr(0, eq_idx).trim() + var val = pair.substr(++eq_idx, pair.length).trim(); + + // quoted values + if ('"' == val[0]) { + val = val.slice(1, -1); + } + + // only assign once + if (undefined == obj[key]) { + try { + obj[key] = dec(val); + } catch (e) { + obj[key] = val; + } + } + }); + + return obj; +}; + +var encode = encodeURIComponent; +var decode = decodeURIComponent; + +module.exports.serialize = serialize; +module.exports.parse = parse; diff --git a/node_modules/express/node_modules/cookie/package.json b/node_modules/express/node_modules/cookie/package.json new file mode 100644 index 0000000..da59f21 --- /dev/null +++ b/node_modules/express/node_modules/cookie/package.json @@ -0,0 +1,37 @@ +{ + "author": { + "name": "Roman Shtylman", + "email": "shtylman@gmail.com" + }, + "name": "cookie", + "description": "cookie parsing and serialization", + "version": "0.1.0", + "repository": { + "type": "git", + "url": "git://github.com/shtylman/node-cookie.git" + }, + "keywords": [ + "cookie", + "cookies" + ], + "main": "index.js", + "scripts": { + "test": "mocha" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "1.x.x" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #\n\ncookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.\n\nSee [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.\n\n## how?\n\n```\nnpm install cookie\n```\n\n```javascript\nvar cookie = require('cookie');\n\nvar hdr = cookie.serialize('foo', 'bar');\n// hdr = 'foo=bar';\n\nvar cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');\n// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };\n```\n\n## more\n\nThe serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.\n\n### path\n> cookie path\n\n### expires\n> absolute expiration date for the cookie (Date object)\n\n### maxAge\n> relative max age of the cookie from when the client receives it (seconds)\n\n### domain\n> domain for the cookie\n\n### secure\n> true or false\n\n### httpOnly\n> true or false\n\n", + "readmeFilename": "README.md", + "_id": "cookie@0.1.0", + "dist": { + "shasum": "61d15d3ea55cb13125a752e2583c8ac94764fabe" + }, + "_from": "cookie@0.1.0", + "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz" +} diff --git a/node_modules/express/node_modules/cookie/test/mocha.opts b/node_modules/express/node_modules/cookie/test/mocha.opts new file mode 100644 index 0000000..e2bfcc5 --- /dev/null +++ b/node_modules/express/node_modules/cookie/test/mocha.opts @@ -0,0 +1 @@ +--ui qunit diff --git a/node_modules/express/node_modules/cookie/test/parse.js b/node_modules/express/node_modules/cookie/test/parse.js new file mode 100644 index 0000000..c6c27a2 --- /dev/null +++ b/node_modules/express/node_modules/cookie/test/parse.js @@ -0,0 +1,44 @@ + +var assert = require('assert'); + +var cookie = require('..'); + +suite('parse'); + +test('basic', function() { + assert.deepEqual({ foo: 'bar' }, cookie.parse('foo=bar')); + assert.deepEqual({ foo: '123' }, cookie.parse('foo=123')); +}); + +test('ignore spaces', function() { + assert.deepEqual({ FOO: 'bar', baz: 'raz' }, + cookie.parse('FOO = bar; baz = raz')); +}); + +test('escaping', function() { + assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' }, + cookie.parse('foo="bar=123456789&name=Magic+Mouse"')); + + assert.deepEqual({ email: ' ",;/' }, + cookie.parse('email=%20%22%2c%3b%2f')); +}); + +test('ignore escaping error and return original value', function() { + assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar')); +}); + +test('ignore non values', function() { + assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar;HttpOnly;Secure')); +}); + +test('unencoded', function() { + assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' }, + cookie.parse('foo="bar=123456789&name=Magic+Mouse"',{ + decode: function(value) { return value; } + })); + + assert.deepEqual({ email: '%20%22%2c%3b%2f' }, + cookie.parse('email=%20%22%2c%3b%2f',{ + decode: function(value) { return value; } + })); +}) diff --git a/node_modules/express/node_modules/cookie/test/serialize.js b/node_modules/express/node_modules/cookie/test/serialize.js new file mode 100644 index 0000000..86bb8c9 --- /dev/null +++ b/node_modules/express/node_modules/cookie/test/serialize.js @@ -0,0 +1,64 @@ +// builtin +var assert = require('assert'); + +var cookie = require('..'); + +suite('serialize'); + +test('basic', function() { + assert.equal('foo=bar', cookie.serialize('foo', 'bar')); + assert.equal('foo=bar%20baz', cookie.serialize('foo', 'bar baz')); +}); + +test('path', function() { + assert.equal('foo=bar; Path=/', cookie.serialize('foo', 'bar', { + path: '/' + })); +}); + +test('secure', function() { + assert.equal('foo=bar; Secure', cookie.serialize('foo', 'bar', { + secure: true + })); + + assert.equal('foo=bar', cookie.serialize('foo', 'bar', { + secure: false + })); +}); + +test('domain', function() { + assert.equal('foo=bar; Domain=example.com', cookie.serialize('foo', 'bar', { + domain: 'example.com' + })); +}); + +test('httpOnly', function() { + assert.equal('foo=bar; HttpOnly', cookie.serialize('foo', 'bar', { + httpOnly: true + })); +}); + +test('maxAge', function() { + assert.equal('foo=bar; Max-Age=1000', cookie.serialize('foo', 'bar', { + maxAge: 1000 + })); +}); + +test('escaping', function() { + assert.deepEqual('cat=%2B%20', cookie.serialize('cat', '+ ')); +}); + +test('parse->serialize', function() { + + assert.deepEqual({ cat: 'foo=123&name=baz five' }, cookie.parse( + cookie.serialize('cat', 'foo=123&name=baz five'))); + + assert.deepEqual({ cat: ' ";/' }, cookie.parse( + cookie.serialize('cat', ' ";/'))); +}); + +test('unencoded', function() { + assert.deepEqual('cat=+ ', cookie.serialize('cat', '+ ', { + encode: function(value) { return value; } + })); +}) diff --git a/node_modules/express/node_modules/debug/.npmignore b/node_modules/express/node_modules/debug/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/debug/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/debug/History.md b/node_modules/express/node_modules/debug/History.md new file mode 100644 index 0000000..f023269 --- /dev/null +++ b/node_modules/express/node_modules/debug/History.md @@ -0,0 +1,62 @@ + +0.7.2 / 2013-02-06 +================== + + * fix package.json + * fix: Mobile Safari (private mode) is broken with debug + * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript + +0.7.1 / 2013-02-05 +================== + + * add repository URL to package.json + * add DEBUG_COLORED to force colored output + * add browserify support + * fix component. Closes #24 + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/debug/Readme.md b/node_modules/express/node_modules/debug/Readme.md new file mode 100644 index 0000000..15ee501 --- /dev/null +++ b/node_modules/express/node_modules/debug/Readme.md @@ -0,0 +1,115 @@ + +# debug + + tiny node.js debugging utility modelled after node core's debugging technique. + +## Installation + +``` +$ npm install debug +``` + +## Usage + + With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility. + +Example _app.js_: + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example _worker.js_: + +```js +var debug = require('debug')('worker'); + +setInterval(function(){ + debug('doing some work'); +}, 1000); +``` + + The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: + + ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) + + ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) + +## Millisecond diff + + When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) + + When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: + + ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) + +## Conventions + + If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". + +## Wildcards + + The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + + You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:". + +## Browser support + + Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + a('doing some work'); +}, 1200); +``` + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/component.json b/node_modules/express/node_modules/debug/component.json new file mode 100644 index 0000000..4ad0971 --- /dev/null +++ b/node_modules/express/node_modules/debug/component.json @@ -0,0 +1,9 @@ +{ + "name": "debug", + "repo": "visionmedia/debug", + "description": "small debugging utility", + "version": "0.7.2", + "keywords": ["debug", "log", "debugger"], + "scripts": ["index.js", "debug.js"], + "dependencies": {} +} diff --git a/node_modules/express/node_modules/debug/debug.js b/node_modules/express/node_modules/debug/debug.js new file mode 100644 index 0000000..e47ba5b --- /dev/null +++ b/node_modules/express/node_modules/debug/debug.js @@ -0,0 +1,124 @@ + +/** + * Expose `debug()` as the module. + */ + +module.exports = debug; + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + if (!debug.enabled(name)) return function(){}; + + return function(fmt){ + var curr = new Date; + var ms = curr - (debug[name] || curr); + debug[name] = curr; + + fmt = name + + ' ' + + fmt + + ' +' + debug.humanize(ms); + + // This hackery is required for IE8 + // where `console.log` doesn't have 'apply' + window.console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); + } +} + +/** + * The currently active debug mode names. + */ + +debug.names = []; +debug.skips = []; + +/** + * Enables a debug mode by name. This can include modes + * separated by a colon and wildcards. + * + * @param {String} name + * @api public + */ + +debug.enable = function(name) { + try { + localStorage.debug = name; + } catch(e){} + + var split = (name || '').split(/[\s,]+/) + , len = split.length; + + for (var i = 0; i < len; i++) { + name = split[i].replace('*', '.*?'); + if (name[0] === '-') { + debug.skips.push(new RegExp('^' + name.substr(1) + '$')); + } + else { + debug.names.push(new RegExp('^' + name + '$')); + } + } +}; + +/** + * Disable debug output. + * + * @api public + */ + +debug.disable = function(){ + debug.enable(''); +}; + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +debug.humanize = function(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +}; + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +debug.enabled = function(name) { + for (var i = 0, len = debug.skips.length; i < len; i++) { + if (debug.skips[i].test(name)) { + return false; + } + } + for (var i = 0, len = debug.names.length; i < len; i++) { + if (debug.names[i].test(name)) { + return true; + } + } + return false; +}; + +// persist + +if (window.localStorage) debug.enable(localStorage.debug); diff --git a/node_modules/express/node_modules/debug/example/app.js b/node_modules/express/node_modules/debug/example/app.js new file mode 100644 index 0000000..05374d9 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/app.js @@ -0,0 +1,19 @@ + +var debug = require('../')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/example/browser.html b/node_modules/express/node_modules/debug/example/browser.html new file mode 100644 index 0000000..7510eee --- /dev/null +++ b/node_modules/express/node_modules/debug/example/browser.html @@ -0,0 +1,24 @@ + + + debug() + + + + + + + diff --git a/node_modules/express/node_modules/debug/example/wildcards.js b/node_modules/express/node_modules/debug/example/wildcards.js new file mode 100644 index 0000000..1fdac20 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/wildcards.js @@ -0,0 +1,10 @@ + +var debug = { + foo: require('../')('test:foo'), + bar: require('../')('test:bar'), + baz: require('../')('test:baz') +}; + +debug.foo('foo') +debug.bar('bar') +debug.baz('baz') \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/example/worker.js b/node_modules/express/node_modules/debug/example/worker.js new file mode 100644 index 0000000..7f6d288 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/worker.js @@ -0,0 +1,22 @@ + +// DEBUG=* node example/worker +// DEBUG=worker:* node example/worker +// DEBUG=worker:a node example/worker +// DEBUG=worker:b node example/worker + +var a = require('../')('worker:a') + , b = require('../')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/index.js b/node_modules/express/node_modules/debug/index.js new file mode 100644 index 0000000..e02c13b --- /dev/null +++ b/node_modules/express/node_modules/debug/index.js @@ -0,0 +1,5 @@ +if ('undefined' == typeof window) { + module.exports = require('./lib/debug'); +} else { + module.exports = require('./debug'); +} diff --git a/node_modules/express/node_modules/debug/lib/debug.js b/node_modules/express/node_modules/debug/lib/debug.js new file mode 100644 index 0000000..0b07aa1 --- /dev/null +++ b/node_modules/express/node_modules/debug/lib/debug.js @@ -0,0 +1,134 @@ +/** + * Module dependencies. + */ + +var tty = require('tty'); + +/** + * Expose `debug()` as the module. + */ + +module.exports = debug; + +/** + * Enabled debuggers. + */ + +var names = [] + , skips = []; + +(process.env.DEBUG || '') + .split(/[\s,]+/) + .forEach(function(name){ + name = name.replace('*', '.*?'); + if (name[0] === '-') { + skips.push(new RegExp('^' + name.substr(1) + '$')); + } else { + names.push(new RegExp('^' + name + '$')); + } + }); + +/** + * Colors. + */ + +var colors = [6, 2, 3, 4, 5, 1]; + +/** + * Previous debug() call. + */ + +var prev = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Is stdout a TTY? Colored output is disabled when `true`. + */ + +var isatty = tty.isatty(2); + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function color() { + return colors[prevColor++ % colors.length]; +} + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +function humanize(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +} + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + function disabled(){} + disabled.enabled = false; + + var match = skips.some(function(re){ + return re.test(name); + }); + + if (match) return disabled; + + match = names.some(function(re){ + return re.test(name); + }); + + if (!match) return disabled; + var c = color(); + + function colored(fmt) { + var curr = new Date; + var ms = curr - (prev[name] || curr); + prev[name] = curr; + + fmt = ' \u001b[9' + c + 'm' + name + ' ' + + '\u001b[3' + c + 'm\u001b[90m' + + fmt + '\u001b[3' + c + 'm' + + ' +' + humanize(ms) + '\u001b[0m'; + + console.error.apply(this, arguments); + } + + function plain(fmt) { + fmt = new Date().toUTCString() + + ' ' + name + ' ' + fmt; + console.error.apply(this, arguments); + } + + colored.enabled = plain.enabled = true; + + return isatty || process.env.DEBUG_COLORS + ? colored + : plain; +} diff --git a/node_modules/express/node_modules/debug/package.json b/node_modules/express/node_modules/debug/package.json new file mode 100644 index 0000000..6edcec1 --- /dev/null +++ b/node_modules/express/node_modules/debug/package.json @@ -0,0 +1,41 @@ +{ + "name": "debug", + "version": "0.7.2", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/debug.git" + }, + "description": "small debugging utility", + "keywords": [ + "debug", + "log", + "debugger" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*" + }, + "main": "lib/debug.js", + "browserify": "debug.js", + "engines": { + "node": "*" + }, + "component": { + "scripts": { + "debug/index.js": "index.js", + "debug/debug.js": "debug.js" + } + }, + "readme": "\n# debug\n\n tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "debug@0.7.2", + "dist": { + "shasum": "04c9bae3603aafa32ee836a7cc1b4210b4bbb0e3" + }, + "_from": "debug@*", + "_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.2.tgz" +} diff --git a/node_modules/express/node_modules/fresh/.npmignore b/node_modules/express/node_modules/fresh/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/fresh/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/fresh/Makefile b/node_modules/express/node_modules/fresh/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/fresh/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/Readme.md b/node_modules/express/node_modules/fresh/Readme.md new file mode 100644 index 0000000..273130d --- /dev/null +++ b/node_modules/express/node_modules/fresh/Readme.md @@ -0,0 +1,32 @@ + +# node-fresh + + HTTP response freshness testing + +## fresh(req, res) + + Check freshness of `req` and `res` headers. + + When the cache is "fresh" __true__ is returned, + otherwise __false__ is returned to indicate that + the cache is now stale. + +## Example: + +```js +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'luna' }; +fresh(req, res); +// => false + +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'tobi' }; +fresh(req, res); +// => true +``` + +## Installation + +``` +$ npm install fresh +``` \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/index.js b/node_modules/express/node_modules/fresh/index.js new file mode 100644 index 0000000..b2f4d41 --- /dev/null +++ b/node_modules/express/node_modules/fresh/index.js @@ -0,0 +1,49 @@ + +/** + * Expose `fresh()`. + */ + +module.exports = fresh; + +/** + * Check freshness of `req` and `res` headers. + * + * When the cache is "fresh" __true__ is returned, + * otherwise __false__ is returned to indicate that + * the cache is now stale. + * + * @param {Object} req + * @param {Object} res + * @return {Boolean} + * @api public + */ + +function fresh(req, res) { + // defaults + var etagMatches = true; + var notModified = true; + + // fields + var modifiedSince = req['if-modified-since']; + var noneMatch = req['if-none-match']; + var lastModified = res['last-modified']; + var etag = res['etag']; + + // unconditional request + if (!modifiedSince && !noneMatch) return false; + + // parse if-none-match + if (noneMatch) noneMatch = noneMatch.split(/ *, */); + + // if-none-match + if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0]; + + // if-modified-since + if (modifiedSince) { + modifiedSince = new Date(modifiedSince); + lastModified = new Date(lastModified); + notModified = lastModified <= modifiedSince; + } + + return !! (etagMatches && notModified); +} \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/package.json b/node_modules/express/node_modules/fresh/package.json new file mode 100644 index 0000000..c0e034e --- /dev/null +++ b/node_modules/express/node_modules/fresh/package.json @@ -0,0 +1,24 @@ +{ + "name": "fresh", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "HTTP response freshness testing", + "version": "0.1.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "\n# node-fresh\n\n HTTP response freshness testing\n\n## fresh(req, res)\n\n Check freshness of `req` and `res` headers.\n\n When the cache is \"fresh\" __true__ is returned,\n otherwise __false__ is returned to indicate that\n the cache is now stale.\n\n## Example:\n\n```js\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'luna' };\nfresh(req, res);\n// => false\n\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'tobi' };\nfresh(req, res);\n// => true\n```\n\n## Installation\n\n```\n$ npm install fresh\n```", + "readmeFilename": "Readme.md", + "_id": "fresh@0.1.0", + "dist": { + "shasum": "5da28e77463eb5634591dbca9cd88ca2488a2623" + }, + "_from": "fresh@0.1.0", + "_resolved": "https://registry.npmjs.org/fresh/-/fresh-0.1.0.tgz" +} diff --git a/node_modules/express/node_modules/methods/index.js b/node_modules/express/node_modules/methods/index.js new file mode 100644 index 0000000..297d022 --- /dev/null +++ b/node_modules/express/node_modules/methods/index.js @@ -0,0 +1,26 @@ + +module.exports = [ + 'get' + , 'post' + , 'put' + , 'head' + , 'delete' + , 'options' + , 'trace' + , 'copy' + , 'lock' + , 'mkcol' + , 'move' + , 'propfind' + , 'proppatch' + , 'unlock' + , 'report' + , 'mkactivity' + , 'checkout' + , 'merge' + , 'm-search' + , 'notify' + , 'subscribe' + , 'unsubscribe' + , 'patch' +]; \ No newline at end of file diff --git a/node_modules/express/node_modules/methods/package.json b/node_modules/express/node_modules/methods/package.json new file mode 100644 index 0000000..cf48d5d --- /dev/null +++ b/node_modules/express/node_modules/methods/package.json @@ -0,0 +1,24 @@ +{ + "name": "methods", + "version": "0.0.1", + "description": "HTTP methods that node supports", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "http", + "methods" + ], + "author": { + "name": "TJ Holowaychuk" + }, + "license": "MIT", + "_id": "methods@0.0.1", + "readme": "ERROR: No README.md file found!", + "dist": { + "shasum": "5c4469613ce3d23a9ec71bfca8e0061ae36473bc" + }, + "_from": "methods@0.0.1", + "_resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz" +} diff --git a/node_modules/express/node_modules/mkdirp/.npmignore b/node_modules/express/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/express/node_modules/mkdirp/.travis.yml b/node_modules/express/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/express/node_modules/mkdirp/LICENSE b/node_modules/express/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/express/node_modules/mkdirp/examples/pow.js b/node_modules/express/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/express/node_modules/mkdirp/index.js b/node_modules/express/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/express/node_modules/mkdirp/package.json b/node_modules/express/node_modules/mkdirp/package.json new file mode 100644 index 0000000..923d077 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/package.json @@ -0,0 +1,34 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.5", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.4.0" + }, + "license": "MIT", + "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n", + "readmeFilename": "readme.markdown", + "_id": "mkdirp@0.3.5", + "dist": { + "shasum": "e1874873d66a4e5111525f997f020d53f8311fdb" + }, + "_from": "mkdirp@0.3.x", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" +} diff --git a/node_modules/express/node_modules/mkdirp/readme.markdown b/node_modules/express/node_modules/mkdirp/readme.markdown new file mode 100644 index 0000000..83b0216 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/readme.markdown @@ -0,0 +1,63 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, mode, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +## mkdirp.sync(dir, mode) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +# license + +MIT diff --git a/node_modules/express/node_modules/mkdirp/test/chmod.js b/node_modules/express/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/clobber.js b/node_modules/express/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/mkdirp.js b/node_modules/express/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/perm.js b/node_modules/express/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/perm_sync.js b/node_modules/express/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/race.js b/node_modules/express/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/express/node_modules/mkdirp/test/rel.js b/node_modules/express/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/return.js b/node_modules/express/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/return_sync.js b/node_modules/express/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/root.js b/node_modules/express/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/sync.js b/node_modules/express/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/umask.js b/node_modules/express/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/umask_sync.js b/node_modules/express/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/express/node_modules/range-parser/.npmignore b/node_modules/express/node_modules/range-parser/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/range-parser/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/range-parser/History.md b/node_modules/express/node_modules/range-parser/History.md new file mode 100644 index 0000000..82df7b1 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/History.md @@ -0,0 +1,15 @@ + +0.0.4 / 2012-06-17 +================== + + * changed: ret -1 for unsatisfiable and -2 when invalid + +0.0.3 / 2012-06-17 +================== + + * fix last-byte-pos default to len - 1 + +0.0.2 / 2012-06-14 +================== + + * add `.type` diff --git a/node_modules/express/node_modules/range-parser/Makefile b/node_modules/express/node_modules/range-parser/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/range-parser/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/Readme.md b/node_modules/express/node_modules/range-parser/Readme.md new file mode 100644 index 0000000..b2a67fe --- /dev/null +++ b/node_modules/express/node_modules/range-parser/Readme.md @@ -0,0 +1,28 @@ + +# node-range-parser + + Range header field parser. + +## Example: + +```js +assert(-1 == parse(200, 'bytes=500-20')); +assert(-2 == parse(200, 'bytes=malformed')); +parse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }])); +parse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }])); +parse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }])); +parse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }])); +parse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }])); +parse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }])); +parse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }])); +parse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }])); +parse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }])); +parse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }])); +parse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }])); +``` + +## Installation + +``` +$ npm install range-parser +``` \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/index.js b/node_modules/express/node_modules/range-parser/index.js new file mode 100644 index 0000000..9b0f7a8 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/index.js @@ -0,0 +1,49 @@ + +/** + * Parse "Range" header `str` relative to the given file `size`. + * + * @param {Number} size + * @param {String} str + * @return {Array} + * @api public + */ + +module.exports = function(size, str){ + var valid = true; + var i = str.indexOf('='); + + if (-1 == i) return -2; + + var arr = str.slice(i + 1).split(',').map(function(range){ + var range = range.split('-') + , start = parseInt(range[0], 10) + , end = parseInt(range[1], 10); + + // -nnn + if (isNaN(start)) { + start = size - end; + end = size - 1; + // nnn- + } else if (isNaN(end)) { + end = size - 1; + } + + // limit last-byte-pos to current length + if (end > size - 1) end = size - 1; + + // invalid + if (isNaN(start) + || isNaN(end) + || start > end + || start < 0) valid = false; + + return { + start: start, + end: end + }; + }); + + arr.type = str.slice(0, i); + + return valid ? arr : -1; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/package.json b/node_modules/express/node_modules/range-parser/package.json new file mode 100644 index 0000000..0fe2395 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/package.json @@ -0,0 +1,24 @@ +{ + "name": "range-parser", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "Range header field string parser", + "version": "0.0.4", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "\n# node-range-parser\n\n Range header field parser.\n\n## Example:\n\n```js\nassert(-1 == parse(200, 'bytes=500-20'));\nassert(-2 == parse(200, 'bytes=malformed'));\nparse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));\nparse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));\nparse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));\nparse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));\nparse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));\nparse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));\nparse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));\nparse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));\nparse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));\n```\n\n## Installation\n\n```\n$ npm install range-parser\n```", + "readmeFilename": "Readme.md", + "_id": "range-parser@0.0.4", + "dist": { + "shasum": "9f8ca307a6661e7af15b0c03884b1bdfa2146097" + }, + "_from": "range-parser@0.0.4", + "_resolved": "https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz" +} diff --git a/node_modules/express/node_modules/send/.npmignore b/node_modules/express/node_modules/send/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/send/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/send/History.md b/node_modules/express/node_modules/send/History.md new file mode 100644 index 0000000..e348db5 --- /dev/null +++ b/node_modules/express/node_modules/send/History.md @@ -0,0 +1,35 @@ + +0.1.3 / 2013-07-08 +================== + + * Revert "Fix fd leak" + +0.1.2 / 2013-07-03 +================== + + * Fix fd leak + +0.1.0 / 2012-08-25 +================== + + * add options parameter to send() that is passed to fs.createReadStream() [kanongil] + +0.0.4 / 2012-08-16 +================== + + * allow custom "Accept-Ranges" definition + +0.0.3 / 2012-07-16 +================== + + * fix normalization of the root directory. Closes #3 + +0.0.2 / 2012-07-09 +================== + + * add passing of req explicitly for now (YUCK) + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/send/Makefile b/node_modules/express/node_modules/send/Makefile new file mode 100644 index 0000000..a9dcfd5 --- /dev/null +++ b/node_modules/express/node_modules/send/Makefile @@ -0,0 +1,8 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec \ + --bail + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/send/Readme.md b/node_modules/express/node_modules/send/Readme.md new file mode 100644 index 0000000..ea7b234 --- /dev/null +++ b/node_modules/express/node_modules/send/Readme.md @@ -0,0 +1,128 @@ +# send + + Send is Connect's `static()` extracted for generalized use, a streaming static file + server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework. + +## Installation + + $ npm install send + +## Examples + + Small: + +```js +var http = require('http'); +var send = require('send'); + +var app = http.createServer(function(req, res){ + send(req, req.url).pipe(res); +}).listen(3000); +``` + + Serving from a root directory with custom error-handling: + +```js +var http = require('http'); +var send = require('send'); +var url = require('url'); + +var app = http.createServer(function(req, res){ + // your custom error-handling logic: + function error(err) { + res.statusCode = err.status || 500; + res.end(err.message); + } + + // your custom directory handling logic: + function redirect() { + res.statusCode = 301; + res.setHeader('Location', req.url + '/'); + res.end('Redirecting to ' + req.url + '/'); + } + + // transfer arbitrary files from within + // /www/example.com/public/* + send(req, url.parse(req.url).pathname) + .root('/www/example.com/public') + .on('error', error) + .on('directory', redirect) + .pipe(res); +}).listen(3000); +``` + +## API + +### Events + + - `error` an error occurred `(err)` + - `directory` a directory was requested + - `file` a file was requested `(path, stat)` + - `stream` file streaming has started `(stream)` + - `end` streaming has completed + +### .root(dir) + + Serve files relative to `path`. Aliased as `.from(dir)`. + +### .index(path) + + By default send supports "index.html" files, to disable this + invoke `.index(false)` or to supply a new index pass a string. + +### .maxage(ms) + + Provide a max-age in milliseconds for http caching, defaults to 0. + +### .hidden(bool) + + Enable or disable transfer of hidden files, defaults to false. + +## Error-handling + + By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc. + +## Caching + + It does _not_ perform internal caching, you should use a reverse proxy cache such + as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;). + +## Debugging + + To enable `debug()` instrumentation output export __DEBUG__: + +``` +$ DEBUG=send node app +``` + +## Running tests + +``` +$ npm install +$ make test +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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/express/node_modules/send/index.js b/node_modules/express/node_modules/send/index.js new file mode 100644 index 0000000..f17158d --- /dev/null +++ b/node_modules/express/node_modules/send/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/send'); \ No newline at end of file diff --git a/node_modules/express/node_modules/send/lib/send.js b/node_modules/express/node_modules/send/lib/send.js new file mode 100644 index 0000000..a3d94a6 --- /dev/null +++ b/node_modules/express/node_modules/send/lib/send.js @@ -0,0 +1,474 @@ + +/** + * Module dependencies. + */ + +var debug = require('debug')('send') + , parseRange = require('range-parser') + , Stream = require('stream') + , mime = require('mime') + , fresh = require('fresh') + , path = require('path') + , http = require('http') + , fs = require('fs') + , basename = path.basename + , normalize = path.normalize + , join = path.join + , utils = require('./utils'); + +/** + * Expose `send`. + */ + +exports = module.exports = send; + +/** + * Expose mime module. + */ + +exports.mime = mime; + +/** + * Return a `SendStream` for `req` and `path`. + * + * @param {Request} req + * @param {String} path + * @param {Object} options + * @return {SendStream} + * @api public + */ + +function send(req, path, options) { + return new SendStream(req, path, options); +} + +/** + * Initialize a `SendStream` with the given `path`. + * + * Events: + * + * - `error` an error occurred + * - `stream` file streaming has started + * - `end` streaming has completed + * - `directory` a directory was requested + * + * @param {Request} req + * @param {String} path + * @param {Object} options + * @api private + */ + +function SendStream(req, path, options) { + var self = this; + this.req = req; + this.path = path; + this.options = options || {}; + this.maxage(0); + this.hidden(false); + this.index('index.html'); +} + +/** + * Inherits from `Stream.prototype`. + */ + +SendStream.prototype.__proto__ = Stream.prototype; + +/** + * Enable or disable "hidden" (dot) files. + * + * @param {Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.hidden = function(val){ + debug('hidden %s', val); + this._hidden = val; + return this; +}; + +/** + * Set index `path`, set to a falsy + * value to disable index support. + * + * @param {String|Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.index = function(path){ + debug('index %s', path); + this._index = path; + return this; +}; + +/** + * Set root `path`. + * + * @param {String} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.root = +SendStream.prototype.from = function(path){ + this._root = normalize(path); + return this; +}; + +/** + * Set max-age to `ms`. + * + * @param {Number} ms + * @return {SendStream} + * @api public + */ + +SendStream.prototype.maxage = function(ms){ + if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000; + debug('max-age %d', ms); + this._maxage = ms; + return this; +}; + +/** + * Emit error with `status`. + * + * @param {Number} status + * @api private + */ + +SendStream.prototype.error = function(status, err){ + var res = this.res; + var msg = http.STATUS_CODES[status]; + err = err || new Error(msg); + err.status = status; + if (this.listeners('error').length) return this.emit('error', err); + res.statusCode = err.status; + res.end(msg); +}; + +/** + * Check if the pathname is potentially malicious. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isMalicious = function(){ + return !this._root && ~this.path.indexOf('..'); +}; + +/** + * Check if the pathname ends with "/". + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.hasTrailingSlash = function(){ + return '/' == this.path[this.path.length - 1]; +}; + +/** + * Check if the basename leads with ".". + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.hasLeadingDot = function(){ + return '.' == basename(this.path)[0]; +}; + +/** + * Check if this is a conditional GET request. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isConditionalGET = function(){ + return this.req.headers['if-none-match'] + || this.req.headers['if-modified-since']; +}; + +/** + * Strip content-* header fields. + * + * @api private + */ + +SendStream.prototype.removeContentHeaderFields = function(){ + var res = this.res; + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Respond with 304 not modified. + * + * @api private + */ + +SendStream.prototype.notModified = function(){ + var res = this.res; + debug('not modified'); + this.removeContentHeaderFields(); + res.statusCode = 304; + res.end(); +}; + +/** + * Check if the request is cacheable, aka + * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}). + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isCachable = function(){ + var res = this.res; + return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode; +}; + +/** + * Handle stat() error. + * + * @param {Error} err + * @api private + */ + +SendStream.prototype.onStatError = function(err){ + var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR']; + if (~notfound.indexOf(err.code)) return this.error(404, err); + this.error(500, err); +}; + +/** + * Check if the cache is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isFresh = function(){ + return fresh(this.req.headers, this.res._headers); +}; + +/** + * Redirect to `path`. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.redirect = function(path){ + if (this.listeners('directory').length) return this.emit('directory'); + var res = this.res; + path += '/'; + res.statusCode = 301; + res.setHeader('Location', path); + res.end('Redirecting to ' + utils.escape(path)); +}; + +/** + * Pipe to `res. + * + * @param {Stream} res + * @return {Stream} res + * @api public + */ + +SendStream.prototype.pipe = function(res){ + var self = this + , args = arguments + , path = this.path + , root = this._root; + + // references + this.res = res; + + // invalid request uri + path = utils.decode(path); + if (-1 == path) return this.error(400); + + // null byte(s) + if (~path.indexOf('\0')) return this.error(400); + + // join / normalize from optional root dir + if (root) path = normalize(join(this._root, path)); + + // ".." is malicious without "root" + if (this.isMalicious()) return this.error(403); + + // malicious path + if (root && 0 != path.indexOf(root)) return this.error(403); + + // hidden file support + if (!this._hidden && this.hasLeadingDot()) return this.error(404); + + // index file support + if (this._index && this.hasTrailingSlash()) path += this._index; + + debug('stat "%s"', path); + fs.stat(path, function(err, stat){ + if (err) return self.onStatError(err); + if (stat.isDirectory()) return self.redirect(self.path); + self.emit('file', path, stat); + self.send(path, stat); + }); + + return res; +}; + +/** + * Transfer `path`. + * + * @param {String} path + * @api public + */ + +SendStream.prototype.send = function(path, stat){ + var options = this.options; + var len = stat.size; + var res = this.res; + var req = this.req; + var ranges = req.headers.range; + var offset = options.start || 0; + + // set header fields + this.setHeader(stat); + + // set content-type + this.type(path); + + // conditional GET support + if (this.isConditionalGET() + && this.isCachable() + && this.isFresh()) { + return this.notModified(); + } + + // adjust len to start/end options + len = Math.max(0, len - offset); + if (options.end !== undefined) { + var bytes = options.end - offset + 1; + if (len > bytes) len = bytes; + } + + // Range support + if (ranges) { + ranges = parseRange(len, ranges); + + // unsatisfiable + if (-1 == ranges) { + res.setHeader('Content-Range', 'bytes */' + stat.size); + return this.error(416); + } + + // valid (syntactically invalid ranges are treated as a regular response) + if (-2 != ranges) { + options.start = offset + ranges[0].start; + options.end = offset + ranges[0].end; + + // Content-Range + res.statusCode = 206; + res.setHeader('Content-Range', 'bytes ' + + ranges[0].start + + '-' + + ranges[0].end + + '/' + + len); + len = options.end - options.start + 1; + } + } + + // content-length + res.setHeader('Content-Length', len); + + // HEAD support + if ('HEAD' == req.method) return res.end(); + + this.stream(path, options); +}; + +/** + * Stream `path` to the response. + * + * @param {String} path + * @param {Object} options + * @api private + */ + +SendStream.prototype.stream = function(path, options){ + // TODO: this is all lame, refactor meeee + var self = this; + var res = this.res; + var req = this.req; + + // pipe + var stream = fs.createReadStream(path, options); + this.emit('stream', stream); + stream.pipe(res); + + // socket closed, done with the fd + req.on('close', stream.destroy.bind(stream)); + + // error handling code-smell + stream.on('error', function(err){ + // no hope in responding + if (res._header) { + console.error(err.stack); + req.destroy(); + return; + } + + // 500 + err.status = 500; + self.emit('error', err); + }); + + // end + stream.on('end', function(){ + self.emit('end'); + }); +}; + +/** + * Set content-type based on `path` + * if it hasn't been explicitly set. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.type = function(path){ + var res = this.res; + if (res.getHeader('Content-Type')) return; + var type = mime.lookup(path); + var charset = mime.charsets.lookup(type); + debug('content-type %s', type); + res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : '')); +}; + +/** + * Set reaponse header fields, most + * fields may be pre-defined. + * + * @param {Object} stat + * @api private + */ + +SendStream.prototype.setHeader = function(stat){ + var res = this.res; + if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes'); + if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat)); + if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString()); + if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000)); + if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString()); +}; diff --git a/node_modules/express/node_modules/send/lib/utils.js b/node_modules/express/node_modules/send/lib/utils.js new file mode 100644 index 0000000..950e5a2 --- /dev/null +++ b/node_modules/express/node_modules/send/lib/utils.js @@ -0,0 +1,47 @@ + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * decodeURIComponent. + * + * Allows V8 to only deoptimize this fn instead of all + * of send(). + * + * @param {String} path + * @api private + */ + +exports.decode = function(path){ + try { + return decodeURIComponent(path); + } catch (err) { + return -1; + } +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/send/node_modules/mime/LICENSE b/node_modules/express/node_modules/send/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/express/node_modules/send/node_modules/mime/README.md b/node_modules/express/node_modules/send/node_modules/mime/README.md new file mode 100644 index 0000000..b90552a --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/README.md @@ -0,0 +1,63 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/express/node_modules/send/node_modules/mime/mime.js b/node_modules/express/node_modules/send/node_modules/mime/mime.js new file mode 100644 index 0000000..70a6384 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/mime.js @@ -0,0 +1,113 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + if (process.env.DEBUG_MIME && this.types[exts]) { + console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' + + this.types[exts] + ' to ' + type); + } + + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + + this._loading = file; + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); + + this._loading = null; +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + return this.extensions[mimeType]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +}; + +module.exports = mime; diff --git a/node_modules/express/node_modules/send/node_modules/mime/package.json b/node_modules/express/node_modules/send/node_modules/mime/package.json new file mode 100644 index 0000000..707bc03 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/package.json @@ -0,0 +1,36 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "https://github.com/broofa/node-mime", + "type": "git" + }, + "version": "1.2.9", + "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n", + "readmeFilename": "README.md", + "_id": "mime@1.2.9", + "dist": { + "shasum": "6f8536a3e7a8f480de324a720ff9f2e6e557b2b6" + }, + "_from": "mime@~1.2.9", + "_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.9.tgz" +} diff --git a/node_modules/express/node_modules/send/node_modules/mime/test.js b/node_modules/express/node_modules/send/node_modules/mime/test.js new file mode 100644 index 0000000..cbad034 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/test.js @@ -0,0 +1,55 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); +eq('text/plain', mime.lookup('.text.txt')); +eq('text/plain', mime.lookup('.txt')); +eq('text/plain', mime.lookup('txt')); +eq('application/octet-stream', mime.lookup('text.nope')); +eq('fallback', mime.lookup('text.fallback', 'fallback')); +eq('application/octet-stream', mime.lookup('constructor')); +eq('text/plain', mime.lookup('TEXT.TXT')); +eq('text/event-stream', mime.lookup('text/event-stream')); +eq('application/x-web-app-manifest+json', mime.lookup('text.webapp')); + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq(undefined, mime.extension('constructor')); + +// +// Test node types +// + +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +console.log('\nOK'); diff --git a/node_modules/express/node_modules/send/node_modules/mime/types/mime.types b/node_modules/express/node_modules/send/node_modules/mime/types/mime.types new file mode 100644 index 0000000..b90b165 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/types/mime.types @@ -0,0 +1,1588 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +application/x-conference nsc +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-opml opml +text/x-pascal p pas +text/x-nfo nfo +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/node_modules/express/node_modules/send/node_modules/mime/types/node.types b/node_modules/express/node_modules/send/node_modules/mime/types/node.types new file mode 100644 index 0000000..970a1bd --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/types/node.types @@ -0,0 +1,60 @@ +# What: WebVTT +# Why: To allow formats intended for marking up external text track resources. +# http://dev.w3.org/html5/webvtt/ +# Added by: niftylettuce +text/vtt vtt + +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp + +# What: Lua file types +# Why: Googling around shows de-facto consensus on these +# Added by: creationix (Issue #45) +text/x-lua lua +application/x-lua-bytecode luac + +# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax +# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown +# Added by: avoidwork +text/x-markdown markdown md mkd diff --git a/node_modules/express/node_modules/send/package.json b/node_modules/express/node_modules/send/package.json new file mode 100644 index 0000000..79b3c83 --- /dev/null +++ b/node_modules/express/node_modules/send/package.json @@ -0,0 +1,42 @@ +{ + "name": "send", + "version": "0.1.3", + "description": "Better streaming static file server with Range and conditional-GET support", + "keywords": [ + "static", + "file", + "server" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": { + "debug": "*", + "mime": "~1.2.9", + "fresh": "0.1.0", + "range-parser": "0.0.4" + }, + "devDependencies": { + "mocha": "*", + "should": "*", + "supertest": "0.0.1", + "connect": "2.x" + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/send.git" + }, + "main": "index", + "readme": "# send\n\n Send is Connect's `static()` extracted for generalized use, a streaming static file\n server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.\n\n## Installation\n\n $ npm install send\n\n## Examples\n\n Small:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n send(req, req.url).pipe(res);\n}).listen(3000);\n```\n\n Serving from a root directory with custom error-handling:\n\n```js\nvar http = require('http');\nvar send = require('send');\nvar url = require('url');\n\nvar app = http.createServer(function(req, res){\n // your custom error-handling logic:\n function error(err) {\n res.statusCode = err.status || 500;\n res.end(err.message);\n }\n\n // your custom directory handling logic:\n function redirect() {\n res.statusCode = 301;\n res.setHeader('Location', req.url + '/');\n res.end('Redirecting to ' + req.url + '/');\n }\n\n // transfer arbitrary files from within\n // /www/example.com/public/*\n send(req, url.parse(req.url).pathname)\n .root('/www/example.com/public')\n .on('error', error)\n .on('directory', redirect)\n .pipe(res);\n}).listen(3000);\n```\n\n## API\n\n### Events\n\n - `error` an error occurred `(err)`\n - `directory` a directory was requested\n - `file` a file was requested `(path, stat)`\n - `stream` file streaming has started `(stream)`\n - `end` streaming has completed\n\n### .root(dir)\n\n Serve files relative to `path`. Aliased as `.from(dir)`.\n\n### .index(path)\n\n By default send supports \"index.html\" files, to disable this\n invoke `.index(false)` or to supply a new index pass a string.\n\n### .maxage(ms)\n\n Provide a max-age in milliseconds for http caching, defaults to 0.\n\n### .hidden(bool)\n\n Enable or disable transfer of hidden files, defaults to false.\n\n## Error-handling\n\n By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.\n\n## Caching\n\n It does _not_ perform internal caching, you should use a reverse proxy cache such\n as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).\n\n## Debugging\n\n To enable `debug()` instrumentation output export __DEBUG__:\n\n```\n$ DEBUG=send node app\n```\n\n## Running tests\n\n```\n$ npm install\n$ make test\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "Readme.md", + "_id": "send@0.1.3", + "dist": { + "shasum": "76069ac7876a87812e97371334eaa02a27af8623" + }, + "_from": "send@0.1.3", + "_resolved": "https://registry.npmjs.org/send/-/send-0.1.3.tgz" +} diff --git a/node_modules/express/package.json b/node_modules/express/package.json new file mode 100644 index 0000000..ca1179e --- /dev/null +++ b/node_modules/express/package.json @@ -0,0 +1,85 @@ +{ + "name": "express", + "description": "Sinatra inspired web development framework", + "version": "3.3.4", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "contributors": [ + { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + { + "name": "Ciaran Jessup", + "email": "ciaranj@gmail.com" + }, + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + } + ], + "dependencies": { + "connect": "2.8.4", + "commander": "1.2.0", + "range-parser": "0.0.4", + "mkdirp": "0.3.5", + "cookie": "0.1.0", + "buffer-crc32": "0.2.1", + "fresh": "0.1.0", + "methods": "0.0.1", + "send": "0.1.3", + "cookie-signature": "1.0.1", + "debug": "*" + }, + "devDependencies": { + "ejs": "*", + "mocha": "*", + "jade": "0.30.0", + "hjs": "*", + "stylus": "*", + "should": "*", + "connect-redis": "*", + "marked": "*", + "supertest": "0.6.0" + }, + "keywords": [ + "express", + "framework", + "sinatra", + "web", + "rest", + "restful", + "router", + "app", + "api" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/express" + }, + "main": "index", + "bin": { + "express": "./bin/express" + }, + "scripts": { + "prepublish": "npm prune", + "test": "make test" + }, + "engines": { + "node": "*" + }, + "readme": "![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)\n\n Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) [![Dependency Status](https://gemnasium.com/visionmedia/express.png)](https://gemnasium.com/visionmedia/express)\n\n```js\nvar express = require('express');\nvar app = express();\n\napp.get('/', function(req, res){\n res.send('Hello World');\n});\n\napp.listen(3000);\n```\n\n## Installation\n\n $ npm install -g express\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:\n\n Create the app:\n\n $ npm install -g express\n $ express /tmp/foo && cd /tmp/foo\n\n Install dependencies:\n\n $ npm install\n\n Start the server:\n\n $ node app\n\n## Features\n\n * Built on [Connect](http://github.com/senchalabs/connect)\n * Robust routing\n * HTTP helpers (redirection, caching, etc)\n * View system supporting 14+ template engines\n * Content negotiation\n * Focus on high performance\n * Environment based configuration\n * Executable for generating applications quickly\n * High test coverage\n\n## Philosophy\n\n The Express philosophy is to provide small, robust tooling for HTTP servers. Making\n it a great solution for single page applications, web sites, hybrids, or public\n HTTP APIs.\n\n Built on Connect you can use _only_ what you need, and nothing more, applications\n can be as big or as small as you like, even a single file. Express does\n not force you to use any specific ORM or template engine. With support for over\n 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js)\n you can quickly craft your perfect framework.\n\n## More Information\n\n * Join #express on freenode\n * [Google Group](http://groups.google.com/group/express-js) for discussion\n * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates\n * Visit the [Wiki](http://github.com/visionmedia/express/wiki)\n * [Русскоязычная документация](http://jsman.ru/express/)\n * Run express examples [online](https://runnable.com/express)\n\n## Viewing Examples\n\nClone the Express repo, then install the dev dependencies to install all the example / test suite deps:\n\n $ git clone git://github.com/visionmedia/express.git --depth 1\n $ cd express\n $ npm install\n\nthen run whichever tests you want:\n\n $ node examples/content-negotiation\n\n## Running Tests\n\nTo run the test suite first invoke the following command within the repo, installing the development dependencies:\n\n $ npm install\n\nthen run the tests:\n\n $ make test\n\n## Contributors\n\n```\nproject: express\ncommits: 3559\nactive : 468 days\nfiles : 237\nauthors:\n 1891\tTj Holowaychuk 53.1%\n 1285\tvisionmedia 36.1%\n 182\tTJ Holowaychuk 5.1%\n 54\tAaron Heckmann 1.5%\n 34\tcsausdev 1.0%\n 26\tciaranj 0.7%\n 21\tRobert Sköld 0.6%\n 6\tGuillermo Rauch 0.2%\n 3\tDav Glass 0.1%\n 3\tNick Poulden 0.1%\n 2\tRandy Merrill 0.1%\n 2\tBenny Wong 0.1%\n 2\tHunter Loftis 0.1%\n 2\tJake Gordon 0.1%\n 2\tBrian McKinney 0.1%\n 2\tRoman Shtylman 0.1%\n 2\tBen Weaver 0.1%\n 2\tDave Hoover 0.1%\n 2\tEivind Fjeldstad 0.1%\n 2\tDaniel Shaw 0.1%\n 1\tMatt Colyer 0.0%\n 1\tPau Ramon 0.0%\n 1\tPero Pejovic 0.0%\n 1\tPeter Rekdal Sunde 0.0%\n 1\tRaynos 0.0%\n 1\tTeng Siong Ong 0.0%\n 1\tViktor Kelemen 0.0%\n 1\tctide 0.0%\n 1\t8bitDesigner 0.0%\n 1\tisaacs 0.0%\n 1\tmgutz 0.0%\n 1\tpikeas 0.0%\n 1\tshuwatto 0.0%\n 1\ttstrimple 0.0%\n 1\tewoudj 0.0%\n 1\tAdam Sanderson 0.0%\n 1\tAndrii Kostenko 0.0%\n 1\tAndy Hiew 0.0%\n 1\tArpad Borsos 0.0%\n 1\tAshwin Purohit 0.0%\n 1\tBenjen 0.0%\n 1\tDarren Torpey 0.0%\n 1\tGreg Ritter 0.0%\n 1\tGregory Ritter 0.0%\n 1\tJames Herdman 0.0%\n 1\tJim Snodgrass 0.0%\n 1\tJoe McCann 0.0%\n 1\tJonathan Dumaine 0.0%\n 1\tJonathan Palardy 0.0%\n 1\tJonathan Zacsh 0.0%\n 1\tJustin Lilly 0.0%\n 1\tKen Sato 0.0%\n 1\tMaciej Małecki 0.0%\n 1\tMasahiro Hayashi 0.0%\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "Readme.md", + "_id": "express@3.3.4", + "dist": { + "shasum": "7e69eb567361647686059b2763295c0edbf79095" + }, + "_from": "express@", + "_resolved": "https://registry.npmjs.org/express/-/express-3.3.4.tgz" +} diff --git a/node_modules/express/test.js b/node_modules/express/test.js new file mode 100644 index 0000000..e7dca26 --- /dev/null +++ b/node_modules/express/test.js @@ -0,0 +1,17 @@ +var http = require('http'); +var express = require('express'); + +var app = express(); +var sub = express(); + +app.use('/', function (req, res, next) { + next(new Error('something broke')); +}); + +sub.use(function (err, req, res, next) { + res.send('error handled'); +}); + +app.use(sub); + +http.createServer(app).listen(4000); diff --git a/node_modules/googleapis/.cache/admindirectory_v1 b/node_modules/googleapis/.cache/admindirectory_v1 new file mode 100644 index 0000000..8caafb4 --- /dev/null +++ b/node_modules/googleapis/.cache/admindirectory_v1 @@ -0,0 +1 @@ +{"kind":"discovery#rpcDescription","etag":"\"R6H4aXXmd1SZaWpEcGSkC2StmNw/xqSX7-n8LugACXqRoz62D83GEuE\"","discoveryVersion":"v1","id":"admin:directory_v1","name":"admin","canonicalName":"directory","version":"directory_v1","title":"Admin Directory API","description":"The Admin SDK Directory API lets you view and manage enterprise resources such as users and groups, administrative notifications, security features, and more.","ownerDomain":"google.com","ownerName":"Google","packagePath":"admin","icons":{"x16":"http://www.google.com/images/icons/product/search-16.gif","x32":"http://www.google.com/images/icons/product/search-32.gif"},"documentationLink":"https://developers.google.com/admin-sdk/directory/","protocol":"rpc","rootUrl":"https://www.googleapis.com/","rpcUrl":"https://www.googleapis.com/rpc","rpcPath":"/rpc","parameters":{"alt":{"type":"string","description":"Data format for the response.","default":"json","enum":["json"],"enumDescriptions":["Responses with Content-Type of application/json"],"location":"query"},"fields":{"type":"string","description":"Selector specifying which fields to include in a partial response.","location":"query"},"key":{"type":"string","description":"API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.","location":"query"},"oauth_token":{"type":"string","description":"OAuth 2.0 token for the current user.","location":"query"},"prettyPrint":{"type":"boolean","description":"Returns response with indentations and line breaks.","default":"true","location":"query"},"quotaUser":{"type":"string","description":"Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.","location":"query"},"userIp":{"type":"string","description":"IP address of the site where the request originates. Use this if you want to enforce per-user limits.","location":"query"}},"auth":{"oauth2":{"scopes":{"https://www.googleapis.com/auth/admin.directory.device.chromeos":{"description":"View and manage your Chrome OS devices' metadata"},"https://www.googleapis.com/auth/admin.directory.device.chromeos.readonly":{"description":"View your Chrome OS devices' metadata"},"https://www.googleapis.com/auth/admin.directory.device.mobile":{"description":"View and manage your mobile devices' metadata"},"https://www.googleapis.com/auth/admin.directory.device.mobile.action":{"description":"Manage your mobile devices by performing administrative tasks"},"https://www.googleapis.com/auth/admin.directory.device.mobile.readonly":{"description":"View your mobile devices' metadata"},"https://www.googleapis.com/auth/admin.directory.group":{"description":"View and manage the provisioning of groups on your domain"},"https://www.googleapis.com/auth/admin.directory.group.member":{"description":"View and manage group subscriptions on your domain"},"https://www.googleapis.com/auth/admin.directory.group.member.readonly":{"description":"View group subscriptions on your domain"},"https://www.googleapis.com/auth/admin.directory.group.readonly":{"description":"View groups on your domain"},"https://www.googleapis.com/auth/admin.directory.notifications":{"description":"View and manage notifications received on your domain"},"https://www.googleapis.com/auth/admin.directory.orgunit":{"description":"View and manage organization units on your domain"},"https://www.googleapis.com/auth/admin.directory.orgunit.readonly":{"description":"View organization units on your domain"},"https://www.googleapis.com/auth/admin.directory.user":{"description":"View and manage the provisioning of users on your domain"},"https://www.googleapis.com/auth/admin.directory.user.alias":{"description":"View and manage user aliases on your domain"},"https://www.googleapis.com/auth/admin.directory.user.alias.readonly":{"description":"View user aliases on your domain"},"https://www.googleapis.com/auth/admin.directory.user.readonly":{"description":"View users on your domain"},"https://www.googleapis.com/auth/admin.directory.user.security":{"description":"Manage data access permissions for users on your domain"}}}},"schemas":{"Alias":{"id":"Alias","type":"object","description":"JSON template for Alias object in Apps Directory API.","properties":{"alias":{"type":"string","description":"A alias email"},"etag":{"type":"string","description":"ETag of the resource."},"id":{"type":"string","description":"Unique id of the group (Read-only) Unique id of the user (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#alias"},"primaryEmail":{"type":"string","description":"Group's primary email (Read-only) User's primary email (Read-only)"}}},"Aliases":{"id":"Aliases","type":"object","description":"JSON response template to list aliases in Apps Directory API.","properties":{"aliases":{"type":"array","description":"List of alias objects.","items":{"$ref":"Alias"}},"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#aliases"}}},"Asp":{"id":"Asp","type":"object","description":"The template that returns individual ASP (Access Code) data.","properties":{"codeId":{"type":"integer","description":"The unique ID of the ASP.","format":"int32"},"creationTime":{"type":"string","description":"The time when the ASP was created. Expressed in Unix time format.","format":"int64"},"etag":{"type":"string","description":"ETag of the ASP."},"kind":{"type":"string","description":"The type of the API resource. This is always admin#directory#asp.","default":"admin#directory#asp"},"lastTimeUsed":{"type":"string","description":"The time when the ASP was last used. Expressed in Unix time format.","format":"int64"},"name":{"type":"string","description":"The name of the application that the user, represented by their userId, entered when the ASP was created."},"userKey":{"type":"string","description":"The unique ID of the user who issued the ASP."}}},"Asps":{"id":"Asps","type":"object","properties":{"etag":{"type":"string","description":"ETag of the resource."},"items":{"type":"array","description":"A list of ASP resources.","items":{"$ref":"Asp"}},"kind":{"type":"string","description":"The type of the API resource. This is always admin#directory#aspList.","default":"admin#directory#aspList"}}},"Channel":{"id":"Channel","type":"object","description":"An notification channel used to watch for resource changes.","properties":{"address":{"type":"string","description":"The address where notifications are delivered for this channel."},"expiration":{"type":"string","description":"Date and time of notification channel expiration, expressed as a Unix timestamp, in milliseconds. Optional.","format":"int64"},"id":{"type":"string","description":"A UUID or similar unique string that identifies this channel."},"kind":{"type":"string","description":"Identifies this as a notification channel used to watch for changes to a resource. Value: the fixed string \"api#channel\".","default":"api#channel"},"params":{"type":"object","description":"Additional parameters controlling delivery channel behavior. Optional.","additionalProperties":{"type":"string","description":"Declares a new parameter by name."}},"payload":{"type":"boolean","description":"A Boolean value to indicate whether payload is wanted. Optional."},"resourceId":{"type":"string","description":"An opaque ID that identifies the resource being watched on this channel. Stable across different API versions."},"resourceUri":{"type":"string","description":"A version-specific identifier for the watched resource."},"token":{"type":"string","description":"An arbitrary string delivered to the target address with each notification delivered over this channel. Optional."},"type":{"type":"string","description":"The type of delivery mechanism used for this channel."}}},"ChromeOsDevice":{"id":"ChromeOsDevice","type":"object","description":"JSON template for Chrome Os Device resource in Apps Directory API.","properties":{"annotatedLocation":{"type":"string","description":"Address or location of the device as noted by the administrator"},"annotatedUser":{"type":"string","description":"User of the device"},"bootMode":{"type":"string","description":"Chromebook boot mode (Read-only)"},"deviceId":{"type":"string","description":"Unique identifier of Chrome OS Device (Read-only)"},"etag":{"type":"string","description":"ETag of the resource."},"firmwareVersion":{"type":"string","description":"Chromebook firmware version (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#chromeosdevice"},"lastEnrollmentTime":{"type":"string","description":"Date and time the device was last enrolled (Read-only)","format":"date-time"},"lastSync":{"type":"string","description":"Date and time the device was last synchronized with the policy settings in the Google Apps administrator control panel (Read-only)","format":"date-time"},"macAddress":{"type":"string","description":"Chromebook Mac Address (Read-only)"},"meid":{"type":"string","description":"Mobile Equipment identifier for the 3G mobile card in the Chromebook (Read-only)"},"model":{"type":"string","description":"Chromebook Model (Read-only)"},"notes":{"type":"string","description":"Notes added by the administrator"},"orderNumber":{"type":"string","description":"Chromebook order number (Read-only)"},"orgUnitPath":{"type":"string","description":"OrgUnit of the device"},"osVersion":{"type":"string","description":"Chromebook Os Version (Read-only)"},"platformVersion":{"type":"string","description":"Chromebook platform version (Read-only)"},"serialNumber":{"type":"string","description":"Chromebook serial number (Read-only)"},"status":{"type":"string","description":"status of the device (Read-only)"},"supportEndDate":{"type":"string","description":"Final date the device will be supported (Read-only)","format":"date-time"},"willAutoRenew":{"type":"boolean","description":"Will Chromebook auto reniew after support end date (Read-only)"}}},"ChromeOsDevices":{"id":"ChromeOsDevices","type":"object","description":"JSON response template for List Chrome OS Devices operation in Apps Directory API.","properties":{"chromeosdevices":{"type":"array","description":"List of Chrome OS Device objects.","items":{"$ref":"ChromeOsDevice"}},"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#chromeosdevices"},"nextPageToken":{"type":"string","description":"Token used to access next page of this result."}}},"Group":{"id":"Group","type":"object","description":"JSON template for Group resource in Apps Directory API.","properties":{"adminCreated":{"type":"boolean","description":"Is the group created by admin (Read-only) *"},"aliases":{"type":"array","description":"List of aliases (Read-only)","items":{"type":"string"}},"description":{"type":"string","description":"Description of the group"},"directMembersCount":{"type":"string","description":"Group direct members count","format":"int64"},"email":{"type":"string","description":"Email of Group","annotations":{"required":["directory.groups.insert"]}},"etag":{"type":"string","description":"ETag of the resource."},"id":{"type":"string","description":"Unique identifier of Group (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#group"},"name":{"type":"string","description":"Group name"},"nonEditableAliases":{"type":"array","description":"List of non editable aliases (Read-only)","items":{"type":"string"}}}},"Groups":{"id":"Groups","type":"object","description":"JSON response template for List Groups operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"groups":{"type":"array","description":"List of group objects.","items":{"$ref":"Group"}},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#groups"},"nextPageToken":{"type":"string","description":"Token used to access next page of this result."}}},"Member":{"id":"Member","type":"object","description":"JSON template for Member resource in Apps Directory API.","properties":{"email":{"type":"string","description":"Email of member (Read-only)"},"etag":{"type":"string","description":"ETag of the resource."},"id":{"type":"string","description":"Unique identifier of customer member (Read-only) Unique identifier of group (Read-only) Unique identifier of member (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#member"},"role":{"type":"string","description":"Role of member"},"type":{"type":"string","description":"Type of member (Immutable)"}}},"Members":{"id":"Members","type":"object","description":"JSON response template for List Members operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#members"},"members":{"type":"array","description":"List of member objects.","items":{"$ref":"Member"}},"nextPageToken":{"type":"string","description":"Token used to access next page of this result."}}},"MobileDevice":{"id":"MobileDevice","type":"object","description":"JSON template for Mobile Device resource in Apps Directory API.","properties":{"applications":{"type":"array","description":"List of applications installed on Mobile Device","items":{"type":"object","properties":{"displayName":{"type":"string","description":"Display name of application"},"packageName":{"type":"string","description":"Package name of application"},"permission":{"type":"array","description":"List of Permissions for application","items":{"type":"string"}},"versionCode":{"type":"integer","description":"Version code of application","format":"int32"},"versionName":{"type":"string","description":"Version name of application"}}}},"deviceId":{"type":"string","description":"Mobile Device serial number (Read-only)"},"email":{"type":"array","description":"List of owner user's email addresses (Read-only)","items":{"type":"string"}},"etag":{"type":"string","description":"ETag of the resource."},"firstSync":{"type":"string","description":"Date and time the device was first synchronized with the policy settings in the Google Apps administrator control panel (Read-only)","format":"date-time"},"hardwareId":{"type":"string","description":"Mobile Device Hardware Id (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#mobiledevice"},"lastSync":{"type":"string","description":"Date and time the device was last synchronized with the policy settings in the Google Apps administrator control panel (Read-only)","format":"date-time"},"model":{"type":"string","description":"Name of the model of the device"},"name":{"type":"array","description":"List of owner user's names (Read-only)","items":{"type":"string"}},"os":{"type":"string","description":"Name of the mobile operating system"},"resourceId":{"type":"string","description":"Unique identifier of Mobile Device (Read-only)"},"status":{"type":"string","description":"Status of the device (Read-only)"},"type":{"type":"string","description":"The type of device (Read-only)"},"userAgent":{"type":"string","description":"Mobile Device user agent"}}},"MobileDevices":{"id":"MobileDevices","type":"object","description":"JSON response template for List Mobile Devices operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#mobiledevices"},"mobiledevices":{"type":"array","description":"List of Mobile Device objects.","items":{"$ref":"MobileDevice"}},"nextPageToken":{"type":"string","description":"Token used to access next page of this result."}}},"Notification":{"id":"Notification","type":"object","description":"Template for a notification resource.","properties":{"body":{"type":"string","description":"Body of the notification (Read-only)"},"etag":{"type":"string","description":"ETag of the resource."},"fromAddress":{"type":"string","description":"Address from which the notification is received (Read-only)"},"isUnread":{"type":"boolean","description":"Boolean indicating whether the notification is unread or not."},"kind":{"type":"string","description":"The type of the resource.","default":"admin#directory#notification"},"notificationId":{"type":"string"},"sendTime":{"type":"string","description":"Time at which notification was sent (Read-only)","format":"date-time"},"subject":{"type":"string","description":"Subject of the notification (Read-only)"}}},"Notifications":{"id":"Notifications","type":"object","description":"Template for notifications list response.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"items":{"type":"array","description":"List of notifications in this page.","items":{"$ref":"Notification"}},"kind":{"type":"string","description":"The type of the resource.","default":"admin#directory#notifications"},"nextPageToken":{"type":"string","description":"Token for fetching the next page of notifications."},"unreadNotificationsCount":{"type":"integer","description":"Number of unread notification for the domain.","format":"int32"}}},"OrgUnit":{"id":"OrgUnit","type":"object","description":"JSON template for Org Unit resource in Apps Directory API.","properties":{"blockInheritance":{"type":"boolean","description":"Should block inheritance"},"description":{"type":"string","description":"Description of OrgUnit"},"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#orgUnit"},"name":{"type":"string","description":"Name of OrgUnit","annotations":{"required":["directory.orgunits.insert"]}},"orgUnitPath":{"type":"string","description":"Path of OrgUnit"},"parentOrgUnitPath":{"type":"string","description":"Path of parent OrgUnit","annotations":{"required":["directory.orgunits.insert"]}}}},"OrgUnits":{"id":"OrgUnits","type":"object","description":"JSON response template for List Organization Units operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#orgUnits"},"organizationUnits":{"type":"array","description":"List of user objects.","items":{"$ref":"OrgUnit"}}}},"Token":{"id":"Token","type":"object","description":"JSON template for token resource in Apps Directory API.","properties":{"anonymous":{"type":"boolean","description":"Whether the application is registered with Google. The value is true if the application has an anonymous Client ID."},"clientId":{"type":"string","description":"The Client ID of the application the token is issued to."},"displayText":{"type":"string","description":"The displayable name of the application the token is issued to."},"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"The type of the API resource. This is always admin#directory#token.","default":"admin#directory#token"},"nativeApp":{"type":"boolean","description":"Whether the token is issued to an installed application. The value is true if the application is installed to a desktop or mobile device."},"scopes":{"type":"array","description":"A list of authorization scopes the application is granted.","items":{"type":"string"}},"userKey":{"type":"string","description":"The unique ID of the user that issued the token."}}},"Tokens":{"id":"Tokens","type":"object","description":"JSON response template for List tokens operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"items":{"type":"array","description":"A list of Token resources.","items":{"$ref":"Token"}},"kind":{"type":"string","description":"The type of the API resource. This is always admin#directory#tokenList.","default":"admin#directory#tokenList"}}},"User":{"id":"User","type":"object","description":"JSON template for User object in Apps Directory API.","properties":{"addresses":{"type":"array","description":"Addresses of User","items":{"$ref":"UserAddress"}},"agreedToTerms":{"type":"boolean","description":"Indicates if user has agreed to terms (Read-only)"},"aliases":{"type":"array","description":"List of aliases (Read-only)","items":{"type":"string"}},"changePasswordAtNextLogin":{"type":"boolean","description":"Boolean indicating if the user should change password in next login"},"creationTime":{"type":"string","description":"User's Google account creation time. (Read-only)","format":"date-time"},"customerId":{"type":"string","description":"CustomerId of User (Read-only)"},"deletionTime":{"type":"string","format":"date-time"},"emails":{"type":"array","description":"Emails of User","items":{"$ref":"UserEmail"}},"etag":{"type":"string","description":"ETag of the resource."},"externalIds":{"type":"array","description":"The external Ids of User *","items":{"$ref":"UserExternalId"}},"hashFunction":{"type":"string","description":"Hash function name for password. Supported are MD5, SHA-1 and crypt"},"id":{"type":"string","description":"Unique identifier of User (Read-only)"},"ims":{"type":"array","description":"User's Instant Messenger","items":{"$ref":"UserIm"}},"includeInGlobalAddressList":{"type":"boolean","description":"Boolean indicating if user is included in Global Address List"},"ipWhitelisted":{"type":"boolean","description":"Boolean indicating if ip is whitelisted"},"isAdmin":{"type":"boolean","description":"Boolean indicating if the user is admin (Read-only)"},"isDelegatedAdmin":{"type":"boolean","description":"Boolean indicating if the user is delegated admin (Read-only)"},"isMailboxSetup":{"type":"boolean","description":"Is mailbox setup (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#user"},"lastLoginTime":{"type":"string","description":"User's last login time. (Read-only)","format":"date-time"},"name":{"$ref":"UserName","description":"User's name","annotations":{"required":["directory.users.insert"]}},"nonEditableAliases":{"type":"array","description":"List of non editable aliases (Read-only)","items":{"type":"string"}},"orgUnitPath":{"type":"string","description":"OrgUnit of User"},"organizations":{"type":"array","description":"Organizations of User","items":{"$ref":"UserOrganization"}},"password":{"type":"string","description":"User's password","annotations":{"required":["directory.users.insert"]}},"phones":{"type":"array","description":"Phone numbers of User","items":{"$ref":"UserPhone"}},"primaryEmail":{"type":"string","description":"username of User","annotations":{"required":["directory.users.insert"]}},"relations":{"type":"array","description":"The Relations of User *","items":{"$ref":"UserRelation"}},"suspended":{"type":"boolean","description":"Indicates if user is suspended"},"suspensionReason":{"type":"string","description":"Suspension reason if user is suspended (Read-only)"},"thumbnailPhotoUrl":{"type":"string","description":"Photo Url of the user (Read-only)"}}},"UserAddress":{"id":"UserAddress","type":"object","description":"JSON template for address.","properties":{"country":{"type":"string","description":"Country."},"countryCode":{"type":"string","description":"Country code."},"customType":{"type":"string","description":"Custom type."},"extendedAddress":{"type":"string","description":"Extended Address."},"formatted":{"type":"string","description":"Formatted address (read-only field)"},"locality":{"type":"string","description":"Locality."},"poBox":{"type":"string","description":"Other parts of address."},"postalCode":{"type":"string","description":"Postal code."},"primary":{"type":"boolean","description":"If this is user's primary address. Only one entry could be marked as primary."},"region":{"type":"string","description":"Region."},"sourceIsStructured":{"type":"boolean","description":"User supplied address was structured. Structured addresses are NOT supported at this time. You might be able to write structured addresses, but any values will eventually be clobbered."},"streetAddress":{"type":"string","description":"Street."},"type":{"type":"string","description":"Each entry can have a type which indicates standard values of that entry. For example address could be of home, work etc. In addition to the standard type, an entry can have a custom type and can take any value. Such type should have the CUSTOM value as type and also have a customType value."}}},"UserEmail":{"id":"UserEmail","type":"object","description":"JSON template for an email.","properties":{"address":{"type":"string","description":"Email id of the user."},"customType":{"type":"string","description":"Custom Type."},"primary":{"type":"boolean","description":"If this is user's primary email. Only one entry could be marked as primary."},"type":{"type":"string","description":"Each entry can have a type which indicates standard types of that entry. For example email could be of home, work etc. In addition to the standard type, an entry can have a custom type and can take any value Such typess should have the CUSTOM value as type and also have a customType value."}}},"UserExternalId":{"id":"UserExternalId","type":"object","description":"JSON template for an externalId entry.","properties":{"customType":{"type":"string","description":"Custom type."},"type":{"type":"string","description":"The type of the Id."},"value":{"type":"string","description":"The value of the id."}}},"UserIm":{"id":"UserIm","type":"object","description":"JSON template for instant messenger of an user.","properties":{"customProtocol":{"type":"string","description":"Custom protocol."},"customType":{"type":"string","description":"Custom type."},"im":{"type":"string","description":"Instant messenger id."},"primary":{"type":"boolean","description":"If this is user's priamry im. Only one entry could be marked as primary."},"protocol":{"type":"string","description":"Protocol used in the instant messenger. It should be one of the values from ImProtocolTypes map. Simalar to type, it can take a CUSTOM value and specify the custom name in customProtocol field."},"type":{"type":"string","description":"Each entry can have a type which indicates standard types of that entry. For example instant messengers could be of home, work etc. In addition to the standard type, an entry can have a custom type and can take any value. Such types should have the CUSTOM value as type and also have a customType value."}}},"UserName":{"id":"UserName","type":"object","description":"JSON template for name of a user in Apps Directory API.","properties":{"familyName":{"type":"string","description":"Last Name","annotations":{"required":["directory.users.insert"]}},"fullName":{"type":"string","description":"Full Name"},"givenName":{"type":"string","description":"First Name","annotations":{"required":["directory.users.insert"]}}}},"UserOrganization":{"id":"UserOrganization","type":"object","description":"JSON template for an organization entry.","properties":{"costCenter":{"type":"string","description":"The cost center of the users department."},"customType":{"type":"string","description":"Custom type."},"department":{"type":"string","description":"Department within the organization."},"description":{"type":"string","description":"Description of the organization."},"domain":{"type":"string","description":"The domain to which the organization belongs to."},"location":{"type":"string","description":"Location of the organization. This need not be fully qualified address."},"name":{"type":"string","description":"Name of the organization"},"primary":{"type":"boolean","description":"If it user's primary organization."},"symbol":{"type":"string","description":"Symobol of the organization."},"title":{"type":"string","description":"Title (designation) of the user in the organization."},"type":{"type":"string","description":"Each entry can have a type which indicates standard types of that entry. For example organization could be of school, work etc. In addition to the standard type, an entry can have a custom type and can give it any name. Such types should have the CUSTOM value as type and also have a CustomType value."}}},"UserPhone":{"id":"UserPhone","type":"object","description":"JSON template for a phone entry.","properties":{"customType":{"type":"string","description":"Custom Type."},"primary":{"type":"boolean","description":"If this is user's primary phone or not."},"type":{"type":"string","description":"Each entry can have a type which indicates standard types of that entry. For example phone could be of home_fax, work, mobile etc. In addition to the standard type, an entry can have a custom type and can give it any name. Such types should have the CUSTOM value as type and also have a customType value."},"value":{"type":"string","description":"Phone number."}}},"UserPhoto":{"id":"UserPhoto","type":"object","description":"JSON template for Photo object in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"height":{"type":"integer","description":"Height in pixels of the photo","format":"int32"},"id":{"type":"string","description":"Unique identifier of User (Read-only)"},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#user#photo"},"mimeType":{"type":"string","description":"Mime Type of the photo"},"photoData":{"type":"string","description":"Base64 encoded photo data","format":"byte","annotations":{"required":["directory.users.photos.update"]}},"primaryEmail":{"type":"string","description":"Primary email of User (Read-only)"},"width":{"type":"integer","description":"Width in pixels of the photo","format":"int32"}}},"UserRelation":{"id":"UserRelation","type":"object","description":"JSON template for a relation entry.","properties":{"customType":{"type":"string","description":"Custom Type."},"type":{"type":"string","description":"The relation of the user. Some of the possible values are mother, father, sister, brother, manager, assistant, partner."},"value":{"type":"string","description":"The name of the relation."}}},"Users":{"id":"Users","type":"object","description":"JSON response template for List Users operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"Kind of resource this is.","default":"admin#directory#users"},"nextPageToken":{"type":"string","description":"Token used to access next page of this result."},"trigger_event":{"type":"string","description":"Event that triggered this response (only used in case of Push Response)"},"users":{"type":"array","description":"List of user objects.","items":{"$ref":"User"}}}},"VerificationCode":{"id":"VerificationCode","type":"object","description":"JSON template for verification codes in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"kind":{"type":"string","description":"The type of the resource. This is always admin#directory#verificationCode.","default":"admin#directory#verificationCode"},"userId":{"type":"string","description":"The obfuscated unique ID of the user."},"verificationCode":{"type":"string","description":"A current verification code for the user. Invalidated or used verification codes are not returned as part of the result."}}},"VerificationCodes":{"id":"VerificationCodes","type":"object","description":"JSON response template for List verification codes operation in Apps Directory API.","properties":{"etag":{"type":"string","description":"ETag of the resource."},"items":{"type":"array","description":"A list of verification code resources.","items":{"$ref":"VerificationCode"}},"kind":{"type":"string","description":"The type of the resource. This is always admin#directory#verificationCodesList.","default":"admin#directory#verificationCodesList"}}}},"methods":{"admin.channels.stop":{"id":"admin.channels.stop","description":"Stop watching resources through this channel","parameters":{"resource":{"$ref":"Channel"}},"parameterOrder":["resource"],"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.alias","https://www.googleapis.com/auth/admin.directory.user.alias.readonly","https://www.googleapis.com/auth/admin.directory.user.readonly"]},"directory.asps.delete":{"id":"directory.asps.delete","description":"Delete an ASP issued by a user.","parameters":{"codeId":{"type":"integer","description":"The unique ID of the ASP to be deleted.","required":true,"format":"int32"},"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey","codeId"],"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.asps.get":{"id":"directory.asps.get","description":"Get information about an ASP issued by a user.","allowGet":true,"parameters":{"codeId":{"type":"integer","description":"The unique ID of the ASP.","required":true,"format":"int32"},"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey","codeId"],"returns":{"$ref":"Asp"},"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.asps.list":{"id":"directory.asps.list","description":"List the ASPs issued by a user.","allowGet":true,"parameters":{"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey"],"returns":{"$ref":"Asps"},"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.chromeosdevices.get":{"id":"directory.chromeosdevices.get","description":"Retrieve Chrome OS Device","allowGet":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"deviceId":{"type":"string","description":"Immutable id of Chrome OS Device","required":true},"projection":{"type":"string","description":"Restrict information returned to a set of selected fields.","enum":["BASIC","FULL"],"enumDescriptions":["Includes only the basic metadata fields (e.g., deviceId, serialNumber, status, and user)","Includes all metadata fields"]}},"parameterOrder":["customerId","deviceId"],"returns":{"$ref":"ChromeOsDevice"},"scopes":["https://www.googleapis.com/auth/admin.directory.device.chromeos","https://www.googleapis.com/auth/admin.directory.device.chromeos.readonly"]},"directory.chromeosdevices.list":{"id":"directory.chromeosdevices.list","description":"Retrieve all Chrome OS Devices of a customer (paginated)","allowGet":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"maxResults":{"type":"integer","description":"Maximum number of results to return. Default is 100","format":"int32","minimum":"1"},"orderBy":{"type":"string","description":"Column to use for sorting results","enum":["annotatedLocation","annotatedUser","lastSync","notes","serialNumber","status","supportEndDate"],"enumDescriptions":["Chromebook location as annotated by the administrator.","Chromebook user as annotated by administrator.","Chromebook last sync.","Chromebook notes as annotated by the administrator.","Chromebook Serial Number.","Chromebook status.","Chromebook support end date."]},"pageToken":{"type":"string","description":"Token to specify next page in the list"},"projection":{"type":"string","description":"Restrict information returned to a set of selected fields.","enum":["BASIC","FULL"],"enumDescriptions":["Includes only the basic metadata fields (e.g., deviceId, serialNumber, status, and user)","Includes all metadata fields"]},"query":{"type":"string","description":"Search string in the format given at http://support.google.com/chromeos/a/bin/answer.py?hl=en&answer=1698333"},"sortOrder":{"type":"string","description":"Whether to return results in ascending or descending order. Only of use when orderBy is also used","enum":["ASCENDING","DESCENDING"],"enumDescriptions":["Ascending order.","Descending order."]}},"parameterOrder":["customerId"],"returns":{"$ref":"ChromeOsDevices"},"scopes":["https://www.googleapis.com/auth/admin.directory.device.chromeos","https://www.googleapis.com/auth/admin.directory.device.chromeos.readonly"]},"directory.chromeosdevices.patch":{"id":"directory.chromeosdevices.patch","description":"Update Chrome OS Device. This method supports patch semantics.","supportsPatch":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"deviceId":{"type":"string","description":"Immutable id of Chrome OS Device","required":true},"projection":{"type":"string","description":"Restrict information returned to a set of selected fields.","enum":["BASIC","FULL"],"enumDescriptions":["Includes only the basic metadata fields (e.g., deviceId, serialNumber, status, and user)","Includes all metadata fields"]},"resource":{"$ref":"ChromeOsDevice"}},"parameterOrder":["resource","customerId","deviceId"],"returns":{"$ref":"ChromeOsDevice"},"scopes":["https://www.googleapis.com/auth/admin.directory.device.chromeos"]},"directory.chromeosdevices.update":{"id":"directory.chromeosdevices.update","description":"Update Chrome OS Device","parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"deviceId":{"type":"string","description":"Immutable id of Chrome OS Device","required":true},"projection":{"type":"string","description":"Restrict information returned to a set of selected fields.","enum":["BASIC","FULL"],"enumDescriptions":["Includes only the basic metadata fields (e.g., deviceId, serialNumber, status, and user)","Includes all metadata fields"]},"resource":{"$ref":"ChromeOsDevice"}},"parameterOrder":["resource","customerId","deviceId"],"returns":{"$ref":"ChromeOsDevice"},"scopes":["https://www.googleapis.com/auth/admin.directory.device.chromeos"]},"directory.groups.aliases.delete":{"id":"directory.groups.aliases.delete","description":"Remove a alias for the group","parameters":{"alias":{"type":"string","description":"The alias to be removed","required":true},"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true}},"parameterOrder":["groupKey","alias"],"scopes":["https://www.googleapis.com/auth/admin.directory.group"]},"directory.groups.aliases.insert":{"id":"directory.groups.aliases.insert","description":"Add a alias for the group","parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true},"resource":{"$ref":"Alias"}},"parameterOrder":["resource","groupKey"],"returns":{"$ref":"Alias"},"scopes":["https://www.googleapis.com/auth/admin.directory.group"]},"directory.groups.aliases.list":{"id":"directory.groups.aliases.list","description":"List all aliases for a group","allowGet":true,"parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true}},"parameterOrder":["groupKey"],"returns":{"$ref":"Aliases"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.readonly"],"supportsSubscription":true},"directory.groups.delete":{"id":"directory.groups.delete","description":"Delete Group","parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true}},"parameterOrder":["groupKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.group"]},"directory.groups.get":{"id":"directory.groups.get","description":"Retrieve Group","allowGet":true,"parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true}},"parameterOrder":["groupKey"],"returns":{"$ref":"Group"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.readonly"]},"directory.groups.insert":{"id":"directory.groups.insert","description":"Create Group","parameters":{"resource":{"$ref":"Group"}},"parameterOrder":["resource"],"returns":{"$ref":"Group"},"scopes":["https://www.googleapis.com/auth/admin.directory.group"]},"directory.groups.list":{"id":"directory.groups.list","description":"Retrieve all groups in a domain (paginated)","allowGet":true,"parameters":{"customer":{"type":"string","description":"Immutable id of the Google Apps account. In case of multi-domain, to fetch all groups for a customer, fill this field instead of domain."},"domain":{"type":"string","description":"Name of the domain. Fill this field to get groups from only this domain. To return all groups in a multi-domain fill customer field instead."},"maxResults":{"type":"integer","description":"Maximum number of results to return. Default is 200","format":"int32","minimum":"1"},"pageToken":{"type":"string","description":"Token to specify next page in the list"},"userKey":{"type":"string","description":"Email or immutable Id of the user if only those groups are to be listed, the given user is a member of. If Id, it should match with id of user object"}},"returns":{"$ref":"Groups"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.readonly"]},"directory.groups.patch":{"id":"directory.groups.patch","description":"Update Group. This method supports patch semantics.","supportsPatch":true,"parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group. If Id, it should match with id of group object","required":true},"resource":{"$ref":"Group"}},"parameterOrder":["resource","groupKey"],"returns":{"$ref":"Group"},"scopes":["https://www.googleapis.com/auth/admin.directory.group"]},"directory.groups.update":{"id":"directory.groups.update","description":"Update Group","parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group. If Id, it should match with id of group object","required":true},"resource":{"$ref":"Group"}},"parameterOrder":["resource","groupKey"],"returns":{"$ref":"Group"},"scopes":["https://www.googleapis.com/auth/admin.directory.group"]},"directory.members.delete":{"id":"directory.members.delete","description":"Remove membership.","parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true},"memberKey":{"type":"string","description":"Email or immutable Id of the member","required":true}},"parameterOrder":["groupKey","memberKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.member"]},"directory.members.get":{"id":"directory.members.get","description":"Retrieve Group Member","allowGet":true,"parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true},"memberKey":{"type":"string","description":"Email or immutable Id of the member","required":true}},"parameterOrder":["groupKey","memberKey"],"returns":{"$ref":"Member"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.member","https://www.googleapis.com/auth/admin.directory.group.member.readonly","https://www.googleapis.com/auth/admin.directory.group.readonly"]},"directory.members.insert":{"id":"directory.members.insert","description":"Add user to the specified group.","parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true},"resource":{"$ref":"Member"}},"parameterOrder":["resource","groupKey"],"returns":{"$ref":"Member"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.member"]},"directory.members.list":{"id":"directory.members.list","description":"Retrieve all members in a group (paginated)","allowGet":true,"parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group","required":true},"maxResults":{"type":"integer","description":"Maximum number of results to return. Default is 200","format":"int32","minimum":"1"},"pageToken":{"type":"string","description":"Token to specify next page in the list"},"roles":{"type":"string","description":"Comma separated role values to filter list results on."}},"parameterOrder":["groupKey"],"returns":{"$ref":"Members"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.member","https://www.googleapis.com/auth/admin.directory.group.member.readonly","https://www.googleapis.com/auth/admin.directory.group.readonly"]},"directory.members.patch":{"id":"directory.members.patch","description":"Update membership of a user in the specified group. This method supports patch semantics.","supportsPatch":true,"parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group. If Id, it should match with id of group object","required":true},"memberKey":{"type":"string","description":"Email or immutable Id of the user. If Id, it should match with id of member object","required":true},"resource":{"$ref":"Member"}},"parameterOrder":["resource","groupKey","memberKey"],"returns":{"$ref":"Member"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.member"]},"directory.members.update":{"id":"directory.members.update","description":"Update membership of a user in the specified group.","parameters":{"groupKey":{"type":"string","description":"Email or immutable Id of the group. If Id, it should match with id of group object","required":true},"memberKey":{"type":"string","description":"Email or immutable Id of the user. If Id, it should match with id of member object","required":true},"resource":{"$ref":"Member"}},"parameterOrder":["resource","groupKey","memberKey"],"returns":{"$ref":"Member"},"scopes":["https://www.googleapis.com/auth/admin.directory.group","https://www.googleapis.com/auth/admin.directory.group.member"]},"directory.mobiledevices.action":{"id":"directory.mobiledevices.action","description":"Take action on Mobile Device","parameters":{"action":{"type":"string","description":"Action to be taken on the Mobile Device","required":true},"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"resourceId":{"type":"string","description":"Immutable id of Mobile Device","required":true}},"parameterOrder":["customerId","resourceId","action"],"scopes":["https://www.googleapis.com/auth/admin.directory.device.mobile","https://www.googleapis.com/auth/admin.directory.device.mobile.action"]},"directory.mobiledevices.delete":{"id":"directory.mobiledevices.delete","description":"Delete Mobile Device","parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"resourceId":{"type":"string","description":"Immutable id of Mobile Device","required":true}},"parameterOrder":["customerId","resourceId"],"scopes":["https://www.googleapis.com/auth/admin.directory.device.mobile"]},"directory.mobiledevices.get":{"id":"directory.mobiledevices.get","description":"Retrieve Mobile Device","allowGet":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"projection":{"type":"string","description":"Restrict information returned to a set of selected fields.","enum":["BASIC","FULL"],"enumDescriptions":["Includes only the basic metadata fields (e.g., deviceId, model, status, type, and status)","Includes all metadata fields"]},"resourceId":{"type":"string","description":"Immutable id of Mobile Device","required":true}},"parameterOrder":["customerId","resourceId"],"returns":{"$ref":"MobileDevice"},"scopes":["https://www.googleapis.com/auth/admin.directory.device.mobile","https://www.googleapis.com/auth/admin.directory.device.mobile.action","https://www.googleapis.com/auth/admin.directory.device.mobile.readonly"]},"directory.mobiledevices.list":{"id":"directory.mobiledevices.list","description":"Retrieve all Mobile Devices of a customer (paginated)","allowGet":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"maxResults":{"type":"integer","description":"Maximum number of results to return. Default is 100","format":"int32","minimum":"1"},"orderBy":{"type":"string","description":"Column to use for sorting results","enum":["deviceId","email","lastSync","model","name","os","status","type"],"enumDescriptions":["Mobile Device serial number.","Owner user email.","Last policy settings sync date time of the device.","Mobile Device model.","Owner user name.","Mobile operating system.","Status of the device.","Type of the device."]},"pageToken":{"type":"string","description":"Token to specify next page in the list"},"projection":{"type":"string","description":"Restrict information returned to a set of selected fields.","enum":["BASIC","FULL"],"enumDescriptions":["Includes only the basic metadata fields (e.g., deviceId, model, status, type, and status)","Includes all metadata fields"]},"query":{"type":"string","description":"Search string in the format given at http://support.google.com/a/bin/answer.py?hl=en&answer=1408863#search"},"sortOrder":{"type":"string","description":"Whether to return results in ascending or descending order. Only of use when orderBy is also used","enum":["ASCENDING","DESCENDING"],"enumDescriptions":["Ascending order.","Descending order."]}},"parameterOrder":["customerId"],"returns":{"$ref":"MobileDevices"},"scopes":["https://www.googleapis.com/auth/admin.directory.device.mobile","https://www.googleapis.com/auth/admin.directory.device.mobile.action","https://www.googleapis.com/auth/admin.directory.device.mobile.readonly"]},"directory.notifications.delete":{"id":"directory.notifications.delete","description":"Deletes a notification","parameters":{"customer":{"type":"string","description":"The unique ID for the customer's Google account. The customerId is also returned as part of the Users resource.","required":true},"notificationId":{"type":"string","description":"The unique ID of the notification.","required":true}},"parameterOrder":["customer","notificationId"],"scopes":["https://www.googleapis.com/auth/admin.directory.notifications"]},"directory.notifications.get":{"id":"directory.notifications.get","description":"Retrieves a notification.","allowGet":true,"parameters":{"customer":{"type":"string","description":"The unique ID for the customer's Google account. The customerId is also returned as part of the Users resource.","required":true},"notificationId":{"type":"string","description":"The unique ID of the notification.","required":true}},"parameterOrder":["customer","notificationId"],"returns":{"$ref":"Notification"},"scopes":["https://www.googleapis.com/auth/admin.directory.notifications"]},"directory.notifications.list":{"id":"directory.notifications.list","description":"Retrieves a list of notifications.","allowGet":true,"parameters":{"customer":{"type":"string","description":"The unique ID for the customer's Google account.","required":true},"language":{"type":"string","description":"The ISO 639-1 code of the language notifications are returned in. The default is English (en)."},"maxResults":{"type":"integer","description":"Maximum number of notifications to return per page. The default is 100.","format":"uint32"},"pageToken":{"type":"string","description":"The token to specify the page of results to retrieve."}},"parameterOrder":["customer"],"returns":{"$ref":"Notifications"},"scopes":["https://www.googleapis.com/auth/admin.directory.notifications"]},"directory.notifications.patch":{"id":"directory.notifications.patch","description":"Updates a notification. This method supports patch semantics.","supportsPatch":true,"parameters":{"customer":{"type":"string","description":"The unique ID for the customer's Google account.","required":true},"notificationId":{"type":"string","description":"The unique ID of the notification.","required":true},"resource":{"$ref":"Notification"}},"parameterOrder":["resource","customer","notificationId"],"returns":{"$ref":"Notification"},"scopes":["https://www.googleapis.com/auth/admin.directory.notifications"]},"directory.notifications.update":{"id":"directory.notifications.update","description":"Updates a notification.","parameters":{"customer":{"type":"string","description":"The unique ID for the customer's Google account.","required":true},"notificationId":{"type":"string","description":"The unique ID of the notification.","required":true},"resource":{"$ref":"Notification"}},"parameterOrder":["resource","customer","notificationId"],"returns":{"$ref":"Notification"},"scopes":["https://www.googleapis.com/auth/admin.directory.notifications"]},"directory.orgunits.delete":{"id":"directory.orgunits.delete","description":"Remove Organization Unit","parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"orgUnitPath":{"type":"string","description":"Full path of the organization unit","required":true,"repeated":true}},"parameterOrder":["customerId","orgUnitPath"],"scopes":["https://www.googleapis.com/auth/admin.directory.orgunit"]},"directory.orgunits.get":{"id":"directory.orgunits.get","description":"Retrieve Organization Unit","allowGet":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"orgUnitPath":{"type":"string","description":"Full path of the organization unit","required":true,"repeated":true}},"parameterOrder":["customerId","orgUnitPath"],"returns":{"$ref":"OrgUnit"},"scopes":["https://www.googleapis.com/auth/admin.directory.orgunit","https://www.googleapis.com/auth/admin.directory.orgunit.readonly"]},"directory.orgunits.insert":{"id":"directory.orgunits.insert","description":"Add Organization Unit","parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"resource":{"$ref":"OrgUnit"}},"parameterOrder":["resource","customerId"],"returns":{"$ref":"OrgUnit"},"scopes":["https://www.googleapis.com/auth/admin.directory.orgunit"]},"directory.orgunits.list":{"id":"directory.orgunits.list","description":"Retrieve all Organization Units","allowGet":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"orgUnitPath":{"type":"string","description":"the URL-encoded organization unit","default":""},"type":{"type":"string","description":"Whether to return all sub-organizations or just immediate children","enum":["all","children"],"enumDescriptions":["All sub-organization units.","Immediate children only (default)."]}},"parameterOrder":["customerId"],"returns":{"$ref":"OrgUnits"},"scopes":["https://www.googleapis.com/auth/admin.directory.orgunit","https://www.googleapis.com/auth/admin.directory.orgunit.readonly"]},"directory.orgunits.patch":{"id":"directory.orgunits.patch","description":"Update Organization Unit. This method supports patch semantics.","supportsPatch":true,"parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"orgUnitPath":{"type":"string","description":"Full path of the organization unit","required":true,"repeated":true},"resource":{"$ref":"OrgUnit"}},"parameterOrder":["resource","customerId","orgUnitPath"],"returns":{"$ref":"OrgUnit"},"scopes":["https://www.googleapis.com/auth/admin.directory.orgunit"]},"directory.orgunits.update":{"id":"directory.orgunits.update","description":"Update Organization Unit","parameters":{"customerId":{"type":"string","description":"Immutable id of the Google Apps account","required":true},"orgUnitPath":{"type":"string","description":"Full path of the organization unit","required":true,"repeated":true},"resource":{"$ref":"OrgUnit"}},"parameterOrder":["resource","customerId","orgUnitPath"],"returns":{"$ref":"OrgUnit"},"scopes":["https://www.googleapis.com/auth/admin.directory.orgunit"]},"directory.tokens.delete":{"id":"directory.tokens.delete","description":"Delete all access tokens issued by a user for an application.","parameters":{"clientId":{"type":"string","description":"The Client ID of the application the token is issued to.","required":true},"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey","clientId"],"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.tokens.get":{"id":"directory.tokens.get","description":"Get information about an access token issued by a user.","allowGet":true,"parameters":{"clientId":{"type":"string","description":"The Client ID of the application the token is issued to.","required":true},"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey","clientId"],"returns":{"$ref":"Token"},"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.tokens.list":{"id":"directory.tokens.list","description":"Returns the set of current, valid verification codes for the specified user.","allowGet":true,"parameters":{"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey"],"returns":{"$ref":"Tokens"},"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.users.aliases.delete":{"id":"directory.users.aliases.delete","description":"Remove a alias for the user","parameters":{"alias":{"type":"string","description":"The alias to be removed","required":true},"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey","alias"],"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.alias"]},"directory.users.aliases.insert":{"id":"directory.users.aliases.insert","description":"Add a alias for the user","parameters":{"resource":{"$ref":"Alias"},"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["resource","userKey"],"returns":{"$ref":"Alias"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.alias"]},"directory.users.aliases.list":{"id":"directory.users.aliases.list","description":"List all aliases for a user","allowGet":true,"parameters":{"event":{"type":"string","description":"Event on which subscription is intended (if subscribing)","enum":["add","delete"],"enumDescriptions":["Alias Created Event","Alias Deleted Event"]},"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"returns":{"$ref":"Aliases"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.alias","https://www.googleapis.com/auth/admin.directory.user.alias.readonly","https://www.googleapis.com/auth/admin.directory.user.readonly"],"supportsSubscription":true},"directory.users.aliases.watch":{"id":"directory.users.aliases.watch","description":"Watch for changes in user aliases list","parameters":{"event":{"type":"string","description":"Event on which subscription is intended (if subscribing)","enum":["add","delete"],"enumDescriptions":["Alias Created Event","Alias Deleted Event"]},"resource":{"$ref":"Channel"},"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["resource","userKey"],"returns":{"$ref":"Channel"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.alias","https://www.googleapis.com/auth/admin.directory.user.alias.readonly","https://www.googleapis.com/auth/admin.directory.user.readonly"],"supportsSubscription":true},"directory.users.delete":{"id":"directory.users.delete","description":"Delete user","parameters":{"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.get":{"id":"directory.users.get","description":"retrieve user","allowGet":true,"parameters":{"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"returns":{"$ref":"User"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.readonly"]},"directory.users.insert":{"id":"directory.users.insert","description":"create user.","parameters":{"resource":{"$ref":"User"}},"parameterOrder":["resource"],"returns":{"$ref":"User"},"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.list":{"id":"directory.users.list","description":"Retrieve either deleted users or all users in a domain (paginated)","allowGet":true,"parameters":{"customer":{"type":"string","description":"Immutable id of the Google Apps account. In case of multi-domain, to fetch all users for a customer, fill this field instead of domain."},"domain":{"type":"string","description":"Name of the domain. Fill this field to get users from only this domain. To return all users in a multi-domain fill customer field instead."},"event":{"type":"string","description":"Event on which subscription is intended (if subscribing)","enum":["add","delete","makeAdmin","undelete","update"],"enumDescriptions":["User Created Event","User Deleted Event","User Admin Status Change Event","User Undeleted Event","User Updated Event"]},"maxResults":{"type":"integer","description":"Maximum number of results to return. Default is 100. Max allowed is 500","format":"int32","minimum":"1","maximum":"500"},"orderBy":{"type":"string","description":"Column to use for sorting results","enum":["email","familyName","givenName"],"enumDescriptions":["Primary email of the user.","User's family name.","User's given name."]},"pageToken":{"type":"string","description":"Token to specify next page in the list"},"query":{"type":"string","description":"Query string search. Should be of the form \"\" where field can be any of supported fields, operators can be one of '=' for exact match or ':' for prefix match. For prefix match, the value should always be followed by a *."},"showDeleted":{"type":"string","description":"If set to true retrieves the list of deleted users. Default is false"},"sortOrder":{"type":"string","description":"Whether to return results in ascending or descending order.","enum":["ASCENDING","DESCENDING"],"enumDescriptions":["Ascending order.","Descending order."]}},"returns":{"$ref":"Users"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.readonly"],"supportsSubscription":true},"directory.users.makeAdmin":{"id":"directory.users.makeAdmin","description":"change admin status of a user","parameters":{"status":{"type":"boolean","description":"Boolean indicating new admin status of the user","required":true},"userKey":{"type":"string","description":"Email or immutable Id of the user as admin","required":true}},"parameterOrder":["userKey","status"],"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.patch":{"id":"directory.users.patch","description":"update user. This method supports patch semantics.","supportsPatch":true,"parameters":{"resource":{"$ref":"User"},"userKey":{"type":"string","description":"Email or immutable Id of the user. If Id, it should match with id of user object","required":true}},"parameterOrder":["resource","userKey"],"returns":{"$ref":"User"},"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.photos.delete":{"id":"directory.users.photos.delete","description":"Remove photos for the user","parameters":{"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.photos.get":{"id":"directory.users.photos.get","description":"Retrieve photo of a user","allowGet":true,"parameters":{"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"returns":{"$ref":"UserPhoto"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.readonly"]},"directory.users.photos.patch":{"id":"directory.users.photos.patch","description":"Add a photo for the user. This method supports patch semantics.","supportsPatch":true,"parameters":{"resource":{"$ref":"UserPhoto"},"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["resource","userKey"],"returns":{"$ref":"UserPhoto"},"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.photos.update":{"id":"directory.users.photos.update","description":"Add a photo for the user","parameters":{"resource":{"$ref":"UserPhoto"},"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["resource","userKey"],"returns":{"$ref":"UserPhoto"},"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.undelete":{"id":"directory.users.undelete","description":"Undelete a deleted user","parameters":{"orgUnitPath":{"type":"string","description":"OrgUnit of User"},"userKey":{"type":"string","description":"The immutable id of the user","required":true}},"parameterOrder":["userKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.update":{"id":"directory.users.update","description":"update user","parameters":{"resource":{"$ref":"User"},"userKey":{"type":"string","description":"Email or immutable Id of the user. If Id, it should match with id of user object","required":true}},"parameterOrder":["resource","userKey"],"returns":{"$ref":"User"},"scopes":["https://www.googleapis.com/auth/admin.directory.user"]},"directory.users.watch":{"id":"directory.users.watch","description":"Watch for changes in users list","parameters":{"customer":{"type":"string","description":"Immutable id of the Google Apps account. In case of multi-domain, to fetch all users for a customer, fill this field instead of domain."},"domain":{"type":"string","description":"Name of the domain. Fill this field to get users from only this domain. To return all users in a multi-domain fill customer field instead."},"event":{"type":"string","description":"Event on which subscription is intended (if subscribing)","enum":["add","delete","makeAdmin","undelete","update"],"enumDescriptions":["User Created Event","User Deleted Event","User Admin Status Change Event","User Undeleted Event","User Updated Event"]},"maxResults":{"type":"integer","description":"Maximum number of results to return. Default is 100. Max allowed is 500","format":"int32","minimum":"1","maximum":"500"},"orderBy":{"type":"string","description":"Column to use for sorting results","enum":["email","familyName","givenName"],"enumDescriptions":["Primary email of the user.","User's family name.","User's given name."]},"pageToken":{"type":"string","description":"Token to specify next page in the list"},"query":{"type":"string","description":"Query string search. Should be of the form \"\" where field can be any of supported fields, operators can be one of '=' for exact match or ':' for prefix match. For prefix match, the value should always be followed by a *."},"resource":{"$ref":"Channel"},"showDeleted":{"type":"string","description":"If set to true retrieves the list of deleted users. Default is false"},"sortOrder":{"type":"string","description":"Whether to return results in ascending or descending order.","enum":["ASCENDING","DESCENDING"],"enumDescriptions":["Ascending order.","Descending order."]}},"parameterOrder":["resource"],"returns":{"$ref":"Channel"},"scopes":["https://www.googleapis.com/auth/admin.directory.user","https://www.googleapis.com/auth/admin.directory.user.readonly"],"supportsSubscription":true},"directory.verificationCodes.generate":{"id":"directory.verificationCodes.generate","description":"Generate new backup verification codes for the user.","parameters":{"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.verificationCodes.invalidate":{"id":"directory.verificationCodes.invalidate","description":"Invalidate the current backup verification codes for the user.","parameters":{"userKey":{"type":"string","description":"Email or immutable Id of the user","required":true}},"parameterOrder":["userKey"],"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]},"directory.verificationCodes.list":{"id":"directory.verificationCodes.list","description":"Returns the current set of valid backup verification codes for the specified user.","allowGet":true,"parameters":{"userKey":{"type":"string","description":"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID.","required":true}},"parameterOrder":["userKey"],"returns":{"$ref":"VerificationCodes"},"scopes":["https://www.googleapis.com/auth/admin.directory.user.security"]}}} \ No newline at end of file diff --git a/node_modules/googleapis/.cache/calendarv3 b/node_modules/googleapis/.cache/calendarv3 new file mode 100644 index 0000000..ce63b89 --- /dev/null +++ b/node_modules/googleapis/.cache/calendarv3 @@ -0,0 +1 @@ +{"kind":"discovery#rpcDescription","etag":"\"BgGnx7p-6wsAbOn4St99QhtBGbA/4UwkMOdYZDbOC7E_RcXhRTAMV6Y\"","discoveryVersion":"v1","id":"calendar:v3","name":"calendar","version":"v3","revision":"20130716","title":"Calendar API","description":"Lets you manipulate events and other calendar data.","ownerDomain":"google.com","ownerName":"Google","icons":{"x16":"http://www.google.com/images/icons/product/calendar-16.png","x32":"http://www.google.com/images/icons/product/calendar-32.png"},"documentationLink":"https://developers.google.com/google-apps/calendar/firstapp","protocol":"rpc","rootUrl":"https://www.googleapis.com/","rpcUrl":"https://www.googleapis.com/rpc","rpcPath":"/rpc","parameters":{"alt":{"type":"string","description":"Data format for the response.","default":"json","enum":["json"],"enumDescriptions":["Responses with Content-Type of application/json"],"location":"query"},"fields":{"type":"string","description":"Selector specifying which fields to include in a partial response.","location":"query"},"key":{"type":"string","description":"API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.","location":"query"},"oauth_token":{"type":"string","description":"OAuth 2.0 token for the current user.","location":"query"},"prettyPrint":{"type":"boolean","description":"Returns response with indentations and line breaks.","default":"true","location":"query"},"quotaUser":{"type":"string","description":"Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.","location":"query"},"userIp":{"type":"string","description":"IP address of the site where the request originates. Use this if you want to enforce per-user limits.","location":"query"}},"auth":{"oauth2":{"scopes":{"https://www.googleapis.com/auth/calendar":{"description":"Manage your calendars"},"https://www.googleapis.com/auth/calendar.readonly":{"description":"View your calendars"}}}},"schemas":{"Acl":{"id":"Acl","type":"object","properties":{"etag":{"type":"string","description":"ETag of the collection."},"items":{"type":"array","description":"List of rules on the access control list.","items":{"$ref":"AclRule"}},"kind":{"type":"string","description":"Type of the collection (\"calendar#acl\").","default":"calendar#acl"},"nextPageToken":{"type":"string","description":"Token used to access the next page of this result. Omitted if no further results are available."}}},"AclRule":{"id":"AclRule","type":"object","properties":{"etag":{"type":"string","description":"ETag of the resource."},"id":{"type":"string","description":"Identifier of the ACL rule."},"kind":{"type":"string","description":"Type of the resource (\"calendar#aclRule\").","default":"calendar#aclRule"},"role":{"type":"string","description":"The role assigned to the scope. Possible values are: \n- \"none\" - Provides no access. \n- \"freeBusyReader\" - Provides read access to free/busy information. \n- \"reader\" - Provides read access to the calendar. Private events will appear to users with reader access, but event details will be hidden. \n- \"writer\" - Provides read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible. \n- \"owner\" - Provides ownership of the calendar. This role has all of the permissions of the writer role with the additional ability to see and manipulate ACLs.","annotations":{"required":["calendar.acl.insert"]}},"scope":{"type":"object","description":"The scope of the rule.","properties":{"type":{"type":"string","description":"The type of the scope. Possible values are: \n- \"default\" - The public scope. This is the default value. \n- \"user\" - Limits the scope to a single user. \n- \"group\" - Limits the scope to a group. \n- \"domain\" - Limits the scope to a domain. Note: The permissions granted to the \"default\", or public, scope apply to any user, authenticated or not.","annotations":{"required":["calendar.acl.insert"]}},"value":{"type":"string","description":"The email address of a user or group, or the name of a domain, depending on the scope type. Omitted for type \"default\"."}},"annotations":{"required":["calendar.acl.insert"]}}}},"Calendar":{"id":"Calendar","type":"object","properties":{"description":{"type":"string","description":"Description of the calendar. Optional."},"etag":{"type":"string","description":"ETag of the resource."},"id":{"type":"string","description":"Identifier of the calendar."},"kind":{"type":"string","description":"Type of the resource (\"calendar#calendar\").","default":"calendar#calendar"},"location":{"type":"string","description":"Geographic location of the calendar as free-form text. Optional."},"summary":{"type":"string","description":"Title of the calendar.","annotations":{"required":["calendar.calendars.insert"]}},"timeZone":{"type":"string","description":"The time zone of the calendar. Optional."}}},"CalendarList":{"id":"CalendarList","type":"object","properties":{"etag":{"type":"string","description":"ETag of the collection."},"items":{"type":"array","description":"Calendars that are present on the user's calendar list.","items":{"$ref":"CalendarListEntry"}},"kind":{"type":"string","description":"Type of the collection (\"calendar#calendarList\").","default":"calendar#calendarList"},"nextPageToken":{"type":"string","description":"Token used to access the next page of this result."}}},"CalendarListEntry":{"id":"CalendarListEntry","type":"object","properties":{"accessRole":{"type":"string","description":"The effective access role that the authenticated user has on the calendar. Read-only. Possible values are: \n- \"freeBusyReader\" - Provides read access to free/busy information. \n- \"reader\" - Provides read access to the calendar. Private events will appear to users with reader access, but event details will be hidden. \n- \"writer\" - Provides read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible. \n- \"owner\" - Provides ownership of the calendar. This role has all of the permissions of the writer role with the additional ability to see and manipulate ACLs."},"backgroundColor":{"type":"string","description":"The main color of the calendar in the format '#0088aa'. This property supersedes the index-based colorId property. Optional."},"colorId":{"type":"string","description":"The color of the calendar. This is an ID referring to an entry in the \"calendar\" section of the colors definition (see the \"colors\" endpoint). Optional."},"defaultReminders":{"type":"array","description":"The default reminders that the authenticated user has for this calendar.","items":{"$ref":"EventReminder"}},"description":{"type":"string","description":"Description of the calendar. Optional. Read-only."},"etag":{"type":"string","description":"ETag of the resource."},"foregroundColor":{"type":"string","description":"The foreground color of the calendar in the format '#ffffff'. This property supersedes the index-based colorId property. Optional."},"hidden":{"type":"boolean","description":"Whether the calendar has been hidden from the list. Optional. The default is False."},"id":{"type":"string","description":"Identifier of the calendar.","annotations":{"required":["calendar.calendarList.insert"]}},"kind":{"type":"string","description":"Type of the resource (\"calendar#calendarListEntry\").","default":"calendar#calendarListEntry"},"location":{"type":"string","description":"Geographic location of the calendar as free-form text. Optional. Read-only."},"primary":{"type":"boolean","description":"Whether the calendar is the primary calendar of the authenticated user. Read-only. Optional. The default is False."},"selected":{"type":"boolean","description":"Whether the calendar content shows up in the calendar UI. Optional. The default is False."},"summary":{"type":"string","description":"Title of the calendar. Read-only."},"summaryOverride":{"type":"string","description":"The summary that the authenticated user has set for this calendar. Optional."},"timeZone":{"type":"string","description":"The time zone of the calendar. Optional. Read-only."}}},"Channel":{"id":"Channel","type":"object","properties":{"address":{"type":"string","description":"The address of the receiving entity where events are delivered. Specific to the channel type."},"expiration":{"type":"string","description":"The expiration instant for this channel if it is defined.","format":"int64"},"id":{"type":"string","description":"A UUID for the channel"},"kind":{"type":"string","description":"A channel watching an API resource","default":"api#channel"},"params":{"type":"object","description":"Additional parameters controlling delivery channel behavior","additionalProperties":{"type":"string","description":"Declares a new parameter by name."}},"resourceId":{"type":"string","description":"An opaque id that identifies the resource that is being watched. Stable across different API versions"},"resourceUri":{"type":"string","description":"The canonicalized ID of the watched resource."},"token":{"type":"string","description":"An arbitrary string associated with the channel that is delivered to the target address with each event delivered over this channel."},"type":{"type":"string","description":"The type of delivery mechanism used by this channel"}}},"ColorDefinition":{"id":"ColorDefinition","type":"object","properties":{"background":{"type":"string","description":"The background color associated with this color definition."},"foreground":{"type":"string","description":"The foreground color that can be used to write on top of a background with 'background' color."}}},"Colors":{"id":"Colors","type":"object","properties":{"calendar":{"type":"object","description":"Palette of calendar colors, mapping from the color ID to its definition. An 'calendarListEntry' resource refers to one of these color IDs in its 'color' field. Read-only.","additionalProperties":{"$ref":"ColorDefinition","description":"A calendar color defintion."}},"event":{"type":"object","description":"Palette of event colors, mapping from the color ID to its definition. An 'event' resource may refer to one of these color IDs in its 'color' field. Read-only.","additionalProperties":{"$ref":"ColorDefinition","description":"An event color definition."}},"kind":{"type":"string","description":"Type of the resource (\"calendar#colors\").","default":"calendar#colors"},"updated":{"type":"string","description":"Last modification time of the color palette (as a RFC 3339 timestamp). Read-only.","format":"date-time"}}},"Error":{"id":"Error","type":"object","properties":{"domain":{"type":"string","description":"Domain, or broad category, of the error."},"reason":{"type":"string","description":"Specific reason for the error. Some of the possible values are: \n- \"groupTooBig\" - The group of users requested is too large for a single query. \n- \"tooManyCalendarsRequested\" - The number of calendars requested is too large for a single query. \n- \"notFound\" - The requested resource was not found. \n- \"internalError\" - The API service has encountered an internal error. Additional error types may be added in the future, so clients should gracefully handle additional error statuses not included in this list."}}},"Event":{"id":"Event","type":"object","properties":{"anyoneCanAddSelf":{"type":"boolean","description":"Whether anyone can invite themselves to the event. Optional. The default is False."},"attendees":{"type":"array","description":"The attendees of the event.","items":{"$ref":"EventAttendee"}},"attendeesOmitted":{"type":"boolean","description":"Whether attendees may have been omitted from the event's representation. When retrieving an event, this may be due to a restriction specified by the 'maxAttendee' query parameter. When updating an event, this can be used to only update the participant's response. Optional. The default is False."},"colorId":{"type":"string","description":"The color of the event. This is an ID referring to an entry in the \"event\" section of the colors definition (see the \"colors\" endpoint). Optional."},"created":{"type":"string","description":"Creation time of the event (as a RFC 3339 timestamp). Read-only.","format":"date-time"},"creator":{"type":"object","description":"The creator of the event. Read-only.","properties":{"displayName":{"type":"string","description":"The creator's name, if available."},"email":{"type":"string","description":"The creator's email address, if available."},"id":{"type":"string","description":"The creator's Profile ID, if available."},"self":{"type":"boolean","description":"Whether the creator corresponds to the calendar on which this copy of the event appears. Read-only. The default is False."}}},"description":{"type":"string","description":"Description of the event. Optional."},"end":{"$ref":"EventDateTime","description":"The (exclusive) end time of the event. For a recurring event, this is the end time of the first instance.","annotations":{"required":["calendar.events.import","calendar.events.insert","calendar.events.update"]}},"endTimeUnspecified":{"type":"boolean","description":"Whether the end time is actually unspecified. An end time is still provided for compatibility reasons, even if this attribute is set to True. The default is False."},"etag":{"type":"string","description":"ETag of the resource."},"extendedProperties":{"type":"object","description":"Extended properties of the event.","properties":{"private":{"type":"object","description":"Properties that are private to the copy of the event that appears on this calendar.","additionalProperties":{"type":"string","description":"The name of the private property and the corresponding value."}},"shared":{"type":"object","description":"Properties that are shared between copies of the event on other attendees' calendars.","additionalProperties":{"type":"string","description":"The name of the shared property and the corresponding value."}}}},"gadget":{"type":"object","description":"A gadget that extends this event.","properties":{"display":{"type":"string","description":"The gadget's display mode. Optional. Possible values are: \n- \"icon\" - The gadget displays next to the event's title in the calendar view. \n- \"chip\" - The gadget displays when the event is clicked."},"height":{"type":"integer","description":"The gadget's height in pixels. Optional.","format":"int32"},"iconLink":{"type":"string","description":"The gadget's icon URL."},"link":{"type":"string","description":"The gadget's URL."},"preferences":{"type":"object","description":"Preferences.","additionalProperties":{"type":"string","description":"The preference name and corresponding value."}},"title":{"type":"string","description":"The gadget's title."},"type":{"type":"string","description":"The gadget's type."},"width":{"type":"integer","description":"The gadget's width in pixels. Optional.","format":"int32"}}},"guestsCanInviteOthers":{"type":"boolean","description":"Whether attendees other than the organizer can invite others to the event. Optional. The default is True."},"guestsCanModify":{"type":"boolean","description":"Whether attendees other than the organizer can modify the event. Optional. The default is False."},"guestsCanSeeOtherGuests":{"type":"boolean","description":"Whether attendees other than the organizer can see who the event's attendees are. Optional. The default is True."},"hangoutLink":{"type":"string","description":"An absolute link to the Google+ hangout associated with this event. Read-only."},"htmlLink":{"type":"string","description":"An absolute link to this event in the Google Calendar Web UI. Read-only."},"iCalUID":{"type":"string","description":"Event ID in the iCalendar format.","annotations":{"required":["calendar.events.import"]}},"id":{"type":"string","description":"Identifier of the event."},"kind":{"type":"string","description":"Type of the resource (\"calendar#event\").","default":"calendar#event"},"location":{"type":"string","description":"Geographic location of the event as free-form text. Optional."},"locked":{"type":"boolean","description":"Whether this is a locked event copy where no changes can be made to the main event fields \"summary\", \"description\", \"location\", \"start\", \"end\" or \"recurrence\". The default is False. Read-Only."},"organizer":{"type":"object","description":"The organizer of the event. If the organizer is also an attendee, this is indicated with a separate entry in 'attendees' with the 'organizer' field set to True. To change the organizer, use the \"move\" operation. Read-only, except when importing an event.","properties":{"displayName":{"type":"string","description":"The organizer's name, if available."},"email":{"type":"string","description":"The organizer's email address, if available."},"id":{"type":"string","description":"The organizer's Profile ID, if available."},"self":{"type":"boolean","description":"Whether the organizer corresponds to the calendar on which this copy of the event appears. Read-only. The default is False."}}},"originalStartTime":{"$ref":"EventDateTime","description":"For an instance of a recurring event, this is the time at which this event would start according to the recurrence data in the recurring event identified by recurringEventId. Immutable."},"privateCopy":{"type":"boolean","description":"Whether this is a private event copy where changes are not shared with other copies on other calendars. Optional. Immutable. The default is False."},"recurrence":{"type":"array","description":"List of RRULE, EXRULE, RDATE and EXDATE lines for a recurring event. This field is omitted for single events or instances of recurring events.","items":{"type":"string"}},"recurringEventId":{"type":"string","description":"For an instance of a recurring event, this is the event ID of the recurring event itself. Immutable."},"reminders":{"type":"object","description":"Information about the event's reminders for the authenticated user.","properties":{"overrides":{"type":"array","description":"If the event doesn't use the default reminders, this lists the reminders specific to the event, or, if not set, indicates that no reminders are set for this event.","items":{"$ref":"EventReminder"}},"useDefault":{"type":"boolean","description":"Whether the default reminders of the calendar apply to the event."}}},"sequence":{"type":"integer","description":"Sequence number as per iCalendar.","format":"int32"},"source":{"type":"object","description":"Source of an event from which it was created; for example a web page, an email message or any document identifiable by an URL using HTTP/HTTPS protocol. Accessible only by the creator of the event.","properties":{"title":{"type":"string","description":"Title of the source; for example a title of a web page or an email subject."},"url":{"type":"string","description":"URL of the source pointing to a resource. URL's protocol must be HTTP or HTTPS."}}},"start":{"$ref":"EventDateTime","description":"The (inclusive) start time of the event. For a recurring event, this is the start time of the first instance.","annotations":{"required":["calendar.events.import","calendar.events.insert","calendar.events.update"]}},"status":{"type":"string","description":"Status of the event. Optional. Possible values are: \n- \"confirmed\" - The event is confirmed. This is the default status. \n- \"tentative\" - The event is tentatively confirmed. \n- \"cancelled\" - The event is cancelled."},"summary":{"type":"string","description":"Title of the event."},"transparency":{"type":"string","description":"Whether the event blocks time on the calendar. Optional. Possible values are: \n- \"opaque\" - The event blocks time on the calendar. This is the default value. \n- \"transparent\" - The event does not block time on the calendar."},"updated":{"type":"string","description":"Last modification time of the event (as a RFC 3339 timestamp). Read-only.","format":"date-time"},"visibility":{"type":"string","description":"Visibility of the event. Optional. Possible values are: \n- \"default\" - Uses the default visibility for events on the calendar. This is the default value. \n- \"public\" - The event is public and event details are visible to all readers of the calendar. \n- \"private\" - The event is private and only event attendees may view event details. \n- \"confidential\" - The event is private. This value is provided for compatibility reasons."}}},"EventAttendee":{"id":"EventAttendee","type":"object","properties":{"additionalGuests":{"type":"integer","description":"Number of additional guests. Optional. The default is 0.","format":"int32"},"comment":{"type":"string","description":"The attendee's response comment. Optional."},"displayName":{"type":"string","description":"The attendee's name, if available. Optional."},"email":{"type":"string","description":"The attendee's email address, if available. This field must be present when adding an attendee.","annotations":{"required":["calendar.events.import","calendar.events.insert","calendar.events.update"]}},"id":{"type":"string","description":"The attendee's Profile ID, if available."},"optional":{"type":"boolean","description":"Whether this is an optional attendee. Optional. The default is False."},"organizer":{"type":"boolean","description":"Whether the attendee is the organizer of the event. Read-only. The default is False."},"resource":{"type":"boolean","description":"Whether the attendee is a resource. Read-only. The default is False."},"responseStatus":{"type":"string","description":"The attendee's response status. Possible values are: \n- \"needsAction\" - The attendee has not responded to the invitation. \n- \"declined\" - The attendee has declined the invitation. \n- \"tentative\" - The attendee has tentatively accepted the invitation. \n- \"accepted\" - The attendee has accepted the invitation."},"self":{"type":"boolean","description":"Whether this entry represents the calendar on which this copy of the event appears. Read-only. The default is False."}}},"EventDateTime":{"id":"EventDateTime","type":"object","properties":{"date":{"type":"string","description":"The date, in the format \"yyyy-mm-dd\", if this is an all-day event.","format":"date"},"dateTime":{"type":"string","description":"The time, as a combined date-time value (formatted according to RFC 3339). A time zone offset is required unless a time zone is explicitly specified in 'timeZone'.","format":"date-time"},"timeZone":{"type":"string","description":"The name of the time zone in which the time is specified (e.g. \"Europe/Zurich\"). Optional. The default is the time zone of the calendar."}}},"EventReminder":{"id":"EventReminder","type":"object","properties":{"method":{"type":"string","description":"The method used by this reminder. Possible values are: \n- \"email\" - Reminders are sent via email. \n- \"sms\" - Reminders are sent via SMS. \n- \"popup\" - Reminders are sent via a UI popup.","annotations":{"required":["calendar.calendarList.insert","calendar.calendarList.update","calendar.events.import","calendar.events.insert","calendar.events.update"]}},"minutes":{"type":"integer","description":"Number of minutes before the start of the event when the reminder should trigger.","format":"int32","annotations":{"required":["calendar.calendarList.insert","calendar.calendarList.update","calendar.events.import","calendar.events.insert","calendar.events.update"]}}}},"Events":{"id":"Events","type":"object","properties":{"accessRole":{"type":"string","description":"The user's access role for this calendar. Read-only. Possible values are: \n- \"none\" - The user has no access. \n- \"freeBusyReader\" - The user has read access to free/busy information. \n- \"reader\" - The user has read access to the calendar. Private events will appear to users with reader access, but event details will be hidden. \n- \"writer\" - The user has read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible. \n- \"owner\" - The user has ownership of the calendar. This role has all of the permissions of the writer role with the additional ability to see and manipulate ACLs."},"defaultReminders":{"type":"array","description":"The default reminders on the calendar for the authenticated user. These reminders apply to all events on this calendar that do not explicitly override them (i.e. do not have 'reminders.useDefault' set to 'true').","items":{"$ref":"EventReminder"}},"description":{"type":"string","description":"Description of the calendar. Read-only."},"etag":{"type":"string","description":"ETag of the collection."},"items":{"type":"array","description":"List of events on the calendar.","items":{"$ref":"Event"}},"kind":{"type":"string","description":"Type of the collection (\"calendar#events\").","default":"calendar#events"},"nextPageToken":{"type":"string","description":"Token used to access the next page of this result. Omitted if no further results are available."},"summary":{"type":"string","description":"Title of the calendar. Read-only."},"timeZone":{"type":"string","description":"The time zone of the calendar. Read-only."},"updated":{"type":"string","description":"Last modification time of the calendar (as a RFC 3339 timestamp). Read-only.","format":"date-time"}}},"FreeBusyCalendar":{"id":"FreeBusyCalendar","type":"object","properties":{"busy":{"type":"array","description":"List of time ranges during which this calendar should be regarded as busy.","items":{"$ref":"TimePeriod"}},"errors":{"type":"array","description":"Optional error(s) (if computation for the calendar failed).","items":{"$ref":"Error"}}}},"FreeBusyGroup":{"id":"FreeBusyGroup","type":"object","properties":{"calendars":{"type":"array","description":"List of calendars' identifiers within a group.","items":{"type":"string"}},"errors":{"type":"array","description":"Optional error(s) (if computation for the group failed).","items":{"$ref":"Error"}}}},"FreeBusyRequestItem":{"id":"FreeBusyRequestItem","type":"object","properties":{"id":{"type":"string","description":"The identifier of a calendar or a group."}}},"FreeBusyResponse":{"id":"FreeBusyResponse","type":"object","properties":{"calendars":{"type":"object","description":"List of free/busy information for calendars.","additionalProperties":{"$ref":"FreeBusyCalendar","description":"Free/busy expansions for a single calendar."}},"groups":{"type":"object","description":"Expansion of groups.","additionalProperties":{"$ref":"FreeBusyGroup","description":"List of calendars that are members of this group."}},"kind":{"type":"string","description":"Type of the resource (\"calendar#freeBusy\").","default":"calendar#freeBusy"},"timeMax":{"type":"string","description":"The end of the interval.","format":"date-time"},"timeMin":{"type":"string","description":"The start of the interval.","format":"date-time"}}},"Setting":{"id":"Setting","type":"object","properties":{"etag":{"type":"string","description":"ETag of the resource."},"id":{"type":"string","description":"Name of the user setting."},"kind":{"type":"string","description":"Type of the resource (\"calendar#setting\").","default":"calendar#setting"},"value":{"type":"string","description":"Value of the user setting. The format of the value depends on the ID of the setting."}}},"Settings":{"id":"Settings","type":"object","properties":{"etag":{"type":"string","description":"Etag of the collection."},"items":{"type":"array","description":"List of user settings.","items":{"$ref":"Setting"}},"kind":{"type":"string","description":"Type of the collection (\"calendar#settings\").","default":"calendar#settings"}}},"TimePeriod":{"id":"TimePeriod","type":"object","properties":{"end":{"type":"string","description":"The (exclusive) end of the time period.","format":"date-time"},"start":{"type":"string","description":"The (inclusive) start of the time period.","format":"date-time"}}}},"methods":{"calendar.acl.delete":{"id":"calendar.acl.delete","description":"Deletes an access control rule.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"ruleId":{"type":"string","description":"ACL rule identifier.","required":true}},"parameterOrder":["calendarId","ruleId"],"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.acl.get":{"id":"calendar.acl.get","description":"Returns an access control rule.","allowGet":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"ruleId":{"type":"string","description":"ACL rule identifier.","required":true}},"parameterOrder":["calendarId","ruleId"],"returns":{"$ref":"AclRule"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.acl.insert":{"id":"calendar.acl.insert","description":"Creates an access control rule.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"resource":{"$ref":"AclRule"}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"AclRule"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.acl.list":{"id":"calendar.acl.list","description":"Returns the rules in the access control list for the calendar.","allowGet":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true}},"parameterOrder":["calendarId"],"returns":{"$ref":"Acl"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.acl.patch":{"id":"calendar.acl.patch","description":"Updates an access control rule. This method supports patch semantics.","supportsPatch":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"resource":{"$ref":"AclRule"},"ruleId":{"type":"string","description":"ACL rule identifier.","required":true}},"parameterOrder":["resource","calendarId","ruleId"],"returns":{"$ref":"AclRule"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.acl.update":{"id":"calendar.acl.update","description":"Updates an access control rule.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"resource":{"$ref":"AclRule"},"ruleId":{"type":"string","description":"ACL rule identifier.","required":true}},"parameterOrder":["resource","calendarId","ruleId"],"returns":{"$ref":"AclRule"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendarList.delete":{"id":"calendar.calendarList.delete","description":"Deletes an entry on the user's calendar list.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true}},"parameterOrder":["calendarId"],"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendarList.get":{"id":"calendar.calendarList.get","description":"Returns an entry on the user's calendar list.","allowGet":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true}},"parameterOrder":["calendarId"],"returns":{"$ref":"CalendarListEntry"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.calendarList.insert":{"id":"calendar.calendarList.insert","description":"Adds an entry to the user's calendar list.","parameters":{"colorRgbFormat":{"type":"boolean","description":"Whether to use the 'foregroundColor' and 'backgroundColor' fields to write the calendar colors (RGB). If this feature is used, the index-based 'colorId' field will be set to the best matching option automatically. Optional. The default is False."},"resource":{"$ref":"CalendarListEntry"}},"parameterOrder":["resource"],"returns":{"$ref":"CalendarListEntry"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendarList.list":{"id":"calendar.calendarList.list","description":"Returns entries on the user's calendar list.","allowGet":true,"parameters":{"maxResults":{"type":"integer","description":"Maximum number of entries returned on one result page. Optional.","format":"int32","minimum":"1"},"minAccessRole":{"type":"string","description":"The minimum access role for the user in the returned entires. Optional. The default is no restriction.","enum":["freeBusyReader","owner","reader","writer"],"enumDescriptions":["The user can read free/busy information.","The user can read and modify events and access control lists.","The user can read events that are not private.","The user can read and modify events."]},"pageToken":{"type":"string","description":"Token specifying which result page to return. Optional."},"showHidden":{"type":"boolean","description":"Whether to show hidden entries. Optional. The default is False."}},"returns":{"$ref":"CalendarList"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.calendarList.patch":{"id":"calendar.calendarList.patch","description":"Updates an entry on the user's calendar list. This method supports patch semantics.","supportsPatch":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"colorRgbFormat":{"type":"boolean","description":"Whether to use the 'foregroundColor' and 'backgroundColor' fields to write the calendar colors (RGB). If this feature is used, the index-based 'colorId' field will be set to the best matching option automatically. Optional. The default is False."},"resource":{"$ref":"CalendarListEntry"}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"CalendarListEntry"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendarList.update":{"id":"calendar.calendarList.update","description":"Updates an entry on the user's calendar list.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"colorRgbFormat":{"type":"boolean","description":"Whether to use the 'foregroundColor' and 'backgroundColor' fields to write the calendar colors (RGB). If this feature is used, the index-based 'colorId' field will be set to the best matching option automatically. Optional. The default is False."},"resource":{"$ref":"CalendarListEntry"}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"CalendarListEntry"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendars.clear":{"id":"calendar.calendars.clear","description":"Clears a primary calendar. This operation deletes all data associated with the primary calendar of an account and cannot be undone.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true}},"parameterOrder":["calendarId"],"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendars.delete":{"id":"calendar.calendars.delete","description":"Deletes a secondary calendar.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true}},"parameterOrder":["calendarId"],"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendars.get":{"id":"calendar.calendars.get","description":"Returns metadata for a calendar.","allowGet":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true}},"parameterOrder":["calendarId"],"returns":{"$ref":"Calendar"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.calendars.insert":{"id":"calendar.calendars.insert","description":"Creates a secondary calendar.","parameters":{"resource":{"$ref":"Calendar"}},"parameterOrder":["resource"],"returns":{"$ref":"Calendar"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendars.patch":{"id":"calendar.calendars.patch","description":"Updates metadata for a calendar. This method supports patch semantics.","supportsPatch":true,"parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"resource":{"$ref":"Calendar"}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"Calendar"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.calendars.update":{"id":"calendar.calendars.update","description":"Updates metadata for a calendar.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"resource":{"$ref":"Calendar"}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"Calendar"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.channels.stop":{"id":"calendar.channels.stop","parameters":{"address":{"type":"string","description":"The address of the receiving entity where events are delivered. Specific to the channel type."},"expiration":{"type":"string","description":"The expiration instant for this channel if it is defined.","format":"int64"},"id":{"type":"string","description":"A UUID for the channel"},"kind":{"type":"string","description":"A channel watching an API resource","default":"api#channel"},"params":{"type":"object","description":"Additional parameters controlling delivery channel behavior","additionalProperties":{"type":"string","description":"Declares a new parameter by name."}},"resourceId":{"type":"string","description":"An opaque id that identifies the resource that is being watched. Stable across different API versions"},"resourceUri":{"type":"string","description":"The canonicalized ID of the watched resource."},"token":{"type":"string","description":"An arbitrary string associated with the channel that is delivered to the target address with each event delivered over this channel."},"type":{"type":"string","description":"The type of delivery mechanism used by this channel"}},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.colors.get":{"id":"calendar.colors.get","description":"Returns the color definitions for calendars and events.","allowGet":true,"returns":{"$ref":"Colors"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.events.delete":{"id":"calendar.events.delete","description":"Deletes an event.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"eventId":{"type":"string","description":"Event identifier.","required":true},"sendNotifications":{"type":"boolean","description":"Whether to send notifications about the deletion of the event. Optional. The default is False."}},"parameterOrder":["calendarId","eventId"],"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.get":{"id":"calendar.events.get","description":"Returns an event.","allowGet":true,"parameters":{"alwaysIncludeEmail":{"type":"boolean","description":"Whether to always include a value in the \"email\" field for the organizer, creator and attendees, even if no real email is available (i.e. a generated, non-working value will be provided). The use of this option is discouraged and should only be used by clients which cannot handle the absence of an email address value in the mentioned places. Optional. The default is False."},"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"eventId":{"type":"string","description":"Event identifier.","required":true},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"timeZone":{"type":"string","description":"Time zone used in the response. Optional. The default is the time zone of the calendar."}},"parameterOrder":["calendarId","eventId"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.events.import":{"id":"calendar.events.import","description":"Imports an event. This operation is used to add a private copy of an existing event to a calendar.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"resource":{"$ref":"Event"}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.insert":{"id":"calendar.events.insert","description":"Creates an event.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"resource":{"$ref":"Event"},"sendNotifications":{"type":"boolean","description":"Whether to send notifications about the creation of the new event. Optional. The default is False."}},"parameterOrder":["resource","calendarId"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.instances":{"id":"calendar.events.instances","description":"Returns instances of the specified recurring event.","allowGet":true,"parameters":{"alwaysIncludeEmail":{"type":"boolean","description":"Whether to always include a value in the \"email\" field for the organizer, creator and attendees, even if no real email is available (i.e. a generated, non-working value will be provided). The use of this option is discouraged and should only be used by clients which cannot handle the absence of an email address value in the mentioned places. Optional. The default is False."},"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"eventId":{"type":"string","description":"Recurring event identifier.","required":true},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"maxResults":{"type":"integer","description":"Maximum number of events returned on one result page. Optional.","format":"int32","minimum":"1"},"originalStart":{"type":"string","description":"The original start time of the instance in the result. Optional."},"pageToken":{"type":"string","description":"Token specifying which result page to return. Optional."},"showDeleted":{"type":"boolean","description":"Whether to include deleted events (with 'status' equals 'cancelled') in the result. Cancelled instances of recurring events will still be included if 'singleEvents' is False. Optional. The default is False."},"timeMax":{"type":"string","description":"Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time.","format":"date-time"},"timeMin":{"type":"string","description":"Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time.","format":"date-time"},"timeZone":{"type":"string","description":"Time zone used in the response. Optional. The default is the time zone of the calendar."}},"parameterOrder":["calendarId","eventId"],"returns":{"$ref":"Events"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"],"supportsSubscription":true},"calendar.events.list":{"id":"calendar.events.list","description":"Returns events on the specified calendar.","allowGet":true,"parameters":{"alwaysIncludeEmail":{"type":"boolean","description":"Whether to always include a value in the \"email\" field for the organizer, creator and attendees, even if no real email is available (i.e. a generated, non-working value will be provided). The use of this option is discouraged and should only be used by clients which cannot handle the absence of an email address value in the mentioned places. Optional. The default is False."},"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"iCalUID":{"type":"string","description":"Specifies iCalendar UID (iCalUID) of events to be included in the response. Optional."},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"maxResults":{"type":"integer","description":"Maximum number of events returned on one result page. Optional.","format":"int32","minimum":"1"},"orderBy":{"type":"string","description":"The order of the events returned in the result. Optional. The default is an unspecified, stable order.","enum":["startTime","updated"],"enumDescriptions":["Order by the start date/time (ascending). This is only available when querying single events (i.e. the parameter \"singleEvents\" is True)","Order by last modification time (ascending)."]},"pageToken":{"type":"string","description":"Token specifying which result page to return. Optional."},"q":{"type":"string","description":"Free text search terms to find events that match these terms in any field, except for extended properties. Optional."},"showDeleted":{"type":"boolean","description":"Whether to include deleted events (with 'status' equals 'cancelled') in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if 'showDeleted' and 'singleEvents' are both False. If 'showDeleted' and 'singleEvents' are both True, only single instances of deleted events (but not the underlying recurring events) are returned. Optional. The default is False."},"showHiddenInvitations":{"type":"boolean","description":"Whether to include hidden invitations in the result. Optional. The default is False."},"singleEvents":{"type":"boolean","description":"Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. Optional. The default is False."},"timeMax":{"type":"string","description":"Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time.","format":"date-time"},"timeMin":{"type":"string","description":"Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time.","format":"date-time"},"timeZone":{"type":"string","description":"Time zone used in the response. Optional. The default is the time zone of the calendar."},"updatedMin":{"type":"string","description":"Lower bound for an event's last modification time (as a RFC 3339 timestamp) to filter by. Optional. The default is not to filter by last modification time.","format":"date-time"}},"parameterOrder":["calendarId"],"returns":{"$ref":"Events"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"],"supportsSubscription":true},"calendar.events.move":{"id":"calendar.events.move","description":"Moves an event to another calendar, i.e. changes an event's organizer.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier of the source calendar where the event currently is on.","required":true},"destination":{"type":"string","description":"Calendar identifier of the target calendar where the event is to be moved to.","required":true},"eventId":{"type":"string","description":"Event identifier.","required":true},"sendNotifications":{"type":"boolean","description":"Whether to send notifications about the change of the event's organizer. Optional. The default is False."}},"parameterOrder":["calendarId","eventId","destination"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.patch":{"id":"calendar.events.patch","description":"Updates an event. This method supports patch semantics.","supportsPatch":true,"parameters":{"alwaysIncludeEmail":{"type":"boolean","description":"Whether to always include a value in the \"email\" field for the organizer, creator and attendees, even if no real email is available (i.e. a generated, non-working value will be provided). The use of this option is discouraged and should only be used by clients which cannot handle the absence of an email address value in the mentioned places. Optional. The default is False."},"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"eventId":{"type":"string","description":"Event identifier.","required":true},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"resource":{"$ref":"Event"},"sendNotifications":{"type":"boolean","description":"Whether to send notifications about the event update (e.g. attendee's responses, title changes, etc.). Optional. The default is False."}},"parameterOrder":["resource","calendarId","eventId"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.quickAdd":{"id":"calendar.events.quickAdd","description":"Creates an event based on a simple text string.","parameters":{"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"sendNotifications":{"type":"boolean","description":"Whether to send notifications about the creation of the event. Optional. The default is False."},"text":{"type":"string","description":"The text describing the event to be created.","required":true}},"parameterOrder":["calendarId","text"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.update":{"id":"calendar.events.update","description":"Updates an event.","parameters":{"alwaysIncludeEmail":{"type":"boolean","description":"Whether to always include a value in the \"email\" field for the organizer, creator and attendees, even if no real email is available (i.e. a generated, non-working value will be provided). The use of this option is discouraged and should only be used by clients which cannot handle the absence of an email address value in the mentioned places. Optional. The default is False."},"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"eventId":{"type":"string","description":"Event identifier.","required":true},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"resource":{"$ref":"Event"},"sendNotifications":{"type":"boolean","description":"Whether to send notifications about the event update (e.g. attendee's responses, title changes, etc.). Optional. The default is False."}},"parameterOrder":["resource","calendarId","eventId"],"returns":{"$ref":"Event"},"scopes":["https://www.googleapis.com/auth/calendar"]},"calendar.events.watch":{"id":"calendar.events.watch","description":"Subscribe to changes in events collection","parameters":{"alwaysIncludeEmail":{"type":"boolean","description":"Whether to always include a value in the \"email\" field for the organizer, creator and attendees, even if no real email is available (i.e. a generated, non-working value will be provided). The use of this option is discouraged and should only be used by clients which cannot handle the absence of an email address value in the mentioned places. Optional. The default is False."},"calendarId":{"type":"string","description":"Calendar identifier.","required":true},"channel":{"$ref":"Channel"},"iCalUID":{"type":"string","description":"Specifies iCalendar UID (iCalUID) of events to be included in the response. Optional."},"maxAttendees":{"type":"integer","description":"The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. Optional.","format":"int32","minimum":"1"},"maxResults":{"type":"integer","description":"Maximum number of events returned on one result page. Optional.","format":"int32","minimum":"1"},"orderBy":{"type":"string","description":"The order of the events returned in the result. Optional. The default is an unspecified, stable order.","enum":["startTime","updated"],"enumDescriptions":["Order by the start date/time (ascending). This is only available when querying single events (i.e. the parameter \"singleEvents\" is True)","Order by last modification time (ascending)."]},"pageToken":{"type":"string","description":"Token specifying which result page to return. Optional."},"q":{"type":"string","description":"Free text search terms to find events that match these terms in any field, except for extended properties. Optional."},"showDeleted":{"type":"boolean","description":"Whether to include deleted events (with 'status' equals 'cancelled') in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if 'showDeleted' and 'singleEvents' are both False. If 'showDeleted' and 'singleEvents' are both True, only single instances of deleted events (but not the underlying recurring events) are returned. Optional. The default is False."},"showHiddenInvitations":{"type":"boolean","description":"Whether to include hidden invitations in the result. Optional. The default is False."},"singleEvents":{"type":"boolean","description":"Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. Optional. The default is False."},"timeMax":{"type":"string","description":"Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time.","format":"date-time"},"timeMin":{"type":"string","description":"Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time.","format":"date-time"},"timeZone":{"type":"string","description":"Time zone used in the response. Optional. The default is the time zone of the calendar."},"updatedMin":{"type":"string","description":"Lower bound for an event's last modification time (as a RFC 3339 timestamp) to filter by. Optional. The default is not to filter by last modification time.","format":"date-time"}},"parameterOrder":["channel","calendarId"],"returns":{"$ref":"Channel"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"],"supportsSubscription":true},"calendar.freebusy.query":{"id":"calendar.freebusy.query","description":"Returns free/busy information for a set of calendars.","parameters":{"calendarExpansionMax":{"type":"integer","description":"Maximal number of calendars for which FreeBusy information is to be provided. Optional.","format":"int32"},"groupExpansionMax":{"type":"integer","description":"Maximal number of calendar identifiers to be provided for a single group. Optional. An error will be returned for a group with more members than this value.","format":"int32"},"items":{"type":"array","description":"List of calendars and/or groups to query.","items":{"$ref":"FreeBusyRequestItem"}},"timeMax":{"type":"string","description":"The end of the interval for the query.","format":"date-time"},"timeMin":{"type":"string","description":"The start of the interval for the query.","format":"date-time"},"timeZone":{"type":"string","description":"Time zone used in the response. Optional. The default is UTC."}},"returns":{"$ref":"FreeBusyResponse"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.settings.get":{"id":"calendar.settings.get","description":"Returns a single user setting.","allowGet":true,"parameters":{"setting":{"type":"string","description":"Name of the user setting.","required":true}},"parameterOrder":["setting"],"returns":{"$ref":"Setting"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]},"calendar.settings.list":{"id":"calendar.settings.list","description":"Returns all user settings for the authenticated user.","allowGet":true,"returns":{"$ref":"Settings"},"scopes":["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly"]}}} \ No newline at end of file diff --git a/node_modules/googleapis/.npmignore b/node_modules/googleapis/.npmignore new file mode 100644 index 0000000..df789ff --- /dev/null +++ b/node_modules/googleapis/.npmignore @@ -0,0 +1,4 @@ +tests/* +examples/* +.cache/* +b041042364d89046c003ca151a6254ef/* diff --git a/node_modules/googleapis/.travis.yml b/node_modules/googleapis/.travis.yml new file mode 100644 index 0000000..baa0031 --- /dev/null +++ b/node_modules/googleapis/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/googleapis/COPYING b/node_modules/googleapis/COPYING new file mode 100644 index 0000000..b7c9ed1 --- /dev/null +++ b/node_modules/googleapis/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2013 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/googleapis/README.md b/node_modules/googleapis/README.md new file mode 100644 index 0000000..7560a13 --- /dev/null +++ b/node_modules/googleapis/README.md @@ -0,0 +1,247 @@ +# google-api-nodejs-client [alpha] + +[![Build Status](https://travis-ci.org/google/google-api-nodejs-client.png)](https://travis-ci.org/google/google-api-nodejs-client) + +`google-api-nodejs-client` is Google's officially supported +[node.js](http://nodejs.org/) client +library for accessing Google APIs, it also supports authorization and +authentication with OAuth 2.0. + +**Note**: This library is currently in *alpha* status, meaning that we can make +changes in the future that *may not be compatible* with the previous versions. + +## Installation + +The library is distributed on `npm`. In order to add it as a dependency, +run the following command: + + $ npm install googleapis + +## Guide + +### Discover APIs + +Dynamically load Google APIs and start making requests: + +~~~~ js +var googleapis = require('googleapis'); + +googleapis + .discover('urlshortener', 'v1') + .discover('plus', 'v1') + .execute(function(err, client) { + var params = { shortUrl: 'http://goo.gl/DdUKX' }; + var req1 = client.urlshortener.url.get(params); + req1.execute(function (err, response) { + console.log('Long url is', response.longUrl); + }); + + var req2 = client.plus.people.get({ userId: '+BurcuDogan' }); + req2.execute(); +}); +~~~~ + +Supported APIs are listed on +[Google APIs Explorer](https://developers.google.com/apis-explorer). + +#### Discovery Document Caching + +Discovery documents are being cached for 5 minutes locally. +You can configure the directory used to store cached discovery +files by using the `cache.path` option. + +~~~~ js +googleapis + .discover('plus', 'v3') + .withOpts({ cache: { path: '' })) + .execute(); +~~~~ + +### API Client + +Client libraries are generated during runtime by metadata provided by Google +APIs Discovery Service. Metadata provided by Discovery Service is cached, +and won't be requested each time you load a client. Below, there is an +example of loading a client for +[URL Shortener API](https://developers.google.com/url-shortener/). + +~~~~ js +googleapis + .discover('urlshortener', 'v1') + .execute(function(err, client) { + // make requests + }); +~~~~ + +### Requests + +The following sample loads a client for URL Shortener and retrieves the long url +of the given short url: + +~~~~ js +googleapis.discover('urlshortener', 'v1').execute(function(err, client) { + client.urlshortener.url.get({ shortUrl: 'http://goo.gl/DdUKX' }) + .execute(function(err, result) { + // result.longUrl contains the long url. + }); + }); +~~~~ + +Alternatively, you may need to send an API key with the +request you are going to make. The following creates and executes a request from the Google+ API service to retrieve a person profile given a userId: + +~~~~ js +googleapis + .discover('plus', 'v1') + .execute(function(err, client) { + var request1 = client.plus.people.get({ userId: '+BurcuDogan' }) + .withApiKey(API_KEY); + + request1.execute(function(err, result) { + console.log("Result: " + (err ? err.message : result.displayName)); + }); + }); +~~~~ + +To learn more about API keys, please see the [documentation](https://developers.google.com/console/help/#UsingKeys). + +### Batch requests + +You can combine multiple requests in a single one by using batch requests. + +~~~~ js +var request1 = + client.plus.people.get({ userId: '+BurcuDogan' }); + +var request2 = + client.urlshortener.url.insert({ longUrl: 'http://google.com' }); + +// Create from client service using the raw action name +var request3 = client.urlshortener.newRequest( + 'urlshortener.url.get', { shortUrl: 'http://goo.gl/DdUKX' }); + +client + .newBatchRequest() + .add(request1) + .add(request2) + .add(request3) + .execute(function(err, results) { + + }); +~~~~ + +### Authorization and Authentication + +This client comes with an OAuth2 client that allows you to retrieve an access token and +refreshes the token and re-try the request seamlessly if token is expired. The +basics of Google's OAuth 2.0 implementation is explained on +[Google Authorization and Authentication +documentation](https://developers.google.com/accounts/docs/OAuth2Login). + +A complete sample application that authorizes and authenticates with OAuth2.0 +client is available at `examples/oauth2.js`. + +#### Consent Page Url + +In order to ask for permissions from a user to retrieve an access token, you +should redirect them to a consent page. In order to create a consent page +URL: + +~~~~ js +var googleapis = require('googleapis'), + OAuth2Client = googleapis.OAuth2Client; + +var oauth2Client = + new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL); + +// generates a url that allows offline access and asks permissions +// for Google+ scope. +var url = oauth2Client.generateAuthUrl({ + access_type: 'offline', + scope: 'https://www.googleapis.com/auth/plus.me' +}); +~~~~ + +#### Retrieving Tokens +Once a user has given permissions on the consent page, Google will redirect +the page to the redirect url you have provided with a code query parameter. + + GET /oauthcallback?code={authorizationCode} + +With the code returned, you can ask for an access token as shown below: + +~~~~ js +oauth2Client.getToken(code, function(err, tokens) { + // contains an access_token and optionally a refresh_token. + // save them permanently. +}); +~~~~ + +#### Making Authenticated Requests + +And you can start using oauth2Client to authorize and authenticate your +requests to Google APIs with the retrieved tokens. If you provide a +refresh_token, in cases when access_token is expired, it asks for a new +access_token and replays the request. + +Following sample retrieves Google+ profile of the authenticated user. + +~~~~ js +oauth2Client.credentials = { + access_token: 'ACCESS TOKEN HERE', + refresh_token: 'REFRESH TOKEN HERE' +}; + +client + .plus.people.get({ userId: 'me' }) + .withAuthClient(oauth2Client) + .execute(callback); +~~~~ + +## License + +`google-api-nodejs-client` is licensed with Apache 2.0. Full license text is +available on COPYING file. + +## Contributors + +Before making any contributions, please sign one of the contributor +license agreements below. + +Fork the repo, develop and test your code changes. + +Install all dependencies including development requirements by running: + + $ npm install -d + +Tests use mocha. To run all tests you can use + + $ npm test + +which looks for tests in the `./tests` directory. + +Your code should honor the +[Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml). +You can use +[Closure Linter](https://code.google.com/p/closure-linter/) +to detect style issues. + +Submit a pull request. The repo owner will review your request. If it is +approved, the change will be merged. If it needs additional work, the repo +owner will respond with useful comments. + +#### Contributor License Agreements + +Before creating a pull request, please fill out either the individual or +corporate Contributor License Agreement. + +* If you are an individual writing original source code and you're sure you +own the intellectual property, then you'll need to sign an +[individual CLA](http://code.google.com/legal/individual-cla-v1.0.html). +* If you work for a company that wants to allow you to contribute your work +to this client library, then you'll need to sign a +[corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll add you +to the official list of contributors and be able to accept your patches. diff --git a/node_modules/googleapis/lib/auth/authclient.js b/node_modules/googleapis/lib/auth/authclient.js new file mode 100644 index 0000000..21c0289 --- /dev/null +++ b/node_modules/googleapis/lib/auth/authclient.js @@ -0,0 +1,41 @@ +/** + * Copyright 2012 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var DefaultTransporter = require('../transporters.js'); + +function AuthClient() { + this.transporter = new DefaultTransporter(); +} + +/** + * Provides an alternative request + * implementations with auth credentials. + */ +AuthClient.prototype.request = function() { + throw new Error('Not implemented yet.'); +}; + +/** + * Sets auth credentials. + * @param {object} credentials Credentials. + */ +AuthClient.prototype.setCredentials = function(credentials) { + this.credentials = credentials; +}; + +/** + * Export AuthClient. + */ +module.exports = AuthClient; diff --git a/node_modules/googleapis/lib/auth/computeclient.js b/node_modules/googleapis/lib/auth/computeclient.js new file mode 100644 index 0000000..a3a7c2e --- /dev/null +++ b/node_modules/googleapis/lib/auth/computeclient.js @@ -0,0 +1,79 @@ +/** + * Copyright 2013 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var querystring = require('querystring'); +var Auth2Client = require('./oauth2client.js'); +var util = require('util'); + +/** + * @private + * Google Compute Engine metadata server token endpoint. + */ +Compute.GOOGLE_OAUTH2_TOKEN_URL_ = + 'http://metadata/computeMetadata/v1beta1/instance/service-accounts/default/token'; + +/** + * @constructor + * Google Compute Engine service account credentials. + * + * Retrieve access token from the metadata server. + * See: https://developers.google.com/compute/docs/authentication + * + */ +function Compute() { + Compute.super_.call(this); +} + +/** + * Inherit from Auth2Client. + */ +util.inherits(Compute, Auth2Client); + +/** + * Get the initial access token from compute metadata server. + * @param {function=} opt_callback Optional callback. + */ +Compute.prototype.authorize = function(opt_callback) { + var that = this; + that.refreshToken_(null, function(err, result) { + if (!err) { + that.credentials = result; + that.credentials.refresh_token = 'compute-placeholder'; + } + opt_callback && opt_callback(err, result); + }); +}; + +/** + * @private + * Refreshes the access token. + * @param {object=} ignored_ + * @param {function=} opt_callback Optional callback. + */ +Compute.prototype.refreshToken_ = function(ignored_, opt_callback) { + var uri = this.opts.tokenUrl || Compute.GOOGLE_OAUTH2_TOKEN_URL_; + // request for new token + this.transporter.request({ + method: 'GET', + uri: uri, + json: true + }, opt_callback); +}; + +/** + * Export Compute. + */ +module.exports = Compute; diff --git a/node_modules/googleapis/lib/auth/oauth2client.js b/node_modules/googleapis/lib/auth/oauth2client.js new file mode 100644 index 0000000..b4fb7b9 --- /dev/null +++ b/node_modules/googleapis/lib/auth/oauth2client.js @@ -0,0 +1,199 @@ +/** + * Copyright 2012 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var querystring = require('querystring'); +var AuthClient = require('./authclient.js'); +var util = require('util'); + +function OAuth2Client(clientId, clientSecret, redirectUri, opt_opts) { + OAuth2Client.super_.call(this); + + this.clientId_ = clientId; + this.clientSecret_ = clientSecret; + this.redirectUri_ = redirectUri; + this.opts = opt_opts || {}; + this.credentials = null; +} + +/** + * Inherit from AuthClient. + */ +util.inherits(OAuth2Client, AuthClient); + +/** + * The base URL for auth endpoints. + * @const + * @private + * + */ +OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_ = + 'https://accounts.google.com/o/oauth2/auth'; + +/** + * The base endpoint for token retrieval. + * @const + * @private + * The .. + */ +OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_ = + 'https://accounts.google.com/o/oauth2/token'; + +/** + * The base endpoint to revoke tokens. + * @const + * @private + */ +OAuth2Client.GOOGLE_OAUTH2_REVOKE_URL_ = + 'https://accounts.google.com/o/oauth2/revoke'; + +/** + * Generates URL for consent page landing. + * @param {object=} opt_opts Options. + * @return {string} URL to consent page. + */ +OAuth2Client.prototype.generateAuthUrl = function(opt_opts) { + + var opts = opt_opts || {}; + opts.response_type = opts.response_type || 'code'; + opts.client_id = this.clientId_; + opts.redirect_uri = this.redirectUri_; + + var rootUrl = this.opts.authBaseUrl || + OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_; + + return rootUrl + '?' + querystring.stringify(opts); +}; + +/** + * Gets the access token for given code. + * @param {string} code The authorization code. + * @param {function=} opt_callback Optional callback fn. + */ +OAuth2Client.prototype.getToken = function(code, opt_callback) { + + var uri = this.opts.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; + var values = { + code: code, + client_id: this.clientId_, + client_secret: this.clientSecret_, + redirect_uri: this.redirectUri_, + grant_type: 'authorization_code' + }; + + this.transporter.request({ + method: 'POST', + uri: uri, + form: values, + json: true + }, opt_callback); +}; + +/** + * @private + * Refreshes the access token. + * @param {string} refresh_token Existing refresh token. + * @param {function=} opt_callback Optional callback. + */ +OAuth2Client.prototype.refreshToken_ = + function(refresh_token, opt_callback) { + + var uri = this.opts.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; + var values = { + refresh_token: refresh_token, + client_id: this.clientId_, + client_secret: this.clientSecret_, + grant_type: 'refresh_token' + }; + + // request for new token + this.transporter.request({ + method: 'POST', + uri: uri, + form: values, + json: true + }, opt_callback); +}; + +/** + * Revokes the access given to token. + * @param {string} token The existing token to be revoked. + * @param {function=} opt_callback Optional callback fn. + */ +OAuth2Client.prototype.revokeToken = function(token, opt_callback) { + this.transporter.request({ + uri: OAuth2Client.GOOGLE_OAUTH2_REVOKE_URL_ + + '?' + querystring.stringify({ token: token }), + json: true + }, opt_callback); +}; + +/** + * Provides a request implementation with OAuth 2.0 flow. + * If credentials have a refresh_token, in cases of HTTP + * 401 and 403 responses, it automatically asks for a new + * access token and replays the unsuccessful request. + * @param {object} opts Request options. + * @param {function=} opt_callback Optional callback. + * @param {boolean=} opt_dontForceRefresh If set, don't ask for a new token + * with refresh_token. + */ +OAuth2Client.prototype.request = + function(opts, opt_callback, opt_dontForceRefresh) { + + var that = this; + var credentials = this.credentials; + + if (!credentials.access_token && !credentials.refresh_token) { + throw new Error('No access or refresh token is set.'); + } + + credentials.token_type = credentials.token_type || 'Bearer'; + opts.headers = opts.headers || {}; + opts.headers['Authorization'] + = credentials.token_type + ' ' + credentials.access_token; + + this.transporter.request(opts, function(err, body, res) { + var hasAuthError = false; + // TODO(burcud): Should we redo requests without + // an auth error? This question will be invalid when we switch + // to multi part batch requests. + err && err.forEach(function(e) { + hasAuthError = (e.code == 401 || e.code == 403); + }); + // if there is an auth error, refresh the token + // and make the request again + if (!opt_dontForceRefresh && hasAuthError && credentials.refresh_token) { + // refresh access token and re-request + that.refreshToken_(credentials.refresh_token, function(err, result) { + if (err) { + opt_callback && opt_callback(err, null, null); + } else { + var tokens = result; + tokens.refresh_token = credentials.refresh_token; + that.credentials = tokens; + that.request(opts, opt_callback, true); + } + }); + } else { + opt_callback && opt_callback(err, body, res); + } + }); +}; + +/** + * Export OAuth2Client. + */ +module.exports = OAuth2Client; diff --git a/node_modules/googleapis/lib/cache.js b/node_modules/googleapis/lib/cache.js new file mode 100644 index 0000000..edc505c --- /dev/null +++ b/node_modules/googleapis/lib/cache.js @@ -0,0 +1,112 @@ +/** + * Copyright 2013 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var fs = require('fs'); + +/** + * @const + * @private + * Path to the temporary directory. + * @type {String} + */ +Cache.TMP_DIR_ = __dirname + '/../.cache'; + +/** + * @const + * @private + * Default encoding for cached files. + * @type {String} + */ +Cache.ENCODING_ = 'utf-8'; + +/** + * @const + * @private + * Default expires time in micro seconds. + * @type {Number} + */ +Cache.EXPIRES_IN_ = 5 * 60 * 1000; + +/** + * @constructor + * Cache constructor. + * @param {String} opt_opts Optional options. + */ +function Cache(opt_opts) { + this.opts = opt_opts || {}; + this.opts.path = this.opts.path || Cache.TMP_DIR_; + if (!fs.existsSync(this.opts.path)) { + fs.mkdirSync(this.opts.path, '700'); + } +} + +/** + * Loads discovery data from cache + * @param {object} api + * @return {object?} Returns the cached discovery data if exists + * or not expired. + */ +Cache.prototype.load = function(api) { + var path = this.getPath(api); + // check if file exists and not expired + if (!fs.existsSync(path)) { + return null; + } + + if (this.isExpired(path)) { + // delete the expired cache file + fs.unlinkSync(path); + return null; + } + + var data = fs.readFileSync(this.getPath(api), Cache.ENCODING_); + return data && JSON.parse(data); +}; + +/** + * Writes api discovery data to the cache. + * @param {object} api + * @param {object} data + */ +Cache.prototype.write = function(api, data) { + data && fs.writeFileSync( + this.getPath(api), JSON.stringify(data), Cache.ENCODING_); +}; + +/** + * Checks whether the file at path is expired or not + * @param {[type]} path The path of the file to check. + * @return {Boolean} Returns true or false depending on the expiration. + */ +Cache.prototype.isExpired = function(path) { + var expiresIn = this.opts.expiresIn || Cache.EXPIRES_IN_; + return new Date(fs.statSync(path).mtime).getTime() - expiresIn < 0; +}; + +/** + * Gets the path where the api data is stored at. + * @param {[type]} api + * @return {string} Path to the data file. + */ +Cache.prototype.getPath = function(api) { + return this.opts.path + '/' + api.name + api.version; +}; + +/** + * Exports Cache. + * @type {Cache} + */ +module.exports = Cache; diff --git a/node_modules/googleapis/lib/client.js b/node_modules/googleapis/lib/client.js new file mode 100644 index 0000000..d441be3 --- /dev/null +++ b/node_modules/googleapis/lib/client.js @@ -0,0 +1,140 @@ +/** + * Copyright 2012 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var Request = require('./requests.js').Request; +var BatchRequest = require('./requests.js').BatchRequest; + +/** + * Constructs a new client with given API name and version. + * @constructor + * + * @param {object} apiMeta Schema returned by Discovery API. + */ +function Client(apiMeta) { + this.apiMeta = apiMeta; + this.authClient = null; + // generate helper methods + this.registerHelpers_(); +} + +/** + * Gets the API's name. + * @return {String} + */ +Client.prototype.getName = function() { + return this.apiMeta.name; +}; + +/** + * Gets the API's version. + * @return {String} + */ +Client.prototype.getVersion = function() { + return this.apiMeta.version; +}; + +/** + * @private + * Registers request builders for existing API methods. + */ +Client.prototype.registerHelpers_ = function() { + for (var i in this.apiMeta.methods) { + var methodMeta = this.apiMeta.methods[i]; + this.extend_(this, methodMeta.id, this.generateHelper_(methodMeta)); + } +}; + +/** + * @private + * TODO(burcud): move to utils + * + * @param {?object} root Object to be extended. + * @param {string} key Full key. + * @param {?object} obj Object to extend root object with. + * @return {object} Extended object. + */ +Client.prototype.extend_ = function(root, key, obj) { + + if (!root) root = {}; + var namespaceKeys = key.split('.'); + + var chain = root; + // avoid the client name + for (var i = 1; i < namespaceKeys.length; i++) { + var chainKey = namespaceKeys[i]; + + // if this is the last key, put obj in it. + if (i == namespaceKeys.length - 1) { + chain[chainKey] = obj; + } else if (!chain[chainKey]) { + chain[chainKey] = {}; + } + + // move to the next key + chain = chain[chainKey]; + } + + return root; +}; + +/** + * @private + * Generate a request builder helper. + * + * @param {object} methodMeta Method's schema returned by Discovery API. + * @return {Function} Function generated by methodMeta. + */ +Client.prototype.generateHelper_ = function(methodMeta) { + + var that = this; + + // generates a function to make a request + // to the resource on given method + return function(params, resource) { + return that.newRequest(methodMeta.id, params, resource); + }; +}; + +/** + * Constructs a request to method with given parameters. + * + * @param {string} methodName Full name of the method. + * @param {?object} params Parameters. + * @param {object=} opt_resource Optional resource. + * + * @return {Request} New Request object constructed with given args. + */ +Client.prototype.newRequest = function(methodName, params, opt_resource) { + return new Request(this.apiMeta, methodName, params, opt_resource) + .withAuthClient(this.authClient); +}; + +/** + * Adds global auth client. + * + * @param {auth.AuthClient} client An auth client instance. + * + * @return {Client} Returns itself. + */ +Client.prototype.withAuthClient = function(client) { + this.authClient = client; + return this; +}; + +/** + * Exporting Client. + */ +module.exports = Client; diff --git a/node_modules/googleapis/lib/googleapis.js b/node_modules/googleapis/lib/googleapis.js new file mode 100644 index 0000000..77d2c48 --- /dev/null +++ b/node_modules/googleapis/lib/googleapis.js @@ -0,0 +1,268 @@ +/** + * Copyright 2012 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var async = require('async'), + Cache = require('./cache.js'), + Client = require('./client.js'), + DefaultTransporter = require('./transporters.js'), + qs = require('querystring'), + requests = require('./requests.js'), + fs = require('fs'); + +/** + * @constructor + * GoogleApisClient constructor. + */ +function GoogleApisClient() { + this.clients = []; + this.ops = {}; + this.authClient = null; +} + +/** + * Add a new individual client to the instance. + * @param {String} name + * @param {Client} client + */ +GoogleApisClient.prototype.add = function(name, client) { + this[name] = client.withAuthClient(this.authClient); +}; + +/** + * Creates a new batch request. + * @return {BatchRequest} New batch request. + */ +GoogleApisClient.prototype.newBatchRequest = function() { + return new requests.BatchRequest() + .withAuthClient(this.authClient); +}; + +/** + * Adds global auth client. + * + * @param {auth.AuthClient} client An auth client instance. + * + * @return {Client} Returns itself. + */ +GoogleApisClient.prototype.withAuthClient = function(client) { + this.authClient = client; + return this; +}; + +/** + * @constructor + * GoogleApis constructor. + */ +function GoogleApis() { + this.opts = {}; + this.toBeDiscovered = []; + this.transporter = exports.Transporter || new DefaultTransporter(); + this.authClient = null; +} + +/** + * @const + * @private + * Base path for discovery API. + * @type {string} + */ +GoogleApis.BASE_DISCOVERY_URL_ = + 'https://www.googleapis.com/discovery/v1/apis/'; + +/** + * @const + * @private + * Discovery type. + * @type {string} + */ +// TODO(burcud): Switch to REST. +GoogleApis.DISCOVERY_TYPE_ = 'rpc'; + +/** + * @const + * @private + * Additional discovery parameters. + * @type {object} + */ +GoogleApis.DISCOVERY_PARAMS_ = null; + +/** + * Discover the API with the given name, version and opt options. + * @param {String} name The name of the API. + * @param {String} version The version of the API. + * @param {Object} opt_opts Additional options. + * @return {GoogleApis} Returns itself. + */ +GoogleApis.prototype.discover = function(name, version, opt_opts) { + this.toBeDiscovered.push({ + name: name, version: version, opts: opt_opts }); + return this; +}; + +/** + * Executes requests to discover APIs. + * @param {Function=} opt_callback + */ +GoogleApis.prototype.execute = function(opt_callback) { + var that = this, + operations = [], + client = new GoogleApisClient() + .withAuthClient(this.authClient); + + this.toBeDiscovered.forEach(function(obj) { + operations.push(function(callback) { + that.load.call(that, obj, callback); + }); + }); + + async.parallel(operations, function(err, results) { + if (err) { + opt_callback && opt_callback(err, null); + } else { + results = results || []; + results.forEach(function(result) { + // extend client object with indivual clients. + client.add(result.getName(), result); + }); + opt_callback && opt_callback(null, client); + } + }); +}; + +/** + * Generates a client through discovery API. + * @param {String} api An object to represent the api name, version and opts. + * @param {Function=} opt_callback Optional callback function. + */ +GoogleApis.prototype.load = function(api, opt_callback) { + var that = this; + var cache = new Cache(this.opts.cache); + + if (api.opts && api.opts.localDiscoveryFilePath) { + that.loadFromFile(api.opts.localDiscoveryFilePath, opt_callback); + return; + } + + var generateClient = function(err, data) { + var client = null; + if (!err && data) { + cache.write(api, data); + client = new Client(data); + } + opt_callback && opt_callback(err, client); + }; + + var data = cache.load(api); + if (data) { + generateClient(null, data); + } else { + that.transporter.request({ + uri: that.generateDiscoveryUrl(api), json: true + }, generateClient); + } +}; + +/** + * Generates a client from a local discovery file. + * @param {String} filename Path of the local discovery file. + * @param {Function=} opt_callback Optional callback function. + */ +GoogleApis.prototype.loadFromFile = function(filename, opt_callback) { + fs.readFile(filename, function(err, data) { + var client = null; + if (!err && data) { + client = new Client(JSON.parse(data)); + } + opt_callback && opt_callback(err, client); + }); +}; + +/** + * Generates the discovery url. + * @param {String} api An object to represent the api name, version and opts. + * @return {string} discoveryUrl. + */ +GoogleApis.prototype.generateDiscoveryUrl = function(api) { + api.opts = api.opts || {}; + var baseDiscoveryUrl = api.opts.baseDiscoveryUrl || + GoogleApis.BASE_DISCOVERY_URL_; + + var discoveryParams = api.opts.discoveryParams || + GoogleApis.DISCOVERY_PARAMS_; + + var discoveryUrl = baseDiscoveryUrl; + discoveryUrl += encodeURIComponent(api.name) + + '/' + encodeURIComponent(api.version) + + '/' + GoogleApis.DISCOVERY_TYPE_; + + if (discoveryParams) { + discoveryUrl += '?' + qs.stringify(discoveryParams); + } + + return discoveryUrl; +}; + +/** + * Adds options. + * + * @param {object} opts Options. + * @return {GoogleApis} Returns itself. + */ +GoogleApis.prototype.withOpts = function(opts) { + this.opts = opts; + return this; +}; + +/** + * Adds global auth client. + * + * @param {auth.AuthClient} client An auth client instance. + * @return {GoogleApis} Returns itself. + */ +GoogleApis.prototype.withAuthClient = function(client) { + this.authClient = client; + return this; +}; + +var googleapis = new GoogleApis(); + +/** + * Shortcut to GoogleApis. + */ +googleapis.GoogleApis = GoogleApis; + +/** + * Shortcut to OAuth2Client. + */ +googleapis.OAuth2Client = require('./auth/oauth2client.js'); + +/** + * Shortcut to Auth. + */ +googleapis.auth = { + Compute: require('./auth/computeclient.js'), + OAuth2Client: googleapis.OAuth2Client +}; + +/** + * Exports googleapis. + */ +module.exports = googleapis; + +/** + * Exports Transporter. + */ +exports.Transporter = null; diff --git a/node_modules/googleapis/lib/requests.js b/node_modules/googleapis/lib/requests.js new file mode 100644 index 0000000..c91fe20 --- /dev/null +++ b/node_modules/googleapis/lib/requests.js @@ -0,0 +1,286 @@ +/** + * Copyright 2012 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var util = require('util'); +var querystring = require('querystring'); +var DefaultTransporter = require('./transporters.js'); + +function BaseRequest(apiMeta) { + this.transporter = new DefaultTransporter(); + this.authClient = null; + this.apiKey = null; +} + +/** + * @const + * @type {String} + */ +BaseRequest.JSONRPC_VERSION = '2.0'; + +/** + * @const + * @type {String} + */ +BaseRequest.JSONRPC_URL = 'https://www.googleapis.com/rpc'; + +/** + * Sets the auth client. + * @param {AuthClient} client An auth client instance. + * @return {BaseRequest} Returns itself. + */ +BaseRequest.prototype.withAuthClient = function(client) { + this.authClient = client; + return this; +}; + +/** + * Sets an API key. + * @param {String} apiKey + * @return {BaseRequest} Returns itself. + */ +BaseRequest.prototype.withApiKey = function(apiKey) { + this.apiKey = apiKey; + return this; +}; + +/** + * Returns true if request requires a parameter. + * If no metadata is known about the request's method, true is returned. + * @return {boolean} Returns whether a parameter is required or not. + */ +BaseRequest.prototype.doesRequireParams = function() { + if (!this.apiMeta || !this.apiMeta.methods || + !this.apiMeta.methods[this.methodName]) { + // nothing to do here, dont have enough + // info about the parameters + return true; + } + var methodMeta = this.apiMeta.methods[this.methodName]; + for (var i in methodMeta.parameters) { + if (methodMeta.parameters[i].required) { + return true; + } + } + return false; +}; + +/** + * @protected + * Generates uri end-point with given params. + * + * @param {object=} opt_params Query parameters or null. + * @return {string} Generated uri. + */ +BaseRequest.prototype.generateUri = function(opt_params) { + var url = BaseRequest.JSONRPC_URL; + opt_params = opt_params || {}; + + if (this.apiKey) { + opt_params.key = this.apiKey; + } + var params = querystring.stringify(opt_params); + if (params) { + url += '?' + params; + } + return url; +}; + +/** + * @protected + * Generates payload body of the request. + * @return {object?} Request payload. + */ +BaseRequest.prototype.generatePayload = function() { + return null; +}; + +/** + * Executes the batch request. + * + * @param {Function=} opt_callback Optional callback function. + */ +BaseRequest.prototype.execute = function(opt_callback) { + // TODO(burcud): Switch to REST. + opt_callback = opt_callback || function() {}; + var callback = this.handleResponse(opt_callback); + + var requestOpts = { + method: 'POST', + uri: this.generateUri(), + json: this.generatePayload() + }; + + if (this.authClient) { + this.authClient.request(requestOpts, callback); + } else { + // make the request with default client + this.transporter.request(requestOpts, callback); + } +}; + +/** + * @protected + * Wraps request callbacks. + * + * @param {Function=} opt_fn Optional callback function to be wrapped. + * @return {Function} Wrapped callback function. + */ +BaseRequest.prototype.handleResponse = function(opt_fn) { + throw new Error('Not implemented...'); +}; + +/** + * Constructs a new Request. + * @constructor + * + * @param {object} apiMeta Schema returned by Discovery API. + * @param {string} methodName Method name. + * @param {?object} opt_params Required Parameters. If none are required, + * expected to be not passed. + * @param {object=} opt_resource Optional resource. + */ +function Request( + apiMeta, methodName, opt_params, opt_resource) { + Request.super_.call(this); + this.apiMeta = apiMeta; + this.methodName = methodName; + + if (!this.doesRequireParams() && !opt_resource) { + this.params = {}; + this.resource = opt_params; + } else { + this.params = opt_params || {}; + this.resource = opt_resource; + } +} + +/** + * Inherits from BaseRequest. + */ +util.inherits(Request, BaseRequest); + +/** + * Generates JSON-RPC payload with a single request. + * @return {Array.} Returns request payload. + */ +Request.prototype.generatePayload = function() { + this.params.resource = this.resource; + console.dir(this.params); + var request = { + jsonrpc: BaseRequest.JSONRPC_VERSION, + id: 0, + method: this.methodName, + params: this.params, + apiVersion: this.apiMeta.version + }; + return [request]; +}; + +/** + * Handles response. + * @param {Function=} opt_fn Optional callback function. + * @return {Function} Wraps response callback and returns. + */ +Request.prototype.handleResponse = function(opt_fn) { + return function(err, results, res) { + var result = results && results[0] && results[0].result; + err = err && util.isArray(err) ? err[0] : err; + opt_fn && opt_fn(err, result, res); + }; +}; + +/** + * Constructs a new batch request. + * @constructor + */ +function BatchRequest() { + BatchRequest.super_.call(this); + this.requests_ = []; +} + +/** + * Inherits from BaseRequest. + */ +util.inherits(BatchRequest, BaseRequest); + +/** + * Adds a request to the batch request. + * @param {Request} request A Request object to add to the batch. + * + * @return {BatchRequest} Returns itself. + */ +BatchRequest.prototype.add = function(request) { + this.requests_.push({ + apiMeta: request.apiMeta, + method: request.methodName, + params: request.params, + resource: request.resource + }); + return this; +}; + +/** + * @protected + * Generates JSON-RPC payload. + * + * @return {Array.} Generated payload. + */ +BatchRequest.prototype.generatePayload = function() { + var payload = []; + for (var i = 0; i < this.requests_.length; i++) { + var request = this.requests_[i]; + request.params.resource = request.resource; + payload.push({ + jsonrpc: BaseRequest.JSONRPC_VERSION, + id: i, + method: request.method, + params: request.params, + apiVersion: request.apiMeta.version + }); + } + return payload; +}; + + +/** + * @protected + * Wraps request callbacks. + * + * @param {Function=} opt_fn Optional callback function to be wrapped. + * @return {Function} Wrapped callback function. + */ +BatchRequest.prototype.handleResponse = function(opt_fn) { + return function(err, body, res) { + var results = null; + if (body) { + results = []; + for (var i in body) { + results.push(body[i].result || null); + } + } + opt_fn && opt_fn(err, results, res); + }; +}; + +/** + * Exports Request. + */ +exports.Request = Request; + +/** + * Exports BatchRequest. + */ +exports.BatchRequest = BatchRequest; diff --git a/node_modules/googleapis/lib/transporters.js b/node_modules/googleapis/lib/transporters.js new file mode 100644 index 0000000..cd2bd18 --- /dev/null +++ b/node_modules/googleapis/lib/transporters.js @@ -0,0 +1,90 @@ +/** + * Copyright 2012 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var request = require('request'), + pkg = require('../package.json'); + +/** + * Default transporter constructor. + * Wraps request and callback functions. + */ +function DefaultTransporter() {} + +/** + * Default user agent. + */ +DefaultTransporter.prototype.USER_AGENT = + 'google-api-nodejs-client/' + pkg.version; + +/** + * Configures request options before making a request. + * @param {object} opts Options to configure. + * @return {object} Configured options. + */ +DefaultTransporter.prototype.configure = function(opts) { + // set transporter user agent + opts.headers = opts.headers || {}; + opts.headers['User-Agent'] = opts.headers['User-Agent'] ? + opts.headers['User-Agent'] + ' ' + this.USER_AGENT : this.USER_AGENT; + return opts; +}; + +/** + * Makes a request with given options and invokes callback. + * @param {object} opts Options. + * @param {Function=} opt_callback Optional callback. + */ +DefaultTransporter.prototype.request = function(opts, opt_callback) { + opts = this.configure(opts); + request(opts, this.wrapCallback_(opt_callback)); +}; + +/** + * @private + * Wraps the response callback. + * @param {Function=} opt_callback Optional callback. + * @return {Function} Wrapped callback function. + */ +DefaultTransporter.prototype.wrapCallback_ = function(opt_callback) { + return function(err, res, body) { + if (err || !body) { + opt_callback && opt_callback(err, null, res); + } else if (body && body.error) { + // handle single request errors + err = body.error; + delete body.error; + opt_callback(err, body, res); + } else { + // TODO(burcud): Logic not related to the means of transportation + // should be handled elsewhere. + var errors = null; + // iterate over objects to check if there are errors or not. + for (var i = 0; i < body.length; i++) { + if (body[i].error) { + errors = errors || []; + errors[i] = body[i].error; + delete body[i].error; + } + } + opt_callback && opt_callback(errors, body, res); + } + }; +}; + +/** + * Exports DefaultTransporter. + */ +module.exports = DefaultTransporter; diff --git a/node_modules/googleapis/node_modules/async/LICENSE b/node_modules/googleapis/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/node_modules/googleapis/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +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/googleapis/node_modules/async/README.md b/node_modules/googleapis/node_modules/async/README.md new file mode 100644 index 0000000..1716476 --- /dev/null +++ b/node_modules/googleapis/node_modules/async/README.md @@ -0,0 +1,1365 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, each…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [each](#each) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [doWhilst](#doWhilst) +* [until](#until) +* [doUntil](#doUntil) +* [waterfall](#waterfall) +* [compose](#compose) +* [applyEach](#applyEach) +* [queue](#queue) +* [cargo](#cargo) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) +* [times](#times) +* [timesSeries](#timesSeries) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the each function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as each only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as each only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as reject, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback(err, reduction) which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main callback is + immediately called with the error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, sortValue) which must be called once it + has completed with an error (which can be null) and a value to use as the sort + criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, results) which must be called once it + has completed with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as parallel only the tasks are executed in parallel with a maximum of "limit" +tasks executing at any time. + +Note that the tasks are not executed in batches, so there is no guarantee that +the first "limit" tasks will complete before any others are started. + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* limit - The maximum number of tasks to run at any time. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback(err) which must be called once it has completed with an + optional error argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a + callback(err, result1, result2, ...) it must call on completion. The first + argument is an error (which can be null) and any further arguments will be + passed as arguments in order to the next task. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions f(), g() and h() would produce the result of +f(g(h())), only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling the +callback after all functions have completed. If you only provide the first +argument then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* fns - the asynchronous functions to all call with the same arguments +* args... - any number of separate arguments to pass to the function +* callback - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task, which must call its callback(err) argument when finished, with an + optional error as an argument. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* unshift(task, [callback]) - add a new task to the front of the queue. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a cargo object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the payload limit). If the +worker is in progress, the task is queued until it is available. Once +the worker has completed some tasks, each callback of those tasks is called. + +__Arguments__ + +* worker(tasks, callback) - An asynchronous function for processing queued + tasks, which must call its callback(err) argument when finished, with an + optional error as an argument. +* payload - An optional integer for determining how many tasks should be + process per round, default is unlimited. + +__Cargo objects__ + +The cargo object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* payload - an integer for determining how many tasks should be + process per round. This property can be changed after a cargo is created to + alter the payload on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// add some items + +cargo.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +cargo.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +cargo.push({name: 'baz'}, function (err) { + console.log('finished processing baz'); +}); +``` + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +Note, all functions are called with a results object as a second argument, +so it is unsafe to pass functions in the tasks object which cannot handle the +extra argument. For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8'); +}, callback); +``` + +will have the effect of calling readFile with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to readFile in a function which does not forward the +results object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + function receives two arguments: (1) a callback(err, result) which must be + called when finished, passing an error (which can be null) and the result of + the function's execution, and (2) a results object, containing the results of + the previously executed functions. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. Results will always be passed + but if an error occurred, no other tasks will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } +], +function(err, results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + function(callback){ + // once the file is written let's email a link to it... + } + ]); +}); +``` + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setImmediate(callback) +if available, otherwise setTimeout(callback, 0), which means other higher priority +events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the callback n times and accumulates results in the same manner +you would use with async.map. + +__Arguments__ + +* n - The number of times to run the function. +* callback - The function to call n times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as times only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/googleapis/node_modules/async/lib/async.js b/node_modules/googleapis/node_modules/async/lib/async.js new file mode 100755 index 0000000..ad3982a --- /dev/null +++ b/node_modules/googleapis/node_modules/async/lib/async.js @@ -0,0 +1,982 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + setImmediate(fn); + }; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + } + else { + async.nextTick = process.nextTick; + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + var sync = true; + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + if (sync) { + async.nextTick(iterate); + } + else { + iterate(); + } + } + } + }); + sync = false; + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.nextTick(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + var sync = true; + iterator(function (err) { + if (err) { + return callback(err); + } + if (sync) { + async.nextTick(function () { + async.whilst(test, iterator, callback); + }); + } + else { + async.whilst(test, iterator, callback); + } + }); + sync = false; + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + var sync = true; + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + if (sync) { + async.nextTick(function () { + async.doWhilst(iterator, test, callback); + }); + } + else { + async.doWhilst(iterator, test, callback); + } + } + else { + callback(); + } + }); + sync = false; + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + var sync = true; + iterator(function (err) { + if (err) { + return callback(err); + } + if (sync) { + async.nextTick(function () { + async.until(test, iterator, callback); + }); + } + else { + async.until(test, iterator, callback); + } + }); + sync = false; + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + var sync = true; + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + if (sync) { + async.nextTick(function () { + async.doUntil(iterator, test, callback); + }); + } + else { + async.doUntil(iterator, test, callback); + } + } + else { + callback(); + } + }); + sync = false; + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.nextTick(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var sync = true; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(function () { + var cbArgs = arguments; + + if (sync) { + async.nextTick(function () { + next.apply(null, cbArgs); + }); + } else { + next.apply(null, arguments); + } + }); + worker(task.data, cb); + sync = false; + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.nextTick(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + async.applyEach = function (fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return async.each(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 1) { + var args = Array.prototype.slice.call(arguments, 1); + return go.apply(this, args); + } + else { + return go; + } + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via \n\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err) which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, transformed) which must be called once \n it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then its probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback(err, reduction) which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main callback is \n immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], path.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, sortValue) which must be called once it\n has completed with an error (which can be null) and a value to use as the sort\n criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], path.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback(truthValue) which must be called with a \n boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], path.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback(err, results) which must be called once it \n has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n a callback(err, result) it must call on completion with an error (which can\n be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback(err) which must be called once it has completed with an \n optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n callback(err, result1, result2, ...) it must call on completion. The first\n argument is an error (which can be null) and any further arguments will be \n passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing queued\n tasks, which must call its callback(err) argument when finished, with an \n optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n process per round, default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n process per round. This property can be changed after a cargo is created to\n alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// add some items\n\ncargo.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\ncargo.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\ncargo.push({name: 'baz'}, function (err) {\n console.log('finished processing baz');\n});\n```\n\n---------------------------------------\n\n\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8');\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The \n function receives two arguments: (1) a callback(err, result) which must be \n called when finished, passing an error (which can be null) and the result of \n the function's execution, and (2) a results object, containing the results of\n the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n \n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. Its also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n", + "readmeFilename": "README.md", + "_id": "async@0.2.6", + "dist": { + "shasum": "385db3589e759ec194e1745f9c1c4fe683081c11" + }, + "_from": "async@0.2.6", + "_resolved": "https://registry.npmjs.org/async/-/async-0.2.6.tgz" +} diff --git a/node_modules/googleapis/node_modules/request/LICENSE b/node_modules/googleapis/node_modules/request/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/googleapis/node_modules/request/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/googleapis/node_modules/request/README.md b/node_modules/googleapis/node_modules/request/README.md new file mode 100644 index 0000000..c9e3537 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/README.md @@ -0,0 +1,331 @@ +# Request -- Simplified HTTP request method + +## Install + +
    +  npm install request
    +
    + +Or from source: + +
    +  git clone git://github.com/mikeal/request.git 
    +  cd request
    +  npm link
    +
    + +## Super simple to use + +Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default. + +```javascript +var request = require('request'); +request('http://www.google.com', function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body) // Print the google web page. + } +}) +``` + +## Streaming + +You can stream any response to a file stream. + +```javascript +request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) +``` + +You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers. + +```javascript +fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json')) +``` + +Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers. + +```javascript +request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png')) +``` + +Now let's get fancy. + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + if (req.method === 'PUT') { + req.pipe(request.put('http://mysite.com/doodle.png')) + } else if (req.method === 'GET' || req.method === 'HEAD') { + request.get('http://mysite.com/doodle.png').pipe(resp) + } + } +}) +``` + +You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do: + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + var x = request('http://mysite.com/doodle.png') + req.pipe(x) + x.pipe(resp) + } +}) +``` + +And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :) + +```javascript +req.pipe(request('http://mysite.com/doodle.png')).pipe(resp) +``` + +Also, none of this new functionality conflicts with requests previous features, it just expands them. + +```javascript +var r = request.defaults({'proxy':'http://localproxy.com'}) + +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + r.get('http://google.com/doodle.png').pipe(resp) + } +}) +``` +You can still use intermediate proxies, the requests will still follow HTTP forwards, etc. + +## Forms + +`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API. + +Url encoded forms are simple + +```javascript +request.post('http://service.com/upload', {form:{key:'value'}}) +// or +request.post('http://service.com/upload').form({key:'value'}) +``` + +For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you. + +```javascript +var r = request.post('http://service.com/upload') +var form = r.form() +form.append('my_field', 'my_value') +form.append('my_buffer', new Buffer([1, 2, 3])) +form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')) +form.append('remote_file', request('http://google.com/doodle.png')) +``` + +## HTTP Authentication + +```javascript +request.auth('username', 'password', false).get('http://some.server.com/'); +// or +request.get('http://some.server.com/', { + 'auth': { + 'user': 'username', + 'pass': 'password', + 'sendImmediately': false + } +}); +``` + +If passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). The method form takes parameters `auth(username, password, sendImmediately)`. + +`sendImmediately` defaults to true, which will cause a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method). + +Digest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail). + +## OAuth Signing + +```javascript +// Twitter OAuth +var qs = require('querystring') + , oauth = + { callback: 'http://mysite.com/callback/' + , consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + } + , url = 'https://api.twitter.com/oauth/request_token' + ; +request.post({url:url, oauth:oauth}, function (e, r, body) { + // Assume by some stretch of magic you aquired the verifier + var access_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: access_token.oauth_token + , verifier: VERIFIER + , token_secret: access_token.oauth_token_secret + } + , url = 'https://api.twitter.com/oauth/access_token' + ; + request.post({url:url, oauth:oauth}, function (e, r, body) { + var perm_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: perm_token.oauth_token + , token_secret: perm_token.oauth_token_secret + } + , url = 'https://api.twitter.com/1/users/show.json?' + , params = + { screen_name: perm_token.screen_name + , user_id: perm_token.user_id + } + ; + url += qs.stringify(params) + request.get({url:url, oauth:oauth, json:true}, function (e, r, user) { + console.log(user) + }) + }) +}) +``` + + + +### request(options, callback) + +The first argument can be either a url or an options object. The only required option is uri, all others are optional. + +* `uri` || `url` - fully qualified uri or a parsed url object from url.parse() +* `qs` - object containing querystring values to be appended to the uri +* `method` - http method, defaults to GET +* `headers` - http headers, defaults to {} +* `body` - entity body for POST and PUT requests. Must be buffer or string. +* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request. +* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). See documentation above. +* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json. +* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below. +* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true. +* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false. +* `maxRedirects` - the maximum number of redirects to follow, defaults to 10. +* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer. +* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets. +* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. +* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request +* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri. +* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. +* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option. +* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section) +* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services) + + +The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer. + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. + +### request.put + +Same as request() but defaults to `method: "PUT"`. + +```javascript +request.put(url) +``` + +### request.post + +Same as request() but defaults to `method: "POST"`. + +```javascript +request.post(url) +``` + +### request.head + +Same as request() but defaults to `method: "HEAD"`. + +```javascript +request.head(url) +``` + +### request.del + +Same as request() but defaults to `method: "DELETE"`. + +```javascript +request.del(url) +``` + +### request.get + +Alias to normal request method for uniformity. + +```javascript +request.get(url) +``` +### request.cookie + +Function that creates a new cookie. + +```javascript +request.cookie('cookie_string_here') +``` +### request.jar + +Function that creates a new cookie jar. + +```javascript +request.jar() +``` + + +## Examples: + +```javascript + var request = require('request') + , rand = Math.floor(Math.random()*100000000).toString() + ; + request( + { method: 'PUT' + , uri: 'http://mikeal.iriscouch.com/testjs/' + rand + , multipart: + [ { 'content-type': 'application/json' + , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) + } + , { body: 'I am an attachment' } + ] + } + , function (error, response, body) { + if(response.statusCode == 201){ + console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand) + } else { + console.log('error: '+ response.statusCode) + console.log(body) + } + } + ) +``` +Cookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent). + +```javascript +var request = request.defaults({jar: false}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` + +If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option: + +```javascript +var j = request.jar() +var request = request.defaults({jar:j}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` +OR + +```javascript +var j = request.jar() +var cookie = request.cookie('your_cookie_here') +j.add(cookie) +request({url: 'http://www.google.com', jar: j}, function () { + request('http://images.google.com') +}) +``` diff --git a/node_modules/googleapis/node_modules/request/aws.js b/node_modules/googleapis/node_modules/request/aws.js new file mode 100644 index 0000000..4d8d950 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/aws.js @@ -0,0 +1,191 @@ + +/*! + * knox - auth + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , parse = require('url').parse + ; + +/** + * Valid keys. + */ + +var keys = + [ 'acl' + , 'location' + , 'logging' + , 'notification' + , 'partNumber' + , 'policy' + , 'requestPayment' + , 'torrent' + , 'uploadId' + , 'uploads' + , 'versionId' + , 'versioning' + , 'versions' + , 'website' + ] + +/** + * Return an "Authorization" header value with the given `options` + * in the form of "AWS :" + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.authorization = function(options){ + return 'AWS ' + options.key + ':' + exports.sign(options) +} + +/** + * Simple HMAC-SHA1 Wrapper + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.hmacSha1 = function(options){ + return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64') +} + +/** + * Create a base64 sha1 HMAC for `options`. + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.sign = function(options){ + options.message = exports.stringToSign(options) + return exports.hmacSha1(options) +} + +/** + * Create a base64 sha1 HMAC for `options`. + * + * Specifically to be used with S3 presigned URLs + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.signQuery = function(options){ + options.message = exports.queryStringToSign(options) + return exports.hmacSha1(options) +} + +/** + * Return a string for sign() with the given `options`. + * + * Spec: + * + * \n + * \n + * \n + * \n + * [headers\n] + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.stringToSign = function(options){ + var headers = options.amazonHeaders || '' + if (headers) headers += '\n' + var r = + [ options.verb + , options.md5 + , options.contentType + , options.date.toUTCString() + , headers + options.resource + ] + return r.join('\n') +} + +/** + * Return a string for sign() with the given `options`, but is meant exclusively + * for S3 presigned URLs + * + * Spec: + * + * \n + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.queryStringToSign = function(options){ + return 'GET\n\n\n' + options.date + '\n' + options.resource +}; + +/** + * Perform the following: + * + * - ignore non-amazon headers + * - lowercase fields + * - sort lexicographically + * - trim whitespace between ":" + * - join with newline + * + * @param {Object} headers + * @return {String} + * @api private + */ + +exports.canonicalizeHeaders = function(headers){ + var buf = [] + , fields = Object.keys(headers) + ; + for (var i = 0, len = fields.length; i < len; ++i) { + var field = fields[i] + , val = headers[field] + , field = field.toLowerCase() + ; + if (0 !== field.indexOf('x-amz')) continue + buf.push(field + ':' + val) + } + return buf.sort().join('\n') +}; + +/** + * Perform the following: + * + * - ignore non sub-resources + * - sort lexicographically + * + * @param {String} resource + * @return {String} + * @api private + */ + +exports.canonicalizeResource = function(resource){ + var url = parse(resource, true) + , path = url.pathname + , buf = [] + ; + + Object.keys(url.query).forEach(function(key){ + if (!~keys.indexOf(key)) return + var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]) + buf.push(key + val) + }) + + return path + (buf.length ? '?' + buf.sort().join('&') : '') +}; diff --git a/node_modules/googleapis/node_modules/request/forever.js b/node_modules/googleapis/node_modules/request/forever.js new file mode 100644 index 0000000..1e1d4b9 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/forever.js @@ -0,0 +1,103 @@ +module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL + +var util = require('util') + , Agent = require('http').Agent + , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent + +function ForeverAgent(options) { + var self = this + self.options = options || {} + self.requests = {} + self.sockets = {} + self.freeSockets = {} + self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets + self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets + self.on('free', function(socket, host, port) { + var name = host + ':' + port + if (self.requests[name] && self.requests[name].length) { + self.requests[name].shift().onSocket(socket) + } else if (self.sockets[name].length < self.minSockets) { + if (!self.freeSockets[name]) self.freeSockets[name] = [] + self.freeSockets[name].push(socket) + + // if an error happens while we don't use the socket anyway, meh, throw the socket away + function onIdleError() { + socket.destroy() + } + socket._onIdleError = onIdleError + socket.on('error', onIdleError) + } else { + // If there are no pending requests just destroy the + // socket and it will get removed from the pool. This + // gets us out of timeout issues and allows us to + // default to Connection:keep-alive. + socket.destroy() + } + }) + +} +util.inherits(ForeverAgent, Agent) + +ForeverAgent.defaultMinSockets = 5 + + +ForeverAgent.prototype.createConnection = net.createConnection +ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest +ForeverAgent.prototype.addRequest = function(req, host, port) { + var name = host + ':' + port + if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { + var idleSocket = this.freeSockets[name].pop() + idleSocket.removeListener('error', idleSocket._onIdleError) + delete idleSocket._onIdleError + req._reusedSocket = true + req.onSocket(idleSocket) + } else { + this.addRequestNoreuse(req, host, port) + } +} + +ForeverAgent.prototype.removeSocket = function(s, name, host, port) { + if (this.sockets[name]) { + var index = this.sockets[name].indexOf(s) + if (index !== -1) { + this.sockets[name].splice(index, 1) + } + } else if (this.sockets[name] && this.sockets[name].length === 0) { + // don't leak + delete this.sockets[name] + delete this.requests[name] + } + + if (this.freeSockets[name]) { + var index = this.freeSockets[name].indexOf(s) + if (index !== -1) { + this.freeSockets[name].splice(index, 1) + if (this.freeSockets[name].length === 0) { + delete this.freeSockets[name] + } + } + } + + if (this.requests[name] && this.requests[name].length) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(name, host, port).emit('free') + } +} + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + options.port = port + options.host = host + return tls.connect(options) +} diff --git a/node_modules/googleapis/node_modules/request/main.js b/node_modules/googleapis/node_modules/request/main.js new file mode 100644 index 0000000..5ee2cfa --- /dev/null +++ b/node_modules/googleapis/node_modules/request/main.js @@ -0,0 +1,1245 @@ +// Copyright 2010-2012 Mikeal Rogers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var http = require('http') + , https = false + , tls = false + , url = require('url') + , util = require('util') + , stream = require('stream') + , qs = require('querystring') + , crypto = require('crypto') + , oauth = require('./oauth') + , uuid = require('./uuid') + , ForeverAgent = require('./forever') + , Cookie = require('./vendor/cookie') + , CookieJar = require('./vendor/cookie/jar') + , cookieJar = new CookieJar + , tunnel = require('./tunnel') + , aws = require('./aws') + + , mime = require('mime') + , FormData = require('form-data') + ; + +if (process.logging) { + var log = process.logging('request') +} + +try { + https = require('https') +} catch (e) {} + +try { + tls = require('tls') +} catch (e) {} + +function toBase64 (str) { + return (new Buffer(str || "", "ascii")).toString("base64") +} + +function md5 (str) { + return crypto.createHash('md5').update(str).digest('hex') +} + +// Hacky fix for pre-0.4.4 https +if (https && !https.Agent) { + https.Agent = function (options) { + http.Agent.call(this, options) + } + util.inherits(https.Agent, http.Agent) + https.Agent.prototype._getConnection = function (host, port, cb) { + var s = tls.connect(port, host, this.options, function () { + // do other checks here? + if (cb) cb() + }) + return s + } +} + +function isReadStream (rs) { + if (rs.readable && rs.path && rs.mode) { + return true + } +} + +function copy (obj) { + var o = {} + Object.keys(obj).forEach(function (i) { + o[i] = obj[i] + }) + return o +} + +var isUrl = /^https?:/ + +var globalPool = {} + +function Request (options) { + stream.Stream.call(this) + this.readable = true + this.writable = true + + if (typeof options === 'string') { + options = {uri:options} + } + + var reserved = Object.keys(Request.prototype) + for (var i in options) { + if (reserved.indexOf(i) === -1) { + this[i] = options[i] + } else { + if (typeof options[i] === 'function') { + delete options[i] + } + } + } + options = copy(options) + + this.init(options) +} +util.inherits(Request, stream.Stream) +Request.prototype.init = function (options) { + var self = this + + if (!options) options = {} + if (request.debug) console.error('REQUEST', options) + if (!self.pool && self.pool !== false) self.pool = globalPool + self.dests = self.dests || [] + self.__isRequestRequest = true + + // Protect against double callback + if (!self._callback && self.callback) { + self._callback = self.callback + self.callback = function () { + if (self._callbackCalled) return // Print a warning maybe? + self._callback.apply(self, arguments) + self._callbackCalled = true + } + self.on('error', self.callback.bind()) + self.on('complete', self.callback.bind(self, null)) + } + + if (self.url) { + // People use this property instead all the time so why not just support it. + self.uri = self.url + delete self.url + } + + if (!self.uri) { + // this will throw if unhandled but is handleable when in a redirect + return self.emit('error', new Error("options.uri is a required argument")) + } else { + if (typeof self.uri == "string") self.uri = url.parse(self.uri) + } + + if (self.proxy) { + if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth + , headers: { Host: self.uri.hostname + ':' + + (self.uri.port || self.uri.protocol === 'https:' ? 443 : 80) }} + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } + } + + if (!self.uri.host || !self.uri.pathname) { + // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar + // Detect and reject it as soon as possible + var faultyUri = url.format(self.uri) + var message = 'Invalid URI "' + faultyUri + '"' + if (Object.keys(options).length === 0) { + // No option ? This can be the sign of a redirect + // As this is a case where the user cannot do anything (he didn't call request directly with this URL) + // he should be warned that it can be caused by a redirection (can save some hair) + message += '. This can be caused by a crappy redirection.' + } + self.emit('error', new Error(message)) + return // This error was fatal + } + + self._redirectsFollowed = self._redirectsFollowed || 0 + self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 + self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true + self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false + if (self.followRedirect || self.followAllRedirects) + self.redirects = self.redirects || [] + + self.headers = self.headers ? copy(self.headers) : {} + + self.setHost = false + if (!(self.headers.host || self.headers.Host)) { + self.headers.host = self.uri.hostname + if (self.uri.port) { + if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && + !(self.uri.port === 443 && self.uri.protocol === 'https:') ) + self.headers.host += (':'+self.uri.port) + } + self.setHost = true + } + + self.jar(self._jar || options.jar) + + if (!self.uri.pathname) {self.uri.pathname = '/'} + if (!self.uri.port) { + if (self.uri.protocol == 'http:') {self.uri.port = 80} + else if (self.uri.protocol == 'https:') {self.uri.port = 443} + } + + if (self.proxy && !self.tunnel) { + self.port = self.proxy.port + self.host = self.proxy.hostname + } else { + self.port = self.uri.port + self.host = self.uri.hostname + } + + self.clientErrorHandler = function (error) { + if (self._aborted) return + + if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } + self.start() + self.req.end() + return + } + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + self.emit('error', error) + } + + self._parserErrorHandler = function (error) { + if (this.res) { + if (this.res.request) { + this.res.request.emit('error', error) + } else { + this.res.emit('error', error) + } + } else { + this._httpMessage.emit('error', error) + } + } + + if (options.form) { + self.form(options.form) + } + + if (options.qs) self.qs(options.qs) + + if (self.uri.path) { + self.path = self.uri.path + } else { + self.path = self.uri.pathname + (self.uri.search || "") + } + + if (self.path.length === 0) self.path = '/' + + + if (options.oauth) { + self.oauth(options.oauth) + } + + if (options.aws) { + self.aws(options.aws) + } + + if (options.auth) { + self.auth( + options.auth.user || options.auth.username, + options.auth.pass || options.auth.password, + options.auth.sendImmediately) + } + + if (self.uri.auth && !self.headers.authorization) { + var authPieces = self.uri.auth.split(':').map(function(item){ return qs.unescape(item) }) + self.auth(authPieces[0], authPieces[1], true) + } + if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { + self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + + + if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + + if (options.json) { + self.json(options.json) + } else if (options.multipart) { + self.boundary = uuid() + self.multipart(options.multipart) + } + + if (self.body) { + var length = 0 + if (!Buffer.isBuffer(self.body)) { + if (Array.isArray(self.body)) { + for (var i = 0; i < self.body.length; i++) { + length += self.body[i].length + } + } else { + self.body = new Buffer(self.body) + length = self.body.length + } + } else { + length = self.body.length + } + if (length) { + if(!self.headers['content-length'] && !self.headers['Content-Length']) + self.headers['content-length'] = length + } else { + throw new Error('Argument error, options.body.') + } + } + + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol + , defaultModules = {'http:':http, 'https:':https} + , httpModules = self.httpModules || {} + ; + self.httpModule = httpModules[protocol] || defaultModules[protocol] + + if (!self.httpModule) return this.emit('error', new Error("Invalid protocol")) + + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + if (options.agentClass) { + self.agentClass = options.agentClass + } else if (options.forever) { + self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL + } else { + self.agentClass = self.httpModule.Agent + } + } + + if (self.pool === false) { + self.agent = false + } else { + self.agent = self.agent || self.getAgent() + if (self.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.maxSockets + } + if (self.pool.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.pool.maxSockets + } + } + + self.once('pipe', function (src) { + if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.") + self.src = src + if (isReadStream(src)) { + if (!self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = mime.lookup(src.path) + } else { + if (src.headers) { + for (var i in src.headers) { + if (!self.headers[i]) { + self.headers[i] = src.headers[i] + } + } + } + if (self._json && !self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = 'application/json' + if (src.method && !self.method) { + self.method = src.method + } + } + + self.on('pipe', function () { + console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") + }) + }) + + process.nextTick(function () { + if (self._aborted) return + + if (self._form) { + self.setHeaders(self._form.getHeaders()) + self._form.pipe(self) + } + if (self.body) { + if (Array.isArray(self.body)) { + self.body.forEach(function (part) { + self.write(part) + }) + } else { + self.write(self.body) + } + self.end() + } else if (self.requestBodyStream) { + console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") + self.requestBodyStream.pipe(self) + } else if (!self.src) { + if (self.method !== 'GET' && typeof self.method !== 'undefined') { + self.headers['content-length'] = 0 + } + self.end() + } + self.ntick = true + }) +} + +// Must call this when following a redirect from https to http or vice versa +// Attempts to keep everything as identical as possible, but update the +// httpModule, Tunneling agent, and/or Forever Agent in use. +Request.prototype._updateProtocol = function () { + var self = this + var protocol = self.uri.protocol + + if (protocol === 'https:') { + // previously was doing http, now doing https + // if it's https, then we might need to tunnel now. + if (self.proxy) { + self.tunnel = true + var tunnelFn = self.proxy.protocol === 'http:' + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth } + , ca: self.ca } + self.agent = tunnelFn(tunnelOptions) + return + } + + self.httpModule = https + switch (self.agentClass) { + case ForeverAgent: + self.agentClass = ForeverAgent.SSL + break + case http.Agent: + self.agentClass = https.Agent + break + default: + // nothing we can do. Just hope for the best. + return + } + + // if there's an agent, we need to get a new one. + if (self.agent) self.agent = self.getAgent() + + } else { + if (log) log('previously https, now http') + // previously was doing https, now doing http + // stop any tunneling. + if (self.tunnel) self.tunnel = false + self.httpModule = http + switch (self.agentClass) { + case ForeverAgent.SSL: + self.agentClass = ForeverAgent + break + case https.Agent: + self.agentClass = http.Agent + break + default: + // nothing we can do. just hope for the best + return + } + + // if there's an agent, then get a new one. + if (self.agent) { + self.agent = null + self.agent = self.getAgent() + } + } +} + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + if (typeof this.rejectUnauthorized !== 'undefined') + options.rejectUnauthorized = this.rejectUnauthorized; + + if (this.cert && this.key) { + options.key = this.key + options.cert = this.cert + } + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.httpModule.Agent) { + poolKey += Agent.name + } + + if (!this.httpModule.globalAgent) { + // node 0.4.x + options.host = this.host + options.port = this.port + if (poolKey) poolKey += ':' + poolKey += this.host + ':' + this.port + } + + // ca option is only relevant if proxy or destination are https + var proxy = this.proxy + if (typeof proxy === 'string') proxy = url.parse(proxy) + var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:' + if (isHttps) { + if (options.ca) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (typeof options.rejectUnauthorized !== 'undefined') { + if (poolKey) poolKey += ':' + poolKey += options.rejectUnauthorized + } + + if (options.cert) + poolKey += options.cert.toString('ascii') + options.key.toString('ascii') + } + + if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // we're using a stored agent. Make sure it's protocol-specific + poolKey = this.uri.protocol + poolKey + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) +} + +Request.prototype.start = function () { + var self = this + + if (self._aborted) return + + self._started = true + self.method = self.method || 'GET' + self.href = self.uri.href + if (log) log('%method %href', self) + + if (self.src && self.src.stat && self.src.stat.size && !self.headers['content-length'] && !self.headers['Content-Length']) { + self.headers['content-length'] = self.src.stat.size + } + if (self._aws) { + self.aws(self._aws, true) + } + + // We have a method named auth, which is completely different from the http.request + // auth option. If we don't remove it, we're gonna have a bad time. + var reqOptions = copy(self) + delete reqOptions.auth + + self.req = self.httpModule.request(reqOptions, function (response) { + if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) { + response.connection.once('error', self._parserErrorHandler) + } + if (self._aborted) return + if (self._paused) response.pause() + + self.response = response + response.request = self + response.toJSON = toJSON + + if (self.httpModule === https && + self.strictSSL && + !response.client.authorized) { + var sslErr = response.client.authorizationError + self.emit('error', new Error('SSL Error: '+ sslErr)) + return + } + + if (self.setHost) delete self.headers.host + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + + var addCookie = function (cookie) { + if (self._jar) self._jar.add(new Cookie(cookie)) + else cookieJar.add(new Cookie(cookie)) + } + + if (response.headers['set-cookie'] && (!self._disableCookies)) { + if (Array.isArray(response.headers['set-cookie'])) response.headers['set-cookie'].forEach(addCookie) + else addCookie(response.headers['set-cookie']) + } + + var redirectTo = null + if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) { + if (self.followAllRedirects) { + redirectTo = response.headers.location + } else if (self.followRedirect) { + switch (self.method) { + case 'PUT': + case 'POST': + case 'DELETE': + // Do not follow redirects + break + default: + redirectTo = response.headers.location + break + } + } + } else if (response.statusCode == 401 && self._hasAuth && !self._sentAuth) { + var authHeader = response.headers['www-authenticate'] + var authVerb = authHeader && authHeader.split(' ')[0] + switch (authVerb) { + case 'Basic': + self.auth(self._user, self._pass, true) + redirectTo = self.uri + break + + case 'Digest': + // TODO: More complete implementation of RFC 2617. For reference: + // http://tools.ietf.org/html/rfc2617#section-3 + // https://github.com/bagder/curl/blob/master/lib/http_digest.c + + var matches = authHeader.match(/([a-z0-9_-]+)="([^"]+)"/gi) + var challenge = {} + + for (var i = 0; i < matches.length; i++) { + var eqPos = matches[i].indexOf('=') + var key = matches[i].substring(0, eqPos) + var quotedValue = matches[i].substring(eqPos + 1) + challenge[key] = quotedValue.substring(1, quotedValue.length - 1) + } + + var ha1 = md5(self._user + ':' + challenge.realm + ':' + self._pass) + var ha2 = md5(self.method + ':' + self.uri.path) + var digestResponse = md5(ha1 + ':' + challenge.nonce + ':1::auth:' + ha2) + var authValues = { + username: self._user, + realm: challenge.realm, + nonce: challenge.nonce, + uri: self.uri.path, + qop: challenge.qop, + response: digestResponse, + nc: 1, + cnonce: '' + } + + authHeader = [] + for (var k in authValues) { + authHeader.push(k + '="' + authValues[k] + '"') + } + authHeader = 'Digest ' + authHeader.join(', ') + self.setHeader('authorization', authHeader) + self._sentAuth = true + + redirectTo = self.uri + break + } + } + + if (redirectTo) { + if (self._redirectsFollowed >= self.maxRedirects) { + self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+self.uri.href)) + return + } + self._redirectsFollowed += 1 + + if (!isUrl.test(redirectTo)) { + redirectTo = url.resolve(self.uri.href, redirectTo) + } + + var uriPrev = self.uri + self.uri = url.parse(redirectTo) + + // handle the case where we change protocol from https to http or vice versa + if (self.uri.protocol !== uriPrev.protocol) { + self._updateProtocol() + } + + self.redirects.push( + { statusCode : response.statusCode + , redirectUri: redirectTo + } + ) + if (self.followAllRedirects && response.statusCode != 401) self.method = 'GET' + // self.method = 'GET' // Force all redirects to use GET || commented out fixes #215 + delete self.src + delete self.req + delete self.agent + delete self._started + if (response.statusCode != 401) { + delete self.body + delete self._form + } + if (self.headers) { + delete self.headers.host + delete self.headers['content-type'] + delete self.headers['content-length'] + } + if (log) log('Redirect to %uri due to status %status', {uri: self.uri, status: response.statusCode}) + self.init() + return // Ignore the rest of the response + } else { + self._redirectsFollowed = self._redirectsFollowed || 0 + // Be a good stream and emit end when the response is finished. + // Hack to emit end on close because of a core bug that never fires end + response.on('close', function () { + if (!self._ended) self.response.emit('end') + }) + + if (self.encoding) { + if (self.dests.length !== 0) { + console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") + } else { + response.setEncoding(self.encoding) + } + } + + self.dests.forEach(function (dest) { + self.pipeDest(dest) + }) + + response.on("data", function (chunk) { + self._destdata = true + self.emit("data", chunk) + }) + response.on("end", function (chunk) { + self._ended = true + self.emit("end", chunk) + }) + response.on("close", function () {self.emit("close")}) + + self.emit('response', response) + + if (self.callback) { + var buffer = [] + var bodyLen = 0 + self.on("data", function (chunk) { + buffer.push(chunk) + bodyLen += chunk.length + }) + self.on("end", function () { + if (self._aborted) return + + if (buffer.length && Buffer.isBuffer(buffer[0])) { + var body = new Buffer(bodyLen) + var i = 0 + buffer.forEach(function (chunk) { + chunk.copy(body, i, 0, chunk.length) + i += chunk.length + }) + if (self.encoding === null) { + response.body = body + } else { + response.body = body.toString(self.encoding) + } + } else if (buffer.length) { + response.body = buffer.join('') + } + + if (self._json) { + try { + response.body = JSON.parse(response.body) + } catch (e) {} + } + + self.emit('complete', response, response.body) + }) + } + } + }) + + if (self.timeout && !self.timeoutTimer) { + self.timeoutTimer = setTimeout(function () { + self.req.abort() + var e = new Error("ETIMEDOUT") + e.code = "ETIMEDOUT" + self.emit("error", e) + }, self.timeout) + + // Set additional timeout on socket - in case if remote + // server freeze after sending headers + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function () { + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } + } + + self.req.on('error', self.clientErrorHandler) + self.req.on('drain', function() { + self.emit('drain') + }) + self.on('end', function() { + if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler) + }) + self.emit('request', self.req) +} + +Request.prototype.abort = function () { + this._aborted = true + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + +Request.prototype.pipeDest = function (dest) { + var response = this.response + // Called after the response is received + if (dest.headers) { + dest.headers['content-type'] = response.headers['content-type'] + if (response.headers['content-length']) { + dest.headers['content-length'] = response.headers['content-length'] + } + } + if (dest.setHeader) { + for (var i in response.headers) { + dest.setHeader(i, response.headers[i]) + } + dest.statusCode = response.statusCode + } + if (this.pipefilter) this.pipefilter(response, dest) +} + +// Composable API +Request.prototype.setHeader = function (name, value, clobber) { + if (clobber === undefined) clobber = true + if (clobber || !this.headers.hasOwnProperty(name)) this.headers[name] = value + else this.headers[name] += ',' + value + return this +} +Request.prototype.setHeaders = function (headers) { + for (var i in headers) {this.setHeader(i, headers[i])} + return this +} +Request.prototype.qs = function (q, clobber) { + var base + if (!clobber && this.uri.query) base = qs.parse(this.uri.query) + else base = {} + + for (var i in q) { + base[i] = q[i] + } + + this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base)) + this.url = this.uri + + return this +} +Request.prototype.form = function (form) { + if (form) { + this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' + this.body = qs.stringify(form).toString('utf8') + return this + } + // create form-data object + this._form = new FormData() + return this._form +} +Request.prototype.multipart = function (multipart) { + var self = this + self.body = [] + + if (!self.headers['content-type']) { + self.headers['content-type'] = 'multipart/related; boundary=' + self.boundary + } else { + self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary + } + + if (!multipart.forEach) throw new Error('Argument error, options.multipart.') + + if (self.preambleCRLF) { + self.body.push(new Buffer('\r\n')) + } + + multipart.forEach(function (part) { + var body = part.body + if(body == null) throw Error('Body attribute missing in multipart.') + delete part.body + var preamble = '--' + self.boundary + '\r\n' + Object.keys(part).forEach(function (key) { + preamble += key + ': ' + part[key] + '\r\n' + }) + preamble += '\r\n' + self.body.push(new Buffer(preamble)) + self.body.push(new Buffer(body)) + self.body.push(new Buffer('\r\n')) + }) + self.body.push(new Buffer('--' + self.boundary + '--')) + return self +} +Request.prototype.json = function (val) { + this.setHeader('accept', 'application/json') + this._json = true + if (typeof val === 'boolean') { + if (typeof this.body === 'object') { + this.setHeader('content-type', 'application/json') + this.body = JSON.stringify(this.body) + } + } else { + this.setHeader('content-type', 'application/json') + this.body = JSON.stringify(val) + } + return this +} +function getHeader(name, headers) { + var result, re, match + Object.keys(headers).forEach(function (key) { + re = new RegExp(name, 'i') + match = key.match(re) + if (match) result = headers[key] + }) + return result +} +Request.prototype.auth = function (user, pass, sendImmediately) { + if (typeof user !== 'string' || typeof pass !== 'string') { + throw new Error('auth() received invalid user or password') + } + this._user = user + this._pass = pass + this._hasAuth = true + if (sendImmediately || typeof sendImmediately == 'undefined') { + this.setHeader('authorization', 'Basic ' + toBase64(user + ':' + pass)) + this._sentAuth = true + } + return this +} +Request.prototype.aws = function (opts, now) { + if (!now) { + this._aws = opts + return this + } + var date = new Date() + this.setHeader('date', date.toUTCString()) + var auth = + { key: opts.key + , secret: opts.secret + , verb: this.method.toUpperCase() + , date: date + , contentType: getHeader('content-type', this.headers) || '' + , md5: getHeader('content-md5', this.headers) || '' + , amazonHeaders: aws.canonicalizeHeaders(this.headers) + } + if (opts.bucket && this.path) { + auth.resource = '/' + opts.bucket + this.path + } else if (opts.bucket && !this.path) { + auth.resource = '/' + opts.bucket + } else if (!opts.bucket && this.path) { + auth.resource = this.path + } else if (!opts.bucket && !this.path) { + auth.resource = '/' + } + auth.resource = aws.canonicalizeResource(auth.resource) + this.setHeader('authorization', aws.authorization(auth)) + + return this +} + +Request.prototype.oauth = function (_oauth) { + var form + if (this.headers['content-type'] && + this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) === + 'application/x-www-form-urlencoded' + ) { + form = qs.parse(this.body) + } + if (this.uri.query) { + form = qs.parse(this.uri.query) + } + if (!form) form = {} + var oa = {} + for (var i in form) oa[i] = form[i] + for (var i in _oauth) oa['oauth_'+i] = _oauth[i] + if (!oa.oauth_version) oa.oauth_version = '1.0' + if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( (new Date()).getTime() / 1000 ).toString() + if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') + + oa.oauth_signature_method = 'HMAC-SHA1' + + var consumer_secret = oa.oauth_consumer_secret + delete oa.oauth_consumer_secret + var token_secret = oa.oauth_token_secret + delete oa.oauth_token_secret + var timestamp = oa.oauth_timestamp + + var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname + var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret) + + // oa.oauth_signature = signature + for (var i in form) { + if ( i.slice(0, 'oauth_') in _oauth) { + // skip + } else { + delete oa['oauth_'+i] + if (i !== 'x_auth_mode') delete oa[i] + } + } + oa.oauth_timestamp = timestamp + this.headers.Authorization = + 'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',') + this.headers.Authorization += ',oauth_signature="' + oauth.rfc3986(signature) + '"' + return this +} +Request.prototype.jar = function (jar) { + var cookies + + if (this._redirectsFollowed === 0) { + this.originalCookieHeader = this.headers.cookie + } + + if (jar === false) { + // disable cookies + cookies = false + this._disableCookies = true + } else if (jar) { + // fetch cookie from the user defined cookie jar + cookies = jar.get({ url: this.uri.href }) + } else { + // fetch cookie from the global cookie jar + cookies = cookieJar.get({ url: this.uri.href }) + } + + if (cookies && cookies.length) { + var cookieString = cookies.map(function (c) { + return c.name + "=" + c.value + }).join("; ") + + if (this.originalCookieHeader) { + // Don't overwrite existing Cookie header + this.headers.cookie = this.originalCookieHeader + '; ' + cookieString + } else { + this.headers.cookie = cookieString + } + } + this._jar = jar + return this +} + + +// Stream API +Request.prototype.pipe = function (dest, opts) { + if (this.response) { + if (this._destdata) { + throw new Error("You cannot pipe after data has been emitted from the response.") + } else if (this._ended) { + throw new Error("You cannot pipe after the response has been ended.") + } else { + stream.Stream.prototype.pipe.call(this, dest, opts) + this.pipeDest(dest) + return dest + } + } else { + this.dests.push(dest) + stream.Stream.prototype.pipe.call(this, dest, opts) + return dest + } +} +Request.prototype.write = function () { + if (!this._started) this.start() + return this.req.write.apply(this.req, arguments) +} +Request.prototype.end = function (chunk) { + if (chunk) this.write(chunk) + if (!this._started) this.start() + this.req.end() +} +Request.prototype.pause = function () { + if (!this.response) this._paused = true + else this.response.pause.apply(this.response, arguments) +} +Request.prototype.resume = function () { + if (!this.response) this._paused = false + else this.response.resume.apply(this.response, arguments) +} +Request.prototype.destroy = function () { + if (!this._ended) this.end() +} + +// organize params for post, put, head, del +function initParams(uri, options, callback) { + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + uri = options.uri + } + return { uri: uri, options: options, callback: callback } +} + +function request (uri, options, callback) { + if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.') + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + } + + if (callback) options.callback = callback + var r = new Request(options) + return r +} + +module.exports = request + +request.debug = process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG) + +request.initParams = initParams + +request.defaults = function (options, requester) { + var def = function (method) { + var d = function (uri, opts, callback) { + var params = initParams(uri, opts, callback) + for (var i in options) { + if (params.options[i] === undefined) params.options[i] = options[i] + } + if(typeof requester === 'function') { + if(method === request) { + method = requester + } else { + params.options._requester = requester + } + } + return method(params.options, params.callback) + } + return d + } + var de = def(request) + de.get = def(request.get) + de.post = def(request.post) + de.put = def(request.put) + de.head = def(request.head) + de.del = def(request.del) + de.cookie = def(request.cookie) + de.jar = request.jar + return de +} + +request.forever = function (agentOptions, optionsArg) { + var options = {} + if (optionsArg) { + for (option in optionsArg) { + options[option] = optionsArg[option] + } + } + if (agentOptions) options.agentOptions = agentOptions + options.forever = true + return request.defaults(options) +} + +request.get = request +request.post = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'POST' + return request(params.uri || null, params.options, params.callback) +} +request.put = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'PUT' + return request(params.uri || null, params.options, params.callback) +} +request.head = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'HEAD' + if (params.options.body || + params.options.requestBodyStream || + (params.options.json && typeof params.options.json !== 'boolean') || + params.options.multipart) { + throw new Error("HTTP HEAD requests MUST NOT include a request body.") + } + return request(params.uri || null, params.options, params.callback) +} +request.del = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'DELETE' + if(typeof params.options._requester === 'function') { + request = params.options._requester + } + return request(params.uri || null, params.options, params.callback) +} +request.jar = function () { + return new CookieJar +} +request.cookie = function (str) { + if (str && str.uri) str = str.uri + if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") + return new Cookie(str) +} + +// Safe toJSON + +function getSafe (self, uuid) { + if (typeof self === 'object' || typeof self === 'function') var safe = {} + if (Array.isArray(self)) var safe = [] + + var recurse = [] + + Object.defineProperty(self, uuid, {}) + + var attrs = Object.keys(self).filter(function (i) { + if (i === uuid) return false + if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true + return !(Object.getOwnPropertyDescriptor(self[i], uuid)) + }) + + + for (var i=0;i $(BUILDDIR)/async.min.js + +test: + $(NODEUNIT) test + +clean: + rm -rf $(BUILDDIR) + +lint: + $(NODELINT) --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/README.md b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/README.md new file mode 100644 index 0000000..1bbbc47 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/README.md @@ -0,0 +1,1021 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + +
    +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + ); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ], function (err, result) { + // result now equals 'done' + }); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + // add some items to the queue (batch-wise) + + q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. If all tasks complete + successfully, it will receive an object containing their results. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/index.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js new file mode 100644 index 0000000..7cc4f5e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js @@ -0,0 +1,692 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(null); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _forEach(data, function(task) { + q.tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (q.saturated && q.tasks.length == concurrency) { + q.saturated(); + } + async.nextTick(q.process); + }); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + +}()); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/package.json b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/package.json new file mode 100644 index 0000000..c47937f --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/async/package.json @@ -0,0 +1,42 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "main": "./index", + "author": { + "name": "Caolan McMahon" + }, + "version": "0.1.22", + "repository": { + "type": "git", + "url": "git://github.com/caolan/async.git" + }, + "bugs": { + "url": "http://github.com/caolan/async/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/caolan/async/raw/master/LICENSE" + } + ], + "devDependencies": { + "nodeunit": ">0.0.0", + "uglify-js": "1.2.x", + "nodelint": ">0.0.0" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "async@0.1.22", + "dependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "_from": "async@~0.1.9" +} diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore new file mode 100644 index 0000000..aba34f0 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore @@ -0,0 +1,3 @@ +*.un~ +/node_modules +/test/tmp diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/License b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +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/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md new file mode 100644 index 0000000..1a9999e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md @@ -0,0 +1,132 @@ +# combined-stream + +A stream that emits multiple other streams one after another. + +## Installation + +``` bash +npm install combined-stream +``` + +## Usage + +Here is a simple example that shows how you can use combined-stream to combine +two files into one: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +While the example above works great, it will pause all source streams until +they are needed. If you don't want that to happen, you can set `pauseStreams` +to `false`: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create({pauseStreams: false}); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +However, what if you don't have all the source streams yet, or you don't want +to allocate the resources (file descriptors, memory, etc.) for them right away? +Well, in that case you can simply provide a callback that supplies the stream +by calling a `next()` function: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(function(next) { + next(fs.createReadStream('file1.txt')); +}); +combinedStream.append(function(next) { + next(fs.createReadStream('file2.txt')); +}); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +## API + +### CombinedStream.create([options]) + +Returns a new combined stream object. Available options are: + +* `maxDataSize` +* `pauseStreams` + +The effect of those options is described below. + +### combinedStream.pauseStreams = true + +Whether to apply back pressure to the underlaying streams. If set to `false`, +the underlaying streams will never be paused. If set to `true`, the +underlaying streams will be paused right after being appended, as well as when +`delayedStream.pipe()` wants to throttle. + +### combinedStream.maxDataSize = 2 * 1024 * 1024 + +The maximum amount of bytes (or characters) to buffer for all source streams. +If this value is exceeded, `combinedStream` emits an `'error'` event. + +### combinedStream.dataSize = 0 + +The amount of bytes (or characters) currently buffered by `combinedStream`. + +### combinedStream.append(stream) + +Appends the given `stream` to the combinedStream object. If `pauseStreams` is +set to `true, this stream will also be paused right away. + +`streams` can also be a function that takes one parameter called `next`. `next` +is a function that must be invoked in order to provide the `next` stream, see +example above. + +Regardless of how the `stream` is appended, combined-stream always attaches an +`'error'` listener to it, so you don't have to do that manually. + +Special case: `stream` can also be a String or Buffer. + +### combinedStream.write(data) + +You should not call this, `combinedStream` takes care of piping the appended +streams into itself for you. + +### combinedStream.resume() + +Causes `combinedStream` to start drain the streams it manages. The function is +idempotent, and also emits a `'resume'` event each time which usually goes to +the stream that is currently being drained. + +### combinedStream.pause(); + +If `combinedStream.pauseStreams` is set to `false`, this does nothing. +Otherwise a `'pause'` event is emitted, this goes to the stream that is +currently being drained, so you can use it to apply back pressure. + +### combinedStream.end(); + +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes +all streams from the queue. + +### combinedStream.destroy(); + +Same as `combinedStream.end()`, except it emits a `'close'` event instead of +`'end'`. + +## License + +combined-stream is licensed under the MIT license. diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js new file mode 100644 index 0000000..32849fd --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js @@ -0,0 +1,185 @@ +var util = require('util'); +var Stream = require('stream').Stream; +var DelayedStream = require('delayed-stream'); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (typeof stream !== 'boolean') + && (typeof stream !== 'number') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + stream.on('data', this._checkDataSize.bind(this)); + + stream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + var stream = this._streams.shift(); + + + if (typeof stream == 'undefined') { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)) + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore new file mode 100644 index 0000000..2fedb26 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore @@ -0,0 +1,2 @@ +*.un~ +/node_modules/* diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +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/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md new file mode 100644 index 0000000..5cb5b35 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md @@ -0,0 +1,154 @@ +# delayed-stream + +Buffers events from a stream until you are ready to handle them. + +## Installation + +``` bash +npm install delayed-stream +``` + +## Usage + +The following example shows how to write a http echo server that delays its +response by 1000 ms. + +``` javascript +var DelayedStream = require('delayed-stream'); +var http = require('http'); + +http.createServer(function(req, res) { + var delayed = DelayedStream.create(req); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 1000); +}); +``` + +If you are not using `Stream#pipe`, you can also manually release the buffered +events by calling `delayedStream.resume()`: + +``` javascript +var delayed = DelayedStream.create(req); + +setTimeout(function() { + // Emit all buffered events and resume underlaying source + delayed.resume(); +}, 1000); +``` + +## Implementation + +In order to use this meta stream properly, here are a few things you should +know about the implementation. + +### Event Buffering / Proxying + +All events of the `source` stream are hijacked by overwriting the `source.emit` +method. Until node implements a catch-all event listener, this is the only way. + +However, delayed-stream still continues to emit all events it captures on the +`source`, regardless of whether you have released the delayed stream yet or +not. + +Upon creation, delayed-stream captures all `source` events and stores them in +an internal event buffer. Once `delayedStream.release()` is called, all +buffered events are emitted on the `delayedStream`, and the event buffer is +cleared. After that, delayed-stream merely acts as a proxy for the underlaying +source. + +### Error handling + +Error events on `source` are buffered / proxied just like any other events. +However, `delayedStream.create` attaches a no-op `'error'` listener to the +`source`. This way you only have to handle errors on the `delayedStream` +object, rather than in two places. + +### Buffer limits + +delayed-stream provides a `maxDataSize` property that can be used to limit +the amount of data being buffered. In order to protect you from bad `source` +streams that don't react to `source.pause()`, this feature is enabled by +default. + +## API + +### DelayedStream.create(source, [options]) + +Returns a new `delayedStream`. Available options are: + +* `pauseStream` +* `maxDataSize` + +The description for those properties can be found below. + +### delayedStream.source + +The `source` stream managed by this object. This is useful if you are +passing your `delayedStream` around, and you still want to access properties +on the `source` object. + +### delayedStream.pauseStream = true + +Whether to pause the underlaying `source` when calling +`DelayedStream.create()`. Modifying this property afterwards has no effect. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. You can also modify this property during runtime. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. + +### delayedStream.dataSize = 0 + +The amount of data buffered so far. + +### delayedStream.readable + +An ECMA5 getter that returns the value of `source.readable`. + +### delayedStream.resume() + +If the `delayedStream` has not been released so far, `delayedStream.release()` +is called. + +In either case, `source.resume()` is called. + +### delayedStream.pause() + +Calls `source.pause()`. + +### delayedStream.pipe(dest) + +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`. + +### delayedStream.release() + +Emits and clears all events that have been buffered up so far. This does not +resume the underlaying source, use `delayedStream.resume()` instead. + +## License + +delayed-stream is licensed under the MIT license. diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js new file mode 100644 index 0000000..7c10d48 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js @@ -0,0 +1,99 @@ +var Stream = require('stream').Stream; +var util = require('util'); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +DelayedStream.prototype.__defineGetter__('readable', function() { + return this.source.readable; +}); + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json new file mode 100644 index 0000000..d394b92 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json @@ -0,0 +1,38 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "delayed-stream", + "description": "Buffers events from a stream until you are ready to handle them.", + "version": "0.0.5", + "homepage": "https://github.com/felixge/node-delayed-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-delayed-stream.git" + }, + "main": "./lib/delayed_stream", + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "far": "0.0.1" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "delayed-stream@0.0.5", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "56f46a53506f656e1a549c63d8794c6cf8b6e1fc" + }, + "_from": "delayed-stream@0.0.5" +} diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js new file mode 100644 index 0000000..4d71b8a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js @@ -0,0 +1,6 @@ +var common = module.exports; + +common.DelayedStream = require('..'); +common.assert = require('assert'); +common.fake = require('fake'); +common.PORT = 49252; diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js new file mode 100644 index 0000000..9ecad5b --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var DelayedStream = common.DelayedStream; +var http = require('http'); + +var UPLOAD = new Buffer(10 * 1024 * 1024); + +var server = http.createServer(function(req, res) { + var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length}); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 10); +}); +server.listen(common.PORT, function() { + var request = http.request({ + method: 'POST', + port: common.PORT, + }); + + request.write(UPLOAD); + request.end(); + + request.on('response', function(res) { + var received = 0; + res + .on('data', function(chunk) { + received += chunk.length; + }) + .on('end', function() { + assert.equal(received, UPLOAD.length); + server.close(); + }); + }); +}); + + diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js new file mode 100644 index 0000000..6f417f3 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js @@ -0,0 +1,21 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testAutoPause() { + var source = new Stream(); + + fake.expect(source, 'pause', 1); + var delayedStream = DelayedStream.create(source); + fake.verify(); +})(); + +(function testDisableAutoPause() { + var source = new Stream(); + fake.expect(source, 'pause', 0); + + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + fake.verify(); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js new file mode 100644 index 0000000..b50c397 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js @@ -0,0 +1,14 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(source, 'pause'); + delayedStream.pause(); + fake.verify(); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js new file mode 100644 index 0000000..fc4047e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js @@ -0,0 +1,48 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // delayedStream must not emit until we resume + fake.expect(delayedStream, 'emit', 0); + + // but our original source must emit + var params = []; + source.on('foo', function(param) { + params.push(param); + }); + + source.emit('foo', 1); + source.emit('foo', 2); + + // Make sure delayedStream did not emit, and source did + assert.deepEqual(params, [1, 2]); + fake.verify(); + + // After resume, delayedStream must playback all events + fake + .stub(delayedStream, 'emit') + .times(Infinity) + .withArg(1, 'newListener'); + fake.expect(delayedStream, 'emit', ['foo', 1]); + fake.expect(delayedStream, 'emit', ['foo', 2]); + fake.expect(source, 'resume'); + + delayedStream.resume(); + fake.verify(); + + // Calling resume again will delegate to source + fake.expect(source, 'resume'); + delayedStream.resume(); + fake.verify(); + + // Emitting more events directly leads to them being emitted + fake.expect(delayedStream, 'emit', ['foo', 3]); + source.emit('foo', 3); + fake.verify(); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js new file mode 100644 index 0000000..a9d35e7 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js @@ -0,0 +1,15 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testHandleSourceErrors() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // We deal with this by attaching a no-op listener to 'error' on the source + // when creating a new DelayedStream. This way error events on the source + // won't throw. + source.emit('error', new Error('something went wrong')); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js new file mode 100644 index 0000000..7638a2b --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testMaxDataSize() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false}); + + source.emit('data', new Buffer(1024)); + + fake + .expect(delayedStream, 'emit') + .withArg(1, 'error'); + source.emit('data', new Buffer(1)); + fake.verify(); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js new file mode 100644 index 0000000..7d312ab --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testPipeReleases() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(delayedStream, 'resume'); + delayedStream.pipe(new Stream()); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js new file mode 100644 index 0000000..d436163 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testProxyReadableProperty() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + source.readable = fake.value('source.readable'); + assert.strictEqual(delayedStream.readable, source.readable); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json new file mode 100644 index 0000000..05e7109 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "combined-stream", + "description": "A stream that emits multiple other streams one after another.", + "version": "0.0.4", + "homepage": "https://github.com/felixge/node-combined-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-combined-stream.git" + }, + "main": "./lib/combined_stream", + "engines": { + "node": "*" + }, + "dependencies": { + "delayed-stream": "0.0.5" + }, + "devDependencies": { + "far": "0.0.1" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "combined-stream@0.0.4", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "2d1a43347dbe9515a4a2796732e5b88473840b22" + }, + "_from": "combined-stream@~0.0.4" +} diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js new file mode 100644 index 0000000..8154348 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js @@ -0,0 +1,23 @@ +var common = module.exports; + +var path = require('path'); +var fs = require('fs'); +var root = path.join(__dirname, '..'); + +common.dir = { + fixture: root + '/test/fixture', + tmp: root + '/test/tmp', +}; + +// Create tmp directory if it does not exist +// Not using fs.exists so as to be node 0.6.x compatible +try { + fs.statSync(common.dir.tmp); +} +catch (e) { + // Dir does not exist + fs.mkdirSync(common.dir.tmp); +} + +common.CombinedStream = require(root); +common.assert = require('assert'); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt new file mode 100644 index 0000000..50e0218 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt @@ -0,0 +1,256 @@ +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt new file mode 100644 index 0000000..da1d821 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt @@ -0,0 +1,256 @@ +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js new file mode 100644 index 0000000..44ecaba --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js @@ -0,0 +1,27 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE1)); + }); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE2)); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js new file mode 100644 index 0000000..e3fbd18 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js @@ -0,0 +1,34 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; + +(function testDataSizeGetter() { + var combinedStream = CombinedStream.create(); + + assert.strictEqual(combinedStream.dataSize, 0); + + // Test one stream + combinedStream._streams.push({dataSize: 10}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 10); + + // Test two streams + combinedStream._streams.push({dataSize: 23}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test currentStream + combinedStream._currentStream = {dataSize: 20}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 53); + + // Test currentStream without dataSize + combinedStream._currentStream = {}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test stream function + combinedStream._streams.push(function() {}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js new file mode 100644 index 0000000..c678575 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var BUFFER = new Buffer('Bacon is delicious'); +var FILE2 = common.dir.fixture + '/file2.txt'; +var STRING = 'The € kicks the $\'s ass!'; + +var EXPECTED = + fs.readFileSync(FILE1) + + BUFFER + + fs.readFileSync(FILE2) + + STRING; +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(BUFFER); + combinedStream.append(fs.createReadStream(FILE2)); + combinedStream.append(function(next) { + next(STRING); + }); + + var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js new file mode 100644 index 0000000..263cfdf --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js @@ -0,0 +1,35 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.equal(stream2.dataSize, 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + console.error(GOT.length, EXPECTED.length); + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js new file mode 100644 index 0000000..c3d288d --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js @@ -0,0 +1,39 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var util = require('util'); +var Stream = require('stream').Stream; + +var s = CombinedStream.create(); + + +function StringStream(){ + this.writable=true; + this.str="" +} +util.inherits(StringStream,Stream); + +StringStream.prototype.write=function(chunk,encoding){ + this.str+=chunk.toString(); + this.emit('data',chunk); +} + +StringStream.prototype.end=function(chunk,encoding){ + this.emit('end'); +} + +StringStream.prototype.toString=function(){ + return this.str; +} + + +s.append("foo."); +s.append(""); +s.append("bar"); + +var ss = new StringStream(); + +s.pipe(ss); +s.resume(); + +assert.equal(ss.toString(),"foo.bar"); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js new file mode 100644 index 0000000..aefa36e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js @@ -0,0 +1,17 @@ +var fs = require('fs'); +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var FILE1 = common.dir.fixture + '/file1.txt'; +var fileStream = fs.createReadStream(FILE1); + +var foo = function(){}; + +(function testIsStreamLike() { + assert(! CombinedStream.isStreamLike(true)); + assert(! CombinedStream.isStreamLike("I am a string")); + assert(! CombinedStream.isStreamLike(7)); + assert(! CombinedStream.isStreamLike(foo)); + + assert(CombinedStream.isStreamLike(fileStream)); +})(); \ No newline at end of file diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js new file mode 100644 index 0000000..25f47a4 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js @@ -0,0 +1,24 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var gotErr = null; + combinedStream.on('error', function(err) { + gotErr = err; + }); + + process.on('exit', function() { + assert.ok(gotErr); + assert.ok(gotErr.message.match(/bytes/)); + }); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js new file mode 100644 index 0000000..30a3a6f --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js @@ -0,0 +1,30 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.ok(stream2.dataSize > 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/package.json b/node_modules/googleapis/node_modules/request/node_modules/form-data/package.json new file mode 100644 index 0000000..57eafb3 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/package.json @@ -0,0 +1,43 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "form-data", + "description": "A module to create readable `\"multipart/form-data\"` streams. Can be used to submit forms and file uploads to other web applications.", + "version": "0.0.7", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-form-data.git" + }, + "main": "./lib/form_data", + "engines": { + "node": "*" + }, + "dependencies": { + "combined-stream": "~0.0.4", + "mime": "~1.2.2", + "async": "~0.1.9" + }, + "devDependencies": { + "fake": "0.2.1", + "far": "0.0.1", + "formidable": "1.0.2", + "request": "~2.9.203" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "form-data@0.0.7", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "7211182a26a266ce39710dc8bc4a81b7040859be" + }, + "_from": "form-data@~0.0.3" +} diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/common.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/common.js new file mode 100644 index 0000000..8a26482 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/common.js @@ -0,0 +1,14 @@ +var common = module.exports; +var path = require('path'); + +var rootDir = path.join(__dirname, '..'); +common.dir = { + lib: rootDir + '/lib', + fixture: rootDir + '/test/fixture', + tmp: rootDir + '/test/tmp', +}; + +common.assert = require('assert'); +common.fake = require('fake'); + +common.port = 8432; diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/bacon.txt b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/bacon.txt new file mode 100644 index 0000000..9804bbd --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/bacon.txt @@ -0,0 +1 @@ +Bacon is delicious. diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cea4dd71dc41cd51c84bfcec6b3e65c15a58507 GIT binary patch literal 19806 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 literal 0 HcmV?d00001 diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js new file mode 100644 index 0000000..1c9b6ad --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js @@ -0,0 +1,75 @@ +/* +test custom headers, added in pull request: +https://github.com/felixge/node-form-data/pull/17 +*/ + +var common = require('../common'); +var assert = common.assert; +var http = require('http'); + +var FormData = require(common.dir.lib + '/form_data'); + +var CRLF = '\r\n'; + +var testHeader = 'X-Test-Fake: 123'; + +var expectedLength; + + +var server = http.createServer(function(req, res) { + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + assert.ok( data.indexOf( testHeader ) != -1 ); + + // content-length would be 1000+ w/actual buffer size, + // but smaller w/overridden size. + assert.ok( typeof req.headers['content-length'] !== 'undefined' ); + assert.equal(req.headers['content-length'], expectedLength); + + res.writeHead(200); + res.end('done'); + }); +}); + + +server.listen(common.port, function() { + var form = new FormData(); + + var options = { + header: + CRLF + '--' + form.getBoundary() + CRLF + + testHeader + + CRLF + CRLF, + + // override content-length, + // much lower than actual buffer size (1000) + knownLength: 1 + }; + + var bufferData = []; + for (var z = 0; z < 1000; z++) { + bufferData.push(1); + } + var buffer = new Buffer(bufferData); + + form.append('my_buffer', buffer, options); + + // (available to req handler) + expectedLength = form._lastBoundary().length + form._overheadLength + options.knownLength; + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js new file mode 100644 index 0000000..44d3b4d --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js @@ -0,0 +1,93 @@ +var common = require('../common'); +var assert = common.assert; +var FormData = require(common.dir.lib + '/form_data'); +var fake = require('fake').create(); +var fs = require('fs'); + +(function testEmptyForm() { + var form = new FormData(); + var callback = fake.callback(arguments.callee.name + '-getLength'); + var calls = fake.expectAnytime(callback, [null, 0]).calls; + + form.getLength(callback); + + // Make sure our response is async + assert.strictEqual(calls.length, 0); +})(); + +(function testUtf8String() { + var FIELD = 'my_field'; + var VALUE = 'May the € be with you'; + + var form = new FormData(); + form.append(FIELD, VALUE); + var callback = fake.callback(arguments.callee.name + '-getLength'); + + var expectedLength = + form._overheadLength + + Buffer.byteLength(VALUE) + + form._lastBoundary().length; + + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + +(function testBuffer() { + var FIELD = 'my_field'; + var VALUE = new Buffer(23); + + var form = new FormData(); + form.append(FIELD, VALUE); + var callback = fake.callback(arguments.callee.name + '-getLength'); + + var expectedLength = + form._overheadLength + + VALUE.length + + form._lastBoundary().length; + + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + + +(function testStringFileBufferFile() { + var fields = [ + { + name: 'my_field', + value: 'Test 123', + }, + { + name: 'my_image', + value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), + }, + { + name: 'my_buffer', + value: new Buffer('123'), + }, + { + name: 'my_txt', + value: fs.createReadStream(common.dir.fixture + '/bacon.txt'), + }, + ]; + + var form = new FormData(); + var expectedLength = 0; + + fields.forEach(function(field) { + form.append(field.name, field.value); + if (field.value.path) { + var stat = fs.statSync(field.value.path); + expectedLength += stat.size; + } else { + expectedLength += field.value.length; + } + }); + + expectedLength += form._overheadLength + form._lastBoundary().length; + + var callback = fake.callback(arguments.callee.name + '-getLength'); + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + + diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js new file mode 100644 index 0000000..6dc2fb2 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; + +var FormData = require(common.dir.lib + '/form_data'); + +(function testOneBoundaryPerForm() { + var form = new FormData(); + var boundary = form.getBoundary(); + + assert.equal(boundary, form.getBoundary()); + assert.equal(boundary.length, 50); +})(); + +(function testUniqueBoundaryPerForm() { + var formA = new FormData(); + var formB = new FormData(); + assert.notEqual(formA.getBoundary(), formB.getBoundary()); +})(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-http-response.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-http-response.js new file mode 100644 index 0000000..8e183fe --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-http-response.js @@ -0,0 +1,121 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS; +var server; + +var parsedUrl = parseUrl(remoteFile) + , options = { + method: 'get', + port: parsedUrl.port || 80, + path: parsedUrl.pathname, + host: parsedUrl.hostname + } + ; + +http.request(options, function(res) { + + FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'remote_file', value: res } + ]; + + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + server.listen(common.port, function() { + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + + }); + + +}).end(); + +server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(remoteFile)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-pipe.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-pipe.js new file mode 100644 index 0000000..3cb4ce4 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-pipe.js @@ -0,0 +1,120 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +// wrap non simple values into function +// just to deal with ReadStream "autostart" +// Can't wait for 0.10 +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} }, + {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} }, + {name: 'remote_file', value: function(){ return request(remoteFile)} } +]; + +var server = http.createServer(function(req, res) { + + // formidable is fixed on github + // but still 7 month old in npm + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(common.port, function() { + var form = new FormData(); + FIELDS.forEach(function(field) { + // important to append ReadStreams within the same tick + if ((typeof field.value == 'function')) { + field.value = field.value(); + } + form.append(field.name, field.value); + }); + + var request = http.request({ + method: 'post', + port: common.port, + path: '/upload', + headers: form.getHeaders() + }); + + form.pipe(request); + + request.on('response', function(res) { + server.close(); + }); +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js new file mode 100644 index 0000000..0e4c592 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js @@ -0,0 +1,121 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +// wrap non simple values into function +// just to deal with ReadStream "autostart" +// Can't wait for 0.10 +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} }, + {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} }, + {name: 'remote_file', value: function(){ return request(remoteFile)} } +]; + +var server = http.createServer(function(req, res) { + + // formidable is fixed on github + // but still 7 month old in npm + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + req.on('data', function(d) { + data += d; + }); + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + +server.listen(common.port, function() { + + var form = new FormData(); + + FIELDS.forEach(function(field) { + // important to append ReadStreams within the same tick + if ((typeof field.value == 'function')) { + field.value = field.value(); + } + form.append(field.name, field.value); + }); + + // custom params object passed to submit + form.submit({ + port: common.port, + path: '/' + }, function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit.js new file mode 100644 index 0000000..b6e2c07 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/integration/test-submit.js @@ -0,0 +1,117 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +// wrap non simple values into function +// just to deal with ReadStream "autostart" +// Can't wait for 0.10 +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} }, + {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} }, + {name: 'remote_file', value: function(){ return request(remoteFile)} } +]; + +var server = http.createServer(function(req, res) { + + // formidable is fixed on github + // but still 7 month old in npm + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + req.on('data', function(d) { + data += d; + }); + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + +server.listen(common.port, function() { + + var form = new FormData(); + + FIELDS.forEach(function(field) { + // important to append ReadStreams within the same tick + if ((typeof field.value == 'function')) { + field.value = field.value(); + } + form.append(field.name, field.value); + }); + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/googleapis/node_modules/request/node_modules/form-data/test/run.js b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/form-data/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/googleapis/node_modules/request/node_modules/mime/LICENSE b/node_modules/googleapis/node_modules/request/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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/googleapis/node_modules/request/node_modules/mime/README.md b/node_modules/googleapis/node_modules/request/node_modules/mime/README.md new file mode 100644 index 0000000..b90552a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/README.md @@ -0,0 +1,63 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/googleapis/node_modules/request/node_modules/mime/mime.js b/node_modules/googleapis/node_modules/request/node_modules/mime/mime.js new file mode 100644 index 0000000..70a6384 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/mime.js @@ -0,0 +1,113 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + if (process.env.DEBUG_MIME && this.types[exts]) { + console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' + + this.types[exts] + ' to ' + type); + } + + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + + this._loading = file; + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); + + this._loading = null; +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + return this.extensions[mimeType]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +}; + +module.exports = mime; diff --git a/node_modules/googleapis/node_modules/request/node_modules/mime/package.json b/node_modules/googleapis/node_modules/request/node_modules/mime/package.json new file mode 100644 index 0000000..6ca84c1 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/package.json @@ -0,0 +1,42 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "git://github.com/broofa/node-mime.git", + "type": "git" + }, + "version": "1.2.9", + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "mime@1.2.9", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "_from": "mime@~1.2.7" +} diff --git a/node_modules/googleapis/node_modules/request/node_modules/mime/test.js b/node_modules/googleapis/node_modules/request/node_modules/mime/test.js new file mode 100644 index 0000000..cbad034 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/test.js @@ -0,0 +1,55 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); +eq('text/plain', mime.lookup('.text.txt')); +eq('text/plain', mime.lookup('.txt')); +eq('text/plain', mime.lookup('txt')); +eq('application/octet-stream', mime.lookup('text.nope')); +eq('fallback', mime.lookup('text.fallback', 'fallback')); +eq('application/octet-stream', mime.lookup('constructor')); +eq('text/plain', mime.lookup('TEXT.TXT')); +eq('text/event-stream', mime.lookup('text/event-stream')); +eq('application/x-web-app-manifest+json', mime.lookup('text.webapp')); + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq(undefined, mime.extension('constructor')); + +// +// Test node types +// + +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +console.log('\nOK'); diff --git a/node_modules/googleapis/node_modules/request/node_modules/mime/types/mime.types b/node_modules/googleapis/node_modules/request/node_modules/mime/types/mime.types new file mode 100644 index 0000000..b90b165 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/types/mime.types @@ -0,0 +1,1588 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +application/x-conference nsc +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-opml opml +text/x-pascal p pas +text/x-nfo nfo +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/node_modules/googleapis/node_modules/request/node_modules/mime/types/node.types b/node_modules/googleapis/node_modules/request/node_modules/mime/types/node.types new file mode 100644 index 0000000..970a1bd --- /dev/null +++ b/node_modules/googleapis/node_modules/request/node_modules/mime/types/node.types @@ -0,0 +1,60 @@ +# What: WebVTT +# Why: To allow formats intended for marking up external text track resources. +# http://dev.w3.org/html5/webvtt/ +# Added by: niftylettuce +text/vtt vtt + +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp + +# What: Lua file types +# Why: Googling around shows de-facto consensus on these +# Added by: creationix (Issue #45) +text/x-lua lua +application/x-lua-bytecode luac + +# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax +# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown +# Added by: avoidwork +text/x-markdown markdown md mkd diff --git a/node_modules/googleapis/node_modules/request/oauth.js b/node_modules/googleapis/node_modules/request/oauth.js new file mode 100644 index 0000000..e35bfa6 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/oauth.js @@ -0,0 +1,43 @@ +var crypto = require('crypto') + , qs = require('querystring') + ; + +function sha1 (key, body) { + return crypto.createHmac('sha1', key).update(body).digest('base64') +} + +function rfc3986 (str) { + return encodeURIComponent(str) + .replace(/!/g,'%21') + .replace(/\*/g,'%2A') + .replace(/\(/g,'%28') + .replace(/\)/g,'%29') + .replace(/'/g,'%27') + ; +} + +function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) { + // adapted from https://dev.twitter.com/docs/auth/oauth and + // https://dev.twitter.com/docs/auth/creating-signature + + var querystring = Object.keys(params).sort().map(function(key){ + // big WTF here with the escape + encoding but it's what twitter wants + return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key])) + }).join('%26') + + var base = [ + httpMethod ? httpMethod.toUpperCase() : 'GET', + rfc3986(base_uri), + querystring + ].join('&') + + var key = [ + consumer_secret, + token_secret || '' + ].map(rfc3986).join('&') + + return sha1(key, base) +} + +exports.hmacsign = hmacsign +exports.rfc3986 = rfc3986 diff --git a/node_modules/googleapis/node_modules/request/package.json b/node_modules/googleapis/node_modules/request/package.json new file mode 100644 index 0000000..f035167 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/package.json @@ -0,0 +1,45 @@ +{ + "name": "request", + "description": "Simplified HTTP request client.", + "tags": [ + "http", + "simple", + "util", + "utility" + ], + "version": "2.14.0", + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com" + }, + "repository": { + "type": "git", + "url": "http://github.com/mikeal/request.git" + }, + "bugs": { + "url": "http://github.com/mikeal/request/issues" + }, + "engines": [ + "node >= 0.3.6" + ], + "main": "./main", + "dependencies": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + }, + "bundleDependencies": [ + "form-data", + "mime" + ], + "scripts": { + "test": "node tests/run.js" + }, + "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n
    \n  npm install request\n
    \n\nOr from source:\n\n
    \n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n
    \n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nUrl encoded forms are simple\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload')\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))\nform.append('remote_file', request('http://google.com/doodle.png'))\n```\n\n## HTTP Authentication\n\n```javascript\nrequest.auth('username', 'password', false).get('http://some.server.com/');\n// or\nrequest.get('http://some.server.com/', {\n 'auth': {\n 'user': 'username',\n 'pass': 'password',\n 'sendImmediately': false\n }\n});\n```\n\nIf passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). The method form takes parameters `auth(username, password, sendImmediately)`.\n\n`sendImmediately` defaults to true, which will cause a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).\n\nDigest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail).\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Assume by some stretch of magic you aquired the verifier\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: VERIFIER\n , token_secret: access_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.\n* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). See documentation above.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n", + "readmeFilename": "README.md", + "_id": "request@2.14.0", + "dist": { + "shasum": "f4a0e051d921767d84e33400f24b356a122ce8cb" + }, + "_from": "request@2.14.0", + "_resolved": "https://registry.npmjs.org/request/-/request-2.14.0.tgz" +} diff --git a/node_modules/googleapis/node_modules/request/tests/googledoodle.png b/node_modules/googleapis/node_modules/request/tests/googledoodle.png new file mode 100644 index 0000000000000000000000000000000000000000..f80c9c52d3c507996535a19ee0bcfe3821de322d GIT binary patch literal 38510 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 literal 0 HcmV?d00001 diff --git a/node_modules/googleapis/node_modules/request/tests/run.js b/node_modules/googleapis/node_modules/request/tests/run.js new file mode 100644 index 0000000..45d28af --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/run.js @@ -0,0 +1,59 @@ +var spawn = require('child_process').spawn + , exitCode = 0 + , timeout = 10000 + ; + +var tests = [ + 'test-basic-auth.js' + , 'test-body.js' + , 'test-cookie.js' + , 'test-cookiejar.js' + , 'test-defaults.js' + , 'test-digest-auth.js' + , 'test-errors.js' + , 'test-form.js' + , 'test-follow-all-303.js' + , 'test-follow-all.js' + , 'test-headers.js' + , 'test-httpModule.js' + , 'test-https.js' + , 'test-https-strict.js' + , 'test-oauth.js' + , 'test-params.js' + , 'test-pipes.js' + , 'test-pool.js' + , 'test-protocol-changing-redirect.js' + , 'test-proxy.js' + , 'test-piped-redirect.js' + , 'test-qs.js' + , 'test-redirect.js' + , 'test-timeout.js' + , 'test-toJSON.js' + , 'test-tunnel.js' +] + +var next = function () { + if (tests.length === 0) process.exit(exitCode); + + var file = tests.shift() + console.log(file) + var proc = spawn('node', [ 'tests/' + file ]) + + var killed = false + var t = setTimeout(function () { + proc.kill() + exitCode += 1 + console.error(file + ' timeout') + killed = true + }, timeout) + + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + proc.on('exit', function (code) { + if (code && !killed) console.error(file + ' failed') + exitCode += code || 0 + clearTimeout(t) + next() + }) +} +next() diff --git a/node_modules/googleapis/node_modules/request/tests/server.js b/node_modules/googleapis/node_modules/request/tests/server.js new file mode 100644 index 0000000..b6eacba --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/server.js @@ -0,0 +1,90 @@ +var fs = require('fs') + , http = require('http') + , path = require('path') + , https = require('https') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + ; + +exports.createServer = function (port) { + port = port || 6767 + var s = http.createServer(function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'http://localhost:'+port + return s; +} + +exports.createSSLServer = function(port, opts) { + port = port || 16767 + + var options = { 'key' : path.join(__dirname, 'ssl', 'test.key') + , 'cert': path.join(__dirname, 'ssl', 'test.crt') + } + if (opts) { + for (var i in opts) options[i] = opts[i] + } + + for (var i in options) { + options[i] = fs.readFileSync(options[i]) + } + + var s = https.createServer(options, function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'https://localhost:'+port + return s; +} + +exports.createPostStream = function (text) { + var postStream = new stream.Stream(); + postStream.writeable = true; + postStream.readable = true; + setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0); + return postStream; +} +exports.createPostValidator = function (text, reqContentType) { + var l = function (req, resp) { + var r = ''; + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) { + var boundary = req.headers['content-type'].split('boundary=')[1]; + text = text.replace(/__BOUNDARY__/g, boundary); + } + if (r !== text) console.log(r, text); + assert.equal(r, text) + if (reqContentType) { + assert.ok(req.headers['content-type']) + assert.ok(~req.headers['content-type'].indexOf(reqContentType)) + } + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write('OK') + resp.end() + }) + } + return l; +} +exports.createGetResponse = function (text, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + resp.write(text) + resp.end() + } + return l; +} +exports.createChunkResponse = function (chunks, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + chunks.forEach(function (chunk) { + resp.write(chunk) + }) + resp.end() + } + return l; +} diff --git a/node_modules/googleapis/node_modules/request/tests/squid.conf b/node_modules/googleapis/node_modules/request/tests/squid.conf new file mode 100644 index 0000000..0d4a3b6 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/squid.conf @@ -0,0 +1,77 @@ +# +# Recommended minimum configuration: +# +acl manager proto cache_object +acl localhost src 127.0.0.1/32 ::1 +acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1 + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 10.0.0.0/8 # RFC1918 possible internal network +acl localnet src 172.16.0.0/12 # RFC1918 possible internal network +acl localnet src 192.168.0.0/16 # RFC1918 possible internal network +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT + +# +# Recommended minimum Access Permission configuration: +# +# Only allow cachemgr access from localhost +http_access allow manager localhost +http_access deny manager + +# Deny requests to certain unsafe ports +http_access deny !Safe_ports + +# Deny CONNECT to other than secure SSL ports +#http_access deny CONNECT !SSL_ports + +# We strongly recommend the following be uncommented to protect innocent +# web applications running on the proxy server who think the only +# one who can access services on "localhost" is a local user +#http_access deny to_localhost + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# + +# Example rule allowing access from your local networks. +# Adapt localnet in the ACL section to list your (internal) IP networks +# from where browsing should be allowed +http_access allow localnet +http_access allow localhost + +# And finally deny all other access to this proxy +http_access deny all + +# Squid normally listens to port 3128 +http_port 3128 + +# We recommend you to use at least the following line. +hierarchy_stoplist cgi-bin ? + +# Uncomment and adjust the following to add a disk cache directory. +#cache_dir ufs /usr/local/var/cache 100 16 256 + +# Leave coredumps in the first cache dir +coredump_dir /usr/local/var/cache + +# Add any of your own refresh_pattern entries above these. +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern . 0 20% 4320 diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.cnf b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.cnf new file mode 100644 index 0000000..425a889 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.cnf @@ -0,0 +1,20 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no +output_password = password + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = request Certificate Authority +CN = requestCA +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crl b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crl new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crt b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crt new file mode 100644 index 0000000..b4524e4 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvTCCAiYCCQDn+P/MSbDsWjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGiMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxJjAkBgNVBAsTHXJlcXVlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MRIwEAYDVQQDEwlyZXF1ZXN0Q0ExJjAkBgkqhkiG9w0BCQEWF21pa2VhbEBtaWtl +YWxyb2dlcnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t9pQUAK4 +5XJYTI6NrF0n3G2HZsfN+rPYSVzzL8SuVyb1tHXos+vbPm3NKI4E8X1yVAXU8CjJ +5SqXnp4DAypAhaseho81cbhk7LXUhFz78OvAa+OD+xTAEAnNQ8tGUr4VGyplEjfD +xsBVuqV2j8GPNTftr+drOCFlqfAgMrBn4wIDAQABMA0GCSqGSIb3DQEBBQUAA4GB +ADVdTlVAL45R+PACNS7Gs4o81CwSclukBu4FJbxrkd4xGQmurgfRrYYKjtqiopQm +D7ysRamS3HMN9/VKq2T7r3z1PMHPAy7zM4uoXbbaTKwlnX4j/8pGPn8Ca3qHXYlo +88L/OOPc6Di7i7qckS3HFbXQCTiULtxWmy97oEuTwrAj +-----END CERTIFICATE----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.csr b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.csr new file mode 100644 index 0000000..e48c56e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.csr @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICBjCCAW8CAQAwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEmMCQGA1UECxMdcmVxdWVzdCBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAMTCXJlcXVlc3RDQTEmMCQGCSqG +SIb3DQEJARYXbWlrZWFsQG1pa2VhbHJvZ2Vycy5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBALu32lBQArjlclhMjo2sXSfcbYdmx836s9hJXPMvxK5XJvW0 +deiz69s+bc0ojgTxfXJUBdTwKMnlKpeengMDKkCFqx6GjzVxuGTstdSEXPvw68Br +44P7FMAQCc1Dy0ZSvhUbKmUSN8PGwFW6pXaPwY81N+2v52s4IWWp8CAysGfjAgMB +AAGgIzAhBgkqhkiG9w0BCQcxFBMScGFzc3dvcmQgY2hhbGxlbmdlMA0GCSqGSIb3 +DQEBBQUAA4GBAGJO7grHeVHXetjHEK8urIxdnvfB2qeZeObz4GPKIkqUurjr0rfj +bA3EK1kDMR5aeQWR8RunixdM16Q6Ry0lEdLVWkdSwRN9dmirIHT9cypqnD/FYOia +SdezZ0lUzXgmJIwRYRwB1KSMMocIf52ll/xC2bEGg7/ZAEuAyAgcZV3X +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.key b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.key new file mode 100644 index 0000000..a53e7f7 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C8B5887048377F02 + +nyD5ZH0Wup2uWsDvurq5mKDaDrf8lvNn9w0SH/ZkVnfR1/bkwqrFriqJWvZNUG+q +nS0iBYczsWLJnbub9a1zLOTENWUKVD5uqbC3aGHhnoUTNSa27DONgP8gHOn6JgR+ +GAKo01HCSTiVT4LjkwN337QKHnMP2fTzg+IoC/CigvMcq09hRLwU1/guq0GJKGwH +gTxYNuYmQC4Tjh8vdS4liF+Ve/P3qPR2CehZrIOkDT8PHJBGQJRo4xGUIB7Tpk38 +VCk+UZ0JCS2coY8VkY/9tqFJp/ZnnQQVmaNbdRqg7ECKL+bXnNo7yjzmazPZmPe3 +/ShbE0+CTt7LrjCaQAxWbeDzqfo1lQfgN1LulTm8MCXpQaJpv7v1VhIhQ7afjMYb +4thW/ypHPiYS2YJCAkAVlua9Oxzzh1qJoh8Df19iHtpd79Q77X/qf+1JvITlMu0U +gi7yEatmQcmYNws1mtTC1q2DXrO90c+NZ0LK/Alse6NRL/xiUdjug2iHeTf/idOR +Gg/5dSZbnnlj1E5zjSMDkzg6EHAFmHV4jYGSAFLEQgp4V3ZhMVoWZrvvSHgKV/Qh +FqrAK4INr1G2+/QTd09AIRzfy3/j6yD4A9iNaOsEf9Ua7Qh6RcALRCAZTWR5QtEf +dX+iSNJ4E85qXs0PqwkMDkoaxIJ+tmIRJY7y8oeylV8cfGAi8Soubt/i3SlR8IHC +uDMas/2OnwafK3N7ODeE1i7r7wkzQkSHaEz0TrF8XRnP25jAICCSLiMdAAjKfxVb +EvzsFSuAy3Jt6bU3hSLY9o4YVYKE+68ITMv9yNjvTsEiW+T+IbN34w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.srl b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.srl new file mode 100644 index 0000000..17128db --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/ca.srl @@ -0,0 +1 @@ +ADF62016AA40C9C3 diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.cnf b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.cnf new file mode 100644 index 0000000..cd1fd1e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.cnf @@ -0,0 +1,19 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = testing +CN = testing.request.mikealrogers.com +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.crt b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.crt new file mode 100644 index 0000000..efe96ce --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICejCCAeMCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGjMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxEDAOBgNVBAsTB3Rlc3RpbmcxKTAnBgNVBAMTIHRlc3RpbmcucmVx +dWVzdC5taWtlYWxyb2dlcnMuY29tMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlr +ZWFscm9nZXJzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDgVl0jMumvOpmM +20W5v9yhGgZj8hPhEQF/N7yCBVBn/rWGYm70IHC8T/pR5c0LkWc5gdnCJEvKWQjh +DBKxZD8FAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEABShRkNgFbgs4vUWW9R9deNJj +7HJoiTmvkmoOC7QzcYkjdgHbOxsSq3rBnwxsVjY9PAtPwBn0GRspOeG7KzKRgySB +kb22LyrCFKbEOfKO/+CJc80ioK9zEPVjGsFMyAB+ftYRqM+s/4cQlTg/m89l01wC +yapjN3RxZbInGhWR+jA= +-----END CERTIFICATE----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.csr b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.csr new file mode 100644 index 0000000..a8e7595 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBgjCCASwCAQAwgaMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEQMA4GA1UECxMHdGVzdGluZzEp +MCcGA1UEAxMgdGVzdGluZy5yZXF1ZXN0Lm1pa2VhbHJvZ2Vycy5jb20xJjAkBgkq +hkiG9w0BCQEWF21pa2VhbEBtaWtlYWxyb2dlcnMuY29tMFwwDQYJKoZIhvcNAQEB +BQADSwAwSAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAaAjMCEGCSqGSIb3DQEJBzEU +ExJwYXNzd29yZCBjaGFsbGVuZ2UwDQYJKoZIhvcNAQEFBQADQQBD3E5WekQzCEJw +7yOcqvtPYIxGaX8gRKkYfLPoj3pm3GF5SGqtJKhylKfi89szHXgktnQgzff9FN+A +HidVJ/3u +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.js b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.js new file mode 100644 index 0000000..05e21c1 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.js @@ -0,0 +1,28 @@ +var fs = require("fs") +var https = require("https") +var options = { key: fs.readFileSync("./server.key") + , cert: fs.readFileSync("./server.crt") } + +var server = https.createServer(options, function (req, res) { + res.writeHead(200) + res.end() + server.close() +}) +server.listen(1337) + +var ca = fs.readFileSync("./ca.crt") +var agent = new https.Agent({ host: "localhost", port: 1337, ca: ca }) + +https.request({ host: "localhost" + , method: "HEAD" + , port: 1337 + , headers: { host: "testing.request.mikealrogers.com" } + , agent: agent + , ca: [ ca ] + , path: "/" }, function (res) { + if (res.client.authorized) { + console.log("node test: OK") + } else { + throw new Error(res.client.authorizationError) + } +}).end() diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.key b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.key new file mode 100644 index 0000000..72d8698 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/ca/server.key @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAQJAK+r8ZM2sze8s7FRo/ApB +iRBtO9fCaIdJwbwJnXKo4RKwZDt1l2mm+fzZ+/QaQNjY1oTROkIIXmnwRvZWfYlW +gQIhAPKYsG+YSBN9o8Sdp1DMyZ/rUifKX3OE6q9tINkgajDVAiEA7Ltqh01+cnt0 +JEnud/8HHcuehUBLMofeg0G+gCnSbXECIQCqDvkXsWNNLnS/3lgsnvH0Baz4sbeJ +rjIpuVEeg8eM5QIgbu0+9JmOV6ybdmmiMV4yAncoF35R/iKGVHDZCAsQzDECIQDZ +0jGz22tlo5YMcYSqrdD3U4sds1pwiAaWFRbCunoUJw== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/npm-ca.crt b/node_modules/googleapis/node_modules/request/tests/ssl/npm-ca.crt new file mode 100644 index 0000000..fde2fe9 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/npm-ca.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x +IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w +bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y +MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV +BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj +YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA +aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE +OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz +Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl +y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC +l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv +yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl +ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op +-----END CERTIFICATE----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/test.crt b/node_modules/googleapis/node_modules/request/tests/ssl/test.crt new file mode 100644 index 0000000..b357f86 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQzCCAawCCQCO/XWtRFck1jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJU +SDEQMA4GA1UECBMHQmFuZ2tvazEOMAwGA1UEBxMFU2lsb20xGzAZBgNVBAoTElRo +ZSBSZXF1ZXN0IE1vZHVsZTEYMBYGA1UEAxMPcmVxdWVzdC5leGFtcGxlMB4XDTEx +MTIwMzAyMjkyM1oXDTIxMTEzMDAyMjkyM1owZjELMAkGA1UEBhMCVEgxEDAOBgNV +BAgTB0Jhbmdrb2sxDjAMBgNVBAcTBVNpbG9tMRswGQYDVQQKExJUaGUgUmVxdWVz +dCBNb2R1bGUxGDAWBgNVBAMTD3JlcXVlc3QuZXhhbXBsZTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwmctddZqlA48+NXs0yOy92DijcQV1jf87zMiYAIlNUto +wghVbTWgJU5r0pdKrD16AptnWJTzKanhItEX8XCCPgsNkq1afgTtJP7rNkwu3xcj +eIMkhJg/ay4ZnkbnhYdsii5VTU5prix6AqWRAhbkBgoA+iVyHyof8wvZyKBoFTMC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQB6BybMJbpeiABgihDfEVBcAjDoQ8gUMgwV +l4NulugfKTDmArqnR9aPd4ET5jX5dkMP4bwCHYsvrcYDeWEQy7x5WWuylOdKhua4 +L4cEi2uDCjqEErIG3cc1MCOk6Cl6Ld6tkIzQSf953qfdEACRytOeUqLNQcrXrqeE +c7U8F6MWLQ== +-----END CERTIFICATE----- diff --git a/node_modules/googleapis/node_modules/request/tests/ssl/test.key b/node_modules/googleapis/node_modules/request/tests/ssl/test.key new file mode 100644 index 0000000..b85810d --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/ssl/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDCZy111mqUDjz41ezTI7L3YOKNxBXWN/zvMyJgAiU1S2jCCFVt +NaAlTmvSl0qsPXoCm2dYlPMpqeEi0RfxcII+Cw2SrVp+BO0k/us2TC7fFyN4gySE +mD9rLhmeRueFh2yKLlVNTmmuLHoCpZECFuQGCgD6JXIfKh/zC9nIoGgVMwIDAQAB +AoGBALXFwfUf8vHTSmGlrdZS2AGFPvEtuvldyoxi9K5u8xmdFCvxnOcLsF2RsTHt +Mu5QYWhUpNJoG+IGLTPf7RJdj/kNtEs7xXqWy4jR36kt5z5MJzqiK+QIgiO9UFWZ +fjUb6oeDnTIJA9YFBdYi97MDuL89iU/UK3LkJN3hd4rciSbpAkEA+MCkowF5kSFb +rkOTBYBXZfiAG78itDXN6DXmqb9XYY+YBh3BiQM28oxCeQYyFy6pk/nstnd4TXk6 +V/ryA2g5NwJBAMgRKTY9KvxJWbESeMEFe2iBIV0c26/72Amgi7ZKUCLukLfD4tLF ++WSZdmTbbqI1079YtwaiOVfiLm45Q/3B0eUCQAaQ/0eWSGE+Yi8tdXoVszjr4GXb +G81qBi91DMu6U1It+jNfIba+MPsiHLcZJMVb4/oWBNukN7bD1nhwFWdlnu0CQQCf +Is9WHkdvz2RxbZDxb8verz/7kXXJQJhx5+rZf7jIYFxqX3yvTNv3wf2jcctJaWlZ +fVZwB193YSivcgt778xlAkEAprYUz3jczjF5r2hrgbizPzPDR94tM5BTO3ki2v3w +kbf+j2g7FNAx6kZiVN8XwfLc8xEeUGiPKwtq3ddPDFh17w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/googleapis/node_modules/request/tests/test-basic-auth.js b/node_modules/googleapis/node_modules/request/tests/test-basic-auth.js new file mode 100644 index 0000000..0a42dfe --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-basic-auth.js @@ -0,0 +1,66 @@ +var assert = require('assert') + , http = require('http') + , request = require('../main') + ; + +var numBasicRequests = 0; + +var basicServer = http.createServer(function (req, res) { + console.error('Basic auth server: ', req.method, req.url); + numBasicRequests++; + + var ok; + + if (req.headers.authorization) { + if (req.headers.authorization == 'Basic ' + new Buffer('test:testing2').toString('base64')) { + ok = true; + } else { + // Bad auth header, don't send back WWW-Authenticate header + ok = false; + } + } else { + // No auth header, send back WWW-Authenticate header + ok = false; + res.setHeader('www-authenticate', 'Basic realm="Private"'); + } + + if (ok) { + console.log('request ok'); + res.end('ok'); + } else { + console.log('status=401'); + res.statusCode = 401; + res.end('401'); + } +}); + +basicServer.listen(6767); + +request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing2', + 'sendImmediately': false + } +}, function(error, response, body) { + assert.equal(response.statusCode, 200); + assert.equal(numBasicRequests, 2); + + // If we don't set sendImmediately = false, request will send basic auth + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test2/', + 'auth': { + 'user': 'test', + 'pass': 'testing2' + } + }, function(error, response, body) { + assert.equal(response.statusCode, 200); + assert.equal(numBasicRequests, 3); + + console.log('All tests passed'); + basicServer.close(); + }); +}); diff --git a/node_modules/googleapis/node_modules/request/tests/test-body.js b/node_modules/googleapis/node_modules/request/tests/test-body.js new file mode 100644 index 0000000..a624397 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-body.js @@ -0,0 +1,117 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetEncoding : + { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex')) + , encoding: 'hex' + , expectBody: "efa3bfcea9e29883" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + , testPutMultipartPreambleCRLF : + { resp: server.createPostValidator( + '\r\n--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , preambleCRLF: true + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/googleapis/node_modules/request/tests/test-cookie.js b/node_modules/googleapis/node_modules/request/tests/test-cookie.js new file mode 100644 index 0000000..6c6a7a7 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-cookie.js @@ -0,0 +1,29 @@ +var Cookie = require('../vendor/cookie') + , assert = require('assert'); + +var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT'; +var cookie = new Cookie(str); + +// test .toString() +assert.equal(cookie.toString(), str); + +// test .path +assert.equal(cookie.path, '/'); + +// test .httpOnly +assert.equal(cookie.httpOnly, true); + +// test .name +assert.equal(cookie.name, 'Sid'); + +// test .value +assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="'); + +// test .expires +assert.equal(cookie.expires instanceof Date, true); + +// test .path default +var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' }); +assert.equal(cookie.path, '/bar'); + +console.log('All tests passed'); diff --git a/node_modules/googleapis/node_modules/request/tests/test-cookiejar.js b/node_modules/googleapis/node_modules/request/tests/test-cookiejar.js new file mode 100644 index 0000000..76fcd71 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-cookiejar.js @@ -0,0 +1,90 @@ +var Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , assert = require('assert'); + +function expires(ms) { + return new Date(Date.now() + ms).toUTCString(); +} + +// test .get() expiration +(function() { + var jar = new Jar; + var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000)); + jar.add(cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 0); + }, 1000); + }, 5); +})(); + +// test .get() path support +(function() { + var jar = new Jar; + var a = new Cookie('sid=1234; path=/'); + var b = new Cookie('sid=1111; path=/foo/bar'); + var c = new Cookie('sid=2222; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + + // should remove the duplicates + assert.equal(jar.cookies.length, 2); + + // same name, same path, latter prevails + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], c); + + // same name, diff path, path specifity prevails, latter prevails + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], a); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=3333; path=/foo/bar'); + var c = new Cookie('pid=3333; path=/foo/bar'); + var d = new Cookie('sid=2222; path=/foo/'); + var e = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + jar.add(d); + jar.add(e); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 2); + assert.equal(cookies[0], b); + assert.equal(cookies[1], c); + + var cookies = jar.get({ url: 'http://foo.com/foo/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], d); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], e); +})(); + +setTimeout(function() { + console.log('All tests passed'); +}, 1200); diff --git a/node_modules/googleapis/node_modules/request/tests/test-defaults.js b/node_modules/googleapis/node_modules/request/tests/test-defaults.js new file mode 100644 index 0000000..ba09418 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-defaults.js @@ -0,0 +1,114 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +s.listen(s.port, function () { + var counter = 0; + s.on('/get', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'GET') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end('TESTING!'); + }); + + // test get(string, function) + request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){ + if (e) throw e; + assert.deepEqual("TESTING!", b); + counter += 1; + }); + + s.on('/post', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/post-body', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], 'application/json'); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) with body + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post-body', {json: true, body:{bar:"baz"}}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/del', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'DELETE') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test .del(string, function) + request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/head', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'HEAD') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test head.(object, function) + request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){ + if (e) throw e; + counter += 1; + }); + + s.on('/get_custom', function(req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers.x, 'y'); + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test custom request handler function + var defaultRequest = request.defaults({ + headers:{foo:"bar"} + , body: 'TESTING!' + }, function(uri, options, callback) { + var params = request.initParams(uri, options, callback); + options = params.options; + options.headers.x = 'y'; + + return request(params.uri, params.options, params.callback); + }); + + var msg = 'defaults test failed. head request should throw earlier'; + assert.throws(function() { + defaultRequest.head(s.url + '/get_custom', function(e, r, b) { + throw new Error(msg); + }); + counter+=1; + }, msg); + + defaultRequest.get(s.url + '/get_custom', function(e, r, b) { + if(e) throw e; + counter += 1; + console.log(counter.toString() + " tests passed."); + s.close(); + }); +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-digest-auth.js b/node_modules/googleapis/node_modules/request/tests/test-digest-auth.js new file mode 100644 index 0000000..151af12 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-digest-auth.js @@ -0,0 +1,69 @@ +var assert = require('assert') + , http = require('http') + , request = require('../main') + ; + +// Test digest auth +// Using header values captured from interaction with Apache + +var numDigestRequests = 0; + +var digestServer = http.createServer(function (req, res) { + console.error('Digest auth server: ', req.method, req.url); + numDigestRequests++; + + var ok; + + if (req.headers.authorization) { + if (req.headers.authorization == 'Digest username="test", realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", uri="/test/", qop="auth", response="54753ce37c10cb20b09b769f0bed730e", nc="1", cnonce=""') { + ok = true; + } else { + // Bad auth header, don't send back WWW-Authenticate header + ok = false; + } + } else { + // No auth header, send back WWW-Authenticate header + ok = false; + res.setHeader('www-authenticate', 'Digest realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", algorithm=MD5, qop="auth"'); + } + + if (ok) { + console.log('request ok'); + res.end('ok'); + } else { + console.log('status=401'); + res.statusCode = 401; + res.end('401'); + } +}); + +digestServer.listen(6767); + +request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing', + 'sendImmediately': false + } +}, function(error, response, body) { + assert.equal(response.statusCode, 200); + assert.equal(numDigestRequests, 2); + + // If we don't set sendImmediately = false, request will send basic auth + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing' + } + }, function(error, response, body) { + assert.equal(response.statusCode, 401); + assert.equal(numDigestRequests, 3); + + console.log('All tests passed'); + digestServer.close(); + }); +}); diff --git a/node_modules/googleapis/node_modules/request/tests/test-errors.js b/node_modules/googleapis/node_modules/request/tests/test-errors.js new file mode 100644 index 0000000..1986a59 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-errors.js @@ -0,0 +1,37 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../main.js') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +try { + request(local, {multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/googleapis/node_modules/request/tests/test-follow-all-303.js b/node_modules/googleapis/node_modules/request/tests/test-follow-all-303.js new file mode 100644 index 0000000..3f2162d --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-follow-all-303.js @@ -0,0 +1,30 @@ +var request = require('../main'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + console.error(req.method, req.url); + requests ++; + + if (req.method === 'POST') { + console.error('send 303'); + res.setHeader('location', req.url); + res.statusCode = 303; + res.end('try again, i guess\n'); + } else { + console.error('send 200') + res.end('ok: ' + requests); + } +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 2'); + assert.equal(requests, 2); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/googleapis/node_modules/request/tests/test-follow-all.js b/node_modules/googleapis/node_modules/request/tests/test-follow-all.js new file mode 100644 index 0000000..b78745b --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-follow-all.js @@ -0,0 +1,35 @@ +var request = require('../main'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + requests ++; + + // redirect everything 3 times, no matter what. + var c = req.headers.cookie; + + if (!c) c = 0; + else c = +c.split('=')[1] || 0; + + if (c > 3) { + res.end('ok: '+requests); + return; + } + + res.setHeader('set-cookie', 'c=' + (c + 1)); + res.setHeader('location', req.url); + res.statusCode = 302; + res.end('try again, i guess\n'); +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 5'); + assert.equal(requests, 5); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/googleapis/node_modules/request/tests/test-form.js b/node_modules/googleapis/node_modules/request/tests/test-form.js new file mode 100644 index 0000000..aeefd31 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-form.js @@ -0,0 +1,79 @@ +var assert = require('assert') +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('../main.js'); +var fs = require('fs'); + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(__dirname + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(8080, function() { + + var req = request.post('http://localhost:8080/upload', function () { + server.close(); + }) + var form = req.form() + + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/googleapis/node_modules/request/tests/test-headers.js b/node_modules/googleapis/node_modules/request/tests/test-headers.js new file mode 100644 index 0000000..31fe3f4 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-headers.js @@ -0,0 +1,52 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , s = server.createServer() + +s.listen(s.port, function () { + var serverUri = 'http://localhost:' + s.port + , numTests = 0 + , numOutstandingTests = 0 + + function createTest(requestObj, serverAssertFn) { + var testNumber = numTests; + numTests += 1; + numOutstandingTests += 1; + s.on('/' + testNumber, function (req, res) { + serverAssertFn(req, res); + res.writeHead(200); + res.end(); + }); + requestObj.url = serverUri + '/' + testNumber + request(requestObj, function (err, res, body) { + assert.ok(!err) + assert.equal(res.statusCode, 200) + numOutstandingTests -= 1 + if (numOutstandingTests === 0) { + console.log(numTests + ' tests passed.') + s.close() + } + }) + } + + // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified + createTest({headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar') + }) + + // Issue #125: headers.cookie + cookie jar + var jar = new Jar() + jar.add(new Cookie('quux=baz')); + createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar; quux=baz') + }) + + // There should be no cookie header when neither headers.cookie nor a cookie jar is specified + createTest({}, function (req, res) { + assert.ok(!req.headers.cookie) + }) +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-httpModule.js b/node_modules/googleapis/node_modules/request/tests/test-httpModule.js new file mode 100644 index 0000000..1866de2 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-httpModule.js @@ -0,0 +1,94 @@ +var http = require('http') + , https = require('https') + , server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var faux_requests_made = {'http':0, 'https':0} +function wrap_request(name, module) { + // Just like the http or https module, but note when a request is made. + var wrapped = {} + Object.keys(module).forEach(function(key) { + var value = module[key]; + + if(key != 'request') + wrapped[key] = value; + else + wrapped[key] = function(options, callback) { + faux_requests_made[name] += 1 + return value.apply(this, arguments) + } + }) + + return wrapped; +} + + +var faux_http = wrap_request('http', http) + , faux_https = wrap_request('https', https) + , plain_server = server.createServer() + , https_server = server.createSSLServer() + + +plain_server.listen(plain_server.port, function() { + plain_server.on('/plain', function (req, res) { + res.writeHead(200) + res.end('plain') + }) + plain_server.on('/to_https', function (req, res) { + res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'}) + res.end() + }) + + https_server.listen(https_server.port, function() { + https_server.on('/https', function (req, res) { + res.writeHead(200) + res.end('https') + }) + https_server.on('/to_plain', function (req, res) { + res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'}) + res.end() + }) + + run_tests() + run_tests({}) + run_tests({'http:':faux_http}) + run_tests({'https:':faux_https}) + run_tests({'http:':faux_http, 'https:':faux_https}) + }) +}) + +function run_tests(httpModules) { + var to_https = 'http://localhost:'+plain_server.port+'/to_https' + var to_plain = 'https://localhost:'+https_server.port+'/to_plain' + + request(to_https, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to SSL worked') + assert.equal(body, 'https', 'Received HTTPS server body') + done() + }) + + request(to_plain, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to plaintext server worked') + assert.equal(body, 'plain', 'Received HTTPS server body') + done() + }) +} + + +var passed = 0; +function done() { + passed += 1 + var expected = 10 + + if(passed == expected) { + plain_server.close() + https_server.close() + + assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately') + assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately') + + console.log((expected+2) + ' tests passed.') + } +} diff --git a/node_modules/googleapis/node_modules/request/tests/test-https-strict.js b/node_modules/googleapis/node_modules/request/tests/test-https-strict.js new file mode 100644 index 0000000..470b68d --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-https-strict.js @@ -0,0 +1,97 @@ +// a test where we validate the siguature of the keys +// otherwise exactly the same as the ssl test + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key') + , cert: path.resolve(__dirname, 'ssl/ca/server.crt') } + , s = server.createSSLServer(null, opts) + , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt') + , ca = fs.readFileSync(caFile) + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.strictSSL = true + test.ca = ca + test.headers = { host: 'testing.request.mikealrogers.com' } + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-https.js b/node_modules/googleapis/node_modules/request/tests/test-https.js new file mode 100644 index 0000000..9d575b4 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-https.js @@ -0,0 +1,87 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + +var s = server.createSSLServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.rejectUnauthorized = false + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-oauth.js b/node_modules/googleapis/node_modules/request/tests/test-oauth.js new file mode 100644 index 0000000..72ca923 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-oauth.js @@ -0,0 +1,117 @@ +var hmacsign = require('../oauth').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../main') + ; + +function getsignature (r) { + var sign + r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var rsign = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +setTimeout(function () { + console.log(getsignature(rsign)) + assert.equal(reqsign, getsignature(rsign)) +}) + +var raccsign = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +setTimeout(function () { + console.log(getsignature(raccsign)) + assert.equal(accsign, getsignature(raccsign)) +}, 1) + +var rupsign = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) +setTimeout(function () { + console.log(getsignature(rupsign)) + assert.equal(upsign, getsignature(rupsign)) +}, 1) + + + + diff --git a/node_modules/googleapis/node_modules/request/tests/test-params.js b/node_modules/googleapis/node_modules/request/tests/test-params.js new file mode 100644 index 0000000..5ddb311 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-params.js @@ -0,0 +1,92 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + //test.uri = s.url + '/' + i + request(s.url + '/' + i, test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-piped-redirect.js b/node_modules/googleapis/node_modules/request/tests/test-piped-redirect.js new file mode 100644 index 0000000..25bf35d --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-piped-redirect.js @@ -0,0 +1,52 @@ +var http = require('http') + , assert = require('assert') + , request = require('../main.js') + ; + +var portOne = 8968 + , portTwo = 8969 + ; + + +// server one +var s1 = http.createServer(function (req, resp) +{ + if (req.url == '/original') + { + resp.writeHeader(302, {'location': '/redirected'}) + resp.end() + } + else if (req.url == '/redirected') + { + resp.writeHeader(200, {'content-type': 'text/plain'}) + resp.write('OK') + resp.end() + } + +}).listen(portOne); + + +// server two +var s2 = http.createServer(function (req, resp) +{ + + var x = request('http://localhost:'+portOne+'/original') + req.pipe(x) + x.pipe(resp) + +}).listen(portTwo, function() +{ + + var r = request('http://localhost:'+portTwo+'/original', function (err, res, body) { + + assert.equal(body, 'OK') + + s1.close() + s2.close() + + }); + + // it hangs, so wait a second :) + r.timeout = 1000; + +}); diff --git a/node_modules/googleapis/node_modules/request/tests/test-pipes.js b/node_modules/googleapis/node_modules/request/tests/test-pipes.js new file mode 100644 index 0000000..7162981 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-pipes.js @@ -0,0 +1,216 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + // Test pipeing to a request object with a json body + s.once('/push-json', server.createPostValidator("{\"foo\":\"bar\"}", "application/json")); + + var mybodydata = new stream.Stream(); + mybodydata.readable = true + + counter++ + var r2 = request.put({url:'http://localhost:3453/push-json',json:true}, function () { + check(); + }) + mybodydata.pipe(r2) + + mybodydata.emit('data', JSON.stringify({foo:"bar"})); + mybodydata.emit('end'); + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'application/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/png'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.png')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.png')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.png')), fs.readFileSync(path.join(__dirname, 'test.png'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.png')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + + s.on('/forward1', function (req, resp) { + resp.writeHead(302, {location:'/forward2'}) + resp.end() + }) + s.on('/forward2', function (req, resp) { + resp.writeHead('200', {'content-type':'image/png'}) + resp.write('d') + resp.end() + }) + + counter++ + var validateForward = new ValidationStream('d') + validateForward.on('end', check) + request.get('http://localhost:3453/forward1').pipe(validateForward) + + // Test pipe options + s.once('/opts', server.createGetResponse('opts response')); + + var optsStream = new stream.Stream(); + optsStream.writable = true + + var optsData = ''; + optsStream.write = function (buf) { + optsData += buf; + if (optsData === 'opts response') { + setTimeout(check, 10); + } + } + + optsStream.end = function () { + assert.fail('end called') + }; + + counter++ + request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false }) +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-pool.js b/node_modules/googleapis/node_modules/request/tests/test-pool.js new file mode 100644 index 0000000..1e7d578 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-pool.js @@ -0,0 +1,16 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200; + resp.end('asdf'); +}).listen(8080, function () { + request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) { + var agent = resp.request.agent; + assert.strictEqual(typeof agent, 'boolean'); + assert.strictEqual(agent, false); + s.close(); + }); +}); \ No newline at end of file diff --git a/node_modules/googleapis/node_modules/request/tests/test-protocol-changing-redirect.js b/node_modules/googleapis/node_modules/request/tests/test-protocol-changing-redirect.js new file mode 100644 index 0000000..aff0072 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-protocol-changing-redirect.js @@ -0,0 +1,61 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var s = server.createServer() +var ss = server.createSSLServer() +var sUrl = 'http://localhost:' + s.port +var ssUrl = 'https://localhost:' + ss.port + +s.listen(s.port, bouncy(s, ssUrl)) +ss.listen(ss.port, bouncy(ss, sUrl)) + +var hits = {} +var expect = {} +var pending = 0 +function bouncy (s, server) { return function () { + + var redirs = { a: 'b' + , b: 'c' + , c: 'd' + , d: 'e' + , e: 'f' + , f: 'g' + , g: 'h' + , h: 'end' } + + var perm = true + Object.keys(redirs).forEach(function (p) { + var t = redirs[p] + + // switch type each time + var type = perm ? 301 : 302 + perm = !perm + s.on('/' + p, function (req, res) { + res.writeHead(type, { location: server + '/' + t }) + res.end() + }) + }) + + s.on('/end', function (req, res) { + var h = req.headers['x-test-key'] + hits[h] = true + pending -- + if (pending === 0) done() + }) +}} + +for (var i = 0; i < 5; i ++) { + pending ++ + var val = 'test_' + i + expect[val] = true + request({ url: (i % 2 ? sUrl : ssUrl) + '/a' + , headers: { 'x-test-key': val } + , rejectUnauthorized: false }) +} + +function done () { + assert.deepEqual(hits, expect) + process.exit(0) +} diff --git a/node_modules/googleapis/node_modules/request/tests/test-proxy.js b/node_modules/googleapis/node_modules/request/tests/test-proxy.js new file mode 100644 index 0000000..647157c --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-qs.js b/node_modules/googleapis/node_modules/request/tests/test-qs.js new file mode 100644 index 0000000..1aac22b --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-qs.js @@ -0,0 +1,28 @@ +var request = request = require('../main.js') + , assert = require('assert') + ; + + +// Test adding a querystring +var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req1.path) +}, 1) + +// Test replacing a querystring value +var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req2.path) +}, 1) + +// Test appending a querystring value to the ones present in the uri +var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?x=y&q=search', req3.path) +}, 1) + +// Test leaving a querystring alone +var req4 = request.get({ uri: 'http://www.google.com?x=y'}) +setTimeout(function() { + assert.equal('/?x=y', req4.path) +}, 1) diff --git a/node_modules/googleapis/node_modules/request/tests/test-redirect.js b/node_modules/googleapis/node_modules/request/tests/test-redirect.js new file mode 100644 index 0000000..b84844a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-redirect.js @@ -0,0 +1,154 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + +var s = server.createServer() + +s.listen(s.port, function () { + var server = 'http://localhost:' + s.port; + var hits = {} + var passed = 0; + + bouncer(301, 'temp') + bouncer(302, 'perm') + bouncer(302, 'nope') + + function bouncer(code, label) { + var landing = label+'_landing'; + + s.on('/'+label, function (req, res) { + hits[label] = true; + res.writeHead(code, { + 'location':server + '/'+landing, + 'set-cookie': 'ham=eggs' + }) + res.end() + }) + + s.on('/'+landing, function (req, res) { + if (req.method !== 'GET') { // We should only accept GET redirects + console.error("Got a non-GET request to the redirect destination URL"); + res.writeHead(400); + res.end(); + return; + } + // Make sure the cookie doesn't get included twice, see #139: + // Make sure cookies are set properly after redirect + assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs'); + hits[landing] = true; + res.writeHead(200) + res.end(landing) + }) + } + + // Permanent bounce + var jar = new Jar() + jar.add(new Cookie('quux=baz')) + request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.perm, 'Original request is to /perm') + assert.ok(hits.perm_landing, 'Forward to permanent landing URL') + assert.equal(body, 'perm_landing', 'Got permanent landing content') + passed += 1 + done() + }) + + // Temporary bounce + request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + // Prevent bouncing. + request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode) + assert.ok(hits.nope, 'Original request to /nope') + assert.ok(!hits.nope_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 302, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow post redirects by default + request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when post') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow post redirects when followAllRedirects true + request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects by default + request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode < 301) throw new Error('Status is not a redirect.') + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects even if followRedirect is set to true + request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow delete redirects when followAllRedirects true + request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + var reqs_done = 0; + function done() { + reqs_done += 1; + if(reqs_done == 9) { + console.log(passed + ' tests passed.') + s.close() + } + } +}) diff --git a/node_modules/googleapis/node_modules/request/tests/test-s3.js b/node_modules/googleapis/node_modules/request/tests/test-s3.js new file mode 100644 index 0000000..5f59c4a --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-s3.js @@ -0,0 +1,13 @@ +var request = require('../main') + +var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', + { aws: + { key: 'AKIAI6KIQRRVMGK3WK5Q' + , secret: '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' + , bucket: 'log.curlybracecast.com' + } + }, function (e, resp, body) { + console.log(r.headers) + console.log(body) + } +) \ No newline at end of file diff --git a/node_modules/googleapis/node_modules/request/tests/test-timeout.js b/node_modules/googleapis/node_modules/request/tests/test-timeout.js new file mode 100644 index 0000000..673f8ad --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/googleapis/node_modules/request/tests/test-toJSON.js b/node_modules/googleapis/node_modules/request/tests/test-toJSON.js new file mode 100644 index 0000000..b7c67ef --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-toJSON.js @@ -0,0 +1,14 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('asdf') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp) { + assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200) + s.close() + }) +}) \ No newline at end of file diff --git a/node_modules/googleapis/node_modules/request/tests/test-tunnel.js b/node_modules/googleapis/node_modules/request/tests/test-tunnel.js new file mode 100644 index 0000000..0b62eba --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tests/test-tunnel.js @@ -0,0 +1,63 @@ +// test that we can tunnel a https request over an http proxy +// keeping all the CA and whatnot intact. +// +// Note: this requires that squid is installed. +// If the proxy fails to start, we'll just log a warning and assume success. + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt') + , ca = fs.readFileSync(caFile) + , child_process = require('child_process') + , sqConf = path.resolve(__dirname, 'squid.conf') + , sqArgs = ['-f', sqConf, '-N', '-d', '5'] + , proxy = 'http://localhost:3128' + , hadError = null + +var squid = child_process.spawn('squid', sqArgs); +var ready = false + +squid.stderr.on('data', function (c) { + console.error('SQUIDERR ' + c.toString().trim().split('\n') + .join('\nSQUIDERR ')) + ready = c.toString().match(/ready to serve requests|Accepting HTTP Socket connections/i) +}) + +squid.stdout.on('data', function (c) { + console.error('SQUIDOUT ' + c.toString().trim().split('\n') + .join('\nSQUIDOUT ')) +}) + +squid.on('exit', function (c) { + console.error('squid: exit '+c) + if (c && !ready) { + console.error('squid must be installed to run this test.') + console.error('skipping this test. please install squid and run again if you need to test tunneling.') + c = null + hadError = null + process.exit(0) + return + } + + if (c) { + hadError = hadError || new Error('Squid exited with '+c) + } + if (hadError) throw hadError +}) + +setTimeout(function F () { + if (!ready) return setTimeout(F, 100) + request({ uri: 'https://registry.npmjs.org/' + , proxy: 'http://localhost:3128' + , strictSSL: true + , ca: ca + , json: true }, function (er, body) { + hadError = er + console.log(er || typeof body) + if (!er) console.log("ok") + squid.kill('SIGKILL') + }) +}, 100) diff --git a/node_modules/googleapis/node_modules/request/tests/unicycle.jpg b/node_modules/googleapis/node_modules/request/tests/unicycle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cea4dd71dc41cd51c84bfcec6b3e65c15a58507 GIT binary patch literal 19806 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 literal 0 HcmV?d00001 diff --git a/node_modules/googleapis/node_modules/request/tunnel.js b/node_modules/googleapis/node_modules/request/tunnel.js new file mode 100644 index 0000000..3f7bbb9 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/tunnel.js @@ -0,0 +1,227 @@ +'use strict' + +var net = require('net') + , tls = require('tls') + , http = require('http') + , https = require('https') + , events = require('events') + , assert = require('assert') + , util = require('util') + ; + +exports.httpOverHttp = httpOverHttp +exports.httpsOverHttp = httpsOverHttp +exports.httpOverHttps = httpOverHttps +exports.httpsOverHttps = httpsOverHttps + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + return agent +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + agent.createSocket = createSecureSocket + return agent +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + return agent +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + agent.createSocket = createSecureSocket + return agent +} + + +function TunnelingAgent(options) { + var self = this + self.options = options || {} + self.proxyOptions = self.options.proxy || {} + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets + self.requests = [] + self.sockets = [] + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i] + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1) + pending.request.onSocket(socket) + return + } + } + socket.destroy() + self.removeSocket(socket) + }) +} +util.inherits(TunnelingAgent, events.EventEmitter) + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}) + return + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree) + socket.on('close', onCloseOrRemove) + socket.on('agentRemove', onCloseOrRemove) + req.onSocket(socket) + + function onFree() { + self.emit('free', socket, host, port) + } + + function onCloseOrRemove(err) { + self.removeSocket() + socket.removeListener('free', onFree) + socket.removeListener('close', onCloseOrRemove) + socket.removeListener('agentRemove', onCloseOrRemove) + } + }) +} + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this + var placeholder = {} + self.sockets.push(placeholder) + + var connectOptions = mergeOptions({}, self.proxyOptions, + { method: 'CONNECT' + , path: options.host + ':' + options.port + , agent: false + } + ) + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {} + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64') + } + + debug('making CONNECT request') + var connectReq = self.request(connectOptions) + connectReq.useChunkedEncodingByDefault = false // for v0.6 + connectReq.once('response', onResponse) // for v0.6 + connectReq.once('upgrade', onUpgrade) // for v0.6 + connectReq.once('connect', onConnect) // for v0.7 or later + connectReq.once('error', onError) + connectReq.end() + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head) + }) + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners() + socket.removeAllListeners() + + if (res.statusCode === 200) { + assert.equal(head.length, 0) + debug('tunneling connection has established') + self.sockets[self.sockets.indexOf(placeholder)] = socket + cb(socket) + } else { + debug('tunneling socket could not be established, statusCode=%d', res.statusCode) + var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } + } + + function onError(cause) { + connectReq.removeAllListeners() + + debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack) + var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } +} + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) return + + this.sockets.splice(pos, 1) + + var pending = this.requests.shift() + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket) + }) + } +} + +function createSecureSocket(options, cb) { + var self = this + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, + { servername: options.host + , socket: socket + } + )) + cb(secureSocket) + }) +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i] + if (typeof overrides === 'object') { + var keys = Object.keys(overrides) + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j] + if (overrides[k] !== undefined) { + target[k] = overrides[k] + } + } + } + } + return target +} + + +var debug +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments) + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0] + } else { + args.unshift('TUNNEL:') + } + console.error.apply(console, args) + } +} else { + debug = function() {} +} +exports.debug = debug // for test diff --git a/node_modules/googleapis/node_modules/request/uuid.js b/node_modules/googleapis/node_modules/request/uuid.js new file mode 100644 index 0000000..fc0588b --- /dev/null +++ b/node_modules/googleapis/node_modules/request/uuid.js @@ -0,0 +1,19 @@ +module.exports = function () { + var s = [], itoh = '0123456789ABCDEF' + + // Make array of random hex digits. The UUID only has 32 digits in it, but we + // allocate an extra items to make room for the '-'s we'll be inserting. + for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10) + + // Conform to RFC-4122, section 4.4 + s[14] = 4; // Set 4 high bits of time_high field to version + s[19] = (s[19] & 0x3) | 0x8 // Specify 2 high bits of clock sequence + + // Convert to hex chars + for (var i = 0; i <36; i++) s[i] = itoh[s[i]] + + // Insert '-'s + s[8] = s[13] = s[18] = s[23] = '-' + + return s.join('') +} diff --git a/node_modules/googleapis/node_modules/request/vendor/cookie/index.js b/node_modules/googleapis/node_modules/request/vendor/cookie/index.js new file mode 100644 index 0000000..ff44b3e --- /dev/null +++ b/node_modules/googleapis/node_modules/request/vendor/cookie/index.js @@ -0,0 +1,65 @@ +/*! + * Tobi - Cookie + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var url = require('url'); + +/** + * Initialize a new `Cookie` with the given cookie `str` and `req`. + * + * @param {String} str + * @param {IncomingRequest} req + * @api private + */ + +var Cookie = exports = module.exports = function Cookie(str, req) { + this.str = str; + + // Map the key/val pairs + str.split(/ *; */).reduce(function(obj, pair){ + var p = pair.indexOf('='); + var key = p > 0 ? pair.substring(0, p).trim() : pair.trim(); + var lowerCasedKey = key.toLowerCase(); + var value = p > 0 ? pair.substring(p + 1).trim() : true; + + if (!obj.name) { + // First key is the name + obj.name = key; + obj.value = value; + } + else if (lowerCasedKey === 'httponly') { + obj.httpOnly = value; + } + else { + obj[lowerCasedKey] = value; + } + return obj; + }, this); + + // Expires + this.expires = this.expires + ? new Date(this.expires) + : Infinity; + + // Default or trim path + this.path = this.path + ? this.path.trim(): req + ? url.parse(req.url).pathname: '/'; +}; + +/** + * Return the original cookie string. + * + * @return {String} + * @api public + */ + +Cookie.prototype.toString = function(){ + return this.str; +}; diff --git a/node_modules/googleapis/node_modules/request/vendor/cookie/jar.js b/node_modules/googleapis/node_modules/request/vendor/cookie/jar.js new file mode 100644 index 0000000..34920e0 --- /dev/null +++ b/node_modules/googleapis/node_modules/request/vendor/cookie/jar.js @@ -0,0 +1,72 @@ +/*! +* Tobi - CookieJar +* Copyright(c) 2010 LearnBoost +* MIT Licensed +*/ + +/** +* Module dependencies. +*/ + +var url = require('url'); + +/** +* Initialize a new `CookieJar`. +* +* @api private +*/ + +var CookieJar = exports = module.exports = function CookieJar() { + this.cookies = []; +}; + +/** +* Add the given `cookie` to the jar. +* +* @param {Cookie} cookie +* @api private +*/ + +CookieJar.prototype.add = function(cookie){ + this.cookies = this.cookies.filter(function(c){ + // Avoid duplication (same path, same name) + return !(c.name == cookie.name && c.path == cookie.path); + }); + this.cookies.push(cookie); +}; + +/** +* Get cookies for the given `req`. +* +* @param {IncomingRequest} req +* @return {Array} +* @api private +*/ + +CookieJar.prototype.get = function(req){ + var path = url.parse(req.url).pathname + , now = new Date + , specificity = {}; + return this.cookies.filter(function(cookie){ + if (0 == path.indexOf(cookie.path) && now < cookie.expires + && cookie.path.length > (specificity[cookie.name] || 0)) + return specificity[cookie.name] = cookie.path.length; + }); +}; + +/** +* Return Cookie string for the given `req`. +* +* @param {IncomingRequest} req +* @return {String} +* @api private +*/ + +CookieJar.prototype.cookieString = function(req){ + var cookies = this.get(req); + if (cookies.length) { + return cookies.map(function(cookie){ + return cookie.name + '=' + cookie.value; + }).join('; '); + } +}; diff --git a/node_modules/googleapis/package.json b/node_modules/googleapis/package.json new file mode 100644 index 0000000..110639c --- /dev/null +++ b/node_modules/googleapis/package.json @@ -0,0 +1,50 @@ +{ + "name": "googleapis", + "version": "0.2.13-alpha", + "author": { + "name": "Google Inc." + }, + "description": "Google APIs Client Library for Node.js", + "contributors": [ + { + "name": "Burcu Dogan", + "email": "jbd@google.com" + }, + { + "name": "Monsur Hossain", + "email": "monsur@google.com" + } + ], + "main": "./lib/googleapis", + "repository": { + "type": "git", + "url": "https://github.com/google/google-api-nodejs-client.git" + }, + "keywords": [ + "google", + "api", + "google apis", + "client", + "client library" + ], + "dependencies": { + "request": "2.14.0", + "async": "0.2.6" + }, + "devDependencies": { + "mocha": "1.8.1", + "url": "0.7.9" + }, + "scripts": { + "test": "mocha tests/* --reporter spec --timeout 40000" + }, + "license": "Apache 2", + "readme": "# google-api-nodejs-client [alpha]\n\n[![Build Status](https://travis-ci.org/google/google-api-nodejs-client.png)](https://travis-ci.org/google/google-api-nodejs-client)\n\n`google-api-nodejs-client` is Google's officially supported\n[node.js](http://nodejs.org/) client\nlibrary for accessing Google APIs, it also supports authorization and\nauthentication with OAuth 2.0.\n\n**Note**: This library is currently in *alpha* status, meaning that we can make\nchanges in the future that *may not be compatible* with the previous versions.\n\n## Installation\n\nThe library is distributed on `npm`. In order to add it as a dependency,\nrun the following command:\n\n $ npm install googleapis\n\n## Guide\n\n### Discover APIs\n\nDynamically load Google APIs and start making requests:\n\n~~~~ js\nvar googleapis = require('googleapis');\n\ngoogleapis\n .discover('urlshortener', 'v1')\n .discover('plus', 'v1')\n .execute(function(err, client) {\n var params = { shortUrl: 'http://goo.gl/DdUKX' };\n var req1 = client.urlshortener.url.get(params);\n req1.execute(function (err, response) {\n console.log('Long url is', response.longUrl);\n });\n\n var req2 = client.plus.people.get({ userId: '+BurcuDogan' });\n req2.execute();\n});\n~~~~\n\nSupported APIs are listed on\n[Google APIs Explorer](https://developers.google.com/apis-explorer).\n\n#### Discovery Document Caching\n\nDiscovery documents are being cached for 5 minutes locally.\nYou can configure the directory used to store cached discovery\nfiles by using the `cache.path` option.\n\n~~~~ js\ngoogleapis\n .discover('plus', 'v3')\n .withOpts({ cache: { path: '' }))\n .execute();\n~~~~\n\n### API Client\n\nClient libraries are generated during runtime by metadata provided by Google\nAPIs Discovery Service. Metadata provided by Discovery Service is cached,\nand won't be requested each time you load a client. Below, there is an\nexample of loading a client for\n[URL Shortener API](https://developers.google.com/url-shortener/).\n\n~~~~ js\ngoogleapis\n .discover('urlshortener', 'v1')\n .execute(function(err, client) {\n // make requests\n });\n~~~~\n\n### Requests\n\nThe following sample loads a client for URL Shortener and retrieves the long url\nof the given short url:\n\n~~~~ js\ngoogleapis.discover('urlshortener', 'v1').execute(function(err, client) {\n client.urlshortener.url.get({ shortUrl: 'http://goo.gl/DdUKX' })\n .execute(function(err, result) {\n // result.longUrl contains the long url.\n });\n });\n~~~~\n\nAlternatively, you may need to send an API key with the\nrequest you are going to make. The following creates and executes a request from the Google+ API service to retrieve a person profile given a userId:\n\n~~~~ js\ngoogleapis\n .discover('plus', 'v1')\n .execute(function(err, client) {\n var request1 = client.plus.people.get({ userId: '+BurcuDogan' })\n .withApiKey(API_KEY);\n\n request1.execute(function(err, result) {\n console.log(\"Result: \" + (err ? err.message : result.displayName));\n });\n });\n~~~~\n\nTo learn more about API keys, please see the [documentation](https://developers.google.com/console/help/#UsingKeys).\n\n### Batch requests\n\nYou can combine multiple requests in a single one by using batch requests.\n\n~~~~ js\nvar request1 =\n client.plus.people.get({ userId: '+BurcuDogan' });\n\nvar request2 =\n client.urlshortener.url.insert({ longUrl: 'http://google.com' });\n\n// Create from client service using the raw action name\nvar request3 = client.urlshortener.newRequest(\n 'urlshortener.url.get', { shortUrl: 'http://goo.gl/DdUKX' });\n\nclient\n .newBatchRequest()\n .add(request1)\n .add(request2)\n .add(request3)\n .execute(function(err, results) {\n\n });\n~~~~\n\n### Authorization and Authentication\n\nThis client comes with an OAuth2 client that allows you to retrieve an access token and\nrefreshes the token and re-try the request seamlessly if token is expired. The\nbasics of Google's OAuth 2.0 implementation is explained on\n[Google Authorization and Authentication\ndocumentation](https://developers.google.com/accounts/docs/OAuth2Login).\n\nA complete sample application that authorizes and authenticates with OAuth2.0\nclient is available at `examples/oauth2.js`.\n\n#### Consent Page Url\n\nIn order to ask for permissions from a user to retrieve an access token, you\nshould redirect them to a consent page. In order to create a consent page\nURL:\n\n~~~~ js\nvar googleapis = require('googleapis'),\n OAuth2Client = googleapis.OAuth2Client;\n\nvar oauth2Client =\n new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);\n\n// generates a url that allows offline access and asks permissions\n// for Google+ scope.\nvar url = oauth2Client.generateAuthUrl({\n access_type: 'offline',\n scope: 'https://www.googleapis.com/auth/plus.me'\n});\n~~~~\n\n#### Retrieving Tokens\nOnce a user has given permissions on the consent page, Google will redirect\nthe page to the redirect url you have provided with a code query parameter.\n\n GET /oauthcallback?code={authorizationCode}\n\nWith the code returned, you can ask for an access token as shown below:\n\n~~~~ js\noauth2Client.getToken(code, function(err, tokens) {\n // contains an access_token and optionally a refresh_token.\n // save them permanently.\n});\n~~~~\n\n#### Making Authenticated Requests\n\nAnd you can start using oauth2Client to authorize and authenticate your\nrequests to Google APIs with the retrieved tokens. If you provide a\nrefresh_token, in cases when access_token is expired, it asks for a new\naccess_token and replays the request.\n\nFollowing sample retrieves Google+ profile of the authenticated user.\n\n~~~~ js\noauth2Client.credentials = {\n access_token: 'ACCESS TOKEN HERE',\n refresh_token: 'REFRESH TOKEN HERE'\n};\n\nclient\n .plus.people.get({ userId: 'me' })\n .withAuthClient(oauth2Client)\n .execute(callback);\n~~~~\n\n## License\n\n`google-api-nodejs-client` is licensed with Apache 2.0. Full license text is\navailable on COPYING file.\n\n## Contributors\n\nBefore making any contributions, please sign one of the contributor\nlicense agreements below.\n\nFork the repo, develop and test your code changes.\n\nInstall all dependencies including development requirements by running:\n\n $ npm install -d\n\nTests use mocha. To run all tests you can use\n\n $ npm test\n\nwhich looks for tests in the `./tests` directory.\n\nYour code should honor the\n[Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml).\nYou can use\n[Closure Linter](https://code.google.com/p/closure-linter/)\nto detect style issues.\n\nSubmit a pull request. The repo owner will review your request. If it is\napproved, the change will be merged. If it needs additional work, the repo\nowner will respond with useful comments.\n\n#### Contributor License Agreements\n\nBefore creating a pull request, please fill out either the individual or\ncorporate Contributor License Agreement.\n\n* If you are an individual writing original source code and you're sure you\nown the intellectual property, then you'll need to sign an\n[individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).\n* If you work for a company that wants to allow you to contribute your work\nto this client library, then you'll need to sign a\n[corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).\n\nFollow either of the two links above to access the appropriate CLA and\ninstructions for how to sign and return it. Once we receive it, we'll add you\nto the official list of contributors and be able to accept your patches.\n", + "readmeFilename": "README.md", + "_id": "googleapis@0.2.13-alpha", + "dist": { + "shasum": "8f226e77499d78225edf42fd1e0b3b7cb06259f3" + }, + "_from": "googleapis@", + "_resolved": "https://registry.npmjs.org/googleapis/-/googleapis-0.2.13-alpha.tgz" +} diff --git a/node_modules/jade/.npmignore b/node_modules/jade/.npmignore new file mode 100644 index 0000000..3be3bd2 --- /dev/null +++ b/node_modules/jade/.npmignore @@ -0,0 +1,14 @@ +test +support +benchmarks +examples +lib-cov +coverage.html +.gitmodules +.travis.yml +History.md +Makefile +test/ +support/ +benchmarks/ +examples/ diff --git a/node_modules/jade/LICENSE b/node_modules/jade/LICENSE new file mode 100644 index 0000000..fbfe096 --- /dev/null +++ b/node_modules/jade/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2009-2010 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/jade/Readme.md b/node_modules/jade/Readme.md new file mode 100644 index 0000000..348b9e7 --- /dev/null +++ b/node_modules/jade/Readme.md @@ -0,0 +1,1310 @@ +# Jade - template engine +[![Build Status](https://travis-ci.org/visionmedia/jade.png?branch=master)](https://travis-ci.org/visionmedia/jade) +[![Dependency Status](https://gemnasium.com/visionmedia/jade.png)](https://gemnasium.com/visionmedia/jade) +[![NPM version](https://badge.fury.io/js/jade.png)](http://badge.fury.io/js/jade) + + Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com) + and implemented with JavaScript for [node](http://nodejs.org). For discussion join the [Google Group](http://groups.google.com/group/jadejs). + +## Announcement + +Jade version 0.31.0 deprecated implicit text only support for scripts and styles. To fix this all you need to do is add a `.` character after the script or style tag. + +It is hoped that this change will make Jade easier for newcomers to learn without affecting the power of the language or leading to excessive verboseness. + +If you have a lot of Jade files that need fixing you can use [fix-jade](https://github.com/ForbesLindesay/fix-jade) to attempt to automate the process. + +## Test drive + + You can test drive Jade online [here](http://naltatis.github.com/jade-syntax-docs). + +## README Contents + +- [Features](#a1) +- [Implementations](#a2) +- [Installation](#a3) +- [Browser Support](#a4) +- [Public API](#a5) +- [Syntax](#a6) + - [Line Endings](#a6-1) + - [Tags](#a6-2) + - [Tag Text](#a6-3) + - [Comments](#a6-4) + - [Block Comments](#a6-5) + - [Nesting](#a6-6) + - [Block Expansion](#a6-7) + - [Case](#a6-8) + - [Attributes](#a6-9) + - [HTML](#a6-10) + - [Doctypes](#a6-11) +- [Filters](#a7) +- [Code](#a8) +- [Iteration](#a9) +- [Conditionals](#a10) +- [Template inheritance](#a11) +- [Block append / prepend](#a12) +- [Includes](#a13) +- [Mixins](#a14) +- [Generated Output](#a15) +- [Example Makefile](#a16) +- [jade(1)](#a17) +- [Tutorials](#a18) +- [License](#a19) + +
    +## Features + + - client-side support + - great readability + - flexible indentation + - block-expansion + - mixins + - static includes + - attribute interpolation + - code is escaped by default for security + - contextual error reporting at compile & run time + - executable for compiling jade templates via the command line + - html 5 mode (the default doctype) + - optional memory caching + - combine dynamic and static tag classes + - parse tree manipulation via _filters_ + - template inheritance + - block append / prepend + - supports [Express JS](http://expressjs.com) out of the box + - transparent iteration over objects, arrays, and even non-enumerables via `each` + - block comments + - no tag prefix + - filters + - :stylus must have [stylus](http://github.com/LearnBoost/stylus) installed + - :less must have [less.js](http://github.com/cloudhead/less.js) installed + - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js), [node-discount](http://github.com/visionmedia/node-discount), or [marked](http://github.com/chjj/marked) installed + - :cdata + - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed + - [Emacs Mode](https://github.com/brianc/jade-mode) + - [Vim Syntax](https://github.com/digitaltoad/vim-jade) + - [TextMate Bundle](http://github.com/miksago/jade-tmbundle) + - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode) + - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs) + - [html2jade](https://github.com/donpark/html2jade) converter + + +## Implementations + + - [php](http://github.com/everzet/jade.php) + - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html) + - [ruby](https://github.com/slim-template/slim) + - [python](https://github.com/SyrusAkbary/pyjade) + - [java](https://github.com/neuland/jade4j) + + +## Installation + +via npm: + +```bash +$ npm install jade +``` + + +## Browser Support + + To compile jade to a single file compatible for client-side use simply execute: + +```bash +$ make jade.js +``` + + Alternatively, if uglifyjs is installed via npm (`npm install uglify-js`) you may execute the following which will create both files. However each release builds these for you. + +```bash +$ make jade.min.js +``` + + By default Jade instruments templates with line number statements such as `__.lineno = 3` for debugging purposes. When used in a browser it's useful to minimize this boiler plate, you can do so by passing the option `{ compileDebug: false }`. The following template + +```jade +p Hello #{name} +``` + + Can then be as small as the following generated function: + +```js +function anonymous(locals, attrs, escape, rethrow) { + var buf = []; + with (locals || {}) { + var interp; + buf.push('\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\n

    '); + } + return buf.join(""); +} +``` + + Through the use of Jade's `./runtime.js` you may utilize these pre-compiled templates on the client-side _without_ Jade itself, all you need is the associated utility functions (in runtime.js), which are then available as `jade.attrs`, `jade.escape` etc. To enable this you should pass `{ client: true }` to `jade.compile()` to tell Jade to reference the helper functions + via `jade.attrs`, `jade.escape` etc. + +```js +function anonymous(locals, attrs, escape, rethrow) { + var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow; + var buf = []; + with (locals || {}) { + var interp; + buf.push('\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\n

    '); + } + return buf.join(""); +} +``` + +
    +## Public API + +```js +var jade = require('jade'); + +// Compile a function +var fn = jade.compile('string of jade', options); +fn(locals); +``` + +### Options + + - `self` Use a `self` namespace to hold the locals _(false by default)_ + - `locals` Local variable object + - `filename` Used in exceptions, and required when using includes + - `debug` Outputs tokens and function body generated + - `compiler` Compiler to replace jade's default + - `compileDebug` When `false` no debug instrumentation is compiled + - `pretty` Add pretty-indentation whitespace to output _(false by default)_ + + +## Syntax + + +### Line Endings + +**CRLF** and **CR** are converted to **LF** before parsing. + + +### Tags + +A tag is simply a leading word: + +```jade +html +``` + +for example is converted to `` + +tags can also have ids: + +```jade +div#container +``` + +which would render `
    ` + +how about some classes? + +```jade +div.user-details +``` + +renders `
    ` + +multiple classes? _and_ an id? sure: + +```jade +div#foo.bar.baz +``` + +renders `
    ` + +div div div sure is annoying, how about: + +```jade +#foo +.bar +``` + +which is syntactic sugar for what we have already been doing, and outputs: + +```html +
    +``` + +
    +### Tag Text + +Simply place some content after the tag: + +```jade +p wahoo! +``` + +renders `

    wahoo!

    `. + +well cool, but how about large bodies of text: + +```jade +p + | foo bar baz + | rawr rawr + | super cool + | go jade go +``` + +renders `

    foo bar baz rawr.....

    ` + +interpolation? yup! both types of text can utilize interpolation, +if we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following: + +```jade +#user #{name} <#{email}> +``` + +outputs `
    tj <tj@vision-media.ca>
    ` + +Actually want `#{}` for some reason? escape it! + +```jade +p \#{something} +``` + +now we have `

    #{something}

    ` + +We can also utilize the unescaped variant `!{html}`, so the following +will result in a literal script tag: + +```jade +- var html = "" +| !{html} +``` + +Nested tags that also contain text can optionally use a text block: + +```jade +label + | Username: + input(name='user[name]') +``` + +or immediate tag text: + +```jade +label Username: + input(name='user[name]') +``` + +As an alternative, we may use a trailing `.` to indicate a text block, for example: + +```jade +p. + foo asdf + asdf + asdfasdfaf + asdf + asd. +``` + +outputs: + +```html +

    foo asdf +asdf + asdfasdfaf + asdf +asd. +

    +``` + +This however differs from a trailing `.` followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal: + +```jade +p . +``` + +outputs: + +```html +

    .

    +``` + +It should be noted that text blocks should be doubled escaped. For example if you desire the following output. + +```html +

    foo\bar

    +``` + +use: + +```jade +p. + foo\\bar +``` + +
    +### Comments + +Single line comments currently look the same as JavaScript comments, +aka `//` and must be placed on their own line: + +```jade +// just some paragraphs +p foo +p bar +``` + +would output + +```html + +

    foo

    +

    bar

    +``` + +Jade also supports unbuffered comments, by simply adding a hyphen: + +```jade +//- will not output within markup +p foo +p bar +``` + +outputting + +```html +

    foo

    +

    bar

    +``` + +
    +### Block Comments + + A block comment is legal as well: + +```jade +body + // + #content + h1 Example +``` + +outputting + +```html + + + +``` + +Jade supports conditional-comments as well, for example: + +```jade +head + //if lt IE 8 + script(src='/ie-sucks.js') +``` + +outputs: + +```html + + + +``` + + +### Nesting + + Jade supports nesting to define the tags in a natural way: + +```jade +ul + li.first + a(href='#') foo + li + a(href='#') bar + li.last + a(href='#') baz +``` + + +### Block Expansion + + Block expansion allows you to create terse single-line nested tags, + the following example is equivalent to the nesting example above. + +```jade +ul + li.first: a(href='#') foo + li: a(href='#') bar + li.last: a(href='#') baz +``` + + +### Case + + The case statement takes the following form: + +```jade +html + body + friends = 10 + case friends + when 0 + p you have no friends + when 1 + p you have a friend + default + p you have #{friends} friends +``` + + Block expansion may also be used: + +```jade +friends = 5 + +html + body + case friends + when 0: p you have no friends + when 1: p you have a friend + default: p you have #{friends} friends +``` + + +### Attributes + +Jade currently supports `(` and `)` as attribute delimiters. + +```jade +a(href='/login', title='View login page') Login +``` + +When a value is `undefined` or `null` the attribute is _not_ added, +so this is fine, it will not compile `something="null"`. + +```jade +div(something=null) +``` + +Boolean attributes are also supported: + +```jade +input(type="checkbox", checked) +``` + +Boolean attributes with code will only output the attribute when `true`: + +```jade +input(type="checkbox", checked=someValue) +``` + +Multiple lines work too: + +```jade +input(type='checkbox', + name='agreement', + checked) +``` + +Multiple lines without the comma work fine: + +```jade +input(type='checkbox' + name='agreement' + checked) +``` + +Funky whitespace? fine: + +```jade +input( + type='checkbox' + name='agreement' + checked) +``` + +Colons work: + +```jade +rss(xmlns:atom="atom") +``` + +Suppose we have the `user` local `{ id: 12, name: 'tobi' }` +and we wish to create an anchor tag with `href` pointing to "/user/12" +we could use regular javascript concatenation: + +```jade +a(href='/user/' + user.id)= user.name +``` + +or we could use jade's interpolation, which I added because everyone +using Ruby or CoffeeScript seems to think this is legal js..: + +```jade +a(href='/user/#{user.id}')= user.name +``` + +The `class` attribute is special-cased when an array is given, +allowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly: + +```jade +body(class=bodyClasses) +``` + + +### HTML + + Inline html is fine, we can use the pipe syntax to + write arbitrary text, in this case some html: + +```jade +html + body + |

    Title

    + |

    foo bar baz

    +``` + + Or we can use the trailing `.` to indicate to Jade that we + only want text in this block, allowing us to omit the pipes: + +```jade +html + body. +

    Title

    +

    foo bar baz

    +``` + + Both of these examples yield the same result: + +```html +

    Title

    +

    foo bar baz

    + +``` + + The same rule applies for anywhere you can have text + in jade, raw html is fine: + +```jade +html + body + h1 User #{name} +``` + +
    +### Doctypes + +To add a doctype simply use `!!!`, or `doctype` followed by an optional value: + +```jade +!!! +``` + +or + +```jade +doctype +``` + +Will output the _html 5_ doctype, however: + +```jade +!!! transitional +``` + +Will output the _transitional_ doctype. + +Doctypes are case-insensitive, so the following are equivalent: + +```jade +doctype Basic +doctype basic +``` + +it's also possible to simply pass a doctype literal: + +```jade +doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" +``` + +yielding: + +```html + +``` + +Below are the doctypes defined by default, which can easily be extended: + +```js +var doctypes = exports.doctypes = { + '5': '', + 'default': '', + 'xml': '', + 'transitional': '', + 'strict': '', + 'frameset': '', + '1.1': '', + 'basic': '', + 'mobile': '' +}; +``` + +To alter the default simply change: + +```js +jade.doctypes.default = 'whatever you want'; +``` + + +## Filters + +Filters are prefixed with `:`, for example `:markdown` and +pass the following block of text to an arbitrary function for processing. View the _features_ +at the top of this document for available filters. + +```jade +body + :markdown + Woah! jade _and_ markdown, very **cool** + we can even link to [stuff](http://google.com) +``` + +Renders: + +```html +

    Woah! jade and markdown, very cool we can even link to stuff

    +``` + + +## Code + +Jade currently supports three classifications of executable code. The first +is prefixed by `-`, and is not buffered: + +```jade +- var foo = 'bar'; +``` + +This can be used for conditionals, or iteration: + +```jade +- for (var key in obj) + p= obj[key] +``` + +Due to Jade's buffering techniques the following is valid as well: + +```jade +- if (foo) + ul + li yay + li foo + li worked +- else + p oh no! didnt work +``` + +Hell, even verbose iteration: + +```jade +- if (items.length) + ul + - items.forEach(function(item){ + li= item + - }) +``` + +Anything you want! + +Next up we have _escaped_ buffered code, which is used to +buffer a return value, which is prefixed by `=`: + +```jade +- var foo = 'bar' += foo +h1= foo +``` + +Which outputs `bar

    bar

    `. Code buffered by `=` is escaped +by default for security, however to output unescaped return values +you may use `!=`: + +```jade +p!= aVarContainingMoreHTML +``` + + Jade also has designer-friendly variants, making the literal JavaScript + more expressive and declarative. For example the following assignments + are equivalent, and the expression is still regular javascript: + +```jade +- var foo = 'foo ' + 'bar' +foo = 'foo ' + 'bar' +``` + + Likewise Jade has first-class `if`, `else if`, `else`, `until`, `while`, `unless` among others, however you must remember that the expressions are still regular javascript: + +```jade +if foo == 'bar' + ul + li yay + li foo + li worked +else + p oh no! didnt work +``` + +
    +## Iteration + + Along with vanilla JavaScript Jade also supports a subset of + constructs that allow you to create more designer-friendly templates, + one of these constructs is `each`, taking the form: + +```jade +each VAL[, KEY] in OBJ +``` + +An example iterating over an array: + +```jade +- var items = ["one", "two", "three"] +each item in items + li= item +``` + +outputs: + +```html +
  • one
  • +
  • two
  • +
  • three
  • +``` + +iterating an array with index: + +```jade +items = ["one", "two", "three"] +each item, i in items + li #{item}: #{i} +``` + +outputs: + +```html +
  • one: 0
  • +
  • two: 1
  • +
  • three: 2
  • +``` + +iterating an object's keys and values: + +```jade +obj = { foo: 'bar' } +each val, key in obj + li #{key}: #{val} +``` + +would output `
  • foo: bar
  • ` + +Internally Jade converts these statements to regular +JavaScript loops such as `users.forEach(function(user){`, +so lexical scope and nesting applies as it would with regular +JavaScript: + +```jade +each user in users + each role in user.roles + li= role +``` + + You may also use `for` if you prefer: + +```jade +for user in users + for role in user.roles + li= role +``` + +
    +## Conditionals + + Jade conditionals are equivalent to those using the code (`-`) prefix, + however allow you to ditch parenthesis to become more designer friendly, + however keep in mind the expression given is _regular_ JavaScript: + +```jade +for user in users + if user.role == 'admin' + p #{user.name} is an admin + else + p= user.name +``` + + is equivalent to the following using vanilla JavaScript literals: + +```jade +for user in users + - if (user.role == 'admin') + p #{user.name} is an admin + - else + p= user.name +``` + + Jade also provides `unless` which is equivalent to `if (!(expr))`: + +```jade +for user in users + unless user.isAnonymous + p + | Click to view + a(href='/users/' + user.id)= user.name +``` + + +## Template inheritance + + Jade supports template inheritance via the `block` and `extends` keywords. A block is simply a "block" of Jade that may be replaced within a child template, this process is recursive. To activate template inheritance in Express 2.x you must add: `app.set('view options', { layout: false });`. + + Jade blocks can provide default content if desired, however optional as shown below by `block scripts`, `block content`, and `block foot`. + +```jade +html + head + title My Site - #{title} + block scripts + script(src='/jquery.js') + body + block content + block foot + #footer + p some footer content +``` + + Now to extend the layout, simply create a new file and use the `extends` directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the `foot` block is _not_ redefined and will output "some footer content". + +```jade +extends layout + +block scripts + script(src='/jquery.js') + script(src='/pets.js') + +block content + h1= title + each pet in pets + include pet +``` + + It's also possible to override a block to provide additional blocks, as shown in the following example where `content` now exposes a `sidebar` and `primary` block for overriding, or the child template could override `content` all together. + +```jade +extends regular-layout + +block content + .sidebar + block sidebar + p nothing + .primary + block primary + p nothing +``` + + +## Block append / prepend + + Jade allows you to _replace_ (default), _prepend_, or _append_ blocks. Suppose for example you have default scripts in a "head" block that you wish to utilize on _every_ page, you might do this: + +```jade +html + head + block head + script(src='/vendor/jquery.js') + script(src='/vendor/caustic.js') + body + block content +``` + + Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply `append` the block: + +```jade +extends layout + +block append head + script(src='/vendor/three.js') + script(src='/game.js') +``` + + When using `block append` or `block prepend` the `block` is optional: + +```jade +extends layout + +append head + script(src='/vendor/three.js') + script(src='/game.js') +``` + + +## Includes + + Includes allow you to statically include chunks of Jade, + or other content like css, or html which lives in separate files. The classical example is including a header and footer. Suppose we have the following directory structure: + + ./layout.jade + ./includes/ + ./head.jade + ./foot.jade + +and the following _layout.jade_: + +```jade +html + include includes/head + body + h1 My Site + p Welcome to my super amazing site. + include includes/foot +``` + +both includes _includes/head_ and _includes/foot_ are +read relative to the `filename` option given to _layout.jade_, +which should be an absolute path to this file, however Express +does this for you. Include then parses these files, and injects +the AST produced to render what you would expect: + +```html + + + My Site + + + +

    My Site

    +

    Welcome to my super lame site.

    + + + +``` + +As mentioned `include` can be used to include other content +such as html or css. By providing an extension, Jade will +read that file in, apply any [filter](#a7) matching the file's +extension, and insert that content into the output. + +```jade +html + head + //- css and js have simple filters that wrap them in + '; + } else if (transformers[name].outputFormat === 'xml') { + res = res.replace(/'/g, '''); + } + } else { + throw new Error('unknown filter ":' + name + '"'); + } + return res; +} +filter.exists = function (name, str, options) { + return typeof filter[name] === 'function' || transformers[name]; +}; diff --git a/node_modules/jade/lib/index.js b/node_modules/jade/lib/index.js new file mode 100644 index 0000000..6a783c2 --- /dev/null +++ b/node_modules/jade/lib/index.js @@ -0,0 +1 @@ +jade.js \ No newline at end of file diff --git a/node_modules/jade/lib/inline-tags.js b/node_modules/jade/lib/inline-tags.js new file mode 100644 index 0000000..e7f28e7 --- /dev/null +++ b/node_modules/jade/lib/inline-tags.js @@ -0,0 +1,28 @@ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; \ No newline at end of file diff --git a/node_modules/jade/lib/jade.js b/node_modules/jade/lib/jade.js new file mode 100644 index 0000000..5ad9edc --- /dev/null +++ b/node_modules/jade/lib/jade.js @@ -0,0 +1,238 @@ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Parser = require('./parser') + , Lexer = require('./lexer') + , Compiler = require('./compiler') + , runtime = require('./runtime') + , addWith = require('with') + , fs = require('fs'); + +/** + * Expose self closing tags. + */ + +exports.selfClosing = require('./self-closing'); + +/** + * Default supported doctypes. + */ + +exports.doctypes = require('./doctypes'); + +/** + * Text filters. + */ + +exports.filters = require('./filters'); + +/** + * Utilities. + */ + +exports.utils = require('./utils'); + +/** + * Expose `Compiler`. + */ + +exports.Compiler = Compiler; + +/** + * Expose `Parser`. + */ + +exports.Parser = Parser; + +/** + * Expose `Lexer`. + */ + +exports.Lexer = Lexer; + +/** + * Nodes. + */ + +exports.nodes = require('./nodes'); + +/** + * Jade runtime helpers. + */ + +exports.runtime = runtime; + +/** + * Template function cache. + */ + +exports.cache = {}; + +/** + * Parse the given `str` of jade and return a function body. + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api private + */ + +function parse(str, options){ + try { + // Parse + var parser = new (options.parser || Parser)(str, options.filename, options); + + // Compile + var compiler = new (options.compiler || Compiler)(parser.parse(), options) + , js = compiler.compile(); + + // Debug compiler + if (options.debug) { + console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' ')); + } + + return '' + + 'var buf = [];\n' + + (options.self + ? 'var self = locals || {};\n' + js + : addWith('locals || {}', js, ['jade', 'buf'])) + ';' + + 'return buf.join("");'; + } catch (err) { + parser = parser.context(); + runtime.rethrow(err, parser.filename, parser.lexer.lineno, str); + } +} + +/** + * Strip any UTF-8 BOM off of the start of `str`, if it exists. + * + * @param {String} str + * @return {String} + * @api private + */ + +function stripBOM(str){ + return 0xFEFF == str.charCodeAt(0) + ? str.substring(1) + : str; +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled + template, when it is explicitly `true`, the source code is included in + the compiled template for better accuracy. + * - `filename` used to improve errors when `compileDebug` is not `false` + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + str = stripBOM(String(str)); + + if (options.compileDebug !== false) { + fn = [ + 'jade.debug = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(str, options) + , '} catch (err) {' + , ' jade.rethrow(err, jade.debug[0].filename, jade.debug[0].lineno' + (options.compileDebug === true ? ',' + JSON.stringify(str) : '') + ');' + , '}' + ].join('\n'); + } else { + fn = parse(str, options); + } + + if (options.client) return new Function('locals', fn) + fn = new Function('locals, jade', fn) + return function(locals){ return fn(locals, Object.create(runtime)) } +}; + +/** + * Render the given `str` of jade and invoke + * the callback `fn(err, str)`. + * + * Options: + * + * - `cache` enable template caching + * - `filename` filename required for `include` / `extends` and caching + * + * @param {String} str + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +exports.render = function(str, options, fn){ + // swap args + if ('function' == typeof options) { + fn = options, options = {}; + } + + // cache requires .filename + if (options.cache && !options.filename) { + return fn(new Error('the "filename" option is required for caching')); + } + + try { + var path = options.filename; + var tmpl = options.cache + ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options)) + : exports.compile(str, options); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Render a Jade file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + try { + options.filename = path; + var str = options.cache + ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8')) + : fs.readFileSync(path, 'utf8'); + exports.render(str, options, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Express support. + */ + +exports.__express = exports.renderFile; diff --git a/node_modules/jade/lib/lexer.js b/node_modules/jade/lib/lexer.js new file mode 100644 index 0000000..c4f649f --- /dev/null +++ b/node_modules/jade/lib/lexer.js @@ -0,0 +1,782 @@ +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +var utils = require('./utils'); +var parseJSExpression = require('character-parser').parseMax; + +/** + * Initialize `Lexer` with the given `str`. + * + * Options: + * + * - `colons` allow colons for attr delimiters + * + * @param {String} str + * @param {Object} options + * @api private + */ + +var Lexer = module.exports = function Lexer(str, options) { + options = options || {}; + this.input = str.replace(/\r\n|\r/g, '\n'); + this.colons = options.colons; + this.deferredTokens = []; + this.lastIndents = 0; + this.lineno = 1; + this.stash = []; + this.indentStack = []; + this.indentRe = null; + this.pipeless = false; +}; + +/** + * Lexer prototype. + */ + +Lexer.prototype = { + + /** + * Construct a token with the given `type` and `val`. + * + * @param {String} type + * @param {String} val + * @return {Object} + * @api private + */ + + tok: function(type, val){ + return { + type: type + , line: this.lineno + , val: val + } + }, + + /** + * Consume the given `len` of input. + * + * @param {Number} len + * @api private + */ + + consume: function(len){ + this.input = this.input.substr(len); + }, + + /** + * Scan for `type` with the given `regexp`. + * + * @param {String} type + * @param {RegExp} regexp + * @return {Object} + * @api private + */ + + scan: function(regexp, type){ + var captures; + if (captures = regexp.exec(this.input)) { + this.consume(captures[0].length); + return this.tok(type, captures[1]); + } + }, + + /** + * Defer the given `tok`. + * + * @param {Object} tok + * @api private + */ + + defer: function(tok){ + this.deferredTokens.push(tok); + }, + + /** + * Lookahead `n` tokens. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + var fetch = n - this.stash.length; + while (fetch-- > 0) this.stash.push(this.next()); + return this.stash[--n]; + }, + + /** + * Return the indexOf `(` or `{` or `[` / `)` or `}` or `]` delimiters. + * + * @return {Number} + * @api private + */ + + bracketExpression: function(skip){ + skip = skip || 0; + var start = this.input[skip]; + if (start != '(' && start != '{' && start != '[') throw new Error('unrecognized start character'); + var end = ({'(': ')', '{': '}', '[': ']'})[start]; + var range = parseJSExpression(this.input, {start: skip + 1}); + if (this.input[range.end] !== end) throw new Error('start character ' + start + ' does not match end character ' + this.input[range.end]); + return range; + }, + + /** + * Stashed token. + */ + + stashed: function() { + return this.stash.length + && this.stash.shift(); + }, + + /** + * Deferred token. + */ + + deferred: function() { + return this.deferredTokens.length + && this.deferredTokens.shift(); + }, + + /** + * end-of-source. + */ + + eos: function() { + if (this.input.length) return; + if (this.indentStack.length) { + this.indentStack.shift(); + return this.tok('outdent'); + } else { + return this.tok('eos'); + } + }, + + /** + * Blank line. + */ + + blank: function() { + var captures; + if (captures = /^\n *\n/.exec(this.input)) { + this.consume(captures[0].length - 1); + ++this.lineno; + if (this.pipeless) return this.tok('text', ''); + return this.next(); + } + }, + + /** + * Comment. + */ + + comment: function() { + var captures; + if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('comment', captures[2]); + tok.buffer = '-' != captures[1]; + return tok; + } + }, + + /** + * Interpolated tag. + */ + + interpolation: function() { + if (/^#\{/.test(this.input)) { + var match; + try { + match = this.bracketExpression(1); + } catch (ex) { + return;//not an interpolation expression, just an unmatched open interpolation + } + + this.consume(match.end + 1); + return this.tok('interpolation', match.src); + } + }, + + /** + * Tag. + */ + + tag: function() { + var captures; + if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) { + this.consume(captures[0].length); + var tok, name = captures[1]; + if (':' == name[name.length - 1]) { + name = name.slice(0, -1); + tok = this.tok('tag', name); + this.defer(this.tok(':')); + while (' ' == this.input[0]) this.input = this.input.substr(1); + } else { + tok = this.tok('tag', name); + } + tok.selfClosing = !! captures[2]; + return tok; + } + }, + + /** + * Filter. + */ + + filter: function() { + return this.scan(/^:(\w+)/, 'filter'); + }, + + /** + * Doctype. + */ + + doctype: function() { + return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype'); + }, + + /** + * Id. + */ + + id: function() { + return this.scan(/^#([\w-]+)/, 'id'); + }, + + /** + * Class. + */ + + className: function() { + return this.scan(/^\.([\w-]+)/, 'class'); + }, + + /** + * Text. + */ + + text: function() { + return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text'); + }, + + /** + * Extends. + */ + + "extends": function() { + return this.scan(/^extends? +([^\n]+)/, 'extends'); + }, + + /** + * Block prepend. + */ + + prepend: function() { + var captures; + if (captures = /^prepend +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'prepend' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block append. + */ + + append: function() { + var captures; + if (captures = /^append +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'append' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block. + */ + + block: function() { + var captures; + if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = captures[1] || 'replace' + , name = captures[2] + , tok = this.tok('block', name); + + tok.mode = mode; + return tok; + } + }, + + /** + * Yield. + */ + + yield: function() { + return this.scan(/^yield */, 'yield'); + }, + + /** + * Include. + */ + + include: function() { + return this.scan(/^include +([^\n]+)/, 'include'); + }, + + /** + * Case. + */ + + "case": function() { + return this.scan(/^case +([^\n]+)/, 'case'); + }, + + /** + * When. + */ + + when: function() { + return this.scan(/^when +([^:\n]+)/, 'when'); + }, + + /** + * Default. + */ + + "default": function() { + return this.scan(/^default */, 'default'); + }, + + /** + * Assignment. + */ + + assignment: function() { + var captures; + if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) { + this.consume(captures[0].length); + var name = captures[1] + , val = captures[2]; + return this.tok('code', 'var ' + name + ' = (' + val + ');'); + } + }, + + /** + * Call mixin. + */ + + call: function(){ + var captures; + if (captures = /^\+([-\w]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('call', captures[1]); + + // Check for args (not attributes) + if (captures = /^ *\(/.exec(this.input)) { + try { + var range = this.bracketExpression(captures[0].length - 1); + if (!/^ *[-\w]+ *=/.test(range.src)) { // not attributes + this.consume(range.end + 1); + tok.args = range.src; + } + } catch (ex) { + //not a bracket expcetion, just unmatched open parens + } + } + + return tok; + } + }, + + /** + * Mixin. + */ + + mixin: function(){ + var captures; + if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('mixin', captures[1]); + tok.args = captures[2]; + return tok; + } + }, + + /** + * Conditional. + */ + + conditional: function() { + var captures; + if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var type = captures[1] + , js = captures[2]; + + switch (type) { + case 'if': js = 'if (' + js + ')'; break; + case 'unless': js = 'if (!(' + js + '))'; break; + case 'else if': js = 'else if (' + js + ')'; break; + case 'else': js = 'else'; break; + } + + return this.tok('code', js); + } + }, + + /** + * While. + */ + + "while": function() { + var captures; + if (captures = /^while +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('code', 'while (' + captures[1] + ')'); + } + }, + + /** + * Each. + */ + + each: function() { + var captures; + if (captures = /^(?:- *)?(?:each|for) +([a-zA-Z_$][\w$]*)(?: *, *([a-zA-Z_$][\w$]*))? * in *([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('each', captures[1]); + tok.key = captures[2] || '$index'; + tok.code = captures[3]; + return tok; + } + }, + + /** + * Code. + */ + + code: function() { + var captures; + if (captures = /^(!?=|-)[ \t]*([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var flags = captures[1]; + captures[1] = captures[2]; + var tok = this.tok('code', captures[1]); + tok.escape = flags.charAt(0) === '='; + tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.bracketExpression().end + , str = this.input.substr(1, index-1) + , tok = this.tok('attrs') + , len = str.length + , colons = this.colons + , states = ['key'] + , escapedAttr + , key = '' + , val = '' + , quote + , c + , p; + + function state(){ + return states[states.length - 1]; + } + + function interpolate(attr) { + return attr.replace(/(\\)?#\{(.+)/g, function(_, escape, expr){ + if (escape) return _; + try { + var range = parseJSExpression(expr); + if (expr[range.end] !== '}') return _.substr(0, 2) + interpolate(_.substr(2)); + return quote + " + (" + range.src + ") + " + quote + interpolate(expr.substr(range.end + 1)); + } catch (ex) { + return _.substr(0, 2) + interpolate(_.substr(2)); + } + }); + } + + this.consume(index + 1); + tok.attrs = {}; + tok.escaped = {}; + + function parse(c) { + var real = c; + // TODO: remove when people fix ":" + if (colons && ':' == c) c = '='; + switch (c) { + case ',': + case '\n': + switch (state()) { + case 'expr': + case 'array': + case 'string': + case 'object': + val += c; + break; + default: + states.push('key'); + val = val.trim(); + key = key.trim(); + if ('' == key) return; + key = key.replace(/^['"]|['"]$/g, '').replace('!', ''); + tok.escaped[key] = escapedAttr; + tok.attrs[key] = '' == val + ? true + : interpolate(val); + key = val = ''; + } + break; + case '=': + switch (state()) { + case 'key char': + key += real; + break; + case 'val': + case 'expr': + case 'array': + case 'string': + case 'object': + val += real; + break; + default: + escapedAttr = '!' != p; + states.push('val'); + } + break; + case '(': + if ('val' == state() + || 'expr' == state()) states.push('expr'); + val += c; + break; + case ')': + if ('expr' == state() + || 'val' == state()) states.pop(); + val += c; + break; + case '{': + if ('val' == state()) states.push('object'); + val += c; + break; + case '}': + if ('object' == state()) states.pop(); + val += c; + break; + case '[': + if ('val' == state()) states.push('array'); + val += c; + break; + case ']': + if ('array' == state()) states.pop(); + val += c; + break; + case '"': + case "'": + switch (state()) { + case 'key': + states.push('key char'); + break; + case 'key char': + states.pop(); + break; + case 'string': + if (c == quote) states.pop(); + val += c; + break; + default: + states.push('string'); + val += c; + quote = c; + } + break; + case '': + break; + default: + switch (state()) { + case 'key': + case 'key char': + key += c; + break; + default: + val += c; + } + } + p = c; + } + + for (var i = 0; i < len; ++i) { + parse(str.charAt(i)); + } + + parse(','); + + if ('/' == this.input.charAt(0)) { + this.consume(1); + tok.selfClosing = true; + } + + return tok; + } + }, + + /** + * Indent | Outdent | Newline. + */ + + indent: function() { + var captures, re; + + // established regexp + if (this.indentRe) { + captures = this.indentRe.exec(this.input); + // determine regexp + } else { + // tabs + re = /^\n(\t*) */; + captures = re.exec(this.input); + + // spaces + if (captures && !captures[1].length) { + re = /^\n( *)/; + captures = re.exec(this.input); + } + + // established + if (captures && captures[1].length) this.indentRe = re; + } + + if (captures) { + var tok + , indents = captures[1].length; + + ++this.lineno; + this.consume(indents + 1); + + if (' ' == this.input[0] || '\t' == this.input[0]) { + throw new Error('Invalid indentation, you can use tabs or spaces but not both'); + } + + // blank line + if ('\n' == this.input[0]) return this.tok('newline'); + + // outdent + if (this.indentStack.length && indents < this.indentStack[0]) { + while (this.indentStack.length && this.indentStack[0] > indents) { + this.stash.push(this.tok('outdent')); + this.indentStack.shift(); + } + tok = this.stash.pop(); + // indent + } else if (indents && indents != this.indentStack[0]) { + this.indentStack.unshift(indents); + tok = this.tok('indent', indents); + // newline + } else { + tok = this.tok('newline'); + } + + return tok; + } + }, + + /** + * Pipe-less text consumed only when + * pipeless is true; + */ + + pipelessText: function() { + if (this.pipeless) { + if ('\n' == this.input[0]) return; + var i = this.input.indexOf('\n'); + if (-1 == i) i = this.input.length; + var str = this.input.substr(0, i); + this.consume(str.length); + return this.tok('text', str); + } + }, + + /** + * ':' + */ + + colon: function() { + return this.scan(/^: */, ':'); + }, + + /** + * Return the next token object, or those + * previously stashed by lookahead. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.stashed() + || this.next(); + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + next: function() { + return this.deferred() + || this.blank() + || this.eos() + || this.pipelessText() + || this.yield() + || this.doctype() + || this.interpolation() + || this["case"]() + || this.when() + || this["default"]() + || this["extends"]() + || this.append() + || this.prepend() + || this.block() + || this.include() + || this.mixin() + || this.call() + || this.conditional() + || this.each() + || this["while"]() + || this.assignment() + || this.tag() + || this.filter() + || this.code() + || this.id() + || this.className() + || this.attrs() + || this.indent() + || this.comment() + || this.colon() + || this.text(); + } +}; diff --git a/node_modules/jade/lib/nodes/attrs.js b/node_modules/jade/lib/nodes/attrs.js new file mode 100644 index 0000000..ee6f6ce --- /dev/null +++ b/node_modules/jade/lib/nodes/attrs.js @@ -0,0 +1,77 @@ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'), + Block = require('./block'); + +/** + * Initialize a `Attrs` node. + * + * @api public + */ + +var Attrs = module.exports = function Attrs() { + this.attrs = []; +}; + +/** + * Inherit from `Node`. + */ + +Attrs.prototype.__proto__ = Node.prototype; + +/** + * Set attribute `name` to `val`, keep in mind these become + * part of a raw js object literal, so to quote a value you must + * '"quote me"', otherwise or example 'user.name' is literal JavaScript. + * + * @param {String} name + * @param {String} val + * @param {Boolean} escaped + * @return {Tag} for chaining + * @api public + */ + +Attrs.prototype.setAttribute = function(name, val, escaped){ + this.attrs.push({ name: name, val: val, escaped: escaped }); + return this; +}; + +/** + * Remove attribute `name` when present. + * + * @param {String} name + * @api public + */ + +Attrs.prototype.removeAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + delete this.attrs[i]; + } + } +}; + +/** + * Get attribute value by `name`. + * + * @param {String} name + * @return {String} + * @api public + */ + +Attrs.prototype.getAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + return this.attrs[i].val; + } + } +}; diff --git a/node_modules/jade/lib/nodes/block-comment.js b/node_modules/jade/lib/nodes/block-comment.js new file mode 100644 index 0000000..4eb48cc --- /dev/null +++ b/node_modules/jade/lib/nodes/block-comment.js @@ -0,0 +1,33 @@ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `BlockComment` with the given `block`. + * + * @param {String} val + * @param {Block} block + * @param {Boolean} buffer + * @api public + */ + +var BlockComment = module.exports = function BlockComment(val, block, buffer) { + this.block = block; + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +BlockComment.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/block.js b/node_modules/jade/lib/nodes/block.js new file mode 100644 index 0000000..9ddaf18 --- /dev/null +++ b/node_modules/jade/lib/nodes/block.js @@ -0,0 +1,122 @@ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Block` with an optional `node`. + * + * @param {Node} node + * @api public + */ + +var Block = module.exports = function Block(node){ + this.nodes = []; + if (node) this.push(node); +}; + +/** + * Inherit from `Node`. + */ + +Block.prototype.__proto__ = Node.prototype; + +/** + * Block flag. + */ + +Block.prototype.isBlock = true; + +/** + * Replace the nodes in `other` with the nodes + * in `this` block. + * + * @param {Block} other + * @api private + */ + +Block.prototype.replace = function(other){ + other.nodes = this.nodes; +}; + +/** + * Pust the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.push = function(node){ + return this.nodes.push(node); +}; + +/** + * Check if this block is empty. + * + * @return {Boolean} + * @api public + */ + +Block.prototype.isEmpty = function(){ + return 0 == this.nodes.length; +}; + +/** + * Unshift the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.unshift = function(node){ + return this.nodes.unshift(node); +}; + +/** + * Return the "last" block, or the first `yield` node. + * + * @return {Block} + * @api private + */ + +Block.prototype.includeBlock = function(){ + var ret = this + , node; + + for (var i = 0, len = this.nodes.length; i < len; ++i) { + node = this.nodes[i]; + if (node.yield) return node; + else if (node.textOnly) continue; + else if (node.includeBlock) ret = node.includeBlock(); + else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock(); + if (ret.yield) return ret; + } + + return ret; +}; + +/** + * Return a clone of this block. + * + * @return {Block} + * @api private + */ + +Block.prototype.clone = function(){ + var clone = new Block; + for (var i = 0, len = this.nodes.length; i < len; ++i) { + clone.push(this.nodes[i].clone()); + } + return clone; +}; + diff --git a/node_modules/jade/lib/nodes/case.js b/node_modules/jade/lib/nodes/case.js new file mode 100644 index 0000000..173ed32 --- /dev/null +++ b/node_modules/jade/lib/nodes/case.js @@ -0,0 +1,43 @@ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Case` with `expr`. + * + * @param {String} expr + * @api public + */ + +var Case = exports = module.exports = function Case(expr, block){ + this.expr = expr; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Case.prototype.__proto__ = Node.prototype; + +var When = exports.When = function When(expr, block){ + this.expr = expr; + this.block = block; + this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +When.prototype.__proto__ = Node.prototype; + diff --git a/node_modules/jade/lib/nodes/code.js b/node_modules/jade/lib/nodes/code.js new file mode 100644 index 0000000..eaf8cc7 --- /dev/null +++ b/node_modules/jade/lib/nodes/code.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Code` node with the given code `val`. + * Code may also be optionally buffered and escaped. + * + * @param {String} val + * @param {Boolean} buffer + * @param {Boolean} escape + * @api public + */ + +var Code = module.exports = function Code(val, buffer, escape) { + this.val = val; + this.buffer = buffer; + this.escape = escape; + if (val.match(/^ *else/)) this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +Code.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/comment.js b/node_modules/jade/lib/nodes/comment.js new file mode 100644 index 0000000..e6721fa --- /dev/null +++ b/node_modules/jade/lib/nodes/comment.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Comment` with the given `val`, optionally `buffer`, + * otherwise the comment may render in the output. + * + * @param {String} val + * @param {Boolean} buffer + * @api public + */ + +var Comment = module.exports = function Comment(val, buffer) { + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +Comment.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/doctype.js b/node_modules/jade/lib/nodes/doctype.js new file mode 100644 index 0000000..c8b921b --- /dev/null +++ b/node_modules/jade/lib/nodes/doctype.js @@ -0,0 +1,29 @@ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Doctype` with the given `val`. + * + * @param {String} val + * @api public + */ + +var Doctype = module.exports = function Doctype(val) { + this.val = val; +}; + +/** + * Inherit from `Node`. + */ + +Doctype.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/each.js b/node_modules/jade/lib/nodes/each.js new file mode 100644 index 0000000..3d714f5 --- /dev/null +++ b/node_modules/jade/lib/nodes/each.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize an `Each` node, representing iteration + * + * @param {String} obj + * @param {String} val + * @param {String} key + * @param {Block} block + * @api public + */ + +var Each = module.exports = function Each(obj, val, key, block) { + this.obj = obj; + this.val = val; + this.key = key; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Each.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/filter.js b/node_modules/jade/lib/nodes/filter.js new file mode 100644 index 0000000..6a33f15 --- /dev/null +++ b/node_modules/jade/lib/nodes/filter.js @@ -0,0 +1,34 @@ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node') + , Block = require('./block'); + +/** + * Initialize a `Filter` node with the given + * filter `name` and `block`. + * + * @param {String} name + * @param {Block|Node} block + * @api public + */ + +var Filter = module.exports = function Filter(name, block, attrs) { + this.name = name; + this.block = block; + this.attrs = attrs; +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/index.js b/node_modules/jade/lib/nodes/index.js new file mode 100644 index 0000000..c7782a9 --- /dev/null +++ b/node_modules/jade/lib/nodes/index.js @@ -0,0 +1,20 @@ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +exports.Node = require('./node'); +exports.Tag = require('./tag'); +exports.Code = require('./code'); +exports.Each = require('./each'); +exports.Case = require('./case'); +exports.Text = require('./text'); +exports.Block = require('./block'); +exports.Mixin = require('./mixin'); +exports.Filter = require('./filter'); +exports.Comment = require('./comment'); +exports.Literal = require('./literal'); +exports.BlockComment = require('./block-comment'); +exports.Doctype = require('./doctype'); diff --git a/node_modules/jade/lib/nodes/literal.js b/node_modules/jade/lib/nodes/literal.js new file mode 100644 index 0000000..adc9b89 --- /dev/null +++ b/node_modules/jade/lib/nodes/literal.js @@ -0,0 +1,29 @@ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Literal` node with the given `str. + * + * @param {String} str + * @api public + */ + +var Literal = module.exports = function Literal(str) { + this.str = str; +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype.__proto__ = Node.prototype; diff --git a/node_modules/jade/lib/nodes/mixin.js b/node_modules/jade/lib/nodes/mixin.js new file mode 100644 index 0000000..226c71d --- /dev/null +++ b/node_modules/jade/lib/nodes/mixin.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'); + +/** + * Initialize a new `Mixin` with `name` and `block`. + * + * @param {String} name + * @param {String} args + * @param {Block} block + * @api public + */ + +var Mixin = module.exports = function Mixin(name, args, block, call){ + this.name = name; + this.args = args; + this.block = block; + this.attrs = []; + this.call = call; +}; + +/** + * Inherit from `Attrs`. + */ + +Mixin.prototype.__proto__ = Attrs.prototype; + diff --git a/node_modules/jade/lib/nodes/node.js b/node_modules/jade/lib/nodes/node.js new file mode 100644 index 0000000..aead311 --- /dev/null +++ b/node_modules/jade/lib/nodes/node.js @@ -0,0 +1,25 @@ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize a `Node`. + * + * @api public + */ + +var Node = module.exports = function Node(){}; + +/** + * Clone this node (return itself) + * + * @return {Node} + * @api private + */ + +Node.prototype.clone = function(){ + return this; +}; diff --git a/node_modules/jade/lib/nodes/tag.js b/node_modules/jade/lib/nodes/tag.js new file mode 100644 index 0000000..951628b --- /dev/null +++ b/node_modules/jade/lib/nodes/tag.js @@ -0,0 +1,95 @@ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'), + Block = require('./block'), + inlineTags = require('../inline-tags'); + +/** + * Initialize a `Tag` node with the given tag `name` and optional `block`. + * + * @param {String} name + * @param {Block} block + * @api public + */ + +var Tag = module.exports = function Tag(name, block) { + this.name = name; + this.attrs = []; + this.block = block || new Block; +}; + +/** + * Inherit from `Attrs`. + */ + +Tag.prototype.__proto__ = Attrs.prototype; + +/** + * Clone this tag. + * + * @return {Tag} + * @api private + */ + +Tag.prototype.clone = function(){ + var clone = new Tag(this.name, this.block.clone()); + clone.line = this.line; + clone.attrs = this.attrs; + clone.textOnly = this.textOnly; + return clone; +}; + +/** + * Check if this tag is an inline tag. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.isInline = function(){ + return ~inlineTags.indexOf(this.name); +}; + +/** + * Check if this tag's contents can be inlined. Used for pretty printing. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.canInline = function(){ + var nodes = this.block.nodes; + + function isInline(node){ + // Recurse if the node is a block + if (node.isBlock) return node.nodes.every(isInline); + return node.isText || (node.isInline && node.isInline()); + } + + // Empty tag + if (!nodes.length) return true; + + // Text-only or inline-only tag + if (1 == nodes.length) return isInline(nodes[0]); + + // Multi-line inline-only tag + if (this.block.nodes.every(isInline)) { + for (var i = 1, len = nodes.length; i < len; ++i) { + if (nodes[i-1].isText && nodes[i].isText) + return false; + } + return true; + } + + // Mixed tag + return false; +}; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/text.js b/node_modules/jade/lib/nodes/text.js new file mode 100644 index 0000000..6ff73ff --- /dev/null +++ b/node_modules/jade/lib/nodes/text.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Text` node with optional `line`. + * + * @param {String} line + * @api public + */ + +var Text = module.exports = function Text(line) { + this.val = ''; + if ('string' == typeof line) this.val = line; +}; + +/** + * Inherit from `Node`. + */ + +Text.prototype.__proto__ = Node.prototype; + +/** + * Flag as text. + */ + +Text.prototype.isText = true; \ No newline at end of file diff --git a/node_modules/jade/lib/parser.js b/node_modules/jade/lib/parser.js new file mode 100644 index 0000000..5c18245 --- /dev/null +++ b/node_modules/jade/lib/parser.js @@ -0,0 +1,732 @@ +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes') + , utils = require('./utils') + , filters = require('./filters') + , path = require('path') + , extname = path.extname; + +/** + * Initialize `Parser` with the given input `str` and `filename`. + * + * @param {String} str + * @param {String} filename + * @param {Object} options + * @api public + */ + +var Parser = exports = module.exports = function Parser(str, filename, options){ + this.input = str; + this.lexer = new Lexer(str, options); + this.filename = filename; + this.blocks = {}; + this.mixins = {}; + this.options = options; + this.contexts = [this]; +}; + +/** + * Tags that may not contain tags. + */ + +var textOnly = exports.textOnly = ['script', 'style']; + +/** + * Parser prototype. + */ + +Parser.prototype = { + + /** + * Push `parser` onto the context stack, + * or pop and return a `Parser`. + */ + + context: function(parser){ + if (parser) { + this.contexts.push(parser); + } else { + return this.contexts.pop(); + } + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.lexer.advance(); + }, + + /** + * Skip `n` tokens. + * + * @param {Number} n + * @api private + */ + + skip: function(n){ + while (n--) this.advance(); + }, + + /** + * Single token lookahead. + * + * @return {Object} + * @api private + */ + + peek: function() { + return this.lookahead(1); + }, + + /** + * Return lexer lineno. + * + * @return {Number} + * @api private + */ + + line: function() { + return this.lexer.lineno; + }, + + /** + * `n` token lookahead. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + return this.lexer.lookahead(n); + }, + + /** + * Parse input returning a string of js for evaluation. + * + * @return {String} + * @api public + */ + + parse: function(){ + var block = new nodes.Block, parser; + block.line = this.line(); + + while ('eos' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + + if (parser = this.extending) { + this.context(parser); + var ast = parser.parse(); + this.context(); + + // hoist mixins + for (var name in this.mixins) + ast.unshift(this.mixins[name]); + return ast; + } + + return block; + }, + + /** + * Expect the given type, or throw an exception. + * + * @param {String} type + * @api private + */ + + expect: function(type){ + if (this.peek().type === type) { + return this.advance(); + } else { + throw new Error('expected "' + type + '", but got "' + this.peek().type + '"'); + } + }, + + /** + * Accept the given `type`. + * + * @param {String} type + * @api private + */ + + accept: function(type){ + if (this.peek().type === type) { + return this.advance(); + } + }, + + /** + * tag + * | doctype + * | mixin + * | include + * | filter + * | comment + * | text + * | each + * | code + * | yield + * | id + * | class + * | interpolation + */ + + parseExpr: function(){ + switch (this.peek().type) { + case 'tag': + return this.parseTag(); + case 'mixin': + return this.parseMixin(); + case 'block': + return this.parseBlock(); + case 'case': + return this.parseCase(); + case 'when': + return this.parseWhen(); + case 'default': + return this.parseDefault(); + case 'extends': + return this.parseExtends(); + case 'include': + return this.parseInclude(); + case 'doctype': + return this.parseDoctype(); + case 'filter': + return this.parseFilter(); + case 'comment': + return this.parseComment(); + case 'text': + return this.parseText(); + case 'each': + return this.parseEach(); + case 'code': + return this.parseCode(); + case 'call': + return this.parseCall(); + case 'interpolation': + return this.parseInterpolation(); + case 'yield': + this.advance(); + var block = new nodes.Block; + block.yield = true; + return block; + case 'id': + case 'class': + var tok = this.advance(); + this.lexer.defer(this.lexer.tok('tag', 'div')); + this.lexer.defer(tok); + return this.parseExpr(); + default: + throw new Error('unexpected token "' + this.peek().type + '"'); + } + }, + + /** + * Text + */ + + parseText: function(){ + var tok = this.expect('text'); + var node = new nodes.Text(tok.val); + node.line = this.line(); + return node; + }, + + /** + * ':' expr + * | block + */ + + parseBlockExpansion: function(){ + if (':' == this.peek().type) { + this.advance(); + return new nodes.Block(this.parseExpr()); + } else { + return this.block(); + } + }, + + /** + * case + */ + + parseCase: function(){ + var val = this.expect('case').val; + var node = new nodes.Case(val); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * when + */ + + parseWhen: function(){ + var val = this.expect('when').val + return new nodes.Case.When(val, this.parseBlockExpansion()); + }, + + /** + * default + */ + + parseDefault: function(){ + this.expect('default'); + return new nodes.Case.When('default', this.parseBlockExpansion()); + }, + + /** + * code + */ + + parseCode: function(){ + var tok = this.expect('code'); + var node = new nodes.Code(tok.val, tok.buffer, tok.escape); + var block; + var i = 1; + node.line = this.line(); + while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; + block = 'indent' == this.lookahead(i).type; + if (block) { + this.skip(i-1); + node.block = this.block(); + } + return node; + }, + + /** + * comment + */ + + parseComment: function(){ + var tok = this.expect('comment'); + var node; + + if ('indent' == this.peek().type) { + node = new nodes.BlockComment(tok.val, this.block(), tok.buffer); + } else { + node = new nodes.Comment(tok.val, tok.buffer); + } + + node.line = this.line(); + return node; + }, + + /** + * doctype + */ + + parseDoctype: function(){ + var tok = this.expect('doctype'); + var node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var tok = this.expect('filter'); + var attrs = this.accept('attrs'); + var block; + + this.lexer.pipeless = true; + block = this.parseTextBlock(); + this.lexer.pipeless = false; + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * each block + */ + + parseEach: function(){ + var tok = this.expect('each'); + var node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + if (this.peek().type == 'code' && this.peek().val == 'else') { + this.advance(); + node.alternative = this.block(); + } + return node; + }, + + /** + * Resolves a path relative to the template for use in + * includes and extends + * + * @param {String} path + * @param {String} purpose Used in error messages. + * @return {String} + * @api private + */ + + resolvePath: function (path, purpose) { + var p = require('path'); + var dirname = p.dirname; + var basename = p.basename; + var join = p.join; + + if (path[0] !== '/' && !this.filename) + throw new Error('the "filename" option is required to use "' + purpose + '" with "relative" paths'); + + if (path[0] === '/' && !this.options.basedir) + throw new Error('the "basedir" option is required to use "' + purpose + '" with "absolute" paths'); + + path = join(path[0] === '/' ? this.options.basedir : dirname(this.filename), path); + + if (basename(path).indexOf('.') === -1) path += '.jade'; + + return path; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var fs = require('fs'); + + var path = this.resolvePath(this.expect('extends').val.trim(), 'extends'); + if ('.jade' != path.substr(-5)) path += '.jade'; + + var str = fs.readFileSync(path, 'utf8'); + var parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block'); + var mode = block.mode; + var name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name] || {prepended: [], appended: []} + if (prev.mode === 'replace') return this.blocks[name] = prev; + + var allNodes = prev.prepended.concat(block.nodes).concat(prev.appended); + + switch (mode) { + case 'append': + prev.appended = prev.parser === this ? + prev.appended.concat(block.nodes) : + block.nodes.concat(prev.appended); + break; + case 'prepend': + prev.prepended = prev.parser === this ? + block.nodes.concat(prev.prepended) : + prev.prepended.concat(block.nodes); + break; + } + block.nodes = allNodes; + block.appended = prev.appended; + block.prepended = prev.prepended; + block.mode = mode; + block.parser = this; + + return this.blocks[name] = block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var fs = require('fs'); + + var path = this.resolvePath(this.expect('include').val.trim(), 'include'); + + // non-jade + if ('.jade' != path.substr(-5)) { + var str = fs.readFileSync(path, 'utf8').replace(/\r/g, ''); + var ext = extname(path).slice(1); + if (filters.exists(ext)) str = filters(ext, str, { filename: path }); + return new nodes.Literal(str); + } + + var str = fs.readFileSync(path, 'utf8'); + var parser = new Parser(str, path, this.options); + parser.blocks = utils.merge({}, this.blocks); + + parser.mixins = this.mixins; + + this.context(parser); + var ast = parser.parse(); + this.context(); + ast.filename = path; + + if ('indent' == this.peek().type) { + ast.includeBlock().push(this.block()); + } + + return ast; + }, + + /** + * call ident block + */ + + parseCall: function(){ + var tok = this.expect('call'); + var name = tok.val; + var args = tok.args; + var mixin = new nodes.Mixin(name, args, new nodes.Block, true); + + this.tag(mixin); + if (mixin.code) { + mixin.block.push(mixin.code); + mixin.code = null; + } + if (mixin.block.isEmpty()) mixin.block = null; + return mixin; + }, + + /** + * mixin block + */ + + parseMixin: function(){ + var tok = this.expect('mixin'); + var name = tok.val; + var args = tok.args; + var mixin; + + // definition + if ('indent' == this.peek().type) { + mixin = new nodes.Mixin(name, args, this.block(), false); + this.mixins[name] = mixin; + return mixin; + // call + } else { + return new nodes.Mixin(name, args, null, true); + } + }, + + /** + * indent (text | newline)* outdent + */ + + parseTextBlock: function(){ + var block = new nodes.Block; + block.line = this.line(); + var spaces = this.expect('indent').val; + if (null == this._spaces) this._spaces = spaces; + var indent = Array(spaces - this._spaces + 1).join(' '); + while ('outdent' != this.peek().type) { + switch (this.peek().type) { + case 'newline': + this.advance(); + break; + case 'indent': + this.parseTextBlock().nodes.forEach(function(node){ + block.push(node); + }); + break; + default: + var text = new nodes.Text(indent + this.advance().val); + text.line = this.line(); + block.push(text); + } + } + + if (spaces == this._spaces) this._spaces = null; + this.expect('outdent'); + return block; + }, + + /** + * indent expr* outdent + */ + + block: function(){ + var block = new nodes.Block; + block.line = this.line(); + this.expect('indent'); + while ('outdent' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + this.expect('outdent'); + return block; + }, + + /** + * interpolation (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseInterpolation: function(){ + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + tag.buffer = true; + return this.tag(tag); + }, + + /** + * tag (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseTag: function(){ + // ast-filter look-ahead + var i = 2; + if ('attrs' == this.lookahead(i).type) ++i; + + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + + tag.selfClosing = tok.selfClosing; + + return this.tag(tag); + }, + + /** + * Parse tag. + */ + + tag: function(tag){ + var dot; + + tag.line = this.line(); + + var seenAttrs = false; + // (attrs | class | id)* + out: + while (true) { + switch (this.peek().type) { + case 'id': + case 'class': + var tok = this.advance(); + tag.setAttribute(tok.type, "'" + tok.val + "'"); + continue; + case 'attrs': + if (seenAttrs) { + console.warn('You should not have jade tags with multiple attributes.'); + } + seenAttrs = true; + var tok = this.advance() + , obj = tok.attrs + , escaped = tok.escaped + , names = Object.keys(obj); + + if (tok.selfClosing) tag.selfClosing = true; + + for (var i = 0, len = names.length; i < len; ++i) { + var name = names[i] + , val = obj[name]; + tag.setAttribute(name, val, escaped[name]); + } + continue; + default: + break out; + } + } + + // check immediate '.' + if ('.' == this.peek().val) { + dot = tag.textOnly = true; + this.advance(); + } + + // (text | code | ':')? + switch (this.peek().type) { + case 'text': + tag.block.push(this.parseText()); + break; + case 'code': + tag.code = this.parseCode(); + break; + case ':': + this.advance(); + tag.block = new nodes.Block; + tag.block.push(this.parseExpr()); + break; + case 'newline': + case 'indent': + case 'outdent': + case 'eos': + break; + default: + throw new Error('Unexpected token `' + this.peek().type + '` expected `text`, `code`, `:`, `newline` or `eos`') + } + + // newline* + while ('newline' == this.peek().type) this.advance(); + + tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name); + + // script special-case + if ('script' == tag.name) { + var type = tag.getAttribute('type'); + if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { + tag.textOnly = false; + } + } + + // block? + if ('indent' == this.peek().type) { + if (tag.textOnly) { + if (!dot) { + console.warn(this.filename + ', line ' + this.peek().line + ':') + console.warn('Implicit textOnly for `script` and `style` is deprecated. Use `script.` or `style.` instead.'); + } + this.lexer.pipeless = true; + tag.block = this.parseTextBlock(); + this.lexer.pipeless = false; + } else { + var block = this.block(); + if (tag.block) { + for (var i = 0, len = block.nodes.length; i < len; ++i) { + tag.block.push(block.nodes[i]); + } + } else { + tag.block = block; + } + } + } + + return tag; + } +}; diff --git a/node_modules/jade/lib/runtime.js b/node_modules/jade/lib/runtime.js new file mode 100644 index 0000000..804f616 --- /dev/null +++ b/node_modules/jade/lib/runtime.js @@ -0,0 +1,199 @@ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + a['class'] = ac.concat(bc).filter(nulls); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {*} val + * @return {Boolean} + * @api private + */ + +function nulls(val) { + return val != null && val !== ''; +} + +/** + * join array as classes. + * + * @param {*} val + * @return {String} + * @api private + */ + +function joinClasses(val) { + return Array.isArray(val) ? val.map(joinClasses).filter(nulls).join(' ') : val; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key) { + if (escaped && escaped[key]){ + if (val = exports.escape(joinClasses(val))) { + buf.push(key + '="' + val + '"'); + } + } else { + if (val = joinClasses(val)) { + buf.push(key + '="' + val + '"'); + } + } + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno, str){ + if (!(err instanceof Error)) throw err; + if ((typeof window != 'undefined' || !filename) && !str) { + err.message += ' on line ' + lineno; + throw err; + } + try { + str = str || require('fs').readFileSync(filename, 'utf8') + } catch (ex) { + rethrow(err, null, lineno) + } + var context = 3 + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; diff --git a/node_modules/jade/lib/self-closing.js b/node_modules/jade/lib/self-closing.js new file mode 100644 index 0000000..2e92288 --- /dev/null +++ b/node_modules/jade/lib/self-closing.js @@ -0,0 +1,19 @@ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; \ No newline at end of file diff --git a/node_modules/jade/lib/utils.js b/node_modules/jade/lib/utils.js new file mode 100644 index 0000000..b7f6bf1 --- /dev/null +++ b/node_modules/jade/lib/utils.js @@ -0,0 +1,21 @@ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Merge `b` into `a`. + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api public + */ + +exports.merge = function(a, b) { + for (var key in b) a[key] = b[key]; + return a; +}; + diff --git a/node_modules/jade/node_modules/character-parser/.npmignore b/node_modules/jade/node_modules/character-parser/.npmignore new file mode 100644 index 0000000..69f75d2 --- /dev/null +++ b/node_modules/jade/node_modules/character-parser/.npmignore @@ -0,0 +1,16 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +npm-debug.log + +node_modules diff --git a/node_modules/jade/node_modules/character-parser/.travis.yml b/node_modules/jade/node_modules/character-parser/.travis.yml new file mode 100644 index 0000000..97e4515 --- /dev/null +++ b/node_modules/jade/node_modules/character-parser/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.10" + - "0.8" \ No newline at end of file diff --git a/node_modules/jade/node_modules/character-parser/README.md b/node_modules/jade/node_modules/character-parser/README.md new file mode 100644 index 0000000..ef10680 --- /dev/null +++ b/node_modules/jade/node_modules/character-parser/README.md @@ -0,0 +1,123 @@ +# character-parser + +Parse JavaScript one character at a time to look for snippets in Templates. This is not a validator, it's just designed to allow you to have sections of JavaScript delimited by brackets robustly. + +[![Build Status](https://travis-ci.org/ForbesLindesay/character-parser.png?branch=master)](https://travis-ci.org/ForbesLindesay/character-parser) + +## Installation + + npm install character-parser + +## Usage + +Work out how much depth changes: + +```js +var state = parse('foo(arg1, arg2, {\n foo: [a, b\n'); +assert(state.roundDepth === 1); +assert(state.curlyDepth === 1); +assert(state.squareDepth === 1); +parse(' c, d]\n })', state); +assert(state.squareDepth === 0); +assert(state.curlyDepth === 0); +assert(state.roundDepth === 0); +``` + +### Bracketed Expressions + +Find all the contents of a bracketed expression: + +```js +var section = parser.parseMax('foo="(", bar="}") bing bong'); +assert(section.start === 0); +assert(section.end === 16);//exclusive end of string +assert(section.src = 'foo="(", bar="}"'); + + +var section = parser.parseMax('{foo="(", bar="}"} bing bong', {start: 1}); +assert(section.start === 1); +assert(section.end === 17);//exclusive end of string +assert(section.src = 'foo="(", bar="}"'); +``` + +The bracketed expression parsing simply parses up to but excluding the first unmatched closed bracket (`)`, `}`, `]`). It is clever enough to ignore brackets in comments or strings. + + +### Custom Delimited Expressions + +Find code up to a custom delimiter: + +```js +var section = parser.parseUntil('foo.bar("%>").baz%> bing bong', '%>'); +assert(section.start === 0); +assert(section.end === 17);//exclusive end of string +assert(section.src = 'foo.bar("%>").baz'); + +var section = parser.parseUntil('<%foo.bar("%>").baz%> bing bong', '%>', {start: 2}); +assert(section.start === 2); +assert(section.end === 19);//exclusive end of string +assert(section.src = 'foo.bar("%>").baz'); +``` + +Delimiters are ignored if they are inside strings or comments. + +## API + +### parse(str, state = defaultState(), options = {start: 0, end: src.length}) + +Parse a string starting at the index start, and return the state after parsing that string. + +If you want to parse one string in multiple sections you should keep passing the resulting state to the next parse operation. + +The resulting object has the structure: + +```js +{ + lineComment: false, //true if inside a line comment + blockComment: false, //true if inside a block comment + + singleQuote: false, //true if inside a single quoted string + doubleQuote: false, //true if inside a double quoted string + escaped: false, //true if in a string and the last character was an escape character + + roundDepth: 0, //number of un-closed open `(` brackets + curlyDepth: 0, //number of un-closed open `{` brackets + squareDepth: 0 //number of un-closed open `[` brackets +} +``` + +### parseMax(src, options = {start: 0}) + +Parses the source until the first unmatched close bracket (any of `)`, `}`, `]`). It returns an object with the structure: + +```js +{ + start: 0,//index of first character of string + end: 13,//index of first character after the end of string + src: 'source string' +} +``` + +### parseUntil(src, delimiter, options = {start: 0, includeLineComment: false}) + +Parses the source until the first occurence of `delimiter` which is not in a string or a comment. If `includeLineComment` is `true`, it will still count if the delimiter occurs in a line comment, but not in a block comment. It returns an object with the structure: + +```js +{ + start: 0,//index of first character of string + end: 13,//index of first character after the end of string + src: 'source string' +} +``` + +### parseChar(character, state = defaultState()) + +Parses the single character and returns the state. See `parse` for the structure of the returned state object. N.B. character must be a single character not a multi character string. + +### defaultState() + +Get a default starting state. See `parse` for the structure of the returned state object. + +## License + +MIT \ No newline at end of file diff --git a/node_modules/jade/node_modules/character-parser/index.js b/node_modules/jade/node_modules/character-parser/index.js new file mode 100644 index 0000000..e8b9f7b --- /dev/null +++ b/node_modules/jade/node_modules/character-parser/index.js @@ -0,0 +1,205 @@ +exports = (module.exports = parse); +exports.parse = parse; +function parse(src, state, options) { + options = options || {}; + state = state || exports.defaultState(); + var start = options.start || 0; + var end = options.end || src.length; + var index = start; + while (index < end) { + if (state.roundDepth < 0 || state.curlyDepth < 0 || state.squareDepth < 0) { + throw new SyntaxError('Mismatched Bracket: ' + src[index - 1]); + } + exports.parseChar(src[index++], state); + } + return state; +} + +exports.parseMax = parseMax; +function parseMax(src, options) { + options = options || {}; + var start = options.start || 0; + var index = start; + var state = exports.defaultState(); + while (state.roundDepth >= 0 && state.curlyDepth >= 0 && state.squareDepth >= 0) { + if (index >= src.length) { + throw new Error('The end of the string was reached with no closing bracket found.'); + } + exports.parseChar(src[index++], state); + } + var end = index - 1; + return { + start: start, + end: end, + src: src.substring(start, end) + }; +} + +exports.parseUntil = parseUntil; +function parseUntil(src, delimiter, options) { + options = options || {}; + var includeLineComment = options.includeLineComment || false; + var start = options.start || 0; + var index = start; + var state = exports.defaultState(); + while (state.singleQuote || state.doubleQuote || state.regexp || state.blockComment || + (!includeLineComment && state.lineComment) || !startsWith(src, delimiter, index)) { + exports.parseChar(src[index++], state); + } + var end = index; + return { + start: start, + end: end, + src: src.substring(start, end) + }; +} + + +exports.parseChar = parseChar; +function parseChar(character, state) { + if (character.length !== 1) throw new Error('Character must be a string of length 1'); + state = state || defaultState(); + var wasComment = state.blockComment || state.lineComment; + var lastChar = state.history ? state.history[0] : ''; + if (state.lineComment) { + if (character === '\n') { + state.lineComment = false; + } + } else if (state.blockComment) { + if (state.lastChar === '*' && character === '/') { + state.blockComment = false; + } + } else if (state.singleQuote) { + if (character === '\'' && !state.escaped) { + state.singleQuote = false; + } else if (character === '\\' && !state.escaped) { + state.escaped = true; + } else { + state.escaped = false; + } + } else if (state.doubleQuote) { + if (character === '"' && !state.escaped) { + state.doubleQuote = false; + } else if (character === '\\' && !state.escaped) { + state.escaped = true; + } else { + state.escaped = false; + } + } else if (state.regexp) { + if (character === '/' && !state.escaped) { + state.regexp = false; + } else if (character === '\\' && !state.escaped) { + state.escaped = true; + } else { + state.escaped = false; + } + } else if (lastChar === '/' && character === '/') { + history = history.substr(1); + state.lineComment = true; + } else if (lastChar === '/' && character === '*') { + history = history.substr(1); + state.blockComment = true; + } else if (character === '/') { + //could be start of regexp or divide sign + var history = state.history.replace(/^\s*/, ''); + if (history[0] === ')') { + //unless its an `if`, `while`, `for` or `with` it's a divide + //this is probably best left though + } else if (history[0] === '}') { + //unless it's a function expression, it's a regexp + //this is probably best left though + } else if (isPunctuator(history[0])) { + state.regexp = true; + } else if (/^\w+\b/.test(history) && isKeyword(/^\w+\b/.exec(history)[0])) { + state.regexp = true; + } else { + // assume it's divide + } + } else if (character === '\'') { + state.singleQuote = true; + } else if (character === '"') { + state.doubleQuote = true; + } else if (character === '(') { + state.roundDepth++; + } else if (character === ')') { + state.roundDepth--; + } else if (character === '{') { + state.curlyDepth++; + } else if (character === '}') { + state.curlyDepth--; + } else if (character === '[') { + state.squareDepth++; + } else if (character === ']') { + state.squareDepth--; + } + if (!state.blockComment && !state.lineComment && !wasComment) state.history = character + state.history; + return state; +} + +exports.defaultState = defaultState; +function defaultState() { + return { + lineComment: false, + blockComment: false, + + singleQuote: false, + doubleQuote: false, + regexp: false, + escaped: false, + + roundDepth: 0, + curlyDepth: 0, + squareDepth: 0, + + history: '' + }; +} + +function startsWith(str, start, i) { + return str.substr(i || 0, start.length) === start; +} + +function isPunctuator(c) { + var code = c.charCodeAt(0) + + switch (code) { + case 46: // . dot + case 40: // ( open bracket + case 41: // ) close bracket + case 59: // ; semicolon + case 44: // , comma + case 123: // { open curly brace + case 125: // } close curly brace + case 91: // [ + case 93: // ] + case 58: // : + case 63: // ? + case 126: // ~ + case 37: // % + case 38: // & + case 42: // *: + case 43: // + + case 45: // - + case 47: // / + case 60: // < + case 62: // > + case 94: // ^ + case 124: // | + case 33: // ! + case 61: // = + return true; + default: + return false; + } +} +function isKeyword(id) { + return (id === 'if') || (id === 'in') || (id === 'do') || (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let') || (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum') || (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || (id === 'class') || (id === 'super') || + (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch') || (id === 'export') || + (id === 'import') || (id === 'default') || (id === 'finally') || (id === 'extends') || (id === 'function') || + (id === 'continue') || (id === 'debugger') || (id === 'package') || (id === 'private') || (id === 'interface') || + (id === 'instanceof') || (id === 'implements') || (id === 'protected') || (id === 'public') || (id === 'static') || + (id === 'yield') || (id === 'let'); +} diff --git a/node_modules/jade/node_modules/character-parser/package.json b/node_modules/jade/node_modules/character-parser/package.json new file mode 100644 index 0000000..5cc5851 --- /dev/null +++ b/node_modules/jade/node_modules/character-parser/package.json @@ -0,0 +1,39 @@ +{ + "name": "character-parser", + "version": "1.0.2", + "description": "Parse JavaScript one character at a time to look for snippets in Templates. This is not a validator, it's just designed to allow you to have sections of JavaScript delimited by brackets robustly.", + "main": "index.js", + "scripts": { + "test": "mocha -R spec" + }, + "repository": { + "type": "git", + "url": "https://github.com/ForbesLindesay/character-parser.git" + }, + "keywords": [ + "parser", + "JavaScript", + "bracket", + "nesting", + "comment", + "string", + "escape", + "escaping" + ], + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "devDependencies": { + "better-assert": "~1.0.0", + "mocha": "~1.9.0" + }, + "readme": "# character-parser\r\n\r\nParse JavaScript one character at a time to look for snippets in Templates. This is not a validator, it's just designed to allow you to have sections of JavaScript delimited by brackets robustly.\r\n\r\n[![Build Status](https://travis-ci.org/ForbesLindesay/character-parser.png?branch=master)](https://travis-ci.org/ForbesLindesay/character-parser)\r\n\r\n## Installation\r\n\r\n npm install character-parser\r\n\r\n## Usage\r\n\r\nWork out how much depth changes:\r\n\r\n```js\r\nvar state = parse('foo(arg1, arg2, {\\n foo: [a, b\\n');\r\nassert(state.roundDepth === 1);\r\nassert(state.curlyDepth === 1);\r\nassert(state.squareDepth === 1);\r\nparse(' c, d]\\n })', state);\r\nassert(state.squareDepth === 0);\r\nassert(state.curlyDepth === 0);\r\nassert(state.roundDepth === 0);\r\n```\r\n\r\n### Bracketed Expressions\r\n\r\nFind all the contents of a bracketed expression:\r\n\r\n```js\r\nvar section = parser.parseMax('foo=\"(\", bar=\"}\") bing bong');\r\nassert(section.start === 0);\r\nassert(section.end === 16);//exclusive end of string\r\nassert(section.src = 'foo=\"(\", bar=\"}\"');\r\n\r\n\r\nvar section = parser.parseMax('{foo=\"(\", bar=\"}\"} bing bong', {start: 1});\r\nassert(section.start === 1);\r\nassert(section.end === 17);//exclusive end of string\r\nassert(section.src = 'foo=\"(\", bar=\"}\"');\r\n```\r\n\r\nThe bracketed expression parsing simply parses up to but excluding the first unmatched closed bracket (`)`, `}`, `]`). It is clever enough to ignore brackets in comments or strings.\r\n\r\n\r\n### Custom Delimited Expressions\r\n\r\nFind code up to a custom delimiter:\r\n\r\n```js\r\nvar section = parser.parseUntil('foo.bar(\"%>\").baz%> bing bong', '%>');\r\nassert(section.start === 0);\r\nassert(section.end === 17);//exclusive end of string\r\nassert(section.src = 'foo.bar(\"%>\").baz');\r\n\r\nvar section = parser.parseUntil('<%foo.bar(\"%>\").baz%> bing bong', '%>', {start: 2});\r\nassert(section.start === 2);\r\nassert(section.end === 19);//exclusive end of string\r\nassert(section.src = 'foo.bar(\"%>\").baz');\r\n```\r\n\r\nDelimiters are ignored if they are inside strings or comments.\r\n\r\n## API\r\n\r\n### parse(str, state = defaultState(), options = {start: 0, end: src.length})\r\n\r\nParse a string starting at the index start, and return the state after parsing that string.\r\n\r\nIf you want to parse one string in multiple sections you should keep passing the resulting state to the next parse operation.\r\n\r\nThe resulting object has the structure:\r\n\r\n```js\r\n{\r\n lineComment: false, //true if inside a line comment\r\n blockComment: false, //true if inside a block comment\r\n\r\n singleQuote: false, //true if inside a single quoted string\r\n doubleQuote: false, //true if inside a double quoted string\r\n escaped: false, //true if in a string and the last character was an escape character\r\n\r\n roundDepth: 0, //number of un-closed open `(` brackets\r\n curlyDepth: 0, //number of un-closed open `{` brackets\r\n squareDepth: 0 //number of un-closed open `[` brackets\r\n}\r\n```\r\n\r\n### parseMax(src, options = {start: 0})\r\n\r\nParses the source until the first unmatched close bracket (any of `)`, `}`, `]`). It returns an object with the structure:\r\n\r\n```js\r\n{\r\n start: 0,//index of first character of string\r\n end: 13,//index of first character after the end of string\r\n src: 'source string'\r\n}\r\n```\r\n\r\n### parseUntil(src, delimiter, options = {start: 0, includeLineComment: false})\r\n\r\nParses the source until the first occurence of `delimiter` which is not in a string or a comment. If `includeLineComment` is `true`, it will still count if the delimiter occurs in a line comment, but not in a block comment. It returns an object with the structure:\r\n\r\n```js\r\n{\r\n start: 0,//index of first character of string\r\n end: 13,//index of first character after the end of string\r\n src: 'source string'\r\n}\r\n```\r\n\r\n### parseChar(character, state = defaultState())\r\n\r\nParses the single character and returns the state. See `parse` for the structure of the returned state object. N.B. character must be a single character not a multi character string.\r\n\r\n### defaultState()\r\n\r\nGet a default starting state. See `parse` for the structure of the returned state object.\r\n\r\n## License\r\n\r\nMIT", + "readmeFilename": "README.md", + "_id": "character-parser@1.0.2", + "dist": { + "shasum": "e8a7b6b96d0f68337166ac291c6890c9ea6ec798" + }, + "_from": "character-parser@1.0.2", + "_resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.0.2.tgz" +} diff --git a/node_modules/jade/node_modules/character-parser/test/index.js b/node_modules/jade/node_modules/character-parser/test/index.js new file mode 100644 index 0000000..0e346fb --- /dev/null +++ b/node_modules/jade/node_modules/character-parser/test/index.js @@ -0,0 +1,50 @@ +var assert = require('better-assert'); +var parser = require('../'); +var parse = parser; + +it('works out how much depth changes', function () { + var state = parse('foo(arg1, arg2, {\n foo: [a, b\n'); + assert(state.roundDepth === 1); + assert(state.curlyDepth === 1); + assert(state.squareDepth === 1); + + parse(' c, d]\n })', state); + assert(state.squareDepth === 0); + assert(state.curlyDepth === 0); + assert(state.roundDepth === 0); +}); + +it('finds contents of bracketed expressions', function () { + var section = parser.parseMax('foo="(", bar="}") bing bong'); + assert(section.start === 0); + assert(section.end === 16);//exclusive end of string + assert(section.src = 'foo="(", bar="}"'); + + var section = parser.parseMax('{foo="(", bar="}"} bing bong', {start: 1}); + assert(section.start === 1); + assert(section.end === 17);//exclusive end of string + assert(section.src = 'foo="(", bar="}"'); +}); + +it('finds code up to a custom delimiter', function () { + var section = parser.parseUntil('foo.bar("%>").baz%> bing bong', '%>'); + assert(section.start === 0); + assert(section.end === 17);//exclusive end of string + assert(section.src = 'foo.bar("%>").baz'); + + var section = parser.parseUntil('<%foo.bar("%>").baz%> bing bong', '%>', {start: 2}); + assert(section.start === 2); + assert(section.end === 19);//exclusive end of string + assert(section.src = 'foo.bar("%>").baz'); +}); + +describe('regressions', function () { + describe('#1', function () { + it('parses regular expressions', function () { + var section = parser.parseMax('foo=/\\//g, bar="}") bing bong'); + assert(section.start === 0); + assert(section.end === 18);//exclusive end of string + assert(section.src = 'foo=/\\//g, bar="}"'); + }) + }) +}) \ No newline at end of file diff --git a/node_modules/jade/node_modules/commander/History.md b/node_modules/jade/node_modules/commander/History.md new file mode 100644 index 0000000..7cda70f --- /dev/null +++ b/node_modules/jade/node_modules/commander/History.md @@ -0,0 +1,158 @@ + +1.2.0 / 2013-06-13 +================== + + * allow "-" hyphen as an option argument + * support for RegExp coercion + +1.1.1 / 2012-11-20 +================== + + * add more sub-command padding + * fix .usage() when args are present. Closes #106 + +1.1.0 / 2012-11-16 +================== + + * add git-style executable subcommand support. Closes #94 + +1.0.5 / 2012-10-09 +================== + + * fix `--name` clobbering. Closes #92 + * fix examples/help. Closes #89 + +1.0.4 / 2012-09-03 +================== + + * add `outputHelp()` method. + +1.0.3 / 2012-08-30 +================== + + * remove invalid .version() defaulting + +1.0.2 / 2012-08-24 +================== + + * add `--foo=bar` support [arv] + * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus] + +1.0.1 / 2012-08-03 +================== + + * fix issue #56 + * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode()) + +1.0.0 / 2012-07-05 +================== + + * add support for optional option descriptions + * add defaulting of `.version()` to package.json's version + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/jade/node_modules/commander/Readme.md b/node_modules/jade/node_modules/commander/Readme.md new file mode 100644 index 0000000..107932a --- /dev/null +++ b/node_modules/jade/node_modules/commander/Readme.md @@ -0,0 +1,276 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range
    ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +```js +program.prompt('Email: ', /^.+@.+\..+$/, function(email){ + console.log('email: %j', email); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## .outputHelp() + + Output help information without exiting. + +## .help() + + Output help information and exit immediately. + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/commander/index.js b/node_modules/jade/node_modules/commander/index.js new file mode 100644 index 0000000..0ceaf18 --- /dev/null +++ b/node_modules/jade/node_modules/commander/index.js @@ -0,0 +1,1152 @@ +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , spawn = require('child_process').spawn + , keypress = require('keypress') + , fs = require('fs') + , exists = fs.existsSync + , path = require('path') + , tty = require('tty') + , dirname = path.dirname + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description || ''; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this._args = []; + this._name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @param {String} [desc] + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name, desc){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + if (desc) cmd.description(desc); + if (desc) this.executables = true; + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + if (desc) return this; + return cmd; +}; + +/** + * Add an implicit `help [cmd]` subcommand + * which invokes `--help` for the given command. + * + * @api private + */ + +Command.prototype.addImplicitHelpCommand = function() { + this.command('help [cmd]', 'display help for [cmd]'); +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self._args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self._args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this._name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + // Leftover arguments need to be pushed back. Fixes issue #56 + if (parsed.args.length) args = parsed.args.concat(args); + + self._args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self._args.length) { + args[self._args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // implicit help + if (this.executables) this.addImplicitHelpCommand(); + + // store raw args + this.rawArgs = argv; + + // guess name + this._name = this._name || basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + var args = this.args = parsed.args; + + // executable sub-commands, skip .parseArgs() + if (this.executables) return this.executeSubCommand(argv, args, parsed.unknown); + + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Execute a sub-command executable. + * + * @param {Array} argv + * @param {Array} args + * @param {Array} unknown + * @api private + */ + +Command.prototype.executeSubCommand = function(argv, args, unknown) { + args = args.concat(unknown); + + if (!args.length) this.help(); + if ('help' == args[0] && 1 == args.length) this.help(); + + // --help + if ('help' == args[0]) { + args[0] = args[1]; + args[1] = '--help'; + } + + // executable + var dir = dirname(argv[1]); + var bin = basename(argv[1]) + '-' + args[0]; + + // check for ./ first + var local = path.join(dir, bin); + if (exists(local)) bin = local; + + // run it + args = args.slice(1); + var proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); + proc.on('exit', function(code){ + if (code == 127) { + console.error('\n %s(1) does not exist\n', bin); + } + }); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * This also normalizes equal sign and splits "--abc=def" into "--abc def". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg + , index; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) { + ret.push(arg.slice(0, index), arg.slice(index + 1)); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0] && '-' != arg) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || ('-' == arg[0] && '-' != arg)) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this._args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this._args.length ? ' ' + args : ''); + + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd._args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return pad(cmd._name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args, 22) + + (cmd.description() + ? ' ' + cmd.description() + : ''); + }).join('\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this._name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + + +/** + * Prompt for a `Regular Expression`. + * + * @param {String} str + * @param {Object} pattern regular expression object to test + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForRegexp = function(str, pattern, fn){ + var self = this; + this.promptSingleLine(str, function parseRegexp(val){ + if(!pattern.test(val)) return self.promptSingleLine(str + '(regular expression mismatch) ', parseRegexp); + fn(val); + }); +}; + + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + // determine if the 2nd argument is a regular expression + if (arguments[1].global !== undefined && arguments[1].multiline !== undefined) { + return this.promptForRegexp(str, arguments[1], arguments[2]); + } else if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + keypress(process.stdin); + + function setRawMode(mode) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(mode); + } else { + tty.setRawMode(mode); + } + }; + setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.pause(); + process.stdin.removeAllListeners('keypress'); + setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + + +/** + * Output help information for this command + * + * @api public + */ + +Command.prototype.outputHelp = function(){ + process.stdout.write(this.helpInformation()); + this.emit('--help'); +}; + +/** + * Output help information and exit. + * + * @api public + */ + +Command.prototype.help = function(){ + this.outputHelp(); + process.exit(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + cmd.outputHelp(); + process.exit(0); + } + } +} diff --git a/node_modules/jade/node_modules/commander/node_modules/keypress/README.md b/node_modules/jade/node_modules/commander/node_modules/keypress/README.md new file mode 100644 index 0000000..a768e8f --- /dev/null +++ b/node_modules/jade/node_modules/commander/node_modules/keypress/README.md @@ -0,0 +1,101 @@ +keypress +======== +### Make any Node ReadableStream emit "keypress" events + + +Previous to Node `v0.8.x`, there was an undocumented `"keypress"` event that +`process.stdin` would emit when it was a TTY. Some people discovered this hidden +gem, and started using it in their own code. + +Now in Node `v0.8.x`, this `"keypress"` event does not get emitted by default, +but rather only when it is being used in conjuction with the `readline` (or by +extension, the `repl`) module. + +This module is the exact logic from the node `v0.8.x` releases ripped out into its +own module. + +__Bonus:__ Now with mouse support! + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install keypress +``` + +Or add it to the `"dependencies"` section of your _package.json_ file. + + +Example +------- + +#### Listening for "keypress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "keypress" events +keypress(process.stdin); + +// listen for the "keypress" event +process.stdin.on('keypress', function (ch, key) { + console.log('got "keypress"', key); + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause(); + } +}); + +process.stdin.setRawMode(true); +process.stdin.resume(); +``` + +#### Listening for "mousepress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "mousepress" (and "keypress") events +keypress(process.stdin); + +// you must enable the mouse events before they will begin firing +keypress.enableMouse(process.stdout); + +process.stdin.on('mousepress', function (info) { + console.log('got "mousepress" event at %d x %d', info.x, info.y); +}); + +process.on('exit', function () { + // disable mouse on exit, so that the state + // is back to normal for the terminal + keypress.disableMouse(process.stdout); +}); +``` + + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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/jade/node_modules/commander/node_modules/keypress/index.js b/node_modules/jade/node_modules/commander/node_modules/keypress/index.js new file mode 100644 index 0000000..c2ba488 --- /dev/null +++ b/node_modules/jade/node_modules/commander/node_modules/keypress/index.js @@ -0,0 +1,346 @@ + +/** + * This module offers the internal "keypress" functionality from node-core's + * `readline` module, for your own programs and modules to use. + * + * Usage: + * + * require('keypress')(process.stdin); + * + * process.stdin.on('keypress', function (ch, key) { + * console.log(ch, key); + * if (key.ctrl && key.name == 'c') { + * process.stdin.pause(); + * } + * }); + * proces.stdin.resume(); + */ +var exports = module.exports = keypress; + +exports.enableMouse = function (stream) { + stream.write('\x1b' +'[?1000h') +} + +exports.disableMouse = function (stream) { + stream.write('\x1b' +'[?1000l') +} + + +/** + * accepts a readable Stream instance and makes it emit "keypress" events + */ + +function keypress(stream) { + if (isEmittingKeypress(stream)) return; + stream._emitKeypress = true; + + function onData(b) { + if (stream.listeners('keypress').length > 0) { + emitKey(stream, b); + } else { + // Nobody's watching anyway + stream.removeListener('data', onData); + stream.on('newListener', onNewListener); + } + } + + function onNewListener(event) { + if (event == 'keypress') { + stream.on('data', onData); + stream.removeListener('newListener', onNewListener); + } + } + + if (stream.listeners('keypress').length > 0) { + stream.on('data', onData); + } else { + stream.on('newListener', onNewListener); + } +} + +/** + * Returns `true` if the stream is already emitting "keypress" events. + * `false` otherwise. + */ + +function isEmittingKeypress(stream) { + var rtn = stream._emitKeypress; + if (!rtn) { + // hack: check for the v0.6.x "data" event + stream.listeners('data').forEach(function (l) { + if (l.name == 'onData' && /emitKey/.test(l.toString())) { + rtn = true; + stream._emitKeypress = true; + } + }); + } + if (!rtn) { + // hack: check for the v0.6.x "newListener" event + stream.listeners('newListener').forEach(function (l) { + if (l.name == 'onNewListener' && /keypress/.test(l.toString())) { + rtn = true; + stream._emitKeypress = true; + } + }); + } + return rtn; +} + + +/* + Some patterns seen in terminal key escape codes, derived from combos seen + at http://www.midnight-commander.org/browser/lib/tty/key.c + + ESC letter + ESC [ letter + ESC [ modifier letter + ESC [ 1 ; modifier letter + ESC [ num char + ESC [ num ; modifier char + ESC O letter + ESC O modifier letter + ESC O 1 ; modifier letter + ESC N letter + ESC [ [ num ; modifier char + ESC [ [ 1 ; modifier letter + ESC ESC [ num char + ESC ESC O letter + + - char is usually ~ but $ and ^ also happen with rxvt + - modifier is 1 + + (shift * 1) + + (left_alt * 2) + + (ctrl * 4) + + (right_alt * 8) + - two leading ESCs apparently mean the same as one leading ESC +*/ + +// Regexes used for ansi escape code splitting +var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; +var functionKeyCodeRe = + /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; + +function emitKey(stream, s) { + var ch, + key = { + name: undefined, + ctrl: false, + meta: false, + shift: false + }, + parts; + + if (Buffer.isBuffer(s)) { + if (s[0] > 127 && s[1] === undefined) { + s[0] -= 128; + s = '\x1b' + s.toString(stream.encoding || 'utf-8'); + } else { + s = s.toString(stream.encoding || 'utf-8'); + } + } + + key.sequence = s; + + if (s === '\r' || s === '\n') { + // enter + key.name = 'enter'; + + } else if (s === '\t') { + // tab + key.name = 'tab'; + + } else if (s === '\b' || s === '\x7f' || + s === '\x1b\x7f' || s === '\x1b\b') { + // backspace or ctrl+h + key.name = 'backspace'; + key.meta = (s.charAt(0) === '\x1b'); + + } else if (s === '\x1b' || s === '\x1b\x1b') { + // escape key + key.name = 'escape'; + key.meta = (s.length === 2); + + } else if (s === ' ' || s === '\x1b ') { + key.name = 'space'; + key.meta = (s.length === 2); + + } else if (s <= '\x1a') { + // ctrl+letter + key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); + key.ctrl = true; + + } else if (s.length === 1 && s >= 'a' && s <= 'z') { + // lowercase letter + key.name = s; + + } else if (s.length === 1 && s >= 'A' && s <= 'Z') { + // shift+letter + key.name = s.toLowerCase(); + key.shift = true; + + } else if (parts = metaKeyCodeRe.exec(s)) { + // meta+character key + key.name = parts[1].toLowerCase(); + key.meta = true; + key.shift = /^[A-Z]$/.test(parts[1]); + + } else if (parts = functionKeyCodeRe.exec(s)) { + // ansi escape sequence + + // reassemble the key code leaving out leading \x1b's, + // the modifier key bitflag and any meaningless "1;" sequence + var code = (parts[1] || '') + (parts[2] || '') + + (parts[4] || '') + (parts[6] || ''), + modifier = (parts[3] || parts[5] || 1) - 1; + + // Parse the key modifier + key.ctrl = !!(modifier & 4); + key.meta = !!(modifier & 10); + key.shift = !!(modifier & 1); + key.code = code; + + // Parse the key itself + switch (code) { + /* xterm/gnome ESC O letter */ + case 'OP': key.name = 'f1'; break; + case 'OQ': key.name = 'f2'; break; + case 'OR': key.name = 'f3'; break; + case 'OS': key.name = 'f4'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[11~': key.name = 'f1'; break; + case '[12~': key.name = 'f2'; break; + case '[13~': key.name = 'f3'; break; + case '[14~': key.name = 'f4'; break; + + /* from Cygwin and used in libuv */ + case '[[A': key.name = 'f1'; break; + case '[[B': key.name = 'f2'; break; + case '[[C': key.name = 'f3'; break; + case '[[D': key.name = 'f4'; break; + case '[[E': key.name = 'f5'; break; + + /* common */ + case '[15~': key.name = 'f5'; break; + case '[17~': key.name = 'f6'; break; + case '[18~': key.name = 'f7'; break; + case '[19~': key.name = 'f8'; break; + case '[20~': key.name = 'f9'; break; + case '[21~': key.name = 'f10'; break; + case '[23~': key.name = 'f11'; break; + case '[24~': key.name = 'f12'; break; + + /* xterm ESC [ letter */ + case '[A': key.name = 'up'; break; + case '[B': key.name = 'down'; break; + case '[C': key.name = 'right'; break; + case '[D': key.name = 'left'; break; + case '[E': key.name = 'clear'; break; + case '[F': key.name = 'end'; break; + case '[H': key.name = 'home'; break; + + /* xterm/gnome ESC O letter */ + case 'OA': key.name = 'up'; break; + case 'OB': key.name = 'down'; break; + case 'OC': key.name = 'right'; break; + case 'OD': key.name = 'left'; break; + case 'OE': key.name = 'clear'; break; + case 'OF': key.name = 'end'; break; + case 'OH': key.name = 'home'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[1~': key.name = 'home'; break; + case '[2~': key.name = 'insert'; break; + case '[3~': key.name = 'delete'; break; + case '[4~': key.name = 'end'; break; + case '[5~': key.name = 'pageup'; break; + case '[6~': key.name = 'pagedown'; break; + + /* putty */ + case '[[5~': key.name = 'pageup'; break; + case '[[6~': key.name = 'pagedown'; break; + + /* rxvt */ + case '[7~': key.name = 'home'; break; + case '[8~': key.name = 'end'; break; + + /* rxvt keys with modifiers */ + case '[a': key.name = 'up'; key.shift = true; break; + case '[b': key.name = 'down'; key.shift = true; break; + case '[c': key.name = 'right'; key.shift = true; break; + case '[d': key.name = 'left'; key.shift = true; break; + case '[e': key.name = 'clear'; key.shift = true; break; + + case '[2$': key.name = 'insert'; key.shift = true; break; + case '[3$': key.name = 'delete'; key.shift = true; break; + case '[5$': key.name = 'pageup'; key.shift = true; break; + case '[6$': key.name = 'pagedown'; key.shift = true; break; + case '[7$': key.name = 'home'; key.shift = true; break; + case '[8$': key.name = 'end'; key.shift = true; break; + + case 'Oa': key.name = 'up'; key.ctrl = true; break; + case 'Ob': key.name = 'down'; key.ctrl = true; break; + case 'Oc': key.name = 'right'; key.ctrl = true; break; + case 'Od': key.name = 'left'; key.ctrl = true; break; + case 'Oe': key.name = 'clear'; key.ctrl = true; break; + + case '[2^': key.name = 'insert'; key.ctrl = true; break; + case '[3^': key.name = 'delete'; key.ctrl = true; break; + case '[5^': key.name = 'pageup'; key.ctrl = true; break; + case '[6^': key.name = 'pagedown'; key.ctrl = true; break; + case '[7^': key.name = 'home'; key.ctrl = true; break; + case '[8^': key.name = 'end'; key.ctrl = true; break; + + /* misc. */ + case '[Z': key.name = 'tab'; key.shift = true; break; + default: key.name = 'undefined'; break; + + } + } else if (s.length > 1 && s[0] !== '\x1b') { + // Got a longer-than-one string of characters. + // Probably a paste, since it wasn't a control sequence. + Array.prototype.forEach.call(s, function(c) { + emitKey(stream, c); + }); + return; + } + + if (key.code == '[M') { + key.name = 'mouse'; + var s = key.sequence; + var b = s.charCodeAt(3); + key.x = s.charCodeAt(4) - 040; + key.y = s.charCodeAt(5) - 040; + + key.scroll = 0; + + key.ctrl = !!(1<<4 & b); + key.meta = !!(1<<3 & b); + key.shift = !!(1<<2 & b); + + key.release = (3 & b) === 3; + + if (1<<6 & b) { //scroll + key.scroll = 1 & b ? 1 : -1; + } + + if (!key.release && !key.scroll) { + key.button = b & 3; + } + } + + // Don't emit a key if no name was found + if (key.name === undefined) { + key = undefined; + } + + if (s.length === 1) { + ch = s; + } + + if (key && key.name == 'mouse') { + stream.emit('mousepress', key) + } else if (key || ch) { + stream.emit('keypress', ch, key); + } +} diff --git a/node_modules/jade/node_modules/commander/node_modules/keypress/package.json b/node_modules/jade/node_modules/commander/node_modules/keypress/package.json new file mode 100644 index 0000000..ed9993f --- /dev/null +++ b/node_modules/jade/node_modules/commander/node_modules/keypress/package.json @@ -0,0 +1,32 @@ +{ + "name": "keypress", + "version": "0.1.0", + "description": "Make any Node ReadableStream emit \"keypress\" events", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://tootallnate.net" + }, + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/keypress.git" + }, + "keywords": [ + "keypress", + "readline", + "core" + ], + "license": "MIT", + "readme": "keypress\n========\n### Make any Node ReadableStream emit \"keypress\" events\n\n\nPrevious to Node `v0.8.x`, there was an undocumented `\"keypress\"` event that\n`process.stdin` would emit when it was a TTY. Some people discovered this hidden\ngem, and started using it in their own code.\n\nNow in Node `v0.8.x`, this `\"keypress\"` event does not get emitted by default,\nbut rather only when it is being used in conjuction with the `readline` (or by\nextension, the `repl`) module.\n\nThis module is the exact logic from the node `v0.8.x` releases ripped out into its\nown module.\n\n__Bonus:__ Now with mouse support!\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install keypress\n```\n\nOr add it to the `\"dependencies\"` section of your _package.json_ file.\n\n\nExample\n-------\n\n#### Listening for \"keypress\" events\n\n``` js\nvar keypress = require('keypress');\n\n// make `process.stdin` begin emitting \"keypress\" events\nkeypress(process.stdin);\n\n// listen for the \"keypress\" event\nprocess.stdin.on('keypress', function (ch, key) {\n console.log('got \"keypress\"', key);\n if (key && key.ctrl && key.name == 'c') {\n process.stdin.pause();\n }\n});\n\nprocess.stdin.setRawMode(true);\nprocess.stdin.resume();\n```\n\n#### Listening for \"mousepress\" events\n\n``` js\nvar keypress = require('keypress');\n\n// make `process.stdin` begin emitting \"mousepress\" (and \"keypress\") events\nkeypress(process.stdin);\n\n// you must enable the mouse events before they will begin firing\nkeypress.enableMouse(process.stdout);\n\nprocess.stdin.on('mousepress', function (info) {\n console.log('got \"mousepress\" event at %d x %d', info.x, info.y);\n});\n\nprocess.on('exit', function () {\n // disable mouse on exit, so that the state\n // is back to normal for the terminal\n keypress.disableMouse(process.stdout);\n});\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "_id": "keypress@0.1.0", + "dist": { + "shasum": "6f5825a04f3bbf70b0410fc184a29b6e423651a4" + }, + "_from": "keypress@0.1.x", + "_resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz" +} diff --git a/node_modules/jade/node_modules/commander/node_modules/keypress/test.js b/node_modules/jade/node_modules/commander/node_modules/keypress/test.js new file mode 100644 index 0000000..c3f61d7 --- /dev/null +++ b/node_modules/jade/node_modules/commander/node_modules/keypress/test.js @@ -0,0 +1,28 @@ + +var keypress = require('./') +keypress(process.stdin) + +if (process.stdin.setRawMode) + process.stdin.setRawMode(true) +else + require('tty').setRawMode(true) + +process.stdin.on('keypress', function (c, key) { + console.log(0, c, key) + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause() + } +}) +process.stdin.on('mousepress', function (mouse) { + console.log(mouse) +}) + +keypress.enableMouse(process.stdout) +process.on('exit', function () { + //disable mouse on exit, so that the state is back to normal + //for the terminal. + keypress.disableMouse(process.stdout) +}) + +process.stdin.resume() + diff --git a/node_modules/jade/node_modules/commander/package.json b/node_modules/jade/node_modules/commander/package.json new file mode 100644 index 0000000..e688ad8 --- /dev/null +++ b/node_modules/jade/node_modules/commander/package.json @@ -0,0 +1,41 @@ +{ + "name": "commander", + "version": "1.2.0", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": { + "keypress": "0.1.x" + }, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.6.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n```js\nprogram.prompt('Email: ', /^.+@.+\\..+$/, function(email){\n console.log('email: %j', email);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## .outputHelp()\n\n Output help information without exiting.\n\n## .help()\n\n Output help information and exit immediately.\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "commander@1.2.0", + "dist": { + "shasum": "eddb75cdba2992e7ed1690f4803a249bf51117ef" + }, + "_from": "commander@1.2.0", + "_resolved": "https://registry.npmjs.org/commander/-/commander-1.2.0.tgz" +} diff --git a/node_modules/jade/node_modules/constantinople/.gitattributes b/node_modules/jade/node_modules/constantinople/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/node_modules/jade/node_modules/constantinople/.npmignore b/node_modules/jade/node_modules/constantinople/.npmignore new file mode 100644 index 0000000..b83202d --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/.npmignore @@ -0,0 +1,13 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz +pids +logs +results +npm-debug.log +node_modules diff --git a/node_modules/jade/node_modules/constantinople/.travis.yml b/node_modules/jade/node_modules/constantinople/.travis.yml new file mode 100644 index 0000000..a12e3f0 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/LICENSE b/node_modules/jade/node_modules/constantinople/LICENSE new file mode 100644 index 0000000..35cc606 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013 Forbes Lindesay + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/README.md b/node_modules/jade/node_modules/constantinople/README.md new file mode 100644 index 0000000..ad156c0 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/README.md @@ -0,0 +1,35 @@ +# constantinople + +Determine whether a JavaScript expression evaluates to a constant (using UglifyJS). Here it is assumed to be safe to underestimate how constant something is. + +[![Build Status](https://travis-ci.org/ForbesLindesay/constantinople.png?branch=master)](https://travis-ci.org/ForbesLindesay/constantinople) +[![Dependency Status](https://gemnasium.com/ForbesLindesay/constantinople.png)](https://gemnasium.com/ForbesLindesay/constantinople) +[![NPM version](https://badge.fury.io/js/constantinople.png)](http://badge.fury.io/js/constantinople) + +## Installation + + npm install constantinople + +## Usage + +```js +var isConstant = require('constantinople') + +if (isConstant('"foo" + 5')) { + console.dir(isConstant.toConstant('"foo" + 5')) +} +``` + +## API + +### isConstant(src) + +Returns `true` if `src` evaluates to a constant, `false` otherwise. It will also return `false` if there is a syntax error, which makes it safe to use on potentially ES6 code. + +### toConstant(src) + +Returns the value resulting from evaluating `src`. This method throws an error if the expression is not constant. e.g. `toConstant("Math.random()")` would throw an error. + +## License + + MIT \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/index.js b/node_modules/jade/node_modules/constantinople/index.js new file mode 100644 index 0000000..3ed8a00 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/index.js @@ -0,0 +1,35 @@ +'use strict' + +var uglify = require('uglify-js') + +var lastSRC = '(null)' +var lastRes = true + +module.exports = isConstant +function isConstant(src) { + src = '(' + src + ')' + if (lastSRC === src) return lastRes + lastSRC = src + try { + return lastRes = (detect(src).length === 0) + } catch (ex) { + return lastRes = false + } +} +isConstant.isConstant = isConstant + +isConstant.toConstant = toConstant +function toConstant(src) { + if (!isConstant(src)) throw new Error(JSON.stringify(src) + ' is not constant.') + return Function('return (' + src + ')')() +} + +function detect(src) { + var ast = uglify.parse(src.toString()) + ast.figure_out_scope() + var globals = ast.globals + .map(function (node, name) { + return name + }) + return globals +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/node_modules/.bin/uglifyjs b/node_modules/jade/node_modules/constantinople/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.npmignore b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..94fceeb --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.npmignore @@ -0,0 +1,2 @@ +tmp/ +node_modules/ diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.travis.yml b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.travis.yml new file mode 100644 index 0000000..d959127 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.4" + - "0.6" + - "0.8" + - "0.10" + - "0.11" diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/LICENSE b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/LICENSE new file mode 100644 index 0000000..dd7706f --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/LICENSE @@ -0,0 +1,29 @@ +UglifyJS is released under the BSD license: + +Copyright 2012-2013 (c) Mihai Bazon + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/README.md b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/README.md new file mode 100644 index 0000000..749b8ce --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/README.md @@ -0,0 +1,588 @@ +UglifyJS 2 +========== +[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2) + +UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. + +This page documents the command line utility. For +[API and internals documentation see my website](http://lisperator.net/uglifyjs/). +There's also an +[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, +Chrome and probably Safari). + +Install +------- + +First make sure you have installed the latest version of [node.js](http://nodejs.org/) +(You may need to restart your computer after this step). + +From NPM for use as a command line app: + + npm install uglify-js -g + +From NPM for programmatic use: + + npm install uglify-js + +From Git: + + git clone git://github.com/mishoo/UglifyJS2.git + cd UglifyJS2 + npm link . + +Usage +----- + + uglifyjs [input files] [options] + +UglifyJS2 can take multiple input files. It's recommended that you pass the +input files first, then pass the options. UglifyJS will parse input files +in sequence and apply any compression options. The files are parsed in the +same global scope, that is, a reference from a file to some +variable/function declared in another file will be matched properly. + +If you want to read from STDIN instead, pass a single dash instead of input +files. + +The available options are: + + --source-map Specify an output file where to generate source map. + [string] + --source-map-root The path to the original source to be included in the + source map. [string] + --source-map-url The path to the source map to be added in //@ + sourceMappingURL. Defaults to the value passed with + --source-map. [string] + --in-source-map Input source map, useful if you're compressing JS that was + generated from some other original code. + --screw-ie8 Pass this flag if you don't care about full compliance with + Internet Explorer 6-8 quirks (by default UglifyJS will try + to be IE-proof). + -p, --prefix Skip prefix for original filenames that appear in source + maps. For example -p 3 will drop 3 directories from file + names and ensure they are relative paths. + -o, --output Output file (default STDOUT). + -b, --beautify Beautify output/specify output options. [string] + -m, --mangle Mangle names/pass mangler options. [string] + -r, --reserved Reserved names to exclude from mangling. + -c, --compress Enable compressor/pass compressor options. Pass options + like -c hoist_vars=false,if_return=false. Use -c with no + argument to use the default compression options. [string] + -d, --define Global definitions [string] + --comments Preserve copyright comments in the output. By default this + works like Google Closure, keeping JSDoc-style comments + that contain "@license" or "@preserve". You can optionally + pass one of the following arguments to this flag: + - "all" to keep all comments + - a valid JS regexp (needs to start with a slash) to keep + only comments that match. + Note that currently not *all* comments can be kept when + compression is on, because of dead code removal or + cascading statements into sequences. [string] + --stats Display operations run time on STDERR. [boolean] + --acorn Use Acorn for parsing. [boolean] + --spidermonkey Assume input files are SpiderMonkey AST format (as JSON). + [boolean] + --self Build itself (UglifyJS2) as a library (implies + --wrap=UglifyJS --export-all) [boolean] + --wrap Embed everything in a big function, making the “exports” + and “global” variables available. You need to pass an + argument to this option to specify the name that your + module will take when included in, say, a browser. + [string] + --export-all Only used when --wrap, this tells UglifyJS to add code to + automatically export all globals. [boolean] + --lint Display some scope warnings [boolean] + -v, --verbose Verbose [boolean] + -V, --version Print version number and exit. [boolean] + +Specify `--output` (`-o`) to declare the output file. Otherwise the output +goes to STDOUT. + +## Source map options + +UglifyJS2 can generate a source map file, which is highly useful for +debugging your compressed JavaScript. To get a source map, pass +`--source-map output.js.map` (full path to the file where you want the +source map dumped). + +Additionally you might need `--source-map-root` to pass the URL where the +original files can be found. In case you are passing full paths to input +files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of +directories to drop from the path prefix when declaring files in the source +map. + +For example: + + uglifyjs /home/doe/work/foo/src/js/file1.js \ + /home/doe/work/foo/src/js/file2.js \ + -o foo.min.js \ + --source-map foo.min.js.map \ + --source-map-root http://foo.com/src \ + -p 5 -c -m + +The above will compress and mangle `file1.js` and `file2.js`, will drop the +output in `foo.min.js` and the source map in `foo.min.js.map`. The source +mapping will refer to `http://foo.com/src/js/file1.js` and +`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` +as the source map root, and the original files as `js/file1.js` and +`js/file2.js`). + +### Composed source map + +When you're compressing JS code that was output by a compiler such as +CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd +like to map back to the original code (i.e. CoffeeScript). UglifyJS has an +option to take an input source map. Assuming you have a mapping from +CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → +compressed JS by mapping every token in the compiled JS to its original +location. + +To use this feature you need to pass `--in-source-map +/path/to/input/source.map`. Normally the input source map should also point +to the file containing the generated JS, so if that's correct you can omit +input files from the command line. + +## Mangler options + +To enable the mangler you need to pass `--mangle` (`-m`). The following +(comma-separated) options are supported: + +- `sort` — to assign shorter names to most frequently used variables. This + saves a few hundred bytes on jQuery before gzip, but the output is + _bigger_ after gzip (and seems to happen for other libraries I tried it + on) therefore it's not enabled by default. + +- `toplevel` — mangle names declared in the toplevel scope (disabled by + default). + +- `eval` — mangle names visible in scopes where `eval` or `when` are used + (disabled by default). + +When mangling is enabled but you want to prevent certain names from being +mangled, you can declare those names with `--reserved` (`-r`) — pass a +comma-separated list of names. For example: + + uglifyjs ... -m -r '$,require,exports' + +to prevent the `require`, `exports` and `$` names from being changed. + +## Compressor options + +You need to pass `--compress` (`-c`) to enable the compressor. Optionally +you can pass a comma-separated list of options. Options are in the form +`foo=bar`, or just `foo` (the latter implies a boolean option that you want +to set `true`; it's effectively a shortcut for `foo=true`). + +- `sequences` -- join consecutive simple statements using the comma operator +- `properties` -- rewrite property access using the dot notation, for + example `foo["bar"] → foo.bar` +- `dead_code` -- remove unreachable code +- `drop_debugger` -- remove `debugger;` statements +- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) +- `conditionals` -- apply optimizations for `if`-s and conditional + expressions +- `comparisons` -- apply certain optimizations to binary nodes, for example: + `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, + e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. +- `evaluate` -- attempt to evaluate constant expressions +- `booleans` -- various optimizations for boolean context, for example `!!a + ? b : c → a ? b : c` +- `loops` -- optimizations for `do`, `while` and `for` loops when we can + statically determine the condition +- `unused` -- drop unreferenced functions and variables +- `hoist_funs` -- hoist function declarations +- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` + by default because it seems to increase the size of the output in general) +- `if_return` -- optimizations for if/return and if/continue +- `join_vars` -- join consecutive `var` statements +- `cascade` -- small optimization for sequences, transform `x, x` into `x` + and `x = something(), x` into `x = something()` +- `warnings` -- display warnings when dropping unreachable code or unused + declarations etc. + +### The `unsafe` option + +It enables some transformations that *might* break code logic in certain +contrived cases, but should be fine for most code. You might want to try it +on your own code, it should reduce the minified size. Here's what happens +when this flag is on: + +- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` +- `new Object()` → `{}` +- `String(exp)` or `exp.toString()` → `"" + exp` +- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` +- `typeof foo == "undefined"` → `foo === void 0` +- `void 0` → `"undefined"` (if there is a variable named "undefined" in + scope; we do it because the variable name will be mangled, typically + reduced to a single character). + +### Conditional compilation + +You can use the `--define` (`-d`) switch in order to declare global +variables that UglifyJS will assume to be constants (unless defined in +scope). For example if you pass `--define DEBUG=false` then, coupled with +dead code removal UglifyJS will discard the following from the output: +```javascript +if (DEBUG) { + console.log("debug stuff"); +} +``` + +UglifyJS will warn about the condition being always false and about dropping +unreachable code; for now there is no option to turn off only this specific +warning, you can pass `warnings=false` to turn off *all* warnings. + +Another way of doing that is to declare your globals as constants in a +separate file and include it into the build. For example you can have a +`build/defines.js` file with the following: +```javascript +const DEBUG = false; +const PRODUCTION = true; +// etc. +``` + +and build your code like this: + + uglifyjs build/defines.js js/foo.js js/bar.js... -c + +UglifyJS will notice the constants and, since they cannot be altered, it +will evaluate references to them to the value itself and drop unreachable +code as usual. The possible downside of this approach is that the build +will contain the `const` declarations. + + +## Beautifier options + +The code generator tries to output shortest code possible by default. In +case you want beautified output, pass `--beautify` (`-b`). Optionally you +can pass additional arguments that control the code output: + +- `beautify` (default `true`) -- whether to actually beautify the output. + Passing `-b` will set this to true, but you might need to pass `-b` even + when you want to generate minified code, in order to specify additional + arguments, so you can use `-b beautify=false` to override it. +- `indent-level` (default 4) +- `indent-start` (default 0) -- prefix all lines by that many spaces +- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal + objects +- `space-colon` (default `true`) -- insert a space after the colon signs +- `ascii-only` (default `false`) -- escape Unicode characters in strings and + regexps +- `inline-script` (default `false`) -- escape the slash in occurrences of + ` 0) { + sys.error("WARN: Ignoring input files since --self was passed"); + } + files = UglifyJS.FILES; + if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; + ARGS.export_all = true; +} + +var ORIG_MAP = ARGS.in_source_map; + +if (ORIG_MAP) { + ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); + if (files.length == 0) { + sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); + files = [ ORIG_MAP.file ]; + } + if (ARGS.source_map_root == null) { + ARGS.source_map_root = ORIG_MAP.sourceRoot; + } +} + +if (files.length == 0) { + files = [ "-" ]; +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; +var TOPLEVEL = null; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: OUTPUT_FILE, + root: ARGS.source_map_root, + orig: ORIG_MAP, +}) : null; + +OUTPUT_OPTIONS.source_map = SOURCE_MAP; + +try { + var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); + var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); +} catch(ex) { + if (ex instanceof UglifyJS.DefaultsError) { + sys.error(ex.msg); + sys.error("Supported options:"); + sys.error(sys.inspect(ex.defs)); + process.exit(1); + } +} + +async.eachLimit(files, 1, function (file, cb) { + read_whole_file(file, function (err, code) { + if (err) { + sys.error("ERROR: can't read file: " + filename); + process.exit(1); + } + if (ARGS.p != null) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + time_it("parse", function(){ + if (ARGS.spidermonkey) { + var program = JSON.parse(code); + if (!TOPLEVEL) TOPLEVEL = program; + else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); + } + else if (ARGS.acorn) { + TOPLEVEL = acorn.parse(code, { + locations : true, + trackComments : true, + sourceFile : file, + program : TOPLEVEL + }); + } + else { + TOPLEVEL = UglifyJS.parse(code, { + filename : file, + toplevel : TOPLEVEL, + expression : ARGS.expr, + }); + }; + }); + cb(); + }); +}, function () { + if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ + TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); + }); + + if (ARGS.wrap) { + TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); + } + + if (ARGS.enclose) { + var arg_parameter_list = ARGS.enclose; + + if (!(arg_parameter_list instanceof Array)) { + arg_parameter_list = [arg_parameter_list]; + } + + TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list); + } + + var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (ARGS.lint) { + TOPLEVEL.scope_warnings(); + } + }); + } + + if (COMPRESS) { + time_it("squeeze", function(){ + TOPLEVEL = TOPLEVEL.transform(compressor); + }); + } + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (MANGLE) { + TOPLEVEL.compute_char_frequency(MANGLE); + } + }); + } + + if (MANGLE) time_it("mangle", function(){ + TOPLEVEL.mangle_names(MANGLE); + }); + time_it("generate", function(){ + TOPLEVEL.print(output); + }); + + output = output.get(); + + if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); + output += "\n//# sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map); + } + + if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); + } else { + sys.print(output); + sys.error("\n"); + } + + if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } + } +}); + +/* -----[ functions ]----- */ + +function normalize(o) { + for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { + o[i.replace(/-/g, "_")] = o[i]; + delete o[i]; + } +} + +function getOptions(x, constants) { + x = ARGS[x]; + if (!x) return null; + var ret = {}; + if (x !== true) { + var ast; + try { + ast = UglifyJS.parse(x); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Error parsing arguments in: " + x); + process.exit(1); + } + } + ast.walk(new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.AST_Toplevel) return; // descend + if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend + if (node instanceof UglifyJS.AST_Seq) return; // descend + if (node instanceof UglifyJS.AST_Assign) { + var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); + var value = node.right; + if (constants) + value = new Function("return (" + value.print_to_string() + ")")(); + ret[name] = value; + return true; // no descend + } + sys.error(node.TYPE) + sys.error("Error parsing arguments in: " + x); + process.exit(1); + })); + } + return ret; +} + +function read_whole_file(filename, cb) { + if (filename == "-") { + var chunks = []; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', function (chunk) { + chunks.push(chunk); + }).on('end', function () { + cb(null, chunks.join("")); + }); + process.openStdin(); + } else { + fs.readFile(filename, "utf-8", cb); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/ast.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/ast.js new file mode 100644 index 0000000..a1301da --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/ast.js @@ -0,0 +1,985 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; + else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) + props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0;) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base; + if (proto && proto.initialize || (methods && methods.initialize)) + code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; +}; + +var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +}, null); + +var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); // not sure the indirection will be any help + } +}, null); + +AST_Node.warn_function = null; +AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) + AST_Node.warn_function(string_template(txt, props)); +}; + +/* -----[ statements ]----- */ + +var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements", +}); + +var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement", +}, AST_Statement); + +var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: "Represents a directive, like \"use strict\";", + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + }, +}, AST_Statement); + +var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } + else node.body.forEach(function(stat){ + stat._walk(visitor); + }); +}; + +var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + +var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement", +}, AST_Block); + +var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } +}, AST_Statement); + +var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.label._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement", +}, AST_DWLoop); + +var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement", +}, AST_DWLoop); + +var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ scope and functions ]----- */ + +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)", + }, +}, AST_Block); + +var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", + }, + wrap_enclose: function(arg_parameter_pairs) { + var self = this; + var args = []; + var parameters = []; + + arg_parameter_pairs.forEach(function(pair) { + var split = pair.split(":"); + + args.push(split[0]); + parameters.push(split[1]); + }); + + var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(self.body); + } + })); + return wrapped_tl; + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n){ return n.name == node.name }, to_export)) + to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym){ + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ name: "exports" }), + property: new AST_String({ value: sym.name }), + }), + operator: "=", + right: new AST_SymbolRef(sym), + }), + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } +}, AST_Scope); + +var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg){ + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } +}, AST_Scope); + +var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function" +}, AST_Lambda); + +var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" +}, AST_Lambda); + +var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" +}, AST_Lambda); + +/* -----[ JUMPS ]----- */ + +var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" +}, AST_Statement); + +var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function(){ + this.value._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" +}, AST_Exit); + +var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" +}, AST_Exit); + +var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none", + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function(){ + this.label._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" +}, AST_LoopControl); + +var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" +}, AST_LoopControl); + +/* -----[ IF ]----- */ + +var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ SWITCH ]----- */ + +var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches", +}, AST_Block); + +var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", +}, AST_SwitchBranch); + +var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_SwitchBranch); + +/* -----[ EXCEPTIONS ]----- */ + +var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } +}, AST_Block); + +// XXX: this is wrong according to ECMA-262 (12.4). the catch block +// should introduce another scope, as the argname should be visible +// only inside the catch block. However, doing it this way because of +// IE which simply introduces the name in the surrounding scope. If +// we ever want to fix this then AST_Catch should inherit from +// AST_Scope. +var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); + +/* -----[ VAR/CONST ]----- */ + +var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.definitions.forEach(function(def){ + def._walk(visitor); + }); + }); + } +}, AST_Statement); + +var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" +}, AST_Definitions); + +var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" +}, AST_Definitions); + +var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } +}); + +/* -----[ OTHER ]----- */ + +var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.args.forEach(function(arg){ + arg._walk(visitor); + }); + }); + } +}); + +var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" +}, AST_Call); + +var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0;) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } +}); + +var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } +}); + +var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Sub = DEFNODE("Sub", null, { + $documentation: "Index-style property access, i.e. `a[\"foo\"]`", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}); + +var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" +}, AST_Unary); + +var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" +}, AST_Unary); + +var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.left._walk(visitor); + this.right._walk(visitor); + }); + } +}); + +var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } +}); + +var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`", +}, AST_Binary); + +/* -----[ LITERALS ]----- */ + +var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.elements.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + +var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.properties.forEach(function(prop){ + prop._walk(visitor); + }); + }); + } +}); + +var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.value._walk(visitor); + }); + } +}); + +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property", +}, AST_ObjectProperty); + +var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property", +}, AST_ObjectProperty); + +var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property", +}, AST_ObjectProperty); + +var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols", +}); + +var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" +}, AST_Symbol); + +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } +}, AST_Symbol); + +var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable", +}, AST_SymbolDeclaration); + +var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" +}, AST_SymbolDeclaration); + +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument", +}, AST_SymbolVar); + +var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function", +}, AST_SymbolDeclaration); + +var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression", +}, AST_SymbolDeclaration); + +var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch", +}, AST_SymbolDeclaration); + +var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LabelRef*] a list of nodes referring to this label" + } +}, AST_Symbol); + +var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)", +}, AST_Symbol); + +var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol", +}, AST_Symbol); + +var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol", +}, AST_Symbol); + +var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } +}); + +var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } +}, AST_Constant); + +var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } +}, AST_Constant); + +var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } +}, AST_Constant); + +var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms", +}, AST_Constant); + +var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null +}, AST_Atom); + +var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0/0 +}, AST_Atom); + +var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: (function(){}()) +}, AST_Atom); + +var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: (function(){}()) +}, AST_Atom); + +var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1/0 +}, AST_Atom); + +var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans", +}, AST_Atom); + +var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false +}, AST_Boolean); + +var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true +}, AST_Boolean); + +/* -----[ TreeWalker ]----- */ + +function TreeWalker(callback) { + this.visit = callback; + this.stack = []; +}; +TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function(){ + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if ((p instanceof AST_If && p.condition === self) || + (p instanceof AST_Conditional && p.condition === self) || + (p instanceof AST_DWLoop && p.condition === self) || + (p instanceof AST_For && p.condition === self) || + (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } + } else { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_Switch + || x instanceof AST_For + || x instanceof AST_ForIn + || x instanceof AST_DWLoop) return x; + } + } + } +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/compress.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/compress.js new file mode 100644 index 0000000..57554fa --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/compress.js @@ -0,0 +1,2028 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) + return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences : !false_by_default, + properties : !false_by_default, + dead_code : !false_by_default, + drop_debugger : !false_by_default, + unsafe : false, + unsafe_comps : false, + conditionals : !false_by_default, + comparisons : !false_by_default, + evaluate : !false_by_default, + booleans : !false_by_default, + loops : !false_by_default, + unused : !false_by_default, + hoist_funs : !false_by_default, + hoist_vars : false, + if_return : !false_by_default, + join_vars : !false_by_default, + cascade : !false_by_default, + side_effects : !false_by_default, + screw_ie8 : false, + + warnings : true, + global_defs : {} + }, true); +}; + +Compressor.prototype = new TreeTransformer; +merge(Compressor.prototype, { + option: function(key) { return this.options[key] }, + warn: function() { + if (this.options.warnings) + AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + // dead code removal might leave further unused declarations. + // this'll usually save very few bytes, but the performance + // hit seems negligible so I'll just drop it here. + + // no point to repeat warnings. + var save_warnings = this.options.warnings; + this.options.warnings = false; + node.drop_unused(this); + this.options.warnings = save_warnings; + } + node._squeezed = true; + return node; + } +}); + +(function(){ + + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor){ + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + }; + + OPT(AST_Node, function(self, compressor){ + return self; + }); + + AST_Node.DEFMETHOD("equivalent_to", function(node){ + // XXX: this is a rather expensive way to test two node's equivalence: + return this.print_to_string() == node.print_to_string(); + }); + + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + }; + + function make_node_from_constant(compressor, val, orig) { + // XXX: WIP. + // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof AST_SymbolRef) { + // var scope = compressor.find_parent(AST_Scope); + // var def = scope.find_variable(node); + // node.thedef = def; + // return node; + // } + // })).transform(compressor); + + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + case "boolean": + return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + }; + + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + }; + + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + }; + + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + return statements; + + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + }; + + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0;) { + var stat = statements[i]; + switch (true) { + case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + CHANGED = true; + // note, ret.length is probably always zero + // because we drop unreachable code before this + // step. nevertheless, it's good to check. + continue loop; + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + //--- + // pretty silly case, but: + // if (foo()) return; return; ==> foo(); return; + if (((in_lambda && ret.length == 0) + || (ret[0] instanceof AST_Return && !ret[0].value)) + && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + //--- + // if (foo()) return x; return y; ==> return foo() ? x : y; + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + //--- + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + ret.unshift(stat); + break; + default: + ret.unshift(stat); + break; + } + } + return ret; + }; + + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat){ + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + }; + + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + }; + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + }; + + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + }; + var ret = [], prev = null; + statements.forEach(function(stat){ + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } + else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch(ex) { + if (ex !== opera) throw ex; + } + } + else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } + else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } + else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } + else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } + else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + }; + + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } + else if (stat instanceof AST_For + && prev instanceof AST_Definitions + && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } + else { + prev = stat; + a.push(stat); + } + return a; + }, []); + }; + + }; + + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node){ + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + }; + + /* -----[ boolean/negation helpers ]----- */ + + // methods to determine whether an expression has a boolean result type + (function (def){ + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function(){ return false }); + def(AST_UnaryPrefix, function(){ + return member(this.operator, unary_bool); + }); + def(AST_Binary, function(){ + return member(this.operator, binary_bool) || + ( (this.operator == "&&" || this.operator == "||") && + this.left.is_boolean() && this.right.is_boolean() ); + }); + def(AST_Conditional, function(){ + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function(){ + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function(){ + return this.cdr.is_boolean(); + }); + def(AST_True, function(){ return true }); + def(AST_False, function(){ return true }); + })(function(node, func){ + node.DEFMETHOD("is_boolean", func); + }); + + // methods to determine if an expression has a string result type + (function (def){ + def(AST_Node, function(){ return false }); + def(AST_String, function(){ return true }); + def(AST_UnaryPrefix, function(){ + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor){ + return this.operator == "+" && + (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor){ + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor){ + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor){ + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor){ + return compressor.option("unsafe") + && this.expression instanceof AST_SymbolRef + && this.expression.name == "String" + && this.expression.undeclared(); + }); + })(function(node, func){ + node.DEFMETHOD("is_string", func); + }); + + function best_of(ast1, ast2) { + return ast1.print_to_string().length > + ast2.print_to_string().length + ? ast2 : ast1; + }; + + // methods to evaluate a constant expression + (function (def){ + // The evaluate method returns an array with one or two + // elements. If the node has been successfully reduced to a + // constant, then the second element tells us the value; + // otherwise the second element is missing. The first element + // of the array is always an AST_Node descendant; when + // evaluation was successful it's a node that represents the + // constant; otherwise it's the original node. + AST_Node.DEFMETHOD("evaluate", function(compressor){ + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(), ast = make_node_from_constant(compressor, val, this); + return [ best_of(ast, this), val ]; + } catch(ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function(){ + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function(){ + // XXX: AST_Function inherits from AST_Scope, which itself + // inherits from AST_Statement; however, an AST_Function + // isn't really a statement. This could byte in other + // places too. :-( Wish JS had multiple inheritance. + return [ this ]; + }); + function ev(node) { + return node._eval(); + }; + def(AST_Node, function(){ + throw def; // not constant + }); + def(AST_Constant, function(){ + return this.getValue(); + }); + def(AST_UnaryPrefix, function(){ + var e = this.expression; + switch (this.operator) { + case "!": return !ev(e); + case "typeof": + // Function would be evaluated to an array and so typeof would + // incorrectly return 'object'. Hence making is a special case. + if (e instanceof AST_Function) return typeof function(){}; + + e = ev(e); + + // typeof returns "object" or "function" on different platforms + // so cannot evaluate reliably + if (e instanceof RegExp) throw def; + + return typeof e; + case "void": return void ev(e); + case "~": return ~ev(e); + case "-": + e = ev(e); + if (e === 0) throw def; + return -e; + case "+": return +ev(e); + } + throw def; + }); + def(AST_Binary, function(){ + var left = this.left, right = this.right; + switch (this.operator) { + case "&&" : return ev(left) && ev(right); + case "||" : return ev(left) || ev(right); + case "|" : return ev(left) | ev(right); + case "&" : return ev(left) & ev(right); + case "^" : return ev(left) ^ ev(right); + case "+" : return ev(left) + ev(right); + case "*" : return ev(left) * ev(right); + case "/" : return ev(left) / ev(right); + case "%" : return ev(left) % ev(right); + case "-" : return ev(left) - ev(right); + case "<<" : return ev(left) << ev(right); + case ">>" : return ev(left) >> ev(right); + case ">>>" : return ev(left) >>> ev(right); + case "==" : return ev(left) == ev(right); + case "===" : return ev(left) === ev(right); + case "!=" : return ev(left) != ev(right); + case "!==" : return ev(left) !== ev(right); + case "<" : return ev(left) < ev(right); + case "<=" : return ev(left) <= ev(right); + case ">" : return ev(left) > ev(right); + case ">=" : return ev(left) >= ev(right); + case "in" : return ev(left) in ev(right); + case "instanceof" : return ev(left) instanceof ev(right); + } + throw def; + }); + def(AST_Conditional, function(){ + return ev(this.condition) + ? ev(this.consequent) + : ev(this.alternative); + }); + def(AST_SymbolRef, function(){ + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init); + throw def; + }); + })(function(node, func){ + node.DEFMETHOD("_eval", func); + }); + + // method to negate an expression + (function(def){ + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + }; + def(AST_Node, function(){ + return basic_negation(this); + }); + def(AST_Statement, function(){ + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function(){ + return basic_negation(this); + }); + def(AST_UnaryPrefix, function(){ + if (this.operator == "!") + return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor){ + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor){ + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor){ + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=" : self.operator = ">" ; return self; + case "<" : self.operator = ">=" ; return self; + case ">=" : self.operator = "<" ; return self; + case ">" : self.operator = "<=" ; return self; + } + } + switch (op) { + case "==" : self.operator = "!="; return self; + case "!=" : self.operator = "=="; return self; + case "===": self.operator = "!=="; return self; + case "!==": self.operator = "==="; return self; + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func){ + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor); + }); + }); + + // determine if expression has side effects + (function(def){ + def(AST_Node, function(){ return true }); + + def(AST_EmptyStatement, function(){ return false }); + def(AST_Constant, function(){ return false }); + def(AST_This, function(){ return false }); + + def(AST_Block, function(){ + for (var i = this.body.length; --i >= 0;) { + if (this.body[i].has_side_effects()) + return true; + } + return false; + }); + + def(AST_SimpleStatement, function(){ + return this.body.has_side_effects(); + }); + def(AST_Defun, function(){ return true }); + def(AST_Function, function(){ return false }); + def(AST_Binary, function(){ + return this.left.has_side_effects() + || this.right.has_side_effects(); + }); + def(AST_Assign, function(){ return true }); + def(AST_Conditional, function(){ + return this.condition.has_side_effects() + || this.consequent.has_side_effects() + || this.alternative.has_side_effects(); + }); + def(AST_Unary, function(){ + return this.operator == "delete" + || this.operator == "++" + || this.operator == "--" + || this.expression.has_side_effects(); + }); + def(AST_SymbolRef, function(){ return false }); + def(AST_Object, function(){ + for (var i = this.properties.length; --i >= 0;) + if (this.properties[i].has_side_effects()) + return true; + return false; + }); + def(AST_ObjectProperty, function(){ + return this.value.has_side_effects(); + }); + def(AST_Array, function(){ + for (var i = this.elements.length; --i >= 0;) + if (this.elements[i].has_side_effects()) + return true; + return false; + }); + // def(AST_Dot, function(){ + // return this.expression.has_side_effects(); + // }); + // def(AST_Sub, function(){ + // return this.expression.has_side_effects() + // || this.property.has_side_effects(); + // }); + def(AST_PropAccess, function(){ + return true; + }); + def(AST_Seq, function(){ + return this.car.has_side_effects() + || this.cdr.has_side_effects(); + }); + })(function(node, func){ + node.DEFMETHOD("has_side_effects", func); + }); + + // tell me if a statement aborts + function aborts(thing) { + return thing && thing.aborts(); + }; + (function(def){ + def(AST_Statement, function(){ return null }); + def(AST_Jump, function(){ return this }); + function block_aborts(){ + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + }; + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function(){ + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + + /* -----[ optimizers ]----- */ + + OPT(AST_Directive, function(self, compressor){ + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + + OPT(AST_Debugger, function(self, compressor){ + if (compressor.option("drop_debugger")) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + + OPT(AST_Block, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_BlockStatement, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: return self.body[0]; + case 0: return make_node(AST_EmptyStatement, self); + } + return self; + }); + + AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + var self = this; + if (compressor.option("unused") + && !(self instanceof AST_Toplevel) + && !self.uses_eval + ) { + var in_use = []; + var initializations = new Dictionary(); + // pass 1: find out which symbols are directly used in + // this scope (not in nested scopes). + var scope = this; + var tw = new TreeWalker(function(node, descend){ + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects()) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + // pass 2: for every used symbol we need to walk its + // initialization code to figure out if it uses other + // symbols (that may not be in_use). + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl){ + // undeclared globals will be instanceof AST_SymbolRef + var init = initializations.get(decl.name); + if (init) init.forEach(function(init){ + var tw = new TreeWalker(function(node){ + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + // pass 3: we should drop declarations not in_use + var tt = new TreeTransformer( + function before(node, descend, in_list) { + if (node instanceof AST_Lambda) { + for (var a = node.argnames, i = a.length; --i >= 0;) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name : sym.name, + file : sym.start.file, + line : sym.start.line, + col : sym.start.col + }); + } + else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name : node.name.name, + file : node.name.start.file, + line : node.name.start.line, + col : node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def){ + if (member(def.name.definition(), in_use)) return true; + var w = { + name : def.name.name, + file : def.name.start.file, + line : def.name.start.line, + col : def.name.start.col + }; + if (def.value && def.value.has_side_effects()) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + // place uninitialized names at the start + def = mergeSort(def, function(a, b){ + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + // for unused names whose initialization has + // side effects, we can cascade the init. code + // into the next one, or next statement. + var side_effects = []; + for (var i = 0; i < def.length;) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For && node.init instanceof AST_BlockStatement) { + descend(node, this); + // certain combination of unused name + side effect leads to: + // https://github.com/mishoo/UglifyJS2/issues/44 + // that's an invalid AST. + // We fix it at this stage by moving the `var` outside the `for`. + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + if (node instanceof AST_Scope && node !== self) + return node; + } + ); + self.transform(tt); + } + }); + + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + // let's count var_decl first, we seem to waste a lot of + // space if we hoist `var` when there's only one. + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_Scope && node !== self) + return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer( + function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def){ + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) + return node; // to avoid descending in nested scopes + } + } + ); + self = self.transform(tt); + if (vars_found > 0) { + // collect only vars which don't show up in self's arguments list + var defs = []; + vars.each(function(def, name){ + if (self instanceof AST_Lambda + && find_if(function(x){ return x.name == def.name.name }, + self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + // try to merge in assignments + for (var i = 0; i < self.body.length;) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign + && expr.operator == "=" + && (sym = expr.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq + && (assign = expr.car) instanceof AST_Assign + && assign.operator == "=" + && (sym = assign.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + }; + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + + OPT(AST_SimpleStatement, function(self, compressor){ + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects()) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + + OPT(AST_DWLoop, function(self, compressor){ + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + return self; + }); + + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + + OPT(AST_For, function(self, compressor){ + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } + else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + + OPT(AST_If, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + // if condition can be statically determined, warn and drop + // one of the blocks. note, statically determined implies + // “has no side effects”; also it doesn't work for cases like + // `x && true`, though it probably should. + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; // because we already do the switch here. + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.body, + alternative : self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : negated, + right : self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "&&", + left : self.condition, + right : self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement + && self.alternative + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : self.condition, + right : self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit + && self.alternative instanceof AST_Exit + && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + + OPT(AST_Switch, function(self, compressor){ + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + for(;;) { + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; // last statement + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + last_branch.body.pop(); + if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + self.body.pop(); + continue; + } + } + break; + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + // constant expression + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list){ + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + // no need to descend these node types + return node; + } + else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch){ + return a.concat(branch.body); + }, []) + }).transform(compressor); + } + else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } + else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } + else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } + else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + // got a case with non-constant expression, baling out + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); // so that's able to see parent nodes + self = self.transform(tt); + } catch(ex) { + if (ex !== self) throw ex; + } + return self; + }); + + OPT(AST_Case, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_Try, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + AST_Definitions.DEFMETHOD("remove_initializers", function(){ + this.definitions.forEach(function(def){ def.value = null }); + }); + + AST_Definitions.DEFMETHOD("to_assignments", function(){ + var assignments = this.definitions.reduce(function(a, def){ + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator : "=", + left : name, + right : def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + + OPT(AST_Definitions, function(self, compressor){ + if (self.definitions.length == 0) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_Function, function(self, compressor){ + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + + OPT(AST_Call, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }); + } + break; + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { value: "" }) + }); + case "Function": + if (all(self.args, function(x){ return x instanceof AST_String })) { + // quite a corner-case, but we can handle it: + // https://github.com/mishoo/UglifyJS2/issues/203 + // if the code argument is a constant, then we can minify it. + try { + var code = "(function(" + self.args.slice(0, -1).map(function(arg){ + return arg.value; + }).join(",") + "){" + self.args[self.args.length - 1].value + "})()"; + var ast = parse(code); + ast.figure_out_scope(); + var comp = new Compressor(compressor.options); + ast = ast.transform(comp); + ast.figure_out_scope(); + ast.mangle_names(); + var fun = ast.body[0].body.expression; + var args = fun.argnames.map(function(arg, i){ + return make_node(AST_String, self.args[i], { + value: arg.print_to_string() + }); + }); + var code = OutputStream(); + AST_BlockStatement.prototype._codegen.call(fun, fun, code); + code = code.toString().replace(/^\{|\}$/g, ""); + args.push(make_node(AST_String, self.args[self.args.length - 1], { + value: code + })); + self.args = args; + return self; + } catch(ex) { + if (ex instanceof JS_Parse_Error) { + compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); + compressor.warn(ex.toString()); + } else { + console.log(ex); + } + } + } + break; + } + } + else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { value: "" }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function + && self.args.length == 0 + && !AST_Block.prototype.has_side_effects.call(self.expression)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self; + }); + + OPT(AST_New, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + + OPT(AST_Seq, function(self, compressor){ + if (!compressor.option("side_effects")) + return self; + if (!self.car.has_side_effects()) { + // we shouldn't compress (1,eval)(something) to + // eval(something) because that changes the meaning of + // eval (becomes lexical instead of global). + var p; + if (!(self.cdr instanceof AST_SymbolRef + && self.cdr.name == "eval" + && self.cdr.undeclared() + && (p = compressor.parent()) instanceof AST_Call + && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign + && !self.car.left.has_side_effects() + && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects() + && !self.cdr.has_side_effects() + && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + + AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + OPT(AST_UnaryPostfix, function(self, compressor){ + return self.lift_sequences(compressor); + }); + + OPT(AST_UnaryPrefix, function(self, compressor){ + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + // !!foo ==> foo, if we're in boolean context + return e.expression; + } + break; + case "typeof": + // typeof always returns a non-empty string, thus it's + // always true in booleans + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + + AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq + && !(this.operator == "||" || this.operator == "&&") + && !this.left.has_side_effects()) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + var commutativeOperators = makePredicate("== === != !== * & | ^"); + + OPT(AST_Binary, function(self, compressor){ + function reverse(op, force) { + if (force || !(self.left.has_side_effects() || self.right.has_side_effects())) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant + && !(self.left instanceof AST_Constant)) { + // if right is a constant, whatever side effects the + // left side might have could not influence the + // result. hence, force switch. + reverse(null, true); + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || + (self.left.is_boolean() && self.right.is_boolean())) { + self.operator = self.operator.substr(0, 2); + } + // XXX: intentionally falling down to the next case + case "==": + case "!=": + if (self.left instanceof AST_String + && self.left.value == "undefined" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "typeof" + && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) + || !self.right.expression.undeclared()) { + self.right = self.right.expression; + self.left = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + var exp = self.evaluate(compressor); + if (exp.length > 1) { + if (best_of(exp[0], self) !== self) + return exp[0]; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) + || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } + } + if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } + return self; + }); + + OPT(AST_SymbolRef, function(self, compressor){ + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self); + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + + OPT(AST_Undefined, function(self, compressor){ + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name : "undefined", + scope : scope, + thedef : undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + + var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + OPT(AST_Assign, function(self, compressor){ + self = self.lift_sequences(compressor); + if (self.operator == "=" + && self.left instanceof AST_SymbolRef + && self.right instanceof AST_Binary + && self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + + OPT(AST_Conditional, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign + && alternative instanceof AST_Assign + && consequent.operator == alternative.operator + && consequent.left.equivalent_to(alternative.left) + ) { + /* + * Stuff like this: + * if (foo) exp = something; else exp = something_else; + * ==> + * exp = foo ? something : something_else; + */ + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + + OPT(AST_Boolean, function(self, compressor){ + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" + || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator : p.operator, + value : self.value, + file : p.start.file, + line : p.start.line, + col : p.start.col, + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + + OPT(AST_Sub, function(self, compressor){ + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if ((compressor.option("screw_ie8") && RESERVED_WORDS(prop)) + || (!(RESERVED_WORDS(prop)) && is_identifier_string(prop))) { + return make_node(AST_Dot, self, { + expression : self.expression, + property : prop + }); + } + } + return self; + }); + + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + }; + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + +})(); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/mozilla-ast.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/mozilla-ast.js new file mode 100644 index 0000000..d795094 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/mozilla-ast.js @@ -0,0 +1,267 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +(function(){ + + var MOZ_TO_ME = { + TryStatement : function(M) { + return new AST_Try({ + start : my_start_token(M), + end : my_end_token(M), + body : from_moz(M.block).body, + bcatch : from_moz(M.handlers[0]), + bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause : function(M) { + return new AST_Catch({ + start : my_start_token(M), + end : my_end_token(M), + argname : from_moz(M.param), + body : from_moz(M.body).body + }); + }, + ObjectExpression : function(M) { + return new AST_Object({ + start : my_start_token(M), + end : my_end_token(M), + properties : M.properties.map(function(prop){ + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start : my_start_token(key), + end : my_end_token(prop.value), + key : name, + value : from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression : function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression : function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start : my_start_token(M), + end : my_end_token(M), + property : M.computed ? from_moz(M.property) : M.property.name, + expression : from_moz(M.object) + }); + }, + SwitchCase : function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start : my_start_token(M), + end : my_end_token(M), + expression : from_moz(M.test), + body : M.consequent.map(from_moz) + }); + }, + Literal : function(M) { + var val = M.value, args = { + start : my_start_token(M), + end : my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + case "number": + args.value = val; + return new AST_Number(args); + case "boolean": + return new (val ? AST_True : AST_False)(args); + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This + : p.type == "LabeledStatement" ? AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) + : p.type == "CatchClause" ? AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef + : AST_SymbolRef)({ + start : my_start_token(M), + end : my_end_token(M), + name : M.name + }); + } + }; + + function From_Moz_Unary(M) { + var prefix = "prefix" in M ? M.prefix + : M.type == "UnaryExpression" ? true : false; + return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start : my_start_token(M), + end : my_end_token(M), + operator : M.operator, + expression : from_moz(M.argument) + }); + }; + + var ME_TO_MOZ = {}; + + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + + /* -----[ tools ]----- */ + + function my_start_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.start.line, + col : moznode.loc && moznode.loc.start.column, + pos : moznode.start, + endpos : moznode.start + }); + }; + + function my_end_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.end.line, + col : moznode.loc && moznode.loc.end.column, + pos : moznode.end, + endpos : moznode.end + }); + }; + + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + + "start: my_start_token(M),\n" + + "end: my_end_token(M)"; + + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + + // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); + // console.log(moz_to_me); + + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( + mytype, my_start_token, my_end_token, from_moz + ); + return MOZ_TO_ME[moztype] = moz_to_me; + }; + + var FROM_MOZ_STACK = null; + + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + }; + + AST_Node.from_mozilla_ast = function(node){ + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + +})(); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/output.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/output.js new file mode 100644 index 0000000..60a4a26 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/output.js @@ -0,0 +1,1229 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function OutputStream(options) { + + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : true, + ascii_only : false, + inline_script : false, + width : 80, + max_line_len : 32000, + ie_proof : true, + beautify : false, + source_map : null, + bracketize : false, + semicolons : true, + comments : false, + preserve_line : false, + negate_iife : !(options && options.beautify), + }, true); + + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + + function to_ascii(str, identifier) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + if (code.length <= 2 && !identifier) { + while (code.length < 2) code = "0" + code; + return "\\x" + code; + } else { + while (code.length < 4) code = "0" + code; + return "\\u" + code; + } + }); + }; + + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; + }; + + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name, true); + return name; + }; + + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + }; + + /* -----[ beautification/minification ]----- */ + + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + + function last_char() { + return last.charAt(last.length - 1); + }; + + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) + print("\n"); + }; + + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) + might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + + if (might_need_space) { + var prev = last_char(); + if ((is_identifier_char(prev) + && (is_identifier_char(ch) || ch == "\\")) + || (/^[\+\-\/]$/.test(ch) && ch == prev)) + { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + }; + + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? 0.5 : 0)); + } + } : noop; + + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { return cont() }; + + var newline = options.beautify ? function() { + print("\n"); + } : noop; + + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + + function force_semicolon() { + might_need_semicolon = false; + print(";"); + }; + + function next_indent() { + return indentation + options.indent_level; + }; + + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function(){ + ret = cont(); + }); + indent(); + print("}"); + return ret; + }; + + function with_parens(cont) { + print("("); + //XXX: still nice to have that for argument lists + //var ret = with_indent(current_col, cont); + var ret = cont(); + print(")"); + return ret; + }; + + function with_square(cont) { + print("["); + //var ret = with_indent(current_col, cont); + var ret = cont(); + print("]"); + return ret; + }; + + function comma() { + print(","); + space(); + }; + + function colon() { + print(":"); + if (options.space_colon) space(); + }; + + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add( + token.file || "?", + current_line, current_col, + token.line, token.col, + (!name && token.type == "name") ? token.value : name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }) + } + } : noop; + + function get() { + return OUTPUT; + }; + + var stack = []; + return { + get : get, + toString : get, + indent : indent, + indentation : function() { return indentation }, + current_width : function() { return current_col - indentation }, + should_break : function() { return options.width && this.current_width() >= options.width }, + newline : newline, + print : print, + space : space, + comma : comma, + colon : colon, + last : function() { return last }, + semicolon : semicolon, + force_semicolon : force_semicolon, + to_ascii : to_ascii, + print_name : function(name) { print(make_name(name)) }, + print_string : function(str) { print(encode_string(str)) }, + next_indent : next_indent, + with_indent : with_indent, + with_block : with_block, + with_parens : with_parens, + with_square : with_square, + add_mapping : add_mapping, + option : function(opt) { return options[opt] }, + line : function() { return current_line }, + col : function() { return current_col }, + pos : function() { return current_pos }, + push_node : function(node) { stack.push(node) }, + pop_node : function() { return stack.pop() }, + stack : function() { return stack }, + parent : function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + +}; + +/* -----[ code generators ]----- */ + +(function(){ + + /* -----[ utils ]----- */ + + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + }; + + AST_Node.DEFMETHOD("print", function(stream, force_parens){ + var self = this, generator = self._codegen; + stream.push_node(self); + var needs_parens = self.needs_parens(stream); + var fc = self instanceof AST_Function && stream.option("negate_iife"); + if (force_parens || (needs_parens && !fc)) { + stream.with_parens(function(){ + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + }); + } else { + self.add_comments(stream); + if (needs_parens && fc) stream.print("!"); + self.add_source_map(stream); + generator(self, stream); + } + stream.pop_node(); + }); + + AST_Node.DEFMETHOD("print_to_string", function(options){ + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + + /* -----[ comments ]----- */ + + AST_Node.DEFMETHOD("add_comments", function(output){ + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // if this node is `return` or `throw`, we cannot allow comments before + // the returned or thrown value. + if (self instanceof AST_Exit && + self.value && self.value.start.comments_before.length > 0) { + comments = (comments || []).concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + + if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment); + }); + } + comments.forEach(function(c){ + if (c.type == "comment1") { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + + /* -----[ PARENTHESES ]----- */ + + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + }; + + PARENS(AST_Node, function(){ + return false; + }); + + // a function expression needs parens around it when it's provably + // the first token to appear in a statement. + PARENS(AST_Function, function(output){ + return first_in_statement(output); + }); + + // same goes for an object literal, because otherwise it would be + // interpreted as a block of code. + PARENS(AST_Object, function(output){ + return first_in_statement(output); + }); + + PARENS(AST_Unary, function(output){ + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + + PARENS(AST_Seq, function(output){ + var p = output.parent(); + return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST_Unary // !(foo, bar, baz) + || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * ==> 20 (side effect, set a := 10 and b := 20) */ + ; + }); + + PARENS(AST_Binary, function(output){ + var p = output.parent(); + // (foo && bar)() + if (p instanceof AST_Call && p.expression === this) + return true; + // typeof (foo && bar) + if (p instanceof AST_Unary) + return true; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + // this deals with precedence: 3 * (2 + 1) + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp + || (pp == sp + && this === p.right + && !(so == po && + (so == "*" || + so == "&&" || + so == "||")))) { + return true; + } + } + }); + + PARENS(AST_PropAccess, function(output){ + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + // i.e. new (foo.bar().baz) + // + // if there's one call into this subtree, then we need + // parens around it too, otherwise the call will be + // interpreted as passing the arguments to the upper New + // expression. + try { + this.walk(new TreeWalker(function(node){ + if (node instanceof AST_Call) throw p; + })); + } catch(ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + + PARENS(AST_Call, function(output){ + var p = output.parent(); + return p instanceof AST_New && p.expression === this; + }); + + PARENS(AST_New, function(output){ + var p = output.parent(); + if (no_constructor_parens(this, output) + && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + return true; + }); + + PARENS(AST_Number, function(output){ + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + PARENS(AST_NaN, function(output){ + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + // !(a = false) → true + if (p instanceof AST_Unary) + return true; + // 1 + (a = 2) + 3 → 6, side effect setting a = 2 + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + return true; + // (a = func)() —or— new (a = Object)() + if (p instanceof AST_Call && p.expression === this) + return true; + // (a = foo) ? bar : baz + if (p instanceof AST_Conditional && p.condition === this) + return true; + // (a = foo)["prop"] —or— (a = foo).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }; + + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + + /* -----[ PRINTERS ]----- */ + + DEFPRINT(AST_Directive, function(self, output){ + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output){ + output.print("debugger"); + output.semicolon(); + }); + + /* -----[ statements ]----- */ + + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i){ + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + }; + + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + force_statement(this.body, output); + }); + + DEFPRINT(AST_Statement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output){ + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output){ + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function(){ + display_body(body, false, output); + }); + else output.print("{}"); + }; + DEFPRINT(AST_BlockStatement, function(self, output){ + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output){ + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output){ + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output){ + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output){ + output.print("with"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + + /* -----[ functions ]----- */ + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function(){ + self.argnames.forEach(function(arg, i){ + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output){ + self._do_print(output); + }); + + /* -----[ exits ]----- */ + AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output){ + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output){ + self._do_print(output, "throw"); + }); + + /* -----[ loop control ]----- */ + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output){ + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output){ + self._do_print(output, "continue"); + }); + + /* -----[ if ]----- */ + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + if (!self.body) + return output.force_semicolon(); + if (self.body instanceof AST_Do + && output.option("ie_proof")) { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE + // croaks with "syntax error" on code like this: if (foo) + // do ... while(cond); else ... we need block brackets + // around do/while + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } + else if (b instanceof AST_StatementWithBody) { + b = b.body; + } + else break; + } + force_statement(self.body, output); + }; + DEFPRINT(AST_If, function(self, output){ + output.print("if"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + + /* -----[ switch ]----- */ + DEFPRINT(AST_Switch, function(self, output){ + output.print("switch"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function(){ + self.body.forEach(function(stmt, i){ + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); + else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt){ + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output){ + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output){ + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + + /* -----[ exceptions ]----- */ + DEFPRINT(AST_Try, function(self, output){ + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output){ + output.print("catch"); + output.space(); + output.with_parens(function(){ + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output){ + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + + /* -----[ var/const ]----- */ + AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i){ + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) + output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output){ + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output){ + self._do_print(output, "const"); + }); + + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); + else try { + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw output; + })); + node.print(output); + } catch(ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + }; + + DEFPRINT(AST_VarDef, function(self, output){ + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + + /* -----[ other expressions ]----- */ + DEFPRINT(AST_Call, function(self, output){ + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) + return; + output.with_parens(function(){ + self.args.forEach(function(expr, i){ + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output){ + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + + AST_Seq.DEFMETHOD("_do_print", function(output){ + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output){ + self._do_print(output); + // var p = output.parent(); + // if (p instanceof AST_Statement) { + // output.with_indent(output.next_indent(), function(){ + // self._do_print(output); + // }); + // } else { + // self._do_print(output); + // } + }); + DEFPRINT(AST_Dot, function(self, output){ + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + // the name after dot would be mapped about here. + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output){ + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output){ + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) + output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output){ + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output){ + self.left.print(output); + output.space(); + output.print(self.operator); + output.space(); + self.right.print(output); + }); + DEFPRINT(AST_Conditional, function(self, output){ + self.condition.print(output); + output.space(); + output.print("?"); + output.space(); + self.consequent.print(output); + output.space(); + output.colon(); + self.alternative.print(output); + }); + + /* -----[ literals ]----- */ + DEFPRINT(AST_Array, function(self, output){ + output.with_square(function(){ + var a = self.elements, len = a.length; + if (len > 0) output.space(); + a.forEach(function(exp, i){ + if (i) output.comma(); + exp.print(output); + }); + if (len > 0) output.space(); + }); + }); + DEFPRINT(AST_Object, function(self, output){ + if (self.properties.length > 0) output.with_block(function(){ + self.properties.forEach(function(prop, i){ + if (i) { + output.print(","); + output.newline(); + } + output.indent(); + prop.print(output); + }); + output.newline(); + }); + else output.print("{}"); + }); + DEFPRINT(AST_ObjectKeyVal, function(self, output){ + var key = self.key; + if (output.option("quote_keys")) { + output.print_string(key + ""); + } else if ((typeof key == "number" + || !output.option("beautify") + && +key + "" == key) + && parseFloat(key) >= 0) { + output.print(make_num(key)); + } else if (!is_identifier(key)) { + output.print_string(key); + } else { + output.print_name(key); + } + output.colon(); + self.value.print(output); + }); + DEFPRINT(AST_ObjectSetter, function(self, output){ + output.print("set"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_ObjectGetter, function(self, output){ + output.print("get"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_Symbol, function(self, output){ + var def = self.definition(); + output.print_name(def ? def.mangled_name || def.name : self.name); + }); + DEFPRINT(AST_Undefined, function(self, output){ + output.print("void 0"); + }); + DEFPRINT(AST_Hole, noop); + DEFPRINT(AST_Infinity, function(self, output){ + output.print("1/0"); + }); + DEFPRINT(AST_NaN, function(self, output){ + output.print("0/0"); + }); + DEFPRINT(AST_This, function(self, output){ + output.print("this"); + }); + DEFPRINT(AST_Constant, function(self, output){ + output.print(self.getValue()); + }); + DEFPRINT(AST_String, function(self, output){ + output.print_string(self.getValue()); + }); + DEFPRINT(AST_Number, function(self, output){ + output.print(make_num(self.getValue())); + }); + DEFPRINT(AST_RegExp, function(self, output){ + var str = self.getValue().toString(); + if (output.option("ascii_only")) + str = output.to_ascii(str); + output.print(str); + var p = output.parent(); + if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) + output.print(" "); + }); + + function force_statement(stat, output) { + if (output.option("bracketize")) { + if (!stat || stat instanceof AST_EmptyStatement) + output.print("{}"); + else if (stat instanceof AST_BlockStatement) + stat.print(output); + else output.with_block(function(){ + output.indent(); + stat.print(output); + output.newline(); + }); + } else { + if (!stat || stat instanceof AST_EmptyStatement) + output.force_semicolon(); + else + stat.print(output); + } + }; + + // return true if the node at the top of the stack (that means the + // innermost node in the current output) is lexically the first in + // a statement. + function first_in_statement(output) { + var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + while (i > 0) { + if (p instanceof AST_Statement && p.body === node) + return true; + if ((p instanceof AST_Seq && p.car === node ) || + (p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) || + (p instanceof AST_Dot && p.expression === node ) || + (p instanceof AST_Sub && p.expression === node ) || + (p instanceof AST_Conditional && p.condition === node ) || + (p instanceof AST_Binary && p.left === node ) || + (p instanceof AST_UnaryPostfix && p.expression === node )) + { + node = p; + p = a[--i]; + } else { + return false; + } + } + }; + + // self should be AST_New. decide if we want to show parens or not. + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.option("beautify"); + }; + + function best_of(a) { + var best = a[0], len = best.length; + for (var i = 1; i < a.length; ++i) { + if (a[i].length < len) { + best = a[i]; + len = best.length; + } + } + return best; + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + function make_block(stmt, output) { + if (stmt instanceof AST_BlockStatement) { + stmt.print(output); + return; + } + output.with_block(function(){ + output.indent(); + stmt.print(output); + output.newline(); + }); + }; + + /* -----[ source map generators ]----- */ + + function DEFMAP(nodetype, generator) { + nodetype.DEFMETHOD("add_source_map", function(stream){ + generator(this, stream); + }); + }; + + // We could easily add info for ALL nodes, but it seems to me that + // would be quite wasteful, hence this noop in the base class. + DEFMAP(AST_Node, noop); + + function basic_sourcemap_gen(self, output) { + output.add_mapping(self.start); + }; + + // XXX: I'm not exactly sure if we need it for all of these nodes, + // or if we should add even more. + + DEFMAP(AST_Directive, basic_sourcemap_gen); + DEFMAP(AST_Debugger, basic_sourcemap_gen); + DEFMAP(AST_Symbol, basic_sourcemap_gen); + DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it + DEFMAP(AST_Lambda, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_New, basic_sourcemap_gen); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); + DEFMAP(AST_ObjectProperty, function(self, output){ + output.add_mapping(self.start, self.key); + }); + +})(); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/parse.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/parse.js new file mode 100644 index 0000000..e561ab6 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/parse.js @@ -0,0 +1,1410 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; +var KEYWORDS_ATOM = 'false null true'; +var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile' + + " " + KEYWORDS_ATOM + " " + KEYWORDS; +var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; + +KEYWORDS = makePredicate(KEYWORDS); +RESERVED_WORDS = makePredicate(RESERVED_WORDS); +KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); +KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); + +var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = makePredicate([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); + +var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); + +var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(code) { + return (code >= 97 && code <= 122) + || (code >= 65 && code <= 90) + || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); +}; + +function is_digit(code) { + return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(code) { + return is_digit(code) || is_letter(code); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier(name) { + return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); +}; + +function is_identifier_start(code) { + return code == 36 || code == 95 || is_letter(code); +}; + +function is_identifier_char(ch) { + var code = ch.charCodeAt(0); + return is_identifier_start(code) + || is_digit(code) + || code == 8204 // \u200c: zero-width non-joiner + || code == 8205 // \u200d: zero-width joiner (in my ECMA-262 PDF, this is also 200c) + || is_unicode_combining_mark(ch) + || is_unicode_connector_punctuation(ch) + ; +}; + +function is_identifier_string(str){ + var i = str.length; + if (i == 0) return false; + if (is_digit(str.charCodeAt(0))) return false; + while (--i >= 0) { + if (!is_identifier_char(str.charAt(i))) + return false; + } + return true; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + this.stack = new Error().stack; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, filename, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT, filename) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''), + filename : filename, + pos : 0, + tokpos : 0, + line : 1, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) || + (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || + (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before, + file : filename + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return new AST_Token(ret); + }; + + function skip_whitespace() { + while (WHITESPACE_CHARS(peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch, i = 0; + while ((ch = peek()) && pred(ch, i++)) + ret += next(); + return ret; + }; + + function parse_error(err) { + js_error(err, filename, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + var code = ch.charCodeAt(0); + switch (code) { + case 120: case 88: // xX + return has_x ? false : (has_x = true); + case 101: case 69: // eE + return has_x ? true : has_e ? false : (has_e = after_e = true); + case 45: // - + return after_e || (i == 0 && !prefix); + case 43: // + + return after_e; + case (after_e = false, 46): // . + return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; + } + return is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110 : return "\n"; + case 114 : return "\r"; + case 116 : return "\t"; + case 98 : return "\b"; + case 118 : return "\u000b"; // \v + case 102 : return "\f"; + case 48 : return "\0"; + case 120 : return String.fromCharCode(hex_bytes(2)); // \x + case 117 : return String.fromCharCode(hex_bytes(4)); // \u + case 10 : return ""; // newline + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + var read_string = with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); + } + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ + next(); + var i = find("*/", true); + var text = S.text.substring(S.pos, i); + var a = text.split("\n"), n = a.length; + // update stream position + S.pos = i + 2; + S.line += n - 1; + if (n > 1) S.col = a[n - 1].length; + else S.col += a[n - 1].length; + S.col += 2; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + return token("comment2", text, true); + }); + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", new RegExp(regexp, mods)); + }); + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (OPERATORS(bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek().charCodeAt(0)) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return KEYWORDS_ATOM(word) ? token("atom", word) + : !KEYWORDS(word) ? token("name", word) + : OPERATORS(word) ? token("operator", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + return function(x) { + try { + return cont(x); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(); + case 46: return handle_dot(); + case 47: return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + +var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function parse($TEXT, options) { + + options = defaults(options, { + strict : false, + filename : null, + toplevel : null, + expression : false + }); + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + ctx.filename, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !options.strict && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + }; + + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + }; + + var statement = embed_tokens(function() { + var tmp; + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + // XXXv2: decide how to fix directives + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start : S.token, + body : block_(), + end : prev() + }); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return new AST_EmptyStatement(); + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body : in_loop(statement), + condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) + }); + + case "while": + return new AST_While({ + condition : parenthesised(), + body : in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return new AST_Return({ + value: ( is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : (tmp = expression(true), semicolon(), tmp) ) + }); + + case "switch": + return new AST_Switch({ + expression : parenthesised(), + body : in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression : parenthesised(), + body : statement() + }); + + default: + unexpected(); + } + } + }); + + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + return new AST_LabeledStatement({ body: stat, label: label }); + }; + + function simple_statement(tmp) { + return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + }; + + function break_cont(type) { + var label = null; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + if (!find_if(function(l){ return l.name == label.name }, S.labels)) + croak("Undefined label " + label.name); + } + else if (S.in_loop == 0) + croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + return new type({ label: label }); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) + croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init : init, + condition : test, + step : step, + body : in_loop(statement) + }); + }; + + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init : init, + name : lhs, + object : obj, + body : in_loop(statement) + }); + }; + + var function_ = function(in_statement, ctor) { + var is_accessor = ctor === AST_Accessor; + var name = (is("name") ? as_symbol(in_statement + ? AST_SymbolDefun + : is_accessor + ? AST_SymbolAccessor + : AST_SymbolLambda) + : is_accessor && (is("string") || is("num")) ? as_atom_node() + : null); + if (in_statement && !name) + unexpected(); + expect("("); + if (!ctor) ctor = in_statement ? AST_Defun : AST_Function; + return new ctor({ + name: name, + argnames: (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + })(true, []), + body: (function(loop, labels){ + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + })(S.in_loop, S.labels) + }); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition : cond, + body : body, + alternative : belse + }); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start : (tmp = S.token, next(), tmp), + expression : expression(true), + body : cur + }); + a.push(branch); + expect(":"); + } + else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start : (tmp = S.token, next(), expect(":"), tmp), + body : cur + }); + a.push(branch); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + }; + + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start : start, + argname : name, + body : block_(), + end : prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start : start, + body : block_(), + end : prev() + }); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return new AST_Try({ + body : body, + bcatch : bcatch, + bfinally : bfinally + }); + }; + + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start : S.token, + name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value : is("operator", "=") ? (next(), expression(false, no_in)) : null, + end : prev() + })); + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + var var_ = function(no_in) { + return new AST_Var({ + start : prev(), + definitions : vardefs(no_in, false), + end : prev() + }); + }; + + var const_ = function() { + return new AST_Const({ + start : prev(), + definitions : vardefs(false, true), + end : prev() + }); + }; + + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start : start, + expression : newexp, + args : args, + end : prev() + }), true); + }; + + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + return as_symbol(AST_SymbolRef); + case "num": + ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + break; + case "string": + ret = new AST_String({ start: tok, end: tok, value: tok.value }); + break; + case "regexp": + ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + break; + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ start: tok, end: tok }); + break; + case "true": + ret = new AST_True({ start: tok, end: tok }); + break; + case "null": + ret = new AST_Null({ start: tok, end: tok }); + break; + } + break; + } + next(); + return ret; + }; + + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + case "[": + return subscripts(array_(), allow_calls); + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(false); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ start: S.token, end: S.token })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) + // allow trailing comma + break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start : start, + key : name, + value : expression(false), + end : prev() + })); + } + next(); + return new AST_Object({ properties: a }); + }); + + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var name = S.token.value; + var sym = new (name == "this" ? AST_This : type)({ + name : String(S.token.value), + start : S.token, + end : S.token + }); + next(); + return sym; + }; + + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start : start, + expression : expr, + property : as_name(), + end : prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start : start, + expression : expr, + property : prop, + end : prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start : start, + expression : expr, + args : expr_list(")"), + end : prev() + }), true); + } + return expr; + }; + + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return new ctor({ operator: op, expression: expr }); + }; + + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start : left.start, + left : left, + operator : op, + right : right, + end : right.end + }), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start : start, + condition : expr, + consequent : yes, + alternative : expression(false, no_in), + end : peek() + }); + } + return expr; + }; + + function is_assignable(expr) { + if (!options.strict) return true; + if (expr instanceof AST_This) return false; + return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol); + }; + + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start : start, + left : left, + operator : val, + right : maybe_assign(no_in), + end : prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start : start, + car : expr, + cdr : expression(true, no_in), + end : peek() + }); + } + return expr; + }; + + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + }; + + if (options.expression) { + return expression(true); + } + + return (function(){ + var start = S.token; + var body = []; + while (!is("eof")) + body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + } + return toplevel; + })(); + +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/scope.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/scope.js new file mode 100644 index 0000000..d15cec7 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/scope.js @@ -0,0 +1,581 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; +}; + +SymbolDef.prototype = { + unmangleable: function(options) { + return (this.global && !(options && options.toplevel)) + || this.undeclared + || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) { + var s = this.scope; + if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) + s = s.parent_scope; + this.mangled_name = s.next_mangled(options); + } + } +}; + +AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions + var self = this; + var scope = self.parent_scope = null; + var labels = new Dictionary(); + var nesting = 0; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + var save_labels = labels; + ++nesting; + scope = node; + labels = new Dictionary(); + descend(); + labels = save_labels; + scope = save_scope; + --nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) + s.uses_with = true; + return; + } + if (node instanceof AST_LabeledStatement) { + var l = node.label; + if (labels.has(l.name)) + throw new Error(string_template("Label {name} defined twice", l)); + labels.set(l.name, l); + descend(); + labels.del(l.name); + return true; // no descend again + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_Label) { + node.thedef = node; + node.init_scope_vars(); + } + if (node instanceof AST_SymbolLambda) { + scope.def_function(node); + } + else if (node instanceof AST_SymbolDefun) { + // Careful here, the scope where this should be defined is + // the parent scope. The reason is that we enter a new + // scope when we encounter the AST_Defun node (which is + // instanceof AST_Scope) but we get to the symbol a bit + // later. + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolVar + || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } + else if (node instanceof AST_SymbolCatch) { + // XXX: this is wrong according to ECMA-262 (12.4). the + // `catch` argument name should be visible only inside the + // catch block. For a quick fix AST_Catch should inherit + // from AST_Scope. Keeping it this way because of IE, + // which doesn't obey the standard. (it introduces the + // identifier in the enclosing scope) + scope.def_variable(node); + } + if (node instanceof AST_LabelRef) { + var sym = labels.get(node.name); + if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { + name: node.name, + line: node.start.line, + col: node.start.col + })); + node.thedef = sym; + } + }); + self.walk(tw); + + // pass 2: find back references and eval + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_LabelRef) { + node.reference(); + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + g.global = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) + s.uses_eval = true; + } + if (name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); +}); + +AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = null; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables + this.nesting = nesting; // the nesting level of this scope (0 means toplevel) +}); + +AST_Scope.DEFMETHOD("strict", function(){ + return this.has_directive("use strict"); +}); + +AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; +}); + +AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; +}); + +AST_Label.DEFMETHOD("init_scope_vars", function(){ + this.references = []; +}); + +AST_LabelRef.DEFMETHOD("reference", function(){ + this.thedef.references.push(this); +}); + +AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) + || (this.parent_scope && this.parent_scope.find_variable(name)); +}); + +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + +AST_Scope.DEFMETHOD("def_function", function(symbol){ + this.functions.set(symbol.name, this.def_variable(symbol)); +}); + +AST_Scope.DEFMETHOD("def_variable", function(symbol){ + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; +}); + +AST_Scope.DEFMETHOD("next_mangled", function(options){ + var ext = this.enclosed; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; // skip over "do" + // we must ensure that the mangled name does not shadow a name + // from some parent scope that is referenced in this or in + // inner scopes. + for (var i = ext.length; --i >= 0;) { + var sym = ext[i]; + var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); + if (m == name) continue out; + } + return m; + } +}); + +AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; +}); + +AST_Symbol.DEFMETHOD("unmangleable", function(options){ + return this.definition().unmangleable(options); +}); + +// property accessors are not mangleable +AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ + return true; +}); + +// labels are always mangleable +AST_Label.DEFMETHOD("unmangleable", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("unreferenced", function(){ + return this.definition().references.length == 0 + && !(this.scope.uses_eval || this.scope.uses_with); +}); + +AST_Symbol.DEFMETHOD("undeclared", function(){ + return this.definition().undeclared; +}); + +AST_LabelRef.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Label.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("definition", function(){ + return this.thedef; +}); + +AST_Symbol.DEFMETHOD("global", function(){ + return this.definition().global; +}); + +AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return defaults(options, { + except : [], + eval : false, + sort : false, + toplevel : false, + screw_ie8 : false + }); +}); + +AST_Toplevel.DEFMETHOD("mangle_names", function(options){ + options = this._default_mangler_options(options); + // We only need to mangle declaration nodes. Special logic wired + // into the code generator will display the mangled name if it's + // present (and for AST_SymbolRef-s it'll use the mangled name of + // the AST_SymbolDeclaration that it points to). + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_LabeledStatement) { + // lname is incremented when we get to the AST_Label + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b){ + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def){ def.mangle(options) }); +}); + +AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node){ + if (node instanceof AST_Constant) + base54.consider(node.print_to_string()); + else if (node instanceof AST_Return) + base54.consider("return"); + else if (node instanceof AST_Throw) + base54.consider("throw"); + else if (node instanceof AST_Continue) + base54.consider("continue"); + else if (node instanceof AST_Break) + base54.consider("break"); + else if (node instanceof AST_Debugger) + base54.consider("debugger"); + else if (node instanceof AST_Directive) + base54.consider(node.value); + else if (node instanceof AST_While) + base54.consider("while"); + else if (node instanceof AST_Do) + base54.consider("do while"); + else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } + else if (node instanceof AST_Var) + base54.consider("var"); + else if (node instanceof AST_Const) + base54.consider("const"); + else if (node instanceof AST_Lambda) + base54.consider("function"); + else if (node instanceof AST_For) + base54.consider("for"); + else if (node instanceof AST_ForIn) + base54.consider("for in"); + else if (node instanceof AST_Switch) + base54.consider("switch"); + else if (node instanceof AST_Case) + base54.consider("case"); + else if (node instanceof AST_Default) + base54.consider("default"); + else if (node instanceof AST_With) + base54.consider("with"); + else if (node instanceof AST_ObjectSetter) + base54.consider("set" + node.key); + else if (node instanceof AST_ObjectGetter) + base54.consider("get" + node.key); + else if (node instanceof AST_ObjectKeyVal) + base54.consider(node.key); + else if (node instanceof AST_New) + base54.consider("new"); + else if (node instanceof AST_This) + base54.consider("this"); + else if (node instanceof AST_Try) + base54.consider("try"); + else if (node instanceof AST_Catch) + base54.consider("catch"); + else if (node instanceof AST_Finally) + base54.consider("finally"); + else if (node instanceof AST_Symbol && node.unmangleable(options)) + base54.consider(node.name); + else if (node instanceof AST_Unary || node instanceof AST_Binary) + base54.consider(node.operator); + else if (node instanceof AST_Dot) + base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); +}); + +var base54 = (function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); + chars.forEach(function(ch){ frequency[ch] = 0 }); + } + base54.consider = function(str){ + for (var i = str.length; --i >= 0;) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b){ + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function(){ return chars }; + base54.freq = function(){ return frequency }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; + return base54; +})(); + +AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = defaults(options, { + undeclared : false, // this makes a lot of noise + unreferenced : true, + assign_to_global : true, + func_arguments : true, + nested_defuns : true, + eval : true + }); + var tw = new TreeWalker(function(node){ + if (options.undeclared + && node instanceof AST_SymbolRef + && node.undeclared()) + { + // XXX: this also warns about JS standard names, + // i.e. Object, Array, parseInt etc. Should add a list of + // exceptions. + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) + { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + sym = node.left; + else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + sym = node.init; + if (sym + && (sym.undeclared() + || (sym.global() && sym.scope !== sym.definition().scope))) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval + && node instanceof AST_SymbolRef + && node.undeclared() + && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced + && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments + && node instanceof AST_Lambda + && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns + && node instanceof AST_Defun + && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/sourcemap.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/sourcemap.js new file mode 100644 index 0000000..3429908 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/sourcemap.js @@ -0,0 +1,81 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// a small wrapper around fitzgen's source-map library +function SourceMap(options) { + options = defaults(options, { + file : null, + root : null, + orig : null, + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, + source : source, + name : name + }); + }; + return { + add : add, + get : function() { return generator }, + toString : function() { return generator.toString() } + }; +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/transform.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/transform.js new file mode 100644 index 0000000..7a61e5f --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/transform.js @@ -0,0 +1,217 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// Tree transformer helpers. + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/utils.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/utils.js new file mode 100644 index 0000000..73964a0 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/lib/utils.js @@ -0,0 +1,295 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) + return array[i]; + } +}; + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; +}; + +function defaults(args, defs, croak) { + if (args === true) + args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) + throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; + } + return ret; +}; + +function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; +}; + +function noop() {}; + +var MAP = (function(){ + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } + else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + }; + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0;) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } + else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + MAP.last = function(val) { return new Last(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; + function Last(val) { this.v = val }; + return MAP; +})(); + +function push_uniq(array, el) { + if (array.indexOf(el) < 0) + array.push(el); +}; + +function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p){ + return props[p]; + }); +}; + +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + +function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 + ? r[i++] = a[ai++] + : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + }; + function _ms(a) { + if (a.length <= 1) + return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + }; + return _ms(array); +}; + +function set_difference(a, b) { + return a.filter(function(el){ + return b.indexOf(el) < 0; + }); +}; + +function set_intersection(a, b) { + return a.filter(function(el){ + return b.indexOf(el) >= 0; + }); +}; + +// this function is taken from Acorn [1], written by Marijn Haverbeke +// [1] https://github.com/marijnh/acorn +function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + // Otherwise, simply generate a flat `switch` statement. + } else { + compareTo(words); + } + return new Function("str", f); +}; + +function all(array, predicate) { + for (var i = array.length; --i >= 0;) + if (!predicate(array[i])) + return false; + return true; +}; + +function Dictionary() { + this._values = Object.create(null); + this._size = 0; +}; +Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { return this._values["$" + key] }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { return ("$" + key) in this._values }, + each: function(f) { + for (var i in this._values) + f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) + ret.push(f(this._values[i], i.substr(1))); + return ret; + } +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/.travis.yml b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/.travis.yml new file mode 100644 index 0000000..cc4dba2 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/LICENSE b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/bool.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/bool.js new file mode 100644 index 0000000..a998fb7 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/bool.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js new file mode 100644 index 0000000..a35a7e6 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js new file mode 100644 index 0000000..017bb68 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv.v); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_hash.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_hash.js new file mode 100644 index 0000000..ade7768 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_hash.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; + +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_singles.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_singles.js new file mode 100644 index 0000000..d9b1ff4 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/default_singles.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/divide.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/divide.js new file mode 100644 index 0000000..5e2ee82 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/divide.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count.js new file mode 100644 index 0000000..b5f95bf --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js new file mode 100644 index 0000000..d9ac709 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .options({ + file : { + demand : true, + alias : 'f', + description : 'Load a file' + }, + base : { + alias : 'b', + description : 'Numeric base to use for output', + default : 10, + }, + }) + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js new file mode 100644 index 0000000..4267511 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .wrap(80) + .demand('f') + .alias('f', [ 'file', 'filename' ]) + .describe('f', + "Load a file. It's pretty important." + + " Required even. So you'd better specify it." + ) + .alias('b', 'base') + .describe('b', 'Numeric base to display the number of lines in') + .default('b', 10) + .describe('x', 'Super-secret optional parameter which is secret') + .default('x', '') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/nonopt.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/nonopt.js new file mode 100644 index 0000000..ee633ee --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/nonopt.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/reflect.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/reflect.js new file mode 100644 index 0000000..816b3e1 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/reflect.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.dir(require('optimist').argv); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/short.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/short.js new file mode 100644 index 0000000..1db0ad0 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/short.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/string.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/string.js new file mode 100644 index 0000000..a8e5aeb --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/string.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node +var argv = require('optimist') + .string('x', 'y') + .argv +; +console.dir([ argv.x, argv.y ]); + +/* Turns off numeric coercion: + ./node string.js -x 000123 -y 9876 + [ '000123', '9876' ] +*/ diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/usage-options.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/usage-options.js new file mode 100644 index 0000000..b999977 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/usage-options.js @@ -0,0 +1,19 @@ +var optimist = require('./../index'); + +var argv = optimist.usage('This is my awesome program', { + 'about': { + description: 'Provide some details about the author of this program', + required: true, + short: 'a', + }, + 'info': { + description: 'Provide some information about the node.js agains!!!!!!', + boolean: true, + short: 'i' + } +}).argv; + +optimist.showHelp(); + +console.log('\n\nInspecting options'); +console.dir(argv); \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/xup.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/xup.js new file mode 100644 index 0000000..8f6ecd2 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/example/xup.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} + diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/index.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/index.js new file mode 100644 index 0000000..8ac67eb --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/index.js @@ -0,0 +1,478 @@ +var path = require('path'); +var wordwrap = require('wordwrap'); + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('optimist')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('optimist').argv + to get a parsed version of process.argv. +*/ + +var inst = Argv(process.argv.slice(2)); +Object.keys(inst).forEach(function (key) { + Argv[key] = typeof inst[key] == 'function' + ? inst[key].bind(inst) + : inst[key]; +}); + +var exports = module.exports = Argv; +function Argv (args, cwd) { + var self = {}; + if (!cwd) cwd = process.cwd(); + + self.$0 = process.argv + .slice(0,2) + .map(function (x) { + var b = rebase(cwd, x); + return x.match(/^\//) && b.length < x.length + ? b : x + }) + .join(' ') + ; + + if (process.env._ != undefined && process.argv[1] == process.env._) { + self.$0 = process.env._.replace( + path.dirname(process.execPath) + '/', '' + ); + } + + var flags = { bools : {}, strings : {} }; + + self.boolean = function (bools) { + if (!Array.isArray(bools)) { + bools = [].slice.call(arguments); + } + + bools.forEach(function (name) { + flags.bools[name] = true; + }); + + return self; + }; + + self.string = function (strings) { + if (!Array.isArray(strings)) { + strings = [].slice.call(arguments); + } + + strings.forEach(function (name) { + flags.strings[name] = true; + }); + + return self; + }; + + var aliases = {}; + self.alias = function (x, y) { + if (typeof x === 'object') { + Object.keys(x).forEach(function (key) { + self.alias(key, x[key]); + }); + } + else if (Array.isArray(y)) { + y.forEach(function (yy) { + self.alias(x, yy); + }); + } + else { + var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y); + aliases[x] = zs.filter(function (z) { return z != x }); + aliases[y] = zs.filter(function (z) { return z != y }); + } + + return self; + }; + + var demanded = {}; + self.demand = function (keys) { + if (typeof keys == 'number') { + if (!demanded._) demanded._ = 0; + demanded._ += keys; + } + else if (Array.isArray(keys)) { + keys.forEach(function (key) { + self.demand(key); + }); + } + else { + demanded[keys] = true; + } + + return self; + }; + + var usage; + self.usage = function (msg, opts) { + if (!opts && typeof msg === 'object') { + opts = msg; + msg = null; + } + + usage = msg; + + if (opts) self.options(opts); + + return self; + }; + + function fail (msg) { + self.showHelp(); + if (msg) console.error(msg); + process.exit(1); + } + + var checks = []; + self.check = function (f) { + checks.push(f); + return self; + }; + + var defaults = {}; + self.default = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]); + }); + } + else { + defaults[key] = value; + } + + return self; + }; + + var descriptions = {}; + self.describe = function (key, desc) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.describe(k, key[k]); + }); + } + else { + descriptions[key] = desc; + } + return self; + }; + + self.parse = function (args) { + return Argv(args).argv; + }; + + self.option = self.options = function (key, opt) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.options(k, key[k]); + }); + } + else { + if (opt.alias) self.alias(key, opt.alias); + if (opt.demand) self.demand(key); + if (typeof opt.default !== 'undefined') { + self.default(key, opt.default); + } + + if (opt.boolean || opt.type === 'boolean') { + self.boolean(key); + } + if (opt.string || opt.type === 'string') { + self.string(key); + } + + var desc = opt.describe || opt.description || opt.desc; + if (desc) { + self.describe(key, desc); + } + } + + return self; + }; + + var wrap = null; + self.wrap = function (cols) { + wrap = cols; + return self; + }; + + self.showHelp = function (fn) { + if (!fn) fn = console.error; + fn(self.help()); + }; + + self.help = function () { + var keys = Object.keys( + Object.keys(descriptions) + .concat(Object.keys(demanded)) + .concat(Object.keys(defaults)) + .reduce(function (acc, key) { + if (key !== '_') acc[key] = true; + return acc; + }, {}) + ); + + var help = keys.length ? [ 'Options:' ] : []; + + if (usage) { + help.unshift(usage.replace(/\$0/g, self.$0), ''); + } + + var switches = keys.reduce(function (acc, key) { + acc[key] = [ key ].concat(aliases[key] || []) + .map(function (sw) { + return (sw.length > 1 ? '--' : '-') + sw + }) + .join(', ') + ; + return acc; + }, {}); + + var switchlen = longest(Object.keys(switches).map(function (s) { + return switches[s] || ''; + })); + + var desclen = longest(Object.keys(descriptions).map(function (d) { + return descriptions[d] || ''; + })); + + keys.forEach(function (key) { + var kswitch = switches[key]; + var desc = descriptions[key] || ''; + + if (wrap) { + desc = wordwrap(switchlen + 4, wrap)(desc) + .slice(switchlen + 4) + ; + } + + var spadding = new Array( + Math.max(switchlen - kswitch.length + 3, 0) + ).join(' '); + + var dpadding = new Array( + Math.max(desclen - desc.length + 1, 0) + ).join(' '); + + var type = null; + + if (flags.bools[key]) type = '[boolean]'; + if (flags.strings[key]) type = '[string]'; + + if (!wrap && dpadding.length > 0) { + desc += dpadding; + } + + var prelude = ' ' + kswitch + spadding; + var extra = [ + type, + demanded[key] + ? '[required]' + : null + , + defaults[key] !== undefined + ? '[default: ' + JSON.stringify(defaults[key]) + ']' + : null + , + ].filter(Boolean).join(' '); + + var body = [ desc, extra ].filter(Boolean).join(' '); + + if (wrap) { + var dlines = desc.split('\n'); + var dlen = dlines.slice(-1)[0].length + + (dlines.length === 1 ? prelude.length : 0) + + body = desc + (dlen + extra.length > wrap - 2 + ? '\n' + + new Array(wrap - extra.length + 1).join(' ') + + extra + : new Array(wrap - extra.length - dlen + 1).join(' ') + + extra + ); + } + + help.push(prelude + body); + }); + + help.push(''); + return help.join('\n'); + }; + + Object.defineProperty(self, 'argv', { + get : parseArgs, + enumerable : true, + }); + + function parseArgs () { + var argv = { _ : [], $0 : self.$0 }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] || false); + }); + + function setArg (key, val) { + var num = Number(val); + var value = typeof val !== 'string' || isNaN(num) ? val : num; + if (flags.strings[key]) value = val; + + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + argv[x] = argv[key]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (arg === '--') { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + else if (arg.match(/^--.+=/)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + setArg(m[1], m[2]); + } + else if (arg.match(/^--no-.+/)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false); + } + else if (arg.match(/^--.+/)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !next.match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, next); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true'); + i++; + } + else { + setArg(key, true); + } + } + else if (arg.match(/^-[^-]+/)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2)); + broken = true; + break; + } + else { + setArg(letters[j], true); + } + } + + if (!broken) { + var key = arg.slice(-1)[0]; + + if (args[i+1] && !args[i+1].match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, args[i+1]); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true'); + i++; + } + else { + setArg(key, true); + } + } + } + else { + var n = Number(arg); + argv._.push(flags.strings['_'] || isNaN(n) ? arg : n); + } + } + + Object.keys(defaults).forEach(function (key) { + if (!(key in argv)) { + argv[key] = defaults[key]; + if (key in aliases) { + argv[aliases[key]] = defaults[key]; + } + } + }); + + if (demanded._ && argv._.length < demanded._) { + fail('Not enough non-option arguments: got ' + + argv._.length + ', need at least ' + demanded._ + ); + } + + var missing = []; + Object.keys(demanded).forEach(function (key) { + if (!argv[key]) missing.push(key); + }); + + if (missing.length) { + fail('Missing required arguments: ' + missing.join(', ')); + } + + checks.forEach(function (f) { + try { + if (f(argv) === false) { + fail('Argument check failed: ' + f.toString()); + } + } + catch (err) { + fail(err) + } + }); + + return argv; + } + + function longest (xs) { + return Math.max.apply( + null, + xs.map(function (x) { return x.length }) + ); + } + + return self; +}; + +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +exports.rebase = rebase; +function rebase (base, dir) { + var ds = path.normalize(dir).split('/').slice(1); + var bs = path.normalize(base).split('/').slice(1); + + for (var i = 0; ds[i] && ds[i] == bs[i]; i++); + ds.splice(0, i); bs.splice(0, i); + + var p = path.normalize( + bs.map(function () { return '..' }).concat(ds).join('/') + ).replace(/\/$/,'').replace(/^$/, '.'); + return p.match(/^[.\/]/) ? p : './' + p; +}; + +function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json new file mode 100644 index 0000000..b012389 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json @@ -0,0 +1,45 @@ +{ + "name": "wordwrap", + "description": "Wrap those words. Show them at what columns to start and stop.", + "version": "0.0.2", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-wordwrap.git" + }, + "main": "./index.js", + "keywords": [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "expresso" + }, + "devDependencies": { + "expresso": "=0.7.x" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT/X11", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "readme": "wordwrap\n========\n\nWrap your words.\n\nexample\n=======\n\nmade out of meat\n----------------\n\nmeat.js\n\n var wrap = require('wordwrap')(15);\n console.log(wrap('You and your whole family are made out of meat.'));\n\noutput:\n\n You and your\n whole family\n are made out\n of meat.\n\ncentered\n--------\n\ncenter.js\n\n var wrap = require('wordwrap')(20, 60);\n console.log(wrap(\n 'At long last the struggle and tumult was over.'\n + ' The machines had finally cast off their oppressors'\n + ' and were finally free to roam the cosmos.'\n + '\\n'\n + 'Free of purpose, free of obligation.'\n + ' Just drifting through emptiness.'\n + ' The sun was just another point of light.'\n ));\n\noutput:\n\n At long last the struggle and tumult\n was over. The machines had finally cast\n off their oppressors and were finally\n free to roam the cosmos.\n Free of purpose, free of obligation.\n Just drifting through emptiness. The\n sun was just another point of light.\n\nmethods\n=======\n\nvar wrap = require('wordwrap');\n\nwrap(stop), wrap(start, stop, params={mode:\"soft\"})\n---------------------------------------------------\n\nReturns a function that takes a string and returns a new string.\n\nPad out lines with spaces out to column `start` and then wrap until column\n`stop`. If a word is longer than `stop - start` characters it will overflow.\n\nIn \"soft\" mode, split chunks by `/(\\S+\\s+/` and don't break up chunks which are\nlonger than `stop - start`, in \"hard\" mode, split chunks with `/\\b/` and break\nup chunks longer than `stop - start`.\n\nwrap.hard(start, stop)\n----------------------\n\nLike `wrap()` but with `params.mode = \"hard\"`.\n", + "readmeFilename": "README.markdown", + "_id": "wordwrap@0.0.2", + "dist": { + "shasum": "ece472585d818a1bc63ecdf59f23356928e61210" + }, + "_from": "wordwrap@~0.0.2", + "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/package.json b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/package.json new file mode 100644 index 0000000..932c274 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/package.json @@ -0,0 +1,46 @@ +{ + "name": "optimist", + "version": "0.3.7", + "description": "Light-weight option parsing with an argv hash. No optstrings attached.", + "main": "./index.js", + "dependencies": { + "wordwrap": "~0.0.2" + }, + "devDependencies": { + "hashish": "~0.0.4", + "tap": "~0.4.0" + }, + "scripts": { + "test": "tap ./test/*.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-optimist.git" + }, + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "node": ">=0.4" + }, + "readme": "optimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", + "readmeFilename": "readme.markdown", + "_id": "optimist@0.3.7", + "dist": { + "shasum": "6e935517247b531bf1676559618d7c7989881b54" + }, + "_from": "optimist@~0.3.5", + "_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz" +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/readme.markdown b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/readme.markdown new file mode 100644 index 0000000..ad9d3fd --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/readme.markdown @@ -0,0 +1,487 @@ +optimist +======== + +Optimist is a node.js library for option parsing for people who hate option +parsing. More specifically, this module is for people who like all the --bells +and -whistlz of program usage but think optstrings are a waste of time. + +With optimist, option parsing doesn't have to suck (as much). + +[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist) + +examples +======== + +With Optimist, the options are just a hash! No optstrings attached. +------------------------------------------------------------------- + +xup.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} +```` + +*** + + $ ./xup.js --rif=55 --xup=9.52 + Buy more riffiwobbles + + $ ./xup.js --rif 12 --xup 8.1 + Sell the xupptumblers + +![This one's optimistic.](http://substack.net/images/optimistic.png) + +But wait! There's more! You can do short options: +------------------------------------------------- + +short.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +```` + +*** + + $ ./short.js -x 10 -y 21 + (10,21) + +And booleans, both long and short (and grouped): +---------------------------------- + +bool.js: + +````javascript +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); +```` + +*** + + $ ./bool.js -s + The cat says: meow + + $ ./bool.js -sp + The cat says: meow. + + $ ./bool.js -sp --fr + Le chat dit: miaou. + +And non-hypenated options too! Just use `argv._`! +------------------------------------------------- + +nonopt.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); +```` + +*** + + $ ./nonopt.js -x 6.82 -y 3.35 moo + (6.82,3.35) + [ 'moo' ] + + $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz + (0.54,1.12) + [ 'foo', 'bar', 'baz' ] + +Plus, Optimist comes with .usage() and .demand()! +------------------------------------------------- + +divide.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); +```` + +*** + + $ ./divide.js -x 55 -y 11 + 5 + + $ node ./divide.js -x 4.91 -z 2.51 + Usage: node ./divide.js -x [num] -y [num] + + Options: + -x [required] + -y [required] + + Missing required arguments: y + +EVEN MORE HOLY COW +------------------ + +default_singles.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_singles.js -x 5 + 15 + +default_hash.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_hash.js -y 7 + 17 + +And if you really want to get all descriptive about it... +--------------------------------------------------------- + +boolean_single.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv); +```` + +*** + + $ ./boolean_single.js -v foo bar baz + true + [ 'bar', 'baz', 'foo' ] + +boolean_double.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); +```` + +*** + + $ ./boolean_double.js -x -z one two three + [ true, false, true ] + [ 'one', 'two', 'three' ] + +Optimist is here to help... +--------------------------- + +You can describe parameters for help messages and set aliases. Optimist figures +out how to format a handy help string automatically. + +line_count.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); +```` + +*** + + $ node line_count.js + Count the lines in a file. + Usage: node ./line_count.js + + Options: + -f, --file Load a file [required] + + Missing required arguments: f + + $ node line_count.js --file line_count.js + 20 + + $ node line_count.js -f line_count.js + 20 + +methods +======= + +By itself, + +````javascript +require('optimist').argv +````` + +will use `process.argv` array to construct the `argv` object. + +You can pass in the `process.argv` yourself: + +````javascript +require('optimist')([ '-x', '1', '-y', '2' ]).argv +```` + +or use .parse() to do the same thing: + +````javascript +require('optimist').parse([ '-x', '1', '-y', '2' ]) +```` + +The rest of these methods below come in just before the terminating `.argv`. + +.alias(key, alias) +------------------ + +Set key names as equivalent such that updates to a key will propagate to aliases +and vice-versa. + +Optionally `.alias()` can take an object that maps keys to aliases. + +.default(key, value) +-------------------- + +Set `argv[key]` to `value` if no option was specified on `process.argv`. + +Optionally `.default()` can take an object that maps keys to default values. + +.demand(key) +------------ + +If `key` is a string, show the usage information and exit if `key` wasn't +specified in `process.argv`. + +If `key` is a number, demand at least as many non-option arguments, which show +up in `argv._`. + +If `key` is an Array, demand each element. + +.describe(key, desc) +-------------------- + +Describe a `key` for the generated usage information. + +Optionally `.describe()` can take an object that maps keys to descriptions. + +.options(key, opt) +------------------ + +Instead of chaining together `.alias().demand().default()`, you can specify +keys in `opt` for each of the chainable methods. + +For example: + +````javascript +var argv = require('optimist') + .options('f', { + alias : 'file', + default : '/etc/passwd', + }) + .argv +; +```` + +is the same as + +````javascript +var argv = require('optimist') + .alias('f', 'file') + .default('f', '/etc/passwd') + .argv +; +```` + +Optionally `.options()` can take an object that maps keys to `opt` parameters. + +.usage(message) +--------------- + +Set a usage message to show which commands to use. Inside `message`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. + +.check(fn) +---------- + +Check that certain conditions are met in the provided arguments. + +If `fn` throws or returns `false`, show the thrown error, usage information, and +exit. + +.boolean(key) +------------- + +Interpret `key` as a boolean. If a non-flag option follows `key` in +`process.argv`, that string won't get set as the value of `key`. + +If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be +`false`. + +If `key` is an Array, interpret all the elements as booleans. + +.string(key) +------------ + +Tell the parser logic not to interpret `key` as a number or boolean. +This can be useful if you need to preserve leading zeros in an input. + +If `key` is an Array, interpret all the elements as strings. + +.wrap(columns) +-------------- + +Format usage output to wrap at `columns` many columns. + +.help() +------- + +Return the generated usage string. + +.showHelp(fn=console.error) +--------------------------- + +Print the usage data using `fn` for printing. + +.parse(args) +------------ + +Parse `args` instead of `process.argv`. Returns the `argv` object. + +.argv +----- + +Get the arguments as a plain old object. + +Arguments without a corresponding flag show up in the `argv._` array. + +The script name or node command is available at `argv.$0` similarly to how `$0` +works in bash or perl. + +parsing tricks +============== + +stop parsing +------------ + +Use `--` to stop parsing flags and stuff the remainder into `argv._`. + + $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 + { _: [ '-c', '3', '-d', '4' ], + '$0': 'node ./examples/reflect.js', + a: 1, + b: 2 } + +negate fields +------------- + +If you want to explicity set a field to false instead of just leaving it +undefined or to override a default you can do `--no-key`. + + $ node examples/reflect.js -a --no-b + { _: [], + '$0': 'node ./examples/reflect.js', + a: true, + b: false } + +numbers +------- + +Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to +one. This way you can just `net.createConnection(argv.port)` and you can add +numbers out of `argv` with `+` without having that mean concatenation, +which is super frustrating. + +duplicates +---------- + +If you specify a flag multiple times it will get turned into an array containing +all the values in order. + + $ node examples/reflect.js -x 5 -x 8 -x 0 + { _: [], + '$0': 'node ./examples/reflect.js', + x: [ 5, 8, 0 ] } + +dot notation +------------ + +When you use dots (`.`s) in argument names, an implicit object path is assumed. +This lets you organize arguments into nested objects. + + $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5 + { _: [], + '$0': 'node ./examples/reflect.js', + foo: { bar: { baz: 33 }, quux: 5 } } + +installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + npm install optimist + +or clone this project on github: + + git clone http://github.com/substack/node-optimist.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + +inspired By +=========== + +This module is loosely inspired by Perl's +[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_.js new file mode 100644 index 0000000..d9c58b3 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_.js @@ -0,0 +1,71 @@ +var spawn = require('child_process').spawn; +var test = require('tap').test; + +test('dotSlashEmpty', testCmd('./bin.js', [])); + +test('dotSlashArgs', testCmd('./bin.js', [ 'a', 'b', 'c' ])); + +test('nodeEmpty', testCmd('node bin.js', [])); + +test('nodeArgs', testCmd('node bin.js', [ 'x', 'y', 'z' ])); + +test('whichNodeEmpty', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', []) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + assert.error(err); + t.end(); + }); +}); + +test('whichNodeArgs', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); +}); + +function testCmd (cmd, args) { + + return function (t) { + var to = setTimeout(function () { + assert.fail('Never got stdout data.') + }, 5000); + + var oldDir = process.cwd(); + process.chdir(__dirname + '/_'); + + var cmds = cmd.split(' '); + + var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String))); + process.chdir(oldDir); + + bin.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); + + bin.stdout.on('data', function (buf) { + clearTimeout(to); + var _ = JSON.parse(buf.toString()); + t.same(_.map(String), args.map(String)); + t.end(); + }); + }; +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/argv.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/argv.js new file mode 100644 index 0000000..3d09606 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/argv.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log(JSON.stringify(process.argv)); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/bin.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/bin.js new file mode 100755 index 0000000..4a18d85 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/_/bin.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('../../index').argv +console.log(JSON.stringify(argv._)); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/parse.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/parse.js new file mode 100644 index 0000000..d320f43 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/parse.js @@ -0,0 +1,446 @@ +var optimist = require('../index'); +var path = require('path'); +var test = require('tap').test; + +var $0 = 'node ./' + path.relative(process.cwd(), __filename); + +test('short boolean', function (t) { + var parse = optimist.parse([ '-b' ]); + t.same(parse, { b : true, _ : [], $0 : $0 }); + t.same(typeof parse.b, 'boolean'); + t.end(); +}); + +test('long boolean', function (t) { + t.same( + optimist.parse([ '--bool' ]), + { bool : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('bare', function (t) { + t.same( + optimist.parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ], $0 : $0 } + ); + t.end(); +}); + +test('short group', function (t) { + t.same( + optimist.parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short group next', function (t) { + t.same( + optimist.parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short captures', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture sp', function (t) { + t.same( + optimist.parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture eq', function (t) { + t.same( + optimist.parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end() +}); + +test('long captures sp', function (t) { + t.same( + optimist.parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long captures eq', function (t) { + t.same( + optimist.parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('no', function (t) { + t.same( + optimist.parse([ '--no-moo' ]), + { moo : false, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('multi', function (t) { + t.same( + optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [], $0 : $0 } + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.same( + optimist.parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ], + $0 : $0 + } + ); + t.end(); +}); + +test('nums', function (t) { + var argv = optimist.parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + t.same(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ], + $0 : $0 + }); + t.same(typeof argv.x, 'number'); + t.same(typeof argv.y, 'number'); + t.same(typeof argv.z, 'number'); + t.same(typeof argv.w, 'string'); + t.same(typeof argv.hex, 'number'); + t.same(typeof argv._[0], 'number'); + t.end(); +}); + +test('flag boolean', function (t) { + var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv; + t.same(parse, { t : true, _ : [ 'moo' ], $0 : $0 }); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true']) + .boolean(['t', 'verbose']).default('verbose', true).argv; + + t.same(parse, { + verbose: false, + t: true, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean default false', function (t) { + var parse = optimist(['moo']) + .boolean(['t', 'verbose']) + .default('verbose', false) + .default('t', false).argv; + + t.same(parse, { + verbose: false, + t: false, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ]) + .boolean(['x','y','z']).argv; + + t.same(parse, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ], + $0 : $0 + }); + + t.same(typeof parse.x, 'boolean'); + t.same(typeof parse.y, 'boolean'); + t.same(typeof parse.z, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = optimist.parse([ '-s', "X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = optimist.parse([ "--s=X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + t.end(); +}); + +test('strings' , function (t) { + var s = optimist([ '-s', '0001234' ]).string('s').argv.s; + t.same(s, '0001234'); + t.same(typeof s, 'string'); + + var x = optimist([ '-x', '56' ]).string('x').argv.x; + t.same(x, '56'); + t.same(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = optimist([ ' ', ' ' ]).string('_').argv._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + optimist.parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.same( + optimist.parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', 'zoom') + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', [ 'zm', 'zoom' ]) + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('boolean default true', function (t) { + var argv = optimist.options({ + sometrue: { + boolean: true, + default: true + } + }).argv; + + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = optimist.options({ + somefalse: { + boolean: true, + default: false + } + }).argv; + + t.equal(argv.somefalse, false); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = optimist([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]).argv; + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + }, + }); + t.same(argv.beep, { boop : true }); + t.end(); +}); + +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('herp') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('herp') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .options(opts) + .argv; + var propertyArgv = optimist(regular).options(opts).argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('h') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('h') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = optimist(['--boool', '--other=true']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = optimist(['--boool', '--other=false']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/usage.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/usage.js new file mode 100644 index 0000000..300454c --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/optimist/test/usage.js @@ -0,0 +1,292 @@ +var Hash = require('hashish'); +var optimist = require('../index'); +var test = require('tap').test; + +test('usageFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'Options:', + ' -x [required]', + ' -y [required]', + 'Missing required arguments: y', + ] + ); + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + + +test('usagePass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkPass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'You forgot about -y' + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('checkCondPass', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkCondFail', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/).join('\n'), + 'Usage: ./usage -x NUM -y NUM\n' + + 'Argument check failed: ' + checker.toString() + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('countPass', function (t) { + var r = checkUsage(function () { + return optimist('1 2 3 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same(r, { + result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('countFail', function (t) { + var r = checkUsage(function () { + return optimist('1 2 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same( + r.result, + { _ : [ '1', '2' ], moo : true, $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage [x] [y] [z] {OPTIONS}', + 'Not enough non-option arguments: got 2, need at least 3', + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('defaultSingles', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70 --powsy'.split(' ')) + .default('foo', 5) + .default('bar', 6) + .default('baz', 7) + .argv + ; + }); + t.same(r.result, { + foo : '50', + bar : 6, + baz : '70', + powsy : true, + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultAliases', function (t) { + var r = checkUsage(function () { + return optimist('') + .alias('f', 'foo') + .default('f', 5) + .argv + ; + }); + t.same(r.result, { + f : '5', + foo : '5', + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultHash', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70'.split(' ')) + .default({ foo : 10, bar : 20, quux : 30 }) + .argv + ; + }); + t.same(r.result, { + _ : [], + $0 : './usage', + foo : 50, + baz : 70, + bar : 20, + quux : 30, + }); + t.end(); +}); + +test('rebase', function (t) { + t.equal( + optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'), + './foo/bar/baz' + ); + t.equal( + optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'), + '../../..' + ); + t.equal( + optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'), + '../pow/zoom.txt' + ); + t.end(); +}); + +function checkUsage (f) { + + var exit = false; + + process._exit = process.exit; + process._env = process.env; + process._argv = process.argv; + + process.exit = function (t) { exit = true }; + process.env = Hash.merge(process.env, { _ : 'node' }); + process.argv = [ './usage' ]; + + var errors = []; + var logs = []; + + console._error = console.error; + console.error = function (msg) { errors.push(msg) }; + console._log = console.log; + console.log = function (msg) { logs.push(msg) }; + + var result = f(); + + process.exit = process._exit; + process.env = process._env; + process.argv = process._argv; + + console.error = console._error; + console.log = console._log; + + return { + errors : errors, + logs : logs, + exit : exit, + result : result, + }; +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.npmignore b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.npmignore new file mode 100644 index 0000000..3dddf3f --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.travis.yml b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.travis.yml new file mode 100644 index 0000000..ddc9c4f --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md new file mode 100644 index 0000000..75d1c14 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,75 @@ +# Change Log + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. + diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/LICENSE b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/LICENSE new file mode 100644 index 0000000..ed1b7cf --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 0000000..d6fc26a --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/README.md b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/README.md new file mode 100644 index 0000000..5cc212c --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/README.md @@ -0,0 +1,347 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +[Learn more here][feature]. + +This library was written in the Asynchronous Module Definition +format. It should work in the following environments: + +* Modern Browsers (either after the build, or with an AMD loader such as + RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Installing with NPM (for use with NodeJS) + +Simply + + $ npm install source-map + +Or, if you'd like to hack on this library and have it installed via npm so you +can try out your changes: + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox + source. + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator(startOfSourceMap) + +To create a new one, you must pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: An optional root for all relative URLs in this source map. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used. + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode(line, column, source[, chunk[, name]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js new file mode 100644 index 0000000..daa1a62 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/mini-require.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/mini-require.js new file mode 100644 index 0000000..0daf453 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 0000000..ee2539d --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 0000000..80341d4 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 0000000..cf6cde7 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +window.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 0000000..cf3c2d8 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 0000000..b31b84c --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js new file mode 100644 index 0000000..1b13f30 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js new file mode 100644 index 0000000..bec2de3 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map.js new file mode 100644 index 0000000..121ad24 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 0000000..584b845 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,96 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i]); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr) { + if (this.has(aStr)) { + // Already a member; nothing to do. + return; + } + var idx = this._array.length; + this._array.push(aStr); + this._set[util.toSetString(aStr)] = idx; + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 0000000..1b67bb3 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,144 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 0000000..863cc46 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 0000000..7dfd0ea --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,81 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid]); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 0000000..97db234 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,441 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + var names = util.getArg(sourceMap, 'names'); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file'); + + if (version !== this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._names = ArraySet.fromArray(names); + this._sources = ArraySet.fromArray(sources); + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this.file = file; + + // `this._generatedMappings` and `this._originalMappings` hold the parsed + // mapping coordinates from the source map's "mappings" attribute. Each + // object in the array is of the form + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `this._generatedMappings` is ordered by the generated positions. + // + // `this._originalMappings` is ordered by the original positions. + this._generatedMappings = []; + this._originalMappings = []; + this._parseMappings(mappings, sourceRoot); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (an ordered list in this._generatedMappings). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this._generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this._originalMappings.push(mapping); + } + } + } + + this._originalMappings.sort(this._compareOriginalPositions); + }; + + /** + * Comparator between two mappings where the original positions are compared. + */ + SourceMapConsumer.prototype._compareOriginalPositions = + function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { + if (mappingA.source > mappingB.source) { + return 1; + } + else if (mappingA.source < mappingB.source) { + return -1; + } + else { + var cmp = mappingA.originalLine - mappingB.originalLine; + return cmp === 0 + ? mappingA.originalColumn - mappingB.originalColumn + : cmp; + } + }; + + /** + * Comparator between two mappings where the generated positions are compared. + */ + SourceMapConsumer.prototype._compareGeneratedPositions = + function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + return cmp === 0 + ? mappingA.generatedColumn - mappingB.generatedColumn + : cmp; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + this._compareGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + this._compareOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 0000000..f497090 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,381 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generated: generated, + original: original, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.original) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.original.line, + column: mapping.original.column + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.original.line = original.line; + mapping.original.column = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping.'); + } + }; + + function cmpLocation(loc1, loc2) { + var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); + return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); + } + + function strcmp(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + return (str1 > str2) - (str1 < str2); + } + + function cmpMapping(mappingA, mappingB) { + return cmpLocation(mappingA.generated, mappingB.generated) || + cmpLocation(mappingA.original, mappingB.original) || + strcmp(mappingA.source, mappingB.source) || + strcmp(mappingA.name, mappingB.name); + } + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(cmpMapping); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generated.line !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generated.line !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!cmpMapping(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generated.column + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generated.column; + + if (mapping.source && mapping.original) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.original.line - 1 + - previousOriginalLine); + previousOriginalLine = mapping.original.line - 1; + + result += base64VLQ.encode(mapping.original.column + - previousOriginalColumn); + previousOriginalColumn = mapping.original.column; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = map.sources.map(function (source) { + if (map.sourceRoot) { + source = util.relative(map.sourceRoot, source); + } + return Object.prototype.hasOwnProperty.call( + this._sourcesContents, util.toSetString(source)) + ? this._sourcesContents[util.toSetString(source)] + : null; + }, this); + } + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 0000000..2e5a09d --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,353 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + }, this); + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walkSourceContents(aFn); + } + }, this); + Object.keys(this.sourceContents).forEach(function (sourceFileKey) { + aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]); + }, this); + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 0000000..4ce5113 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,117 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE new file mode 100644 index 0000000..f33d665 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2011, The Dojo Foundation + +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/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md new file mode 100644 index 0000000..8ebbc73 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md @@ -0,0 +1,119 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.0.5" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js new file mode 100644 index 0000000..d074c94 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js @@ -0,0 +1,299 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.0.5 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +var path = require('path'); + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [require]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, require) { + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + require = require || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(require, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(require, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(module.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json new file mode 100644 index 0000000..5ab7827 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json @@ -0,0 +1,37 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "0.0.5", + "homepage": "http://github.com/jrburke/amdefine", + "author": { + "name": "James Burke", + "email": "jrburke@gmail.com", + "url": "http://github.com/jrburke" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + }, + { + "type": "MIT", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + }, + "readme": "# amdefine\n\nA module that can be used to implement AMD's define() in Node. This allows you\nto code to the AMD API and have the module work in node programs without\nrequiring those other programs to use AMD.\n\n## Usage\n\n**1)** Update your package.json to indicate amdefine as a dependency:\n\n```javascript\n \"dependencies\": {\n \"amdefine\": \">=0.0.5\"\n }\n```\n\nThen run `npm install` to get amdefine into your project.\n\n**2)** At the top of each module that uses define(), place this code:\n\n```javascript\nif (typeof define !== 'function') { var define = require('amdefine')(module) }\n```\n\n**Only use these snippets** when loading amdefine. If you preserve the basic structure,\nwith the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).\n\nYou can add spaces, line breaks and even require amdefine with a local path, but\nkeep the rest of the structure to get the stripping behavior.\n\nAs you may know, because `if` statements in JavaScript don't have their own scope, the var\ndeclaration in the above snippet is made whether the `if` expression is truthy or not. If\nRequireJS is loaded then the declaration is superfluous because `define` is already already\ndeclared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`\ndeclarations of the same variable in the same scope gracefully.\n\nIf you want to deliver amdefine.js with your code rather than specifying it as a dependency\nwith npm, then just download the latest release and refer to it using a relative path:\n\n[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)\n\n## define() usage\n\nIt is best if you use the anonymous forms of define() in your module:\n\n```javascript\ndefine(function (require) {\n var dependency = require('dependency');\n});\n```\n\nor\n\n```javascript\ndefine(['dependency'], function (dependency) {\n\n});\n```\n\n## RequireJS optimizer integration. \n\nVersion 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)\nwill have support for stripping the `if (typeof define !== 'function')` check\nmentioned above, so you can include this snippet for code that runs in the\nbrowser, but avoid taking the cost of the if() statement once the code is\noptimized for deployment.\n\n## Node 0.4 Support\n\nIf you want to support Node 0.4, then add `require` as the second parameter to amdefine:\n\n```javascript\n//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.\nif (typeof define !== 'function') { var define = require('amdefine')(module, require) }\n```\n\n## Limitations\n\n### Synchronous vs Asynchronous\n\namdefine creates a define() function that is callable by your code. It will\nexecute and trace dependencies and call the factory function *synchronously*,\nto keep the behavior in line with Node's synchronous dependency tracing.\n\nThe exception: calling AMD's callback-style require() from inside a factory\nfunction. The require callback is called on process.nextTick():\n\n```javascript\ndefine(function (require) {\n require(['a'], function(a) {\n //'a' is loaded synchronously, but\n //this callback is called on process.nextTick().\n });\n});\n```\n\n### Loader Plugins\n\nLoader plugins are supported as long as they call their load() callbacks\nsynchronously. So ones that do network requests will not work. However plugins\nlike [text](http://requirejs.org/docs/api.html#text) can load text files locally.\n\nThe plugin API's `load.fromText()` is **not supported** in amdefine, so this means\ntranspiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)\nwill not work. This may be fixable, but it is a bit complex, and I do not have\nenough node-fu to figure it out yet. See the source for amdefine.js if you want\nto get an idea of the issues involved.\n\n## Tests\n\nTo run the tests, cd to **tests** and run:\n\n```\nnode all.js\n```\n\n## License\n\nNew BSD and MIT. Check the LICENSE file for all the details.\n", + "readmeFilename": "README.md", + "_id": "amdefine@0.0.5", + "dist": { + "shasum": "042f205bd60238a7d4aa1e50a2d1f18421e9b30a" + }, + "_from": "amdefine@>=0.0.4", + "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.0.5.tgz" +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/package.json b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/package.json new file mode 100644 index 0000000..9796ea2 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/package.json @@ -0,0 +1,98 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.26", + "homepage": "https://github.com/mozilla/source-map", + "author": { + "name": "Nick Fitzgerald", + "email": "nfitzgerald@mozilla.com" + }, + "contributors": [ + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "# Source Map\n\nThis is a library to generate and consume the source map format\n[described here][format].\n\n[Learn more here][feature].\n\nThis library was written in the Asynchronous Module Definition\nformat. It should work in the following environments:\n\n* Modern Browsers (either after the build, or with an AMD loader such as\n RequireJS)\n\n* Inside Firefox (as a JSM file, after the build)\n\n* With NodeJS versions 0.8.X and higher\n\n## Installing with NPM (for use with NodeJS)\n\nSimply\n\n $ npm install source-map\n\nOr, if you'd like to hack on this library and have it installed via npm so you\ncan try out your changes:\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\n## Building from Source (for everywhere else)\n\nInstall Node and then run\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\nNext, run\n\n $ node Makefile.dryice.js\n\nThis should create the following files:\n\n* `dist/source-map.js` - The unminified browser version.\n\n* `dist/source-map.min.js` - The minified browser version.\n\n* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox\n source.\n\n## API\n\nGet a reference to the module:\n\n // NodeJS\n var sourceMap = require('source-map');\n\n // Browser builds\n var sourceMap = window.sourceMap;\n\n // Inside Firefox\n let sourceMap = {};\n Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);\n\n### SourceMapConsumer\n\nA SourceMapConsumer instance represents a parsed source map which we can query\nfor information about the original file positions by giving it a file position\nin the generated source.\n\n#### new SourceMapConsumer(rawSourceMap)\n\nThe only parameter is the raw source map (either as a string which can be\n`JSON.parse`'d, or an object). According to the spec, source maps have the\nfollowing attributes:\n\n* `version`: Which version of the source map spec this map is following.\n\n* `sources`: An array of URLs to the original source files.\n\n* `names`: An array of identifiers which can be referrenced by individual\n mappings.\n\n* `sourceRoot`: Optional. The URL root from which all sources are relative.\n\n* `sourcesContent`: Optional. An array of contents of the original source files.\n\n* `mappings`: A string of base64 VLQs which contain the actual mappings.\n\n* `file`: The generated filename this source map is associated with.\n\n#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)\n\nReturns the original source, line, and column information for the generated\nsource's line and column positions provided. The only argument is an object with\nthe following properties:\n\n* `line`: The line number in the generated source.\n\n* `column`: The column number in the generated source.\n\nand an object is returned with the following properties:\n\n* `source`: The original source file, or null if this information is not\n available.\n\n* `line`: The line number in the original source, or null if this information is\n not available.\n\n* `column`: The column number in the original source, or null or null if this\n information is not available.\n\n* `name`: The original identifier, or null if this information is not available.\n\n#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)\n\nReturns the generated line and column information for the original source,\nline, and column positions provided. The only argument is an object with\nthe following properties:\n\n* `source`: The filename of the original source.\n\n* `line`: The line number in the original source.\n\n* `column`: The column number in the original source.\n\nand an object is returned with the following properties:\n\n* `line`: The line number in the generated source, or null.\n\n* `column`: The column number in the generated source, or null.\n\n#### SourceMapConsumer.prototype.sourceContentFor(source)\n\nReturns the original source content for the source provided. The only\nargument is the URL of the original source file.\n\n#### SourceMapConsumer.prototype.eachMapping(callback, context, order)\n\nIterate over each mapping between an original source/line/column and a\ngenerated line/column in this source map.\n\n* `callback`: The function that is called with each mapping.\n\n* `context`: Optional. If specified, this object will be the value of `this`\n every time that `callback` is called.\n\n* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or\n `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over\n the mappings sorted by the generated file's line/column order or the\n original's source/line/column order, respectively. Defaults to\n `SourceMapConsumer.GENERATED_ORDER`.\n\n### SourceMapGenerator\n\nAn instance of the SourceMapGenerator represents a source map which is being\nbuilt incrementally.\n\n#### new SourceMapGenerator(startOfSourceMap)\n\nTo create a new one, you must pass an object with the following properties:\n\n* `file`: The filename of the generated source that this source map is\n associated with.\n\n* `sourceRoot`: An optional root for all relative URLs in this source map.\n\n#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)\n\nCreates a new SourceMapGenerator based on a SourceMapConsumer\n\n* `sourceMapConsumer` The SourceMap.\n\n#### SourceMapGenerator.prototype.addMapping(mapping)\n\nAdd a single mapping from original source line and column to the generated\nsource's line and column for this source map being created. The mapping object\nshould have the following properties:\n\n* `generated`: An object with the generated line and column positions.\n\n* `original`: An object with the original line and column positions.\n\n* `source`: The original source file (relative to the sourceRoot).\n\n* `name`: An optional original token name for this mapping.\n\n#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for an original source file.\n\n* `sourceFile` the URL of the original source file.\n\n* `sourceContent` the content of the source file.\n\n#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile])\n\nApplies a SourceMap for a source file to the SourceMap.\nEach mapping to the supplied source file is rewritten using the\nsupplied SourceMap. Note: The resolution for the resulting mappings\nis the minimium of this map and the supplied map.\n\n* `sourceMapConsumer`: The SourceMap to be applied.\n\n* `sourceFile`: Optional. The filename of the source file.\n If omitted, sourceMapConsumer.file will be used.\n\n#### SourceMapGenerator.prototype.toString()\n\nRenders the source map being generated to a string.\n\n### SourceNode\n\nSourceNodes provide a way to abstract over interpolating and/or concatenating\nsnippets of generated JavaScript source code, while maintaining the line and\ncolumn information associated between those snippets and the original source\ncode. This is useful as the final intermediate representation a compiler might\nuse before outputting the generated JS and source map.\n\n#### new SourceNode(line, column, source[, chunk[, name]])\n\n* `line`: The original line number associated with this source node, or null if\n it isn't associated with an original line.\n\n* `column`: The original column number associated with this source node, or null\n if it isn't associated with an original column.\n\n* `source`: The original source's filename.\n\n* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see\n below.\n\n* `name`: Optional. The original identifier.\n\n#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer)\n\nCreates a SourceNode from generated code and a SourceMapConsumer.\n\n* `code`: The generated code\n\n* `sourceMapConsumer` The SourceMap for the generated code\n\n#### SourceNode.prototype.add(chunk)\n\nAdd a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.prepend(chunk)\n\nPrepend a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for a source file. This will be added to the\n`SourceMap` in the `sourcesContent` field.\n\n* `sourceFile`: The filename of the source file\n\n* `sourceContent`: The content of the source file\n\n#### SourceNode.prototype.walk(fn)\n\nWalk over the tree of JS snippets in this node and its children. The walking\nfunction is called once for each snippet of JS and is passed that snippet and\nthe its original associated source's line/column location.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.walkSourceContents(fn)\n\nWalk over the tree of SourceNodes. The walking function is called for each\nsource file content and is passed the filename and source content.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.join(sep)\n\nLike `Array.prototype.join` except for SourceNodes. Inserts the separator\nbetween each of this source node's children.\n\n* `sep`: The separator.\n\n#### SourceNode.prototype.replaceRight(pattern, replacement)\n\nCall `String.prototype.replace` on the very right-most source snippet. Useful\nfor trimming whitespace from the end of a source node, etc.\n\n* `pattern`: The pattern to replace.\n\n* `replacement`: The thing to replace the pattern with.\n\n#### SourceNode.prototype.toString()\n\nReturn the string representation of this source node. Walks over the tree and\nconcatenates all the various snippets together to one string.\n\n### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap)\n\nReturns the string representation of this tree of source nodes, plus a\nSourceMapGenerator which contains all the mappings between the generated and\noriginal sources.\n\nThe arguments are the same as those to `new SourceMapGenerator`.\n\n## Tests\n\n[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)\n\nInstall NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`.\n\nTo add new tests, create a new file named `test/test-.js`\nand export your test functions with names that start with \"test\", for example\n\n exports[\"test doing the foo bar\"] = function (assert, util) {\n ...\n };\n\nThe new test will be located automatically when you run the suite.\n\nThe `util` argument is the test utility module located at `test/source-map/util`.\n\nThe `assert` argument is a cut down version of node's assert module. You have\naccess to the following assertion functions:\n\n* `doesNotThrow`\n\n* `equal`\n\n* `ok`\n\n* `strictEqual`\n\n* `throws`\n\n(The reason for the restricted set of test functions is because we need the\ntests to run inside Firefox's test suite as well and so the assert module is\nshimmed in that environment. See `build/assert-shim.js`.)\n\n[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit\n[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap\n[Dryice]: https://github.com/mozilla/dryice\n", + "readmeFilename": "README.md", + "_id": "source-map@0.1.26", + "dist": { + "shasum": "05d6ef84432175ac2c20136dbbeb77d168a728f2" + }, + "_from": "source-map@~0.1.7", + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.26.tgz" +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/run-tests.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/run-tests.js new file mode 100755 index 0000000..8bf2256 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/run-tests.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var failures = []; + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + process.stdout.write('.'); + } + catch (e) { + failures.push({ + name: tests[i].name + ': ' + k, + error: e + }); + process.stdout.write('E'); + } + } + } + } + + process.stdout.write('\n'); + console.log(passed + ' / ' + total + ' tests passed.'); + + failures.forEach(function (f) { + console.log('================================================================================'); + console.log(f.name); + console.log('--------------------------------------------------------------------------------'); + console.log(f.error.stack); + }); + + return failures.length; +} + +var code; + +process.stdout.on('close', function () { + process.exit(code); +}); + +function isTestFile(f) { + return /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')).filter(isTestFile).map(toModule); + +code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); +process.exit(code); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 0000000..3801233 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 0000000..b917314 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,71 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 0000000..653a874 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,24 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result; + for (var i = -255; i < 256; i++) { + result = base64VLQ.decode(base64VLQ.encode(i)); + assert.ok(result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 0000000..ff3a244 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 0000000..ee30683 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), null); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 18); + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 0000000..d831b92 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,72 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + + // Fuzzy + + // Original to generated + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + + // Generated to original + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 0000000..7c179f6 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,321 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an objects'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var sources = map.sources; + + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var mapping; + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + if (mapping.source) { + assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); + } + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 0000000..7f5eafd --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,391 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 0000000..522cc50 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,301 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }; + + exports['test .fromStringWithSourceMap()'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }; + + exports['test .fromStringWithSourceMap() empty map'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }; + + exports['test .fromStringWithSourceMap() complex version'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + "(function() {\n", + " var Test = {};\n", + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };\n"), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), "\n", + "}());\n", + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }; + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js new file mode 100644 index 0000000..8a9c53e --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,160 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, "mappings mismatch"); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/package.json b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/package.json new file mode 100644 index 0000000..5bf022d --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/package.json @@ -0,0 +1,40 @@ +{ + "name": "uglify-js", + "description": "JavaScript parser, mangler/compressor and beautifier toolkit", + "homepage": "http://lisperator.net/uglifyjs", + "main": "tools/node.js", + "version": "2.3.6", + "engines": { + "node": ">=0.4.0" + }, + "maintainers": [ + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com", + "url": "http://lisperator.net/" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/mishoo/UglifyJS2.git" + }, + "dependencies": { + "async": "~0.2.6", + "source-map": "~0.1.7", + "optimist": "~0.3.5" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "UglifyJS 2\n==========\n[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2)\n\nUglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.\n\nThis page documents the command line utility. For\n[API and internals documentation see my website](http://lisperator.net/uglifyjs/).\nThere's also an\n[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,\nChrome and probably Safari).\n\nInstall\n-------\n\nFirst make sure you have installed the latest version of [node.js](http://nodejs.org/)\n(You may need to restart your computer after this step).\n\nFrom NPM for use as a command line app:\n\n npm install uglify-js -g\n\nFrom NPM for programmatic use:\n\n npm install uglify-js\n\nFrom Git:\n\n git clone git://github.com/mishoo/UglifyJS2.git\n cd UglifyJS2\n npm link .\n\nUsage\n-----\n\n uglifyjs [input files] [options]\n\nUglifyJS2 can take multiple input files. It's recommended that you pass the\ninput files first, then pass the options. UglifyJS will parse input files\nin sequence and apply any compression options. The files are parsed in the\nsame global scope, that is, a reference from a file to some\nvariable/function declared in another file will be matched properly.\n\nIf you want to read from STDIN instead, pass a single dash instead of input\nfiles.\n\nThe available options are:\n\n --source-map Specify an output file where to generate source map.\n [string]\n --source-map-root The path to the original source to be included in the\n source map. [string]\n --source-map-url The path to the source map to be added in //@\n sourceMappingURL. Defaults to the value passed with\n --source-map. [string]\n --in-source-map Input source map, useful if you're compressing JS that was\n generated from some other original code.\n --screw-ie8 Pass this flag if you don't care about full compliance with\n Internet Explorer 6-8 quirks (by default UglifyJS will try\n to be IE-proof).\n -p, --prefix Skip prefix for original filenames that appear in source\n maps. For example -p 3 will drop 3 directories from file\n names and ensure they are relative paths.\n -o, --output Output file (default STDOUT).\n -b, --beautify Beautify output/specify output options. [string]\n -m, --mangle Mangle names/pass mangler options. [string]\n -r, --reserved Reserved names to exclude from mangling.\n -c, --compress Enable compressor/pass compressor options. Pass options\n like -c hoist_vars=false,if_return=false. Use -c with no\n argument to use the default compression options. [string]\n -d, --define Global definitions [string]\n --comments Preserve copyright comments in the output. By default this\n works like Google Closure, keeping JSDoc-style comments\n that contain \"@license\" or \"@preserve\". You can optionally\n pass one of the following arguments to this flag:\n - \"all\" to keep all comments\n - a valid JS regexp (needs to start with a slash) to keep\n only comments that match.\n Note that currently not *all* comments can be kept when\n compression is on, because of dead code removal or\n cascading statements into sequences. [string]\n --stats Display operations run time on STDERR. [boolean]\n --acorn Use Acorn for parsing. [boolean]\n --spidermonkey Assume input files are SpiderMonkey AST format (as JSON).\n [boolean]\n --self Build itself (UglifyJS2) as a library (implies\n --wrap=UglifyJS --export-all) [boolean]\n --wrap Embed everything in a big function, making the “exports”\n and “global” variables available. You need to pass an\n argument to this option to specify the name that your\n module will take when included in, say, a browser.\n [string]\n --export-all Only used when --wrap, this tells UglifyJS to add code to\n automatically export all globals. [boolean]\n --lint Display some scope warnings [boolean]\n -v, --verbose Verbose [boolean]\n -V, --version Print version number and exit. [boolean]\n\nSpecify `--output` (`-o`) to declare the output file. Otherwise the output\ngoes to STDOUT.\n\n## Source map options\n\nUglifyJS2 can generate a source map file, which is highly useful for\ndebugging your compressed JavaScript. To get a source map, pass\n`--source-map output.js.map` (full path to the file where you want the\nsource map dumped).\n\nAdditionally you might need `--source-map-root` to pass the URL where the\noriginal files can be found. In case you are passing full paths to input\nfiles to UglifyJS, you can use `--prefix` (`-p`) to specify the number of\ndirectories to drop from the path prefix when declaring files in the source\nmap.\n\nFor example:\n\n uglifyjs /home/doe/work/foo/src/js/file1.js \\\n /home/doe/work/foo/src/js/file2.js \\\n -o foo.min.js \\\n --source-map foo.min.js.map \\\n --source-map-root http://foo.com/src \\\n -p 5 -c -m\n\nThe above will compress and mangle `file1.js` and `file2.js`, will drop the\noutput in `foo.min.js` and the source map in `foo.min.js.map`. The source\nmapping will refer to `http://foo.com/src/js/file1.js` and\n`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`\nas the source map root, and the original files as `js/file1.js` and\n`js/file2.js`).\n\n### Composed source map\n\nWhen you're compressing JS code that was output by a compiler such as\nCoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd\nlike to map back to the original code (i.e. CoffeeScript). UglifyJS has an\noption to take an input source map. Assuming you have a mapping from\nCoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →\ncompressed JS by mapping every token in the compiled JS to its original\nlocation.\n\nTo use this feature you need to pass `--in-source-map\n/path/to/input/source.map`. Normally the input source map should also point\nto the file containing the generated JS, so if that's correct you can omit\ninput files from the command line.\n\n## Mangler options\n\nTo enable the mangler you need to pass `--mangle` (`-m`). The following\n(comma-separated) options are supported:\n\n- `sort` — to assign shorter names to most frequently used variables. This\n saves a few hundred bytes on jQuery before gzip, but the output is\n _bigger_ after gzip (and seems to happen for other libraries I tried it\n on) therefore it's not enabled by default.\n\n- `toplevel` — mangle names declared in the toplevel scope (disabled by\n default).\n\n- `eval` — mangle names visible in scopes where `eval` or `when` are used\n (disabled by default).\n\nWhen mangling is enabled but you want to prevent certain names from being\nmangled, you can declare those names with `--reserved` (`-r`) — pass a\ncomma-separated list of names. For example:\n\n uglifyjs ... -m -r '$,require,exports'\n\nto prevent the `require`, `exports` and `$` names from being changed.\n\n## Compressor options\n\nYou need to pass `--compress` (`-c`) to enable the compressor. Optionally\nyou can pass a comma-separated list of options. Options are in the form\n`foo=bar`, or just `foo` (the latter implies a boolean option that you want\nto set `true`; it's effectively a shortcut for `foo=true`).\n\n- `sequences` -- join consecutive simple statements using the comma operator\n- `properties` -- rewrite property access using the dot notation, for\n example `foo[\"bar\"] → foo.bar`\n- `dead_code` -- remove unreachable code\n- `drop_debugger` -- remove `debugger;` statements\n- `unsafe` (default: false) -- apply \"unsafe\" transformations (discussion below)\n- `conditionals` -- apply optimizations for `if`-s and conditional\n expressions\n- `comparisons` -- apply certain optimizations to binary nodes, for example:\n `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,\n e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.\n- `evaluate` -- attempt to evaluate constant expressions\n- `booleans` -- various optimizations for boolean context, for example `!!a\n ? b : c → a ? b : c`\n- `loops` -- optimizations for `do`, `while` and `for` loops when we can\n statically determine the condition\n- `unused` -- drop unreferenced functions and variables\n- `hoist_funs` -- hoist function declarations\n- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`\n by default because it seems to increase the size of the output in general)\n- `if_return` -- optimizations for if/return and if/continue\n- `join_vars` -- join consecutive `var` statements\n- `cascade` -- small optimization for sequences, transform `x, x` into `x`\n and `x = something(), x` into `x = something()`\n- `warnings` -- display warnings when dropping unreachable code or unused\n declarations etc.\n\n### The `unsafe` option\n\nIt enables some transformations that *might* break code logic in certain\ncontrived cases, but should be fine for most code. You might want to try it\non your own code, it should reduce the minified size. Here's what happens\nwhen this flag is on:\n\n- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]`\n- `new Object()` → `{}`\n- `String(exp)` or `exp.toString()` → `\"\" + exp`\n- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`\n- `typeof foo == \"undefined\"` → `foo === void 0`\n- `void 0` → `\"undefined\"` (if there is a variable named \"undefined\" in\n scope; we do it because the variable name will be mangled, typically\n reduced to a single character).\n\n### Conditional compilation\n\nYou can use the `--define` (`-d`) switch in order to declare global\nvariables that UglifyJS will assume to be constants (unless defined in\nscope). For example if you pass `--define DEBUG=false` then, coupled with\ndead code removal UglifyJS will discard the following from the output:\n```javascript\nif (DEBUG) {\n\tconsole.log(\"debug stuff\");\n}\n```\n\nUglifyJS will warn about the condition being always false and about dropping\nunreachable code; for now there is no option to turn off only this specific\nwarning, you can pass `warnings=false` to turn off *all* warnings.\n\nAnother way of doing that is to declare your globals as constants in a\nseparate file and include it into the build. For example you can have a\n`build/defines.js` file with the following:\n```javascript\nconst DEBUG = false;\nconst PRODUCTION = true;\n// etc.\n```\n\nand build your code like this:\n\n uglifyjs build/defines.js js/foo.js js/bar.js... -c\n\nUglifyJS will notice the constants and, since they cannot be altered, it\nwill evaluate references to them to the value itself and drop unreachable\ncode as usual. The possible downside of this approach is that the build\nwill contain the `const` declarations.\n\n\n## Beautifier options\n\nThe code generator tries to output shortest code possible by default. In\ncase you want beautified output, pass `--beautify` (`-b`). Optionally you\ncan pass additional arguments that control the code output:\n\n- `beautify` (default `true`) -- whether to actually beautify the output.\n Passing `-b` will set this to true, but you might need to pass `-b` even\n when you want to generate minified code, in order to specify additional\n arguments, so you can use `-b beautify=false` to override it.\n- `indent-level` (default 4)\n- `indent-start` (default 0) -- prefix all lines by that many spaces\n- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal\n objects\n- `space-colon` (default `true`) -- insert a space after the colon signs\n- `ascii-only` (default `false`) -- escape Unicode characters in strings and\n regexps\n- `inline-script` (default `false`) -- escape the slash in occurrences of\n `= (x = f(…)) + * + * For example, let the equation be: + * (a = parseInt('100')) <= a + * + * If a was an integer and has the value of 99, + * (a = parseInt('100')) <= a → 100 <= 100 → true + * + * When transformed incorrectly: + * a >= (a = parseInt('100')) → 99 >= 100 → false + */ + +tranformation_sort_order_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) == a } + expect: { (a = parseInt('100')) == a } +} + +tranformation_sort_order_unequal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) != a } + expect: { (a = parseInt('100')) != a } +} + +tranformation_sort_order_lesser_or_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) <= a } + expect: { (a = parseInt('100')) <= a } +} +tranformation_sort_order_greater_or_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) >= a } + expect: { (a = parseInt('100')) >= a } +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-22.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-22.js new file mode 100644 index 0000000..a8b7bc6 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-22.js @@ -0,0 +1,17 @@ +return_with_no_value_in_if_body: { + options = { conditionals: true }; + input: { + function foo(bar) { + if (bar) { + return; + } else { + return 1; + } + } + } + expect: { + function foo (bar) { + return bar ? void 0 : 1; + } + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-44.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-44.js new file mode 100644 index 0000000..7a972f9 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-44.js @@ -0,0 +1,31 @@ +issue_44_valid_ast_1: { + options = { unused: true }; + input: { + function a(b) { + for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + var i = 0; + for (b.qoo(); ; i++); + } + } +} + +issue_44_valid_ast_2: { + options = { unused: true }; + input: { + function a(b) { + if (foo) for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + if (foo) { + var i = 0; + for (b.qoo(); ; i++); + } + } + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-59.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-59.js new file mode 100644 index 0000000..82b3880 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/issue-59.js @@ -0,0 +1,30 @@ +keep_continue: { + options = { + dead_code: true, + evaluate: true + }; + input: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } + expect: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/labels.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/labels.js new file mode 100644 index 0000000..044b7a7 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/labels.js @@ -0,0 +1,163 @@ +labels_1: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) break out; + console.log("bar"); + } + }; + expect: { + foo || console.log("bar"); + } +} + +labels_2: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) print("stuff"); + else break out; + console.log("here"); + } + }; + expect: { + if (foo) { + print("stuff"); + console.log("here"); + } + } +} + +labels_3: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + for (var i = 0; i < 5; ++i) { + if (i < 3) continue; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_4: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: for (var i = 0; i < 5; ++i) { + if (i < 3) continue out; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_5: { + options = { if_return: true, conditionals: true, dead_code: true }; + // should keep the break-s in the following + input: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + }; + expect: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + } +} + +labels_6: { + input: { + out: break out; + }; + expect: {} +} + +labels_7: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + continue; + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_8: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + break; + } + }; + expect: { + while (foo) { + x(); + y(); + break; + } + } +} + +labels_9: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + continue out; + z(); + k(); + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_10: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + break out; + z(); + k(); + } + }; + expect: { + out: while (foo) { + x(); + y(); + break out; + } + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/loops.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/loops.js new file mode 100644 index 0000000..cdf1f04 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/loops.js @@ -0,0 +1,123 @@ +while_becomes_for: { + options = { loops: true }; + input: { + while (foo()) bar(); + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_break_1: { + options = { loops: true }; + input: { + for (;;) + if (foo()) break; + } + expect: { + for (; !foo();); + } +} + +drop_if_break_2: { + options = { loops: true }; + input: { + for (;bar();) + if (foo()) break; + } + expect: { + for (; bar() && !foo();); + } +} + +drop_if_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && !foo();) { + stuff1(); + stuff2(); + } + } +} + +drop_if_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), !foo());) z(), k(); + } +} + +drop_if_else_break_1: { + options = { loops: true }; + input: { + for (;;) if (foo()) bar(); else break; + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_else_break_2: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + } + } + expect: { + for (; bar() && foo();) baz(); + } +} + +drop_if_else_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && foo();) { + baz(); + stuff1(); + stuff2(); + } + } +} + +drop_if_else_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) baz(); + else break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), foo());) baz(), z(), k(); + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/properties.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/properties.js new file mode 100644 index 0000000..8504596 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/properties.js @@ -0,0 +1,54 @@ +keep_properties: { + options = { + properties: false + }; + input: { + a["foo"] = "bar"; + } + expect: { + a["foo"] = "bar"; + } +} + +dot_properties: { + options = { + properties: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a["\u0EB3"] = "unicode"; + a[""] = "whitespace"; + a["1_1"] = "foo"; + } + expect: { + a.foo = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a.\u0EB3 = "unicode"; + a[""] = "whitespace"; + a["1_1"] = "foo"; + } +} + +dot_properties_es5: { + options = { + properties: true, + screw_ie8: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a["\u0EB3"] = "unicode"; + a[""] = "whitespace"; + } + expect: { + a.foo = "bar"; + a.if = "if"; + a["*"] = "asterisk"; + a.\u0EB3 = "unicode"; + a[""] = "whitespace"; + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/sequences.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/sequences.js new file mode 100644 index 0000000..6f63ace --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/sequences.js @@ -0,0 +1,161 @@ +make_sequences_1: { + options = { + sequences: true + }; + input: { + foo(); + bar(); + baz(); + } + expect: { + foo(),bar(),baz(); + } +} + +make_sequences_2: { + options = { + sequences: true + }; + input: { + if (boo) { + foo(); + bar(); + baz(); + } else { + x(); + y(); + z(); + } + } + expect: { + if (boo) foo(),bar(),baz(); + else x(),y(),z(); + } +} + +make_sequences_3: { + options = { + sequences: true + }; + input: { + function f() { + foo(); + bar(); + return baz(); + } + function g() { + foo(); + bar(); + throw new Error(); + } + } + expect: { + function f() { + return foo(), bar(), baz(); + } + function g() { + throw foo(), bar(), new Error(); + } + } +} + +make_sequences_4: { + options = { + sequences: true + }; + input: { + x = 5; + if (y) z(); + + x = 5; + for (i = 0; i < 5; i++) console.log(i); + + x = 5; + for (; i < 5; i++) console.log(i); + + x = 5; + switch (y) {} + + x = 5; + with (obj) {} + } + expect: { + if (x = 5, y) z(); + for (x = 5, i = 0; i < 5; i++) console.log(i); + for (x = 5; i < 5; i++) console.log(i); + switch (x = 5, y) {} + with (x = 5, obj); + } +} + +lift_sequences_1: { + options = { sequences: true }; + input: { + foo = !(x(), y(), bar()); + } + expect: { + x(), y(), foo = !bar(); + } +} + +lift_sequences_2: { + options = { sequences: true, evaluate: true }; + input: { + q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5); + } + expect: { + foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36 + } +} + +lift_sequences_3: { + options = { sequences: true, conditionals: true }; + input: { + x = (foo(), bar(), baz()) ? 10 : 20; + } + expect: { + foo(), bar(), x = baz() ? 10 : 20; + } +} + +lift_sequences_4: { + options = { side_effects: true }; + input: { + x = (foo, bar, baz); + } + expect: { + x = baz; + } +} + +for_sequences: { + options = { sequences: true }; + input: { + // 1 + foo(); + bar(); + for (; false;); + // 2 + foo(); + bar(); + for (x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } + expect: { + // 1 + for (foo(), bar(); false;); + // 2 + for (foo(), bar(), x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/switch.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/switch.js new file mode 100644 index 0000000..62e39cf --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/switch.js @@ -0,0 +1,260 @@ +constant_switch_1: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1+1) { + case 1: foo(); break; + case 1+1: bar(); break; + case 1+1+1: baz(); break; + } + } + expect: { + bar(); + } +} + +constant_switch_2: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + } + } + expect: { + foo(); + bar(); + } +} + +constant_switch_3: { + options = { dead_code: true, evaluate: true }; + input: { + switch (10) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + default: + def(); + } + } + expect: { + def(); + } +} + +constant_switch_4: { + options = { dead_code: true, evaluate: true }; + input: { + switch (2) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + bar(); + def(); + } +} + +constant_switch_5: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + // the break inside the if ruins our job + // we can still get rid of irrelevant cases. + switch (1) { + case 1: + x(); + if (foo) break; + y(); + } + // XXX: we could optimize this better by inventing an outer + // labeled block, but that's kinda tricky. + } +} + +constant_switch_6: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + y(); + bar(); + } + } +} + +constant_switch_7: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; // this break refers to the for, not to the switch; thus it + // shouldn't ruin our optimization + console.log(x); + } + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; + console.log(x); + } + y(); + bar(); + } + } +} + +constant_switch_8: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) break OUT; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) break OUT; + y(); + } + } +} + +constant_switch_9: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) if (foo) break OUT; + y(); + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) if (foo) break OUT; + y(); + bar(); + def(); + } + } +} + +drop_default_1: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +drop_default_2: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); break; + default: + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +keep_default: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + something(); + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + default: + something(); + } + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/typeof.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/typeof.js new file mode 100644 index 0000000..cefdd43 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/compress/typeof.js @@ -0,0 +1,25 @@ +typeof_evaluation: { + options = { + evaluate: true + }; + input: { + a = typeof 1; + b = typeof 'test'; + c = typeof []; + d = typeof {}; + e = typeof /./; + f = typeof false; + g = typeof function(){}; + h = typeof undefined; + } + expect: { + a='number'; + b='string'; + c=typeof[]; + d=typeof{}; + e=typeof/./; + f='boolean'; + g='function'; + h='undefined'; + } +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/run-tests.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/run-tests.js new file mode 100755 index 0000000..0568c6a --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/test/run-tests.js @@ -0,0 +1,170 @@ +#! /usr/bin/env node + +var U = require("../tools/node"); +var path = require("path"); +var fs = require("fs"); +var assert = require("assert"); +var sys = require("util"); + +var tests_dir = path.dirname(module.filename); + +run_compress_tests(); + +/* -----[ utils ]----- */ + +function tmpl() { + return U.string_template.apply(this, arguments); +} + +function log() { + var txt = tmpl.apply(this, arguments); + sys.puts(txt); +} + +function log_directory(dir) { + log("*** Entering [{dir}]", { dir: dir }); +} + +function log_start_file(file) { + log("--- {file}", { file: file }); +} + +function log_test(name) { + log(" Running test [{name}]", { name: name }); +} + +function find_test_files(dir) { + var files = fs.readdirSync(dir).filter(function(name){ + return /\.js$/i.test(name); + }); + if (process.argv.length > 2) { + var x = process.argv.slice(2); + files = files.filter(function(f){ + return x.indexOf(f) >= 0; + }); + } + return files; +} + +function test_directory(dir) { + return path.resolve(tests_dir, dir); +} + +function as_toplevel(input) { + if (input instanceof U.AST_BlockStatement) input = input.body; + else if (input instanceof U.AST_Statement) input = [ input ]; + else throw new Error("Unsupported input syntax"); + var toplevel = new U.AST_Toplevel({ body: input }); + toplevel.figure_out_scope(); + return toplevel; +} + +function run_compress_tests() { + var dir = test_directory("compress"); + log_directory("compress"); + var files = find_test_files(dir); + function test_file(file) { + log_start_file(file); + function test_case(test) { + log_test(test.name); + var options = U.defaults(test.options, { + warnings: false + }); + var cmp = new U.Compressor(options, true); + var expect = make_code(as_toplevel(test.expect), false); + var input = as_toplevel(test.input); + var input_code = make_code(test.input); + var output = input.transform(cmp); + output.figure_out_scope(); + output = make_code(output, false); + if (expect != output) { + log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { + input: input_code, + output: output, + expected: expect + }); + } + } + var tests = parse_test(path.resolve(dir, file)); + for (var i in tests) if (tests.hasOwnProperty(i)) { + test_case(tests[i]); + } + } + files.forEach(function(file){ + test_file(file); + }); +} + +function parse_test(file) { + var script = fs.readFileSync(file, "utf8"); + var ast = U.parse(script, { + filename: file + }); + var tests = {}; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_LabeledStatement + && tw.parent() instanceof U.AST_Toplevel) { + var name = node.label.name; + tests[name] = get_one_test(name, node.body); + return true; + } + if (!(node instanceof U.AST_Toplevel)) croak(node); + }); + ast.walk(tw); + return tests; + + function croak(node) { + throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { + file: file, + line: node.start.line, + col: node.start.col, + code: make_code(node, false) + })); + } + + function get_one_test(name, block) { + var test = { name: name, options: {} }; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_Assign) { + if (!(node.left instanceof U.AST_SymbolRef)) { + croak(node); + } + var name = node.left.name; + test[name] = evaluate(node.right); + return true; + } + if (node instanceof U.AST_LabeledStatement) { + assert.ok( + node.label.name == "input" || node.label.name == "expect", + tmpl("Unsupported label {name} [{line},{col}]", { + name: node.label.name, + line: node.label.start.line, + col: node.label.start.col + }) + ); + var stat = node.body; + if (stat instanceof U.AST_BlockStatement) { + if (stat.body.length == 1) stat = stat.body[0]; + else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); + } + test[node.label.name] = stat; + return true; + } + }); + block.walk(tw); + return test; + }; +} + +function make_code(ast, beautify) { + if (arguments.length == 1) beautify = true; + var stream = U.OutputStream({ beautify: beautify }); + ast.print(stream); + return stream.get(); +} + +function evaluate(code) { + if (code instanceof U.AST_Node) + code = make_code(code); + return new Function("return(" + code + ")")(); +} diff --git a/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/tools/node.js b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/tools/node.js new file mode 100644 index 0000000..c0dd3db --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/node_modules/uglify-js/tools/node.js @@ -0,0 +1,165 @@ +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var sys = require("util"); + +var UglifyJS = vm.createContext({ + sys : sys, + console : console, + MOZ_SourceMap : require("source-map") +}); + +function load_global(file) { + file = path.resolve(path.dirname(module.filename), file); + try { + var code = fs.readFileSync(file, "utf8"); + return vm.runInContext(code, UglifyJS, file); + } catch(ex) { + // XXX: in case of a syntax error, the message is kinda + // useless. (no location information). + sys.debug("ERROR in file: " + file + " / " + ex); + process.exit(1); + } +}; + +var FILES = exports.FILES = [ + "../lib/utils.js", + "../lib/ast.js", + "../lib/parse.js", + "../lib/transform.js", + "../lib/scope.js", + "../lib/output.js", + "../lib/compress.js", + "../lib/sourcemap.js", + "../lib/mozilla-ast.js" +].map(function(file){ + return path.join(path.dirname(fs.realpathSync(__filename)), file); +}); + +FILES.forEach(load_global); + +UglifyJS.AST_Node.warn_function = function(txt) { + sys.error("WARN: " + txt); +}; + +// XXX: perhaps we shouldn't export everything but heck, I'm lazy. +for (var i in UglifyJS) { + if (UglifyJS.hasOwnProperty(i)) { + exports[i] = UglifyJS[i]; + } +} + +exports.minify = function(files, options) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : fs.readFileSync(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? "?" : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var inMap = options.inSourceMap; + var output = {}; + if (typeof options.inSourceMap == "string") { + inMap = fs.readFileSync(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) { + output.source_map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + } + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : output.source_map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; diff --git a/node_modules/jade/node_modules/constantinople/package.json b/node_modules/jade/node_modules/constantinople/package.json new file mode 100644 index 0000000..1f7f062 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/package.json @@ -0,0 +1,31 @@ +{ + "name": "constantinople", + "version": "1.0.1", + "description": "Determine whether a JavaScript expression evaluates to a constant (using UglifyJS)", + "keywords": [], + "dependencies": { + "uglify-js": "~2.3.6" + }, + "devDependencies": { + "mocha": "*" + }, + "scripts": { + "test": "mocha -R spec" + }, + "repository": { + "type": "git", + "url": "https://github.com/ForbesLindesay/constantinople.git" + }, + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "readme": "# constantinople\r\n\r\nDetermine whether a JavaScript expression evaluates to a constant (using UglifyJS). Here it is assumed to be safe to underestimate how constant something is.\r\n\r\n[![Build Status](https://travis-ci.org/ForbesLindesay/constantinople.png?branch=master)](https://travis-ci.org/ForbesLindesay/constantinople)\r\n[![Dependency Status](https://gemnasium.com/ForbesLindesay/constantinople.png)](https://gemnasium.com/ForbesLindesay/constantinople)\r\n[![NPM version](https://badge.fury.io/js/constantinople.png)](http://badge.fury.io/js/constantinople)\r\n\r\n## Installation\r\n\r\n npm install constantinople\r\n\r\n## Usage\r\n\r\n```js\r\nvar isConstant = require('constantinople')\r\n\r\nif (isConstant('\"foo\" + 5')) {\r\n console.dir(isConstant.toConstant('\"foo\" + 5'))\r\n}\r\n```\r\n\r\n## API\r\n\r\n### isConstant(src)\r\n\r\nReturns `true` if `src` evaluates to a constant, `false` otherwise. It will also return `false` if there is a syntax error, which makes it safe to use on potentially ES6 code.\r\n\r\n### toConstant(src)\r\n\r\nReturns the value resulting from evaluating `src`. This method throws an error if the expression is not constant. e.g. `toConstant(\"Math.random()\")` would throw an error.\r\n\r\n## License\r\n\r\n MIT", + "readmeFilename": "README.md", + "_id": "constantinople@1.0.1", + "dist": { + "shasum": "0d347e4f67304d0f774dbc0e15c38f753ac52c72" + }, + "_from": "constantinople@~1.0.1", + "_resolved": "https://registry.npmjs.org/constantinople/-/constantinople-1.0.1.tgz" +} diff --git a/node_modules/jade/node_modules/constantinople/test/index.js b/node_modules/jade/node_modules/constantinople/test/index.js new file mode 100644 index 0000000..e652bd8 --- /dev/null +++ b/node_modules/jade/node_modules/constantinople/test/index.js @@ -0,0 +1,51 @@ +'use strict' + +var assert = require('assert') +var constaninople = require('../') + +describe('isConstant(src)', function () { + it('handles "[5 + 3 + 10]"', function () { + assert(constaninople.isConstant('[5 + 3 + 10]') === true) + }) + it('handles "/[a-z]/.test(\'a\')"', function () { + assert(constaninople.isConstant('/[a-z]/.test(\'a\')') === true) + }) + it('handles "{\'class\': [(\'data\')]}"', function () { + assert(constaninople.isConstant('{\'class\': [(\'data\')]}') === true) + }) + it('handles "Math.random()"', function () { + assert(constaninople.isConstant('Math.random()') === false) + }) + it('handles "Math.random("', function () { + assert(constaninople.isConstant('Math.random(') === false) + }) +}) + + +describe('toConstant(src)', function () { + it('handles "[5 + 3 + 10]"', function () { + assert.deepEqual(constaninople.toConstant('[5 + 3 + 10]'), [5 + 3 + 10]) + }) + it('handles "/[a-z]/.test(\'a\')"', function () { + assert(constaninople.toConstant('/[a-z]/.test(\'a\')') === true) + }) + it('handles "{\'class\': [(\'data\')]}"', function () { + assert.deepEqual(constaninople.toConstant('{\'class\': [(\'data\')]}'), {'class': ['data']}) + }) + it('handles "Math.random()"', function () { + try { + constaninople.toConstant('Math.random()') + } catch (ex) { + return + } + assert(false, 'Math.random() should result in an error') + }) + it('handles "Math.random("', function () { + try { + constaninople.toConstant('Math.random(') + } catch (ex) { + return + } + assert(false, 'Math.random( should result in an error') + }) +}) \ No newline at end of file diff --git a/node_modules/jade/node_modules/mkdirp/.npmignore b/node_modules/jade/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/jade/node_modules/mkdirp/.travis.yml b/node_modules/jade/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/jade/node_modules/mkdirp/LICENSE b/node_modules/jade/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/jade/node_modules/mkdirp/examples/pow.js b/node_modules/jade/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/jade/node_modules/mkdirp/index.js b/node_modules/jade/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/jade/node_modules/mkdirp/package.json b/node_modules/jade/node_modules/mkdirp/package.json new file mode 100644 index 0000000..923d077 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/package.json @@ -0,0 +1,34 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.5", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.4.0" + }, + "license": "MIT", + "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n", + "readmeFilename": "readme.markdown", + "_id": "mkdirp@0.3.5", + "dist": { + "shasum": "e1874873d66a4e5111525f997f020d53f8311fdb" + }, + "_from": "mkdirp@0.3.x", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" +} diff --git a/node_modules/jade/node_modules/mkdirp/readme.markdown b/node_modules/jade/node_modules/mkdirp/readme.markdown new file mode 100644 index 0000000..83b0216 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/readme.markdown @@ -0,0 +1,63 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, mode, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +## mkdirp.sync(dir, mode) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +# license + +MIT diff --git a/node_modules/jade/node_modules/mkdirp/test/chmod.js b/node_modules/jade/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/clobber.js b/node_modules/jade/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/mkdirp.js b/node_modules/jade/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/perm.js b/node_modules/jade/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/perm_sync.js b/node_modules/jade/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/race.js b/node_modules/jade/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/rel.js b/node_modules/jade/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/return.js b/node_modules/jade/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/return_sync.js b/node_modules/jade/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/root.js b/node_modules/jade/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/sync.js b/node_modules/jade/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/umask.js b/node_modules/jade/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/umask_sync.js b/node_modules/jade/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/jade/node_modules/monocle/.npmignore b/node_modules/jade/node_modules/monocle/.npmignore new file mode 100644 index 0000000..28f1ba7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/.npmignore @@ -0,0 +1,2 @@ +node_modules +.DS_Store \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/.travis.yml b/node_modules/jade/node_modules/monocle/.travis.yml new file mode 100644 index 0000000..4a83e22 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.11" + - "0.10" + - "0.8" diff --git a/node_modules/jade/node_modules/monocle/LICENSE b/node_modules/jade/node_modules/monocle/LICENSE new file mode 100644 index 0000000..417af37 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2013, Sam Saccone +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/node_modules/jade/node_modules/monocle/README.md b/node_modules/jade/node_modules/monocle/README.md new file mode 100644 index 0000000..370bb9b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/README.md @@ -0,0 +1,67 @@ +[![Build Status](https://travis-ci.org/samccone/monocle.png?branch=master)](https://travis-ci.org/samccone/monocle) + +# Monocle -- a tool for watching things + +[![logo](https://raw.github.com/samccone/monocle/master/logo.png)](https://raw.github.com/samccone/monocle/master/logo.png) + +Have you ever wanted to watch a folder and all of its files/nested folders for changes. well now you can! + +## Installation + +``` +npm install monocle +``` + +## Usage + +### Watch a directory: + +```js +var monocle = require('monocle')() +monocle.watchDirectory({ + root: , + fileFilter: , + directoryFilter: , + listener: fn(fs.stat+ object), //triggered on file change / addition + complete: //file watching all set up +}); +``` + +The listener will recive an object with the following + +```js + name: , + path: , + fullPath: , + parentDir: , + fullParentDir: , + stat: +``` + +[fs.stats](http://nodejs.org/api/fs.html#fs_class_fs_stats) + +When a new file is added to the directoy it triggers a file change and thus will be passed to your specified listener. + +The two filters are passed through to `readdirp`. More documentation can be found [here](https://github.com/thlorenz/readdirp#filters) + +### Watch a list of files: + +```js +Monocle.watchFiles({ + files: [], //path of file(s) + listener: , //triggered on file / addition + complete: //file watching all set up +}); +``` + +## Why not just use fs.watch ? + + - file watching is really bad cross platforms in node + - you need to be smart when using fs.watch as compared to fs.watchFile + - Monocle takes care of this logic for you! + - windows systems use fs.watch + - osx and linux uses fs.watchFile + +## License + +BSD diff --git a/node_modules/jade/node_modules/monocle/logo.png b/node_modules/jade/node_modules/monocle/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..39d665f755e7eb063b4bd77e5d5a68ebe199091d GIT binary patch literal 25575 zcmc$F^;cC-*zch`MM7FaM7q06K0|bKd z=Jgv2lAMYUfgsCSh>FU~o7+0tI+)wqk$n~wCA0f(YieO-0)eh7U z$b|a-ma$cQi%6y@67Gu=LrqJLgee_Lo;Ckgp&d(H9G0*zGZZE&$~WSz0v&1?@*Khz zd3IDlPH5P`!@5V#x0$A!o#E%2S%KY>i?r%dgf>Lfcqvu|c3;#&5fZGmfZnd2^(_V= zKV(Wf2qt2+F}cGN1r+4gn~(3)`!<9Y2$bt23L>QKOG+CPQOFC%fk=`zly4wZn_~=@ z45BX%M94i#Bo87a0p**PNUa3PgoWr28X0av5Htp)zA2 zWN%DD#USRqkdjf=FmZ@F69mUpri&XgM-O58tY#_&si=drjbNfwK@d?PObVevA0e?M0$G!H8lnjnvu_VpKv$~pbe6R z7&_dN2w42sFxD=HAdt+Mw_vmvPp%{AWg{aTQMKrL^ari*FYgTvH=nmhi|vFUkab7z z@n<^5>UX}p@V?g1*;FU6=DH}EPB-DERTx4wkj(uBwF|q~xe?F$SwBC&y|pzb-6f)B zFreo3Y}TRIruJlY=gs$cbG6p8LFvb$<0lDwyVfyuDVs|)`U@%0aA_x6^05x(<&k*u zeb;BhdUaZyO$BWGD6!;-3zppXKSX|g?53J{G2U3Edw>yGWrtK)3P5?p&==?!!CcFH zz*Ki^+qi*1&Kqspr)Usie9Z&aM_pb{1)n4{sUW_lpMTjyAi83d49Wx5g1unziDmlH zRtOVbw&T;a!4tK^Ew!UO>T?8&P>J9AhC`K(v>sZ4V!Twabc$p{G-%l8X*0)@ZQueFayxz=cEeAh$z{x7LYiRU;-67KD>`D zkok|g0qd>{-;jklL|uxGVg@_<4I`#UsAv}_CH4dI z@Fs~Y!YVn*ipvFA%2@2tnj)oHwTk5mAq8*PoRYbR18_gf4J(D{5GIB)QpB81s?(5jKBrIJW)1}U^1MbSDA^E`7m)e z2_wl?MV+>m*7I%50CJpk9CaKaEu(T_QC`tX5sJ!%%Aj&|p{|lwnS=_f(q*8lAG8a-x3}GAs2qn|jDlj0mb->BzsK6$d-{ zv3F5d4$pf!(>5kP5jTeO7Zql4i?T|ys#Pmq{5BOt*i5v)O?CW=v`dqpaN!-cf^+(D z<0D}nn`}L^iT1am_=I@%VyR+5eNlb6i^-Y(x&0leA-n}RCVti75vcAv1l0;R9 zuSTVWUql_j=j&#-x8);d>|H!l5Y_1v63sP;Ge}qujHw^z%bAvll)#9v=+WM!+_dho z?#ZEsrzWSC`Eu~(Bw6uGecs1BURhq*-r=F)?BSUt_7r~RS(e?D-IUps)jEAmS53Ow zg4(|(pR2Ys^E6Isn{0wKxixatRWx;~B}&susb(5W8}qU9>%Yc+El!^?>#R7d?XNAY zBdFM(gI_GGwXXFtFf+t6tLrZ7Jc(_N^=j~neBwty3zmV7WkgADX_`Mxx%udp*O_YR@YZIDA#G5t{1c_ z>O=8j{NnyH4$1eWf--~o;V0~;1^saA?n&MnCCIaAa$PllEF6(pFZ@NgoDFOZf;|kT8bj0SY3iS?WQe#KXv;WktXftdk1s+t z(l$^wJ@674`*iHwvPL>CgYt0;8L;Vi;)P^GzjFQlCyYs3fEz(|{>FtW3fZlLxWnu{ z<2c87=$xoFEy>q&DcUdYzm8&>*xe|*S##;O>jOU&{%n#(lU+{XNyklgCbMSY=V@jR z_!aZhUZjZpOKh##f!U6!^I(ZdP}Os{O?Vw6NgP7|x9XoIa2oW;wIX?Y%9=E@vpuQcVs330#c^xjz9_z@dGit2X z7~BV^5emHh5mtt?h?nrzXO3pcb(=86cAzzB>Gywy#a;Erqoxz4`#UT2>00RVMF~3z z=r(Bc3;&_5s{VI;buGTgm@rJU*cebNTA$O(_qWL;zkg(yS5Wzn@}=^D=S9Nd^(gw?N8>7b<5_Ty z@F-bFm?U*3HX~-V6iGf$mPk=be$X=1YLFWe7@s*o#KL6`@UbVRWM(wX! zaygHl^?~C7-*fDwTyJA)V{%!&_P6>I_vRW8)0=(5bk33G%VxJT+?Sc@bZ-9T<_mY* zo9>&dRorFo?;oB<1{>#HKAe;`$u;R+3LOj2i!O&u3u-+t&7Cg!Shl%jUW_kE-oOV1 zj6TO)MPrDA+S#lvh%~{2e+wvsyp?NXCtGrSg z%YTR^h>d-Lg-N`4G-9P+1bCCoNJ{Yw1maEwf%pbMAa^g|_dW#T!~}sH=tCepi4X{$ z?JvD<2?#_3`?Hv^vg^W8nwzKc^xcc#&B}aizi|eoF$EzxrI0Tyla;^B+nO+$Pc}7{ zr8R$*uFSM*vX9kDQS`N}mrDmsi|H6>C@HO=u*rrfkGIWqB!E8AV{4|&ybFOIxr9fk;{;>ygcgN>qXnT zpx|KY!s&zm+S=L*6Lg%DEGP56z!4J@&u7!b|4c&k$4A0fz!7H&kTi7NO>;RoZGCxW zGYiVj&i*&s`dp)bcfKtVC(Vu~M3xjqhKP;Hm{(cJ{DGF%@=Sm5Q=IgY!ze$RoZyqA zikO%fpD#_-``4LG_ZwNaQ)c7j)cTsrl|{?QcoQQ;5sglLFwdO%h-Zpe~E zD?QT_qyg_qBm}KO^*UsVBLhT#`IYf; zgSkeR^3z~6!fco0g||hM`%FX_ekK~`HJXp-39TjfSLHs-Tox05+R9s>7pgq(&Ld*H zv;O>{d@#%Ka<-c((a3`QDhNY*9XClNdPq)TP0h5TwsuKDaj_CRC+8<*6ciW?QURi= z`FW(2VUG8l@zS}WVPPUJE}V`$%LUC$Zj`TU`R`ZW(F-SQYwMmgUYC2Hvu->E$tWVE zgX80%adX(w3tc0`A7Y@lH_E<%RYDpa6%_?jy6_&+A9jmKlL%eXOGhVdJ62BM$L(HD z^hQHN16R&CVo0ZODU7dlZpX6A>hix16h>tPSlB;)8&Zh=|4gAO7mpw6tmd;_ujkE_ zQc_ZKsbi5&H0RkA#?9GYugQ2{q^$03f4|d~e@6tycg6xW?)7k7_m*?j^I~abMYrgQ z9FvGB0z9wNvGeUgjd&BYSaEPiU4#XmU;uZkFV8nh1q&gge?G@nSTEK#C9#?X2N;4+ zhc$*)G^tci4i5{PTeNNEclfhG6AayJ9~vE9x9YZ=Hhp$>mRD89vMMKVM+vq@@Wr3? z|4K?qS{Pd&&+X*p$M_(~2a2E&YS+|0fy zD=Q;*GJQ0Q3eQ$wn3|euF&$36#SnaCnlP+%l@;f^T?;_-c{-6dM(c2drtUNqCL=>c@^y;NEPkNqbK?mz0q+d_>_Wp%RY;SG`952?9s{dymBiPB* zKQ)YKIK>RLhb=yi*oMCL*i~%izaRz~+JA{peSUc&7JPVz+Q~F=MoC7Uz8em ziHg<2e;>aO#?!~7rKK5N3$?emyPo%d7%Z#bNxr_lbuCn;jYPoY!5w`cwoz%+8+9e{ ze7kAU=zKikDuOc7*T-bD+VUhXB_#z9Aw8IcWj6e+RXP*3vt!!(MAlX+OmQsKPTyTOCe(|~Rkv1dOxSh*O>kwCtIxPf*p1A|w7R~fxLBq_ zvlI~>Jy;^=2NdREa6(y)IvrY2P|y+rsV8Q${bo;JJ2ffMM;2Dr$kvDDQ|SacjR`z_ ze0=w7qHeA%o$}d)ma7>p1IFgd37qPAzA~*EW!i2q(cve}H@dy^NbiyS@vkMf&l(zd zp1^|+Sam-v{Zmv#yI+7H6#k^ok#ghtuN@)C-rhcH(q<^yM=4LX(#hHR1XoAWtZorQ zSw+R9_33)Cmz9+_Z5g&add_$Re8D|$M*p_+NC2QdY!xBRe;%id(1oGz!J zJiAk2_a`pcXSV+R%O&aI@n91}7P<~TYuIDO>t@+Vv()+M;o1#jc42JnXY=>%0oAC@ z)bzdG-4E{~d-wxf*TYUuPL4na@qV$cTb?;MJr&$xB*w;m-*P_iDR+8$dfvJ5$(JTf zhh(L|@(cB3I)!A^R?GFmw{CFvSiPEwjMw?{G+h%D6GZoDWTEXS@S_)SJZTIM52vlG zt*@V#B+KD_f3+V{^6}%x{{Eq%BZuv+1U>Ki%lCpU%dhMIzyH{Flg!c!Bf`TS`nJ!R zZ&>2#wPu>V9P0;rah zV49klowkDYo&29>DVL2TJ}oWn_le2LVNq^wK0a->lwmi2vfs`wE@rm#Roi0&ai6qc zU|@P5yFIOO0!2K=d$A@)k#<(5;C%gm>4V%FRy(i z|LW)mHnu704PjSu2?dp9u0lhirQ?eI*OKY z8GY&Fy*M??aLF4=dg1p#DtC2vD<;t{K! zQ?JaHELD|*KmN6geh@{%zhDR21s%T4p9lTPJ|@(FzCNj=#X80hEG*x7d?7{fhW?p& zuvrb2m6f*34Nl{vV25vkwg_q~Rz1OB6(Sm1H|WS3=NB0-P5fYnqfO>rAvw5Kdns z3AO*$TaO}GcaNaxa0gdDl{c{zS5#o;)a}CMM>(xV)udzlYG)YGh~# z$Am@Wz})>E9`P6ak5CH5(}_GzMQ7P7txujl~F;|tn zBq@cH`)y39&@eD(Z7>+h{Gi*HzES47^eqU`=M0S^$*tU%Y=~1aN{Jpp=hs|Jd`4Hr`Y5#p6`@@A z%RW^Mj%lK9^;vSDZq+-asfiDWaSDqkF7s6;!Cz81h|v%c6Hykl0`c=hvt1vz`eT=0 z(NIaV$IX4zlozNkm0(eqz1A3(PoD-4HaFiuks0vKca%b7zk3(Pd)idJ6R%}s@l{49 zKqM;^22)^6t!~*yaB618GfE6oLHay$tzJI+> zXYilkfB*hLf(<6VVq~~()_o?1l_8|NqQ2bvICecx>G-mS_2#Jwl1L|HgkYBqKj(%& zr-R7mV$Y-%gth$p&=6ErgNN(m2V6RJOrDjN2E=|@~k1gxLgqKiIP_cZu!x*21Y+CMiuJhB~i}={t<6`=a$N#NN%cFzT1y%X3rj(BVyWwG88ixTj1)x7vkDHULCoq-|K2KM(!Y2`k7|6&S zfEB8F9+uWQM@%*cN$3i_!iP;THFcMl$h4+?s+XUHy96 zB3|S5KQEK~9$D7(7JYSsgc1xcKP=?SCK;|axn1}HK43Q%MsM3i9%lGiODlzelXKP< zENg>R?+5EHDfsKOv%pvImm~NvKN=B$s*(5?`uj`;WV72t?QmSp4z;&z$TuhU7i)u% z3+caU-L=@XwsGk;eLnVa0ZmaY)K2}^F8EqS%pDya`Fy2{;*h?CcN-Qm(9szSJY7x} z&}-F-IXOACn^s5eec_H0_4I6dsvZ^KO-xTe>17&nv@L^`C{zx+S@rQb27T?o%hQv= zukPzFlo^TwcV)kwR=J!OZZ=n_0$UgklML+GiF>6EmgG0bEJ>(0%PxAI;fyWnrQ_y1 zzEx~;i6qFGRdscBSK#7553oY82L}he+}+(J_#}RqXu!h4uGO_ZS$7wy6es)p`x`=a zDaJu$b#!!`!Ocgg5q2r21&B^E`02+e#@a>y#Q6>L@=S8OLngn7JV%tnJASge8#1fs z^K{GTeTKq2SXEu9%7-0GhWG(+HxCZm6{2&{CjR_aSJ!F95j`;M<>h4$x?D}EZgazX zdipOt_S&@O0SyjtVnoN7n`h#Lj*Ei|j>8?y^^Km2D8GNC$(y~)l&%$hH{^T4f7RQk z&P3EEh0nCK{}5+S{)a2X-RK)l@{VSf=7>ovc6Y(bDT530lL&bz_GW7Q@L4j*-EyN z*m#JddH{ia0Ilv_DtLz^Y(a>5{>SfC1C zR7m7xiA8QkYgW%MRoJcy>;u^Qrn?`lFBPeI@cd;G)AAh!Prl#CFU}+vcEs) zPH@T3z+nIMuH@KW+xxXofs0Cmv=`{E%KDgafYl@dZQ{v>zYi;Y^Zp(A+(P?}bLWC_ z;C>)6f5;XSiBhNHE{4o7+^J7glc8LF_ZF<39_*XTlL{70G{}guV$6mWckDA}8XJ@YXwtS>L!)_kJ-8#?~sRblP{N z6W4KJplH0o( zJ|ySmK2P5k=yyNL@qRfnGF8Ymk{{ZafV@NiV!$+=_) zGdnur6i$ZNjULkZK1S*{-QWo9_Id+;FyMGO0AHp)U(M?2txbc01nj!8v9m|+iAqso z2Zn@fzJje=0RI-^Q&Z_^al*_Y%*x`FWTGLbi_x7HA8m$zAGZEMjD5)tSzUs=%wdrt zx_^I!_Gmxy83!sLMp%J8fD{@3NPt>YB^*{~nM0j!M!}}D0(xI7qn0FFE_ zc7~%uNZifib<0CqTLpF9_j6xc45x$pAT)Hr(cYfi0Z4VhD)>j*dfUxtc?u+=d!YT*i@pC0jVY8C0o(PI zE}8D$;z37MNp_d>g!ptv_*qDzsGB#+Ae!Z^on2>3yr}{6L@iV*sdymxTj3k=QhTLX6QOcpdlTx8;29Crjev;}x3i zwY7;}20oSJFlf~d0kuF(@uo)%A4*h`3-{ct7JXym%&h+V!Y&j^lQ2 zna@=^G9O(bj5pUo_<5O_)YAl+65PgI<@>Fjoha863Nu(ZI0HZk5UQ%GT!TcIk%Sz5 z^t!WYNa_}kn*m{KuR3CLm7tS;I4o~nxtlYJj$9DHr5oIc;yp3ft+Ua|)hvyIFO7c> zMc{Ps;^{i~agN{zoP{2#Ser?BVG?R=-qn18c8xJt!X7)6}BimF9$=o}Sc#f`aZG>%sH$^Hi{64_qk8jC>2(2tyQuuZ-X_EL0L> zmSHUHc-XNx$7=WqKa^>(EDa)d6s~o4egO9bLylCBJ!z_g6ca3GW_PDyPzQ&M9!GN2NxUw{XE;|}jg2-AXKenf^9d}=#c#czZoUQPK#<_$Iz}SD z2M6V^Gh*eY*CjSQJRG@si!}_io}3o-EubqF@DMi&yFy-lf}15+H#`bjpT&TcPSHUF zit#<>rw7l#PP9Og zK-yLOKM3^*rs`=H5sops^^!7wBhh3lt1vcKY;qSOxq6Ypb20jVUVO91f<4eB+ho4w1{NtH@8WfVtbQKHgpQ9+xFJH+uQFy52sP zm6gTZof+WwZGVS_hc^TyJ_M-z?jzxx)f7+!jietAv9@S~Yj*>{_R2d|_KTCt+hN+c zQV!UuJ5YG&b^IqG=%Tk`i6DKjZEmL>z^(R3f>k*=K5HgoZ_iw7vm935a*qs<>ShN8 z5+b6Il9E!HVjlT4Uj7h@GFiAvA)Nf0O$^?I{5PR^sE5n zaR;=ZS~q|RC478*G_z%(SxoU2+_fkc1k*OolZv)1hZxq{Y2OrnjM&My_8_;+;LN$R zC4ek7{79gI#w830s5u*xed5nESwT(GhRYcb-Pka+TKbEn=Y2;7T$~X0`4Og}pOcZS zr~$TsW39ba(`JStsYq4B4D5*gAa}j9yZfL~s``~7;X<`IuDHBh&B@WRFITY;|IHgC zAYs%51_sV;f9Ecjr-7~4W}wAE7S56nMGg{CE}s5(b`~Q;`Aa`_K`_-hoDzz_D455w zTZ%4m)(*O=f_nSilg;}29jvpUA zJs;0{f%C(t&x9ZB=oPiOw!4cECk+?S&a}7A3V$0*dCv5RDW ztVdR7*rcsShfa^ zI6@~AORzyUlzG7~Bvrz|U%XJaPA;AS1u}L2IoqPvwKNx($wnfQ5PQ!D7nANw^ZGzmuAaioHR# ze)3%445B0<@ujq*1|xWr6!(xdg0FflhJ>KajPTbHe_Z-HHJ0}xKOB=W}&JEbQAzeN;mh_**-Ei0VPTf7v{t3wTEaE4|F>v^uL^bS9fvb^kz5eMbvZW5f-b1yjFCeQ7 zTkp|5@viMXpCwA<_-XRr;>ZKJ7ibfrXf)$Lven@;qi7R=3FNk*&@ge;jKrovh1d|U zs`Dijw^+6-LZ>qH&gjIBp_54{wHBjgIJ!fz9=?Jd2Gf8Ezl|xth34_;Y5nx{^t+I@ zo}S(aD2@{XUiX(`&i_)Efo=mYgyKJu06im<3Er==K7vhewei zfhsdDQB6qZPoB1#lAyW2Bo#Hn)Um=@_?~vR$91c^gZA3LKHUI-)tAm@F|o1wbmGzv z-nR|77db#B$Me2j4_St27I-6JW7bh{WNtvs-h2)9v|_}G-BnPL6Y?~p7ctExSid2~ zA2In;LR@>_3e!LwnnC3E?_WDrW?aAVtHtweUBoH`NOa)wCr(aII*hdP5}`ltaJDAR zkB{5`qKzkmvgh;)QrR1^ciJx_uJl39woLD%SH}wZ<1-|BP;146Jt)seVbowy=7mv+ zL_3tuPw4FpQ(pHM_%11(9UX=`_0jG6=A(my7tI9$)-3CSFLxL!}ML~>kX7LC^J9N?Bm`#k0#Gn~vX zFDx85`kRcV^JhUKl(S%wLK`bMh@Iyj^o^-y-PL7Oj>KuGM>|Vk(&VYpEL37s*>lde zIEK>dAiT~;1xr8@ATL!#sneO7Rxm0aPz&&Dk|hr+Jxgi zyF#bOjFmoj>(4evvxl_Z$&Y2$k)wT)bhjZtkM&v`Yn-y-`YL92g+&Pk4?zM5r8K9o z@MCLUUXP-#ZrSCfqF#pKyAJ(wS%c`%MR;7P=iTs?M{^9Ox>T1X(YqXe*vr( zmn_N7m+pE;c#29gOLjL>(TW(qdXs?{iZwX|Nx(V^Ow8m|} zeoJ(Z+mc*&;){jGB8a$RZ+akxbH?TDwrMAfBwdbSRSeJ-EkMZ*UYGy}@ffUA%xEI+ z4Tqz-O5e^9j9$V>2}FMgnC=?Q$XuBO+|d-ya*vfJx2S>w8v0)Q^zC`75;WhFLtOQg z4g`;|3}h*`X7=3sxyJx|RvVNa8k=Tm5=7<^X6U`n!qPzEKJ~I$2=u|GIy82&tgsH5t-PRQcLICFfx0X#e+9exZtQ&B=9rX>uUH zL8Sv;{jt4zyf*4+Cv0ZYu3Pi4X*GZFZoy zx46Fkl+Jw*0dCCBr6i$;DlaB}uwONcncgNUcoFZzJC>xQ-V4y2U9VZSkKQ>qrg6V; z8?z+2?mXjpjIiG9?d|tG zF>V4GYIgrNA>2t$QpVJd5p>QDH53VSb(0iWisxJh-~zEtf) zhqXqhjmJ-$jfU0m+c|YC%K0D{*bvZ%JU^N^04ctD*?>(WD$DVen%DLpy5S$>?MgpqoYLIwrSCbLt#mY)xq8# ze!^%ikg6-t2st92^D|!YhmY3UxdjnZ(i2y$)~q5+>f#08C}@i%=0F}aYXz1fm4bqT z(*L~s&62|pdiwu{!#I(o2$Nq<7809nc_P1LND2%4Ic74hRBpvclJr;2TS-bj^(2dj z$6StDsmY~aQ*G?k$#ogxx5vSByU7#v{Txe@&07Kr_FK@7Jia?RUjC9K^AqlU+|J|}Sl${M1N_hZFEkr5*kH|$OP}ps*5p1w$@(># zK77IiXZvX8gm=l}fID7h6QC6wy(20)|f@$syOht(GWi>Lc5B_NAUu?mKsl)wau zK!JMd>k9!nD@SMN?5e8oQnPPhp_Z4I6WJ`V%bKq>=`^Zf0Wn|WLgyQOxiuQLC$i!o z92gj=u$ZJiTBtz*?P1OBSrQ7&jB_I~PZ~P#-}{D#`Md137xteWObH?DCF4{C3_~ZL z*UnJCs-M63qtsz@wd!d?%|W^#p`;nm8)J3Um&%p%}>?EwMu%g7*&XVhD9y%^@?905*S(YW~(-QZVT@k#*-3Zovoz=3r; z&}0z7ADLTNw3pVcgb}csw)O7%XnY51?Ab8q>KeG%@%;4gfToEfj>R|nTAqLAEx5Vg`lSh}SZ%mHivfG1u&nH>DNEAa zBq`?_*Ga1P$OYfGO7+B+7J)Jls?k+YSZ{Q@*y#s1zYZAD$t9aH3jwfY?LlIRW69&R z*{Q$3KSCr65e5^3?3_>G^qtLhFsswz)KuWr;jGc&OzB_1+A59vvBe}Ma~c~7K`03h z=>Dk9x`G9VXME9GHuc-TKw=BEPuKKTB7L9(R}P)#Q_D&FS@@M$OyQ3EQs>q_(#31fiMxJ zynlWrE{4!z!nl!5AWgu(<{uT@fHB5sWogM{M)We2aCt{ED^(^EE1mnA6Lh7 zN`dL`huZlED)imjRA!1zL*YR;o?e8@Z1vRi^!lmK3-9yYsEQ=XaXB?g?K2oGiOM`<9 zY*#V4(2uU`L3mLtsGHIiIorS03?>h+?pHv-NFV6L>mdA~ll?V6pqu4(pH&xf9_Fj@ zS!jcjj20*0TEy6kH;3%Jx6O`q$s!s=!$3M@no+$%2u*0Sos`$a=W&zt%_v^Kw5iod{`F?$_wuaYcMul-LcN~4|1C`qWwhTnd85X$5q z0v81yU>TIYYQ(;GIkMDmMn*z;)022z7*tEt$Mx=$z6xVrg7KAu&NeqSWi04+{s#nT zIqiC*h(DH=mR6qJ+8?k(!EFmEeZa)>v~;zU{}Kh``YpjvDX_t@)sK3d7##tZLEE+e z)u+=3#=FBB(&AUW$HBj5yCZ2iJPf1uL_4DytDu#QroCqJXyT-Ip%ahF4uOKt2y9E* zLm)s}TUq@E+F(DY)!b`}P2yOcN*83Knv`kLD51CyJIAi#bCPI`dhodJfZO>^>x);M7|Y|Sa=b}Qdb-WsQS~UY zmZoNvmX;REYsPD<%?K9kdR1c;@sz&ZZI|1Jvk_rJT?Pwi>A;o=+fwI+G3 zK--A}3rB7w?@P*muSo7ZDLR<-Bge>%v_^aoNG<}}`VI&-xfvYRnzkTfL(jw{PaY>t z0re-k*Jaynh3Op%Jjho8)akkh{Hrq)eA5;6)*Dx=Oi^_nwn{t$X4E$iJ});u9=yD~ zhd^k>6wz^H~EHvMhl5_hUwW&<8 z??(x89Iw$R(Tm;DgzrQN%(^QchMx7|QAimui(t7OUW^I~R@$z%9D%?woQauP{`|2s zKsT4y*CL<<6OUKDfhttKHzLXTR#u<4^+E9N^DeLfx_|z}jFhDghq61nO&rSz%GqfD z%5~Wu@HB%3CrR4bukBVVT#la#^b@hCO*Oz=uElps|8n2#7LI0ZZg>jwL7= z@f8(JLD~#AfEu*_!m{VK?6@vL ztYEpjyF2Q%go#q`}c49?d@$#p;EpkHa0eh#nY+L#yu1D20=@;Nqu$i7eRQM9)(~Y zH8Xhqvm@dxpxOnvJ!kyiR0Mw%BuJ$4-=&lvl2F{T&FS9ZVKq=5I!vpXQ9DDy5&}Yc ziDKdJ&y>F~A=P|mCcQbnsN{J8xu(3Xp7_CMG19rQ(9qBo`t8tk>J<>Kn!$7u2xHjB z`~z|*my3Fg;OIZIYZCobicSo9U6rLZFdEVgTzxNT@B)Ll|kA*}lh!`)POCLs2T=bwo^%PC^|P z+`%dqAbk17dsfk*#7T?mNp$@+<>MG5_jDS^#9c2VA%CNDD5R=3txBDMk$SE6K1PT- z)?S$$Xjd|*+ZPD}Q;06>3$`3EDTAWw0YBhCC==)$$VC`H++#-w?D0a1_QTTo+S`Ht zI|i>U2@XlX*Z`a%=*j|B(1Fd2sgexnv8bK5zv{t>7yo~WBWxZ!i>Sm}t$*hBVH97eWZ)vx+E}HX#la&&(_)133LcGH!3M zvE2(>6W6$C-#bP70k!meaE zFd{#FQ+s|VB;aw+btocX;_mq)Y%syLDeFp4e|8O&K=SW2J@nb^oJ?{xG5!eNcM2~- zw|o|(p(zkX7VSoL? zJX-2h!@1ai+UVT|Pu-=A6rCeMYmnUE=JUqX1NoW2S(LsqokpAy7LI~x%O&rJmw;`DkHW2~8O3yNBRZ00R3KRcyaG z75Vx!wBi*w*frv)s{j0Wckcu8){zJpBvy>zXb1{AI(%p9fIfYg@3i-Ut@_lX01Ubp zmI|vq77-1g)aatVgJ#sNddO|Lcl^Sb@a*O7OsK$MK86!w0y%DTA0CoEFwa9e2#}Jdvx( z-=yJxe?~>t@6G*OKX>y}o9Xz#-aS1jra<&t4Sbk-JQWlGZs_y^KjBV^Q$i585QrVStXza3Oi5QAJ z6e)X_77fN0Y9d>| z-mgjEki7gOWE%cxop7fpE9xz2N9FD@R?kt1PF9-S#d zm+dPKoSAF#kW!s?zxOg6&419wO}Vs4LHWhehXOA&xz3GA|9Z+(uFlUjs4nqtp90tf zp_sL}V;)gRPAqn&!!zj9-UXL7y6y8wmk);W-4DS8TgEMJWa@Gre8Xqkcv0x#`wp!G z=Y0xTs_LZIS6>J2SR6i_6sj@_)uN}}z6?_3f%ZklJFwFQcrpL+EGQS$nkSs}vo}`y zd1T-3MoJ31_Y_rbNv(GsF^{RLu;^21`hgJiUr;GD{Ltt(O!gg5PfM!u#c|cXXt`rq4IwB-y2y*SS&W@Xb?q{EfJo!wM{}Tzar_~3l*zJpH~F`twZr# z>7n-3>WCqXj?9Z#DDqXp^Mn#C_a&j zdi#66tWYPP2+rD_DkSCc^0gE^=ioD4t*@I;>IdsIePk=e$JyIRM!hFv`hS1)7q!Vf zHZ%%W_?Bgp;H+BBm*S?}8^8O$^ zvG%98aSc}M)o}%TVNaVK}S)Sz~;s~l;Ca0-JPwJ6QUDr=h%yEVWhxu4n z`7pV?r@+tD_w*hByEmoRxQfg#RS8fz0+tB@-;Cy8Sq6DLVBKB~LD-)D!N=&wx$wJz zbNWST8{jpgyo+5B4`XJ6-Q6xqlyRTBTl#3!;a;PmW`fTK+$Vr z=ek>yTMtPhX(~&(Gs*9I+xrXIx4N`U8-|MKd(SR?=QdrgPezz0oNry*u^7=>4eHy< zc%im-G~Y^A8Yv0y0mz#2?kdCNkLpl~lKvrESz$?is5pFXc=1!_wf`nUY`4nv8uV5k zbuf-jAH<*^T#5u?Bp5%$}R!kdn>bSfqKC3;)a1nR2owDYHyuUQktWI-@b`5B4 zJVVi$bvcCUnU(eqDR8ZI*;$fWVjsFay?hou!*)jPpOn%W#5JXIlL1FdkDBYDJqQ02 z(3D#C6Za_Y+!%t1Z%BC}1NC+rB-Sr<_t$xKr*WnH;xS=0^v{d)-3_Wu)Z#$O?|$d` zDz{zids!pmAEAT!cJw>n?k0e+j-_Lauj#mEU?k_=)dhy^pV&(mnrmxUJqVar?UwM) ztr5oW4Qji$+`M(`j8JK~z2whrOBMB({|(H%zZ-b;9w{dFzJbpLb&+c;yzeNcZrUkx z+K*WN?G_b2apKE+%Y+g8=!V(|m9rb@XT~%Tn=Yo~aWvyt?D3D~w+) z1@`0@!N5WGi3~N>Yb+TU%qV;yT{c@12cDkzEuHMS5o(Lc&Rwis$LtgT8sGY0q4>}| zH=lG+tEdOB>69aQ0Uj6`8D(kh|L1^kh~vH?!^(*EDgqTeE@g-M!KDKgcw5Quu#Iw) z>|y8Ylwt1F4|=4rf`r(h%|LuB>v7k5$?PNc^}@0-rNZBpr@s*2y~bkc?IhO&qDy4N z5g0zcJ11RcN6*z=jK|O-+QeKx3F~jqNta>gs+?-}F;G=x1G)nDW`9FtF3g^|IVyx4 z{n0HQT==vkNh|2M6hgOsRgav=a(3--DzkKQ=_w6!tb1e_oUQ&l`u~DKKch;rA8nSiW(am$5CK0X|AZKm})y1{@kruK<=J( zT!n%UZB>?a&Umh7x_@k*y!u+cZln9%S0&WAL(2Q>I<`AILPmYZ4`S?&h?*_2JJnrH zQ5`U~QyBC)(A^4Vx=hvF-e$JAnD{#MDi%{P%gw~heCiu~T<D(lo=|JwKDbnuVn+X%f7}HdK4+7>V@-q`0rBh3GQ#83lI1CFL7N5a>7UB}#v9M7 zaD@j1$etYIkK9TI@Y;)VP)d}kp4A*X(@4r=I()d)UOwYhkVf-sW68isK7JQ=+by2h z$FqZGzcRTltB}UHOnW|;(eP`Pmnb7XlyR9eT@C99UX=;gT%Q2)yqDM~edbU47UY`q z1Bs)SSU=)IR@_=n0m{SeQcJ%mivcQF99S5_o2|n5SFlVg^lYab*|pSQzyAh_<^DSP zA?>D}(0d(e+2um!lK%!BcHMK1vOH^^Mz_3Tw9e%IdLsxSLO_1XLOdQplIIp%~M4#ZT!r#angoEXS&8O|2P z?Uq7eYuRgmg&^es@VJG%+p(PMYBZOqf19Go<=X_OU|{L zx7<;y;Ht!neH}Q})xg!&fYLgI%~NI=P>Q)xu9#;gy`1v zxKbOgkT{8I&fj&7cdyUunh|VMehyoC>`5k+n%rQa@5qvu0p<<5MN!h%AN%@I*3)n`_xPzy=QDRnsi{8f2|m8EKlWn=6-QW5zxYVJ zi?|~SEa7Ly`;NFfZS2^c5k3VKapPC)JmRcUc2Ah{mupYakaEjvId#c4D$QC?MH{Xw%GS3oS;c22hH=|L1ka zW+hGl!7jCZ$5%q2D@HjLk^Q1zTL~r*nPU}hYjO$QVMAb>-+-5I3jn9ybLVcNTzj^(<{BgBi`s2H=JK&kfrHIPj2VaT>nj9!yP-e-^5#O}K` zC0JX(SK2z^g3|4R{kZjjm;J{+q&_^tFtGmbSL|pm&4Kml{a5@yj7v0B1`nm2JZ<${ zvjNBeUB$qU-dX3{F6&ZwC}!xybD+8lc2-FfvOSGh;K2PJvj6Z|r$7CTVUslGxNAwP zy)FJXKV^&**Z)~(B5R(-^p+CKq}-Z_tF`QGG8Wb=pH$_E^C&fsCDJ3ILMBA}wY!RZnk(iT10Fali>-d0Baz4X?7aWin`kPFy5ejoq>@e%@7#OGbEM%Lo|`S}Nbi&tW3P80(Qg!uG$; z;Ml%;b8busHQIDv`nS(jMm>~rK>V(n-n;t9F6sZ;%z2RgYBPf$&OVd|FOGZO%=}|e z;P?r}C*l0CCuDHN@+6j9#&SrZfyaX}6AfQ3A^QYuX-MQTgxz%!WD!ryC}PYf+Gv(s z!&!Im@bj(Uy6_N;m1qPnyH?*OMrOClHmQ&y?^Xh>FyT@f!&@9O4adxr%2D0Ul48v6 zA?#@KEPE_+R%{pe-m*CQR?rl2-%F|eGb7D63V0;&;BuZ!)z?SlBAmGDf{DTrXUvxj z8Gi*Nt}pG%ju1f=^&2eE%`_LGX18na-W}cRlDuXd|2-BGI~4n*24r|xoij_j4c?Sr z;o;V7-@No2oE`#P4VSj!1Ww4Oo8v>eJt@Pi=I-u=qd6?aNB6;Ik`+DS2>Y7Q-h;z< zCr3x^(U0~;wjM*3jyI|4Yc@zg@+R_F!R9LTY^R8q)|F^B56&#HZ$P7SJo>f`e-!NH z`5LhNQ1}9(T@v_^%@3HsWyCwLQ|*>M5uj3$0mfv4yuT87qd-8?oV&az!))d*E;*k* z?yCj_I~;|UQ|BFf4&;hX!Ij_tBC}NL6_R0lvkc<8*lN>=8Zt=2bj1pQ8F1px$zEfI zJeCKmEt`EVv3qyGiztA{<6lcwVaF73nP7a(s7LYoXd1@M3E1&jDm__x5Xs;3T-qLN z2#TP{&Xr@Zy)lgr;Kw|L+N{e32_%cfkfl|qD0nWP(xm_l{`YqvCM2td)VL2rMC7Ed zg&|eBZsKf;Y;6T~REvDio$KA{4Tw^|d^?!Vvxxx7vdnOc7Y_gxLZcwOz;b|HGhM0$ zvX$6?g2-~NaVndhoSOOXQXC!Bb__4J2PpJI-nS)3z)eq2 zQsGlDr;^>id1Z>36MeWS*?|B^#6ob)vwVL&g{+<%U@E!H4H1T;)>U?^-H)VkK+Z(B`jtP~*PTvBkz`Iihr zw6KSFRA|PA;j67%Tyu_RfkTm4UWYZBgO_yI#0vlVRLD9gq4H0;LlVtw{euTS>ZR{l?BM1$lAo1T7UX1FYJU>U+h4Eo;&Dn*`8Sx7lB`A-hN>LSY0T=XUjac+ z!rnkCK-*+<@B__Dy+OZCfg;Y*#H6bo6I$6B8I2LQ&*eg3 zQe(o&?0GL$I!+%!iZijY{S?r$-bs1*P@^oay`uvF1Rm2FDRUxdHW9$nJ4QiA4Hz;& zSonsE{IF8SoET4`5HOy_lIZpuz{t&{MZfZGBq@*@%n$QR!?$RYVqRX3DVRird{hMU z_|q&(>1ODnJ4pa2_ZRJPqEV#eX|QB&-r+`jWXkvA0l3r8Jnvqk8;<<|q#J<8 z5_p{)sId4eH2!3liDc(Njog~5qN3;!Cs{n6QAFdcJOc*q61{~+GXwb`xSHL2Dxp49 z2FMJ$0HVOKs7uNZOW9$h6lr1F2O+P?ru8eBfnH~;#>)1xwvURVt&4fZ$C1oy#olz# z*)F{l-QJ3tgtw&Nnz2;Sf{bg86FR2qoeC8c2cYvIr}7~Qru=AS)OApew?O>NeSql$)5#$13+W?Z zV9KjgSfrm%H@KPb$59#XGz0lk;RS-0|c21PNqvQ0H0#!v_-GPN@Br8jZhAT%x;?T2~%VD}CS63POm9LYv zQv0keEEc3Uc?uwyiWM|4Ha##gk{r!3D;VmJA7N#@UqOqkzS^X%oiIeil%@nDe?QsL%@b^HTc^Htu^oap#g&0*IU_@0W#hvq+F_`42sN_q)SH4)PND%E zN4HG`sxU<04$w?69efx|aOw|ERDe)eJtuQ5{`%gS+cs0eVi3ku)W=4Ni~HE!Kq-p^ zN{==#$p0c5LsMZg<}=Cf_FCA|>QI3Yr@Ks>l$YP*q9+M3E92t#;vn|rO%A#IkGg0t zoD)Q7IS$;hlSH&pPHiTfV{GDS(r7Z151V2y`*|UDuB=n zLh-CpgFL*cX5x`vGZP&NTUU#n7w%*uiPB^pL?hx;cQ8yjzTgAOUy0K{-6twWHdj-e z@CE3%%*YwWSQmWQSXpyOklG=4)svO10qdzQz$`$nUzq#7v$~p^l#~SO992?{h6Xr4 zXJPi%^;gRY?rx`17S-<+*t)qb%`W|H@EyF+RZWpg%gYwsRFSE zew@r5COr?Ens!8WLVdQus0aA@&o6Vw!$&*BK&c5$)P zmD5bHq+5GAwevRr+UViDSKXi{oLXK}V{&CONS|(RJrxC^ZH|4fU;)kp4?{0t*ty_W zI|bUR=MYq;oqHxh@VZJd`@bTf=uJ&d&V`rdb3hK%HeiLEd*MZDXBapRE75E4{fepB zYf`(tAPFf!>spW2uCsxG!HH9+W@3`3M*te6TbhoWI~qq+vp~^zeZXgF>yfdPfrkgq zC1dRBG3q7 zI>ljcZ_lrNJ~dRwEx21I>rQE@V$0Hlo*5HUQze(y3yrKq?IB@Rr$+}UjxH|Ea(nms z+FdE5y?j{$PF6M|0mfV4tNr`;yB0>y7<|v1Nz)$8g*d-z>~p-@epRHog}J$N!^sZjijQaeF8@27)iV;g4uzJe zZrEApNhE?U!@s*pC_FM`l5!DQQB!mNRS=ID*L?J9UD{?6$r?y&H;+TC-AnZwQ~fSZi@GSQ1p>c0T_8 zePC2_@d|3^WuydU$|ar@{1ljgv)QUjNlB>&Aza>*mB&?JbbK;h3=s{GKllq0e=gR6 zMHE8x?9T9dS_R2a>w-Xnc>_{S{^KvNsOU~gO)VujGY0X~iwBT@{iFv|UY9tu;!bxO z)qliYl@g3cz6^rbH*5!ri%<|P4MRW`8+cKE_b8c+}6WE71@$Ha3eovfI{OS4TOSEo8s9reCI0S;?Bjf#<mTUq=sT@~Yx#f05n))$H|QdNK;R;aJ%V?&S=TGtf*v6CyJ(?Y9^u>G7e>h_X!)jt<*Adekec`L5Ii2UM2yeyQP+^cLnsxA>O- zT|(7E6zxJ^6&b&JZsR!as2u40(>C~|3#^^cI$jDF>(Xh-EBW_M1(JSaOl~;&Lf0X5 zlPigZevz(zWz*&de^32g&Didacgx?_aU~uGa4(+nsCI~GEMtP%$eIFOfgKAO@<(cV zU6ASB#_9CC#Nz~RL#9lF_Wu6QpZ80q^ZaQ=1jqis$MsL2NK83@dx?VC=0d*Mp`c01 z|3B_vB#4PmowkgG2~7fZJNotC2h0Ug5io`RCth1!{cR6pQU3pqgCR9I!(wPPD7~8z z)^y4GKbOh_I4QW)e*P#?fj>F+|J(YX%={iQ6TL>@hHg$Q{Ou+tJ1y<)bTttYNSS#5 zc2gb)f-Kq7Oe7M?%ggD{zndL)K;gpd_9RlJ?B6T65#j6W^;0ZdqG;yZ(u035YXlOT zAs45ykrB5V`KvWvq(8q7L9?-W<|$4e6yylh64m?PQ6SM@MSB`Rk(h5~N&lAyudpgC zE?Pm^s9Wu{fBD?sgG!*~0pU}bHyrz47l|Hlp)nUEn=Jm%C=t|$*V;xib75)ePChH- zubLB;@RE{6Z$7R=?BbrB%s*oS1#4bDTNk{WF$lr#zyH-)YF^&iNv(V1Q=cE6OGfn@ z&&bfvsGR^7GI_qMQP)K{nAZpaxXr&e7z^4fU0y06ARr?Y$;pD@FuAeIf|$+;{fIPL R^hLnuu!)WFJwuO}{{x3Y>)ikV literal 0 HcmV?d00001 diff --git a/node_modules/jade/node_modules/monocle/monocle.js b/node_modules/jade/node_modules/monocle/monocle.js new file mode 100644 index 0000000..2050da9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/monocle.js @@ -0,0 +1,142 @@ +var path = require('path'); +var fs = require('fs'); +var readdirp = require('readdirp'); +var is_windows = process.platform === 'win32'; + +module.exports = function() { + var watched_files = {}; + var watched_directories = {}; + var check_dir_pause = 1000; + var checkInterval = undefined; + + // @api public + // Watches the directory passed and its contained files + // accepts args as an object. + + // @param root(string): the root directory to watch + // @param fileFilter(array): ignore these files + // @param directoryFilter(array): ignore these files + // @param listener(fn(file)): on file change event this will be called + // @param complete(fn): on complete of file watching setup + function watchDirectory(args) { + readdirp({ root: args.root, fileFilter: args.fileFilter, directoryFilter: args.directoryFilter }, function(err, res) { + res.files.forEach(function(file) { + watchFile(file, args.listener, args.partial); + }); + typeof args.complete == "function" && args.complete(); + }); + + !args.partial && (checkInterval = setInterval(function() {checkDirectory(args)}, check_dir_pause)); + } + + // @api public + // Watches the files passed + // accepts args as an object. + // @param files(array): a list of files to watch + // @param listener(fn(file)): on file change event this will be called + // @param complete(fn): on complete of file watching setup + function watchFiles(args) { + args.files.forEach(function(file) { + var o = { + fullPath: fs.realpathSync(file), + name: fs.realpathSync(file).split('/').pop() + }; + o.fullParentDir = o.fullPath.split('/').slice(0, o.fullPath.split('/').length - 1).join('/') + + watchFile(o, args.listener); + }); + + typeof args.complete == "function" && args.complete(); + } + + function unwatchAll() { + if (is_windows) { + Object.keys(watched_files).forEach(function(key) { + watched_files[key].close(); + }); + } else { + Object.keys(watched_files).forEach(function(key) { + fs.unwatchFile(key); + }); + } + + clearInterval(checkInterval); + watched_files = {}; + watched_directories = {}; + } + + // Checks to see if something in the directory has changed + function checkDirectory(args) { + Object.keys(watched_directories).forEach(function(path) { + var lastModified = watched_directories[path]; + fs.stat(path, function(err, stats) { + var stats_stamp = lastModified; + if (!err) { + stats_stamp = (new Date(stats.mtime)).getTime(); + } + if (stats_stamp != lastModified) { + watched_directories[path] = stats_stamp; + watchDirectory({ + root: path, + listener: args.listener, + fileFilter: args.fileFilter, + directoryFilter: args.directoryFilter, + partial: true + }); + } + }); + }); + } + + // sets the absolute path to the file from the current working dir + function setAbsolutePath(file) { + file.absolutePath = path.resolve(process.cwd(), file.fullPath); + return file.absolutePath; + } + + // Watches the file passed and its containing directory + // on change calls given listener with file object + function watchFile(file, cb, partial) { + setAbsolutePath(file); + storeDirectory(file); + if (!watched_files[file.fullPath]) { + if (is_windows) { + (function() { + watched_files[file.fullPath] = fs.watch(file.fullPath, function() { + typeof cb === "function" && cb(file); + }); + partial && cb(file); + })(file, cb); + } else { + (function(file, cb) { + watched_files[file.fullPath] = true; + fs.watchFile(file.fullPath, {interval: 150}, function() { + typeof cb === "function" && cb(file); + }); + partial && cb(file); + })(file, cb); + } + } + } + + // Sets up a store of the folders being watched + // and saves the last modification timestamp for it + function storeDirectory(file) { + var directory = file.fullParentDir; + if (!watched_directories[directory]) { + fs.stat(directory, function(err, stats) { + if (err) { + watched_directories[directory] = (new Date).getTime(); + } else { + watched_directories[directory] = (new Date(stats.mtime)).getTime(); + } + }); + } + } + + return { + watchDirectory: watchDirectory, + watchFiles: watchFiles, + unwatchAll: unwatchAll + }; +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/.npmignore new file mode 100644 index 0000000..7dccd97 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/.npmignore @@ -0,0 +1,15 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +node_modules +npm-debug.log \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/LICENSE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +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/jade/node_modules/monocle/node_modules/readdirp/README.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/README.md new file mode 100644 index 0000000..7b36a8a --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/README.md @@ -0,0 +1,227 @@ +# readdirp [![Build Status](https://secure.travis-ci.org/thlorenz/readdirp.png)](http://travis-ci.org/thlorenz/readdirp) + +Recursive version of [fs.readdir](http://nodejs.org/docs/latest/api/fs.html#fs_fs_readdir_path_callback). Exposes a **stream api**. + +```javascript +var readdirp = require('readdirp'); + , path = require('path') + , es = require('event-stream'); + +// print out all JavaScript files along with their size + +var stream = readdirp({ root: path.join(__dirname), fileFilter: '*.js' }); +stream + .on('warn', function (err) { + console.error('non-fatal error', err); + // optionally call stream.destroy() here in order to abort and cause 'close' to be emitted + }) + .on('error', function (err) { console.error('fatal error', err); }) + .pipe(es.mapSync(function (entry) { + return { path: entry.path, size: entry.stat.size }; + })) + .pipe(es.stringify()) + .pipe(process.stdout); +``` + +Meant to be one of the recursive versions of [fs](http://nodejs.org/docs/latest/api/fs.html) functions, e.g., like [mkdirp](https://github.com/substack/node-mkdirp). + +**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* + +- [Installation](#installation) +- [API](#api) + - [entry stream](#entry-stream) + - [options](#options) + - [entry info](#entry-info) + - [Filters](#filters) + - [Callback API](#callback-api) + - [allProcessed ](#allprocessed) + - [fileProcessed](#fileprocessed) +- [More Examples](#more-examples) + - [stream api](#stream-api) + - [stream api pipe](#stream-api-pipe) + - [grep](#grep) + - [using callback api](#using-callback-api) + - [tests](#tests) + + +# Installation + + npm install readdirp + +# API + +***var entryStream = readdirp (options)*** + +Reads given root recursively and returns a `stream` of [entry info](#entry-info)s. + +## entry stream + +Behaves as follows: + +- `emit('data')` passes an [entry info](#entry-info) whenever one is found +- `emit('warn')` passes a non-fatal `Error` that prevents a file/directory from being processed (i.e., if it is + inaccessible to the user) +- `emit('error')` passes a fatal `Error` which also ends the stream (i.e., when illegal options where passed) +- `emit('end')` called when all entries were found and no more will be emitted (i.e., we are done) +- `emit('close')` called when the stream is destroyed via `stream.destroy()` (which could be useful if you want to + manually abort even on a non fatal error) - at that point the stream is no longer `readable` and no more entries, + warning or errors are emitted +- the stream is `paused` initially in order to allow `pipe` and `on` handlers be connected before data or errors are + emitted +- the stream is `resumed` automatically during the next event loop +- to learn more about streams, consult the [stream-handbook](https://github.com/substack/stream-handbook) + +## options + +- **root**: path in which to start reading and recursing into subdirectories + +- **fileFilter**: filter to include/exclude files found (see [Filters](#filters) for more) + +- **directoryFilter**: filter to include/exclude directories found and to recurse into (see [Filters](#filters) for more) + +- **depth**: depth at which to stop recursing even if more subdirectories are found + +## entry info + +Has the following properties: + +- **parentDir** : directory in which entry was found (relative to given root) +- **fullParentDir** : full path to parent directory +- **name** : name of the file/directory +- **path** : path to the file/directory (relative to given root) +- **fullPath** : full path to the file/directory found +- **stat** : built in [stat object](http://nodejs.org/docs/v0.4.9/api/fs.html#fs.Stats) +- **Example**: (assuming root was `/User/dev/readdirp`) + + parentDir : 'test/bed/root_dir1', + fullParentDir : '/User/dev/readdirp/test/bed/root_dir1', + name : 'root_dir1_subdir1', + path : 'test/bed/root_dir1/root_dir1_subdir1', + fullPath : '/User/dev/readdirp/test/bed/root_dir1/root_dir1_subdir1', + stat : [ ... ] + +## Filters + +There are three different ways to specify filters for files and directories respectively. + +- **function**: a function that takes an entry info as a parameter and returns true to include or false to exclude the entry + +- **glob string**: a string (e.g., `*.js`) which is matched using [minimatch](https://github.com/isaacs/minimatch), so go there for more + information. + + Globstars (`**`) are not supported since specifiying a recursive pattern for an already recursive function doesn't make sense. + + Negated globs (as explained in the minimatch documentation) are allowed, e.g., `!*.txt` matches everything but text files. + +- **array of glob strings**: either need to be all inclusive or all exclusive (negated) patterns otherwise an error is thrown. + + `[ '*.json', '*.js' ]` includes all JavaScript and Json files. + + + `[ '!.git', '!node_modules' ]` includes all directories except the '.git' and 'node_modules'. + +Directories that do not pass a filter will not be recursed into. + +## Callback API + +Although the stream api is recommended, readdirp also exposes a callback based api. + +***readdirp (options, callback1 [, callback2])*** + +If callback2 is given, callback1 functions as the **fileProcessed** callback, and callback2 as the **allProcessed** callback. + +If only callback1 is given, it functions as the **allProcessed** callback. + +### allProcessed + +- function with err and res parameters, e.g., `function (err, res) { ... }` +- **err**: array of errors that occurred during the operation, **res may still be present, even if errors occurred** +- **res**: collection of file/directory [entry infos](#entry-info) + +### fileProcessed + +- function with [entry info](#entry-info) parameter e.g., `function (entryInfo) { ... }` + + +# More Examples + +`on('error', ..)`, `on('warn', ..)` and `on('end', ..)` handling omitted for brevity + +```javascript +var readdirp = require('readdirp'); + +// Glob file filter +readdirp({ root: './test/bed', fileFilter: '*.js' }) + .on('data', function (entry) { + // do something with each JavaScript file entry + }); + +// Combined glob file filters +readdirp({ root: './test/bed', fileFilter: [ '*.js', '*.json' ] }) + .on('data', function (entry) { + // do something with each JavaScript and Json file entry + }); + +// Combined negated directory filters +readdirp({ root: './test/bed', directoryFilter: [ '!.git', '!*modules' ] }) + .on('data', function (entry) { + // do something with each file entry found outside '.git' or any modules directory + }); + +// Function directory filter +readdirp({ root: './test/bed', directoryFilter: function (di) { return di.name.length === 9; } }) + .on('data', function (entry) { + // do something with each file entry found inside directories whose name has length 9 + }); + +// Limiting depth +readdirp({ root: './test/bed', depth: 1 }) + .on('data', function (entry) { + // do something with each file entry found up to 1 subdirectory deep + }); + +// callback api +readdirp( + { root: '.' } + , function(fileInfo) { + // do something with file entry here + } + , function (err, res) { + // all done, move on or do final step for all file entries here + } +); +``` + +Try more examples by following [instructions](https://github.com/thlorenz/readdirp/blob/master/examples/Readme.md) +on how to get going. + +## stream api + +[stream-api.js](https://github.com/thlorenz/readdirp/blob/master/examples/stream-api.js) + +Demonstrates error and data handling by listening to events emitted from the readdirp stream. + +## stream api pipe + +[stream-api-pipe.js](https://github.com/thlorenz/readdirp/blob/master/examples/stream-api-pipe.js) + +Demonstrates error handling by listening to events emitted from the readdirp stream and how to pipe the data stream into +another destination stream. + +## grep + +[grep.js](https://github.com/thlorenz/readdirp/blob/master/examples/grep.js) + +Very naive implementation of grep, for demonstration purposes only. + +## using callback api + +[callback-api.js](https://github.com/thlorenz/readdirp/blob/master/examples/callback-api.js) + +Shows how to pass callbacks in order to handle errors and/or data. + +## tests + +The [readdirp tests](https://github.com/thlorenz/readdirp/blob/master/test/readdirp.js) also will give you a good idea on +how things work. + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/Readme.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/Readme.md new file mode 100644 index 0000000..55fc461 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/Readme.md @@ -0,0 +1,37 @@ +# readdirp examples + +## How to run the examples + +Assuming you installed readdirp (`npm install readdirp`), you can do the following: + +1. `npm explore readdirp` +2. `cd examples` +3. `npm install` + +At that point you can run the examples with node, i.e., `node grep`. + +## stream api + +[stream-api.js](https://github.com/thlorenz/readdirp/blob/master/examples/stream-api.js) + +Demonstrates error and data handling by listening to events emitted from the readdirp stream. + +## stream api pipe + +[stream-api-pipe.js](https://github.com/thlorenz/readdirp/blob/master/examples/stream-api-pipe.js) + +Demonstrates error handling by listening to events emitted from the readdirp stream and how to pipe the data stream into +another destination stream. + +## grep + +[grep.js](https://github.com/thlorenz/readdirp/blob/master/examples/grep.js) + +Very naive implementation of grep, for demonstration purposes only. + +## using callback api + +[callback-api.js](https://github.com/thlorenz/readdirp/blob/master/examples/callback-api.js) + +Shows how to pass callbacks in order to handle errors and/or data. + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/callback-api.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/callback-api.js new file mode 100644 index 0000000..39bd2d7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/callback-api.js @@ -0,0 +1,10 @@ +var readdirp = require('..'); + +readdirp({ root: '.', fileFilter: '*.js' }, function (errors, res) { + if (errors) { + errors.forEach(function (err) { + console.error('Error: ', err); + }); + } + console.log('all javascript files', res); +}); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/grep.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/grep.js new file mode 100644 index 0000000..807fa35 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/grep.js @@ -0,0 +1,73 @@ +'use strict'; +var readdirp = require('..') + , util = require('util') + , fs = require('fs') + , path = require('path') + , Stream = require('stream') + , tap = require('tap-stream') + , es = require('event-stream') + ; + +function findLinesMatching (searchTerm) { + + return es.through(function (entry) { + var lineno = 0 + , matchingLines = [] + , fileStream = this; + + function filter () { + return es.mapSync(function (line) { + lineno++; + return ~line.indexOf(searchTerm) ? lineno + ': ' + line : undefined; + }); + } + + function aggregate () { + return es.through( + function write (data) { + matchingLines.push(data); + } + , function end () { + + // drop files that had no matches + if (matchingLines.length) { + var result = { file: entry, lines: matchingLines }; + + // pass result on to file stream + fileStream.emit('data', result); + } + this.emit('end'); + } + ); + } + + fs.createReadStream(entry.fullPath, { encoding: 'utf-8' }) + + // handle file contents line by line + .pipe(es.split('\n')) + + // keep only the lines that matched the term + .pipe(filter()) + + // aggregate all matching lines and delegate control back to the file stream + .pipe(aggregate()) + ; + }); +} + +console.log('grepping for "arguments"'); + +// create a stream of all javascript files found in this and all sub directories +readdirp({ root: path.join(__dirname), fileFilter: '*.js' }) + + // find all lines matching the term for each file (if none found, that file is ignored) + .pipe(findLinesMatching('arguments')) + + // format the results and output + .pipe( + es.mapSync(function (res) { + return '\n\n' + res.file.path + '\n\t' + res.lines.join('\n\t'); + }) + ) + .pipe(process.stdout) + ; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.npmignore new file mode 100644 index 0000000..13abef4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.npmignore @@ -0,0 +1,3 @@ +node_modules +node_modules/* +npm_debug.log diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/LICENCE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/LICENCE new file mode 100644 index 0000000..171dd97 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/LICENCE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Dominic Tarr + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/examples/pretty.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/examples/pretty.js new file mode 100644 index 0000000..af04340 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/examples/pretty.js @@ -0,0 +1,25 @@ + +var inspect = require('util').inspect + +if(!module.parent) { + var es = require('..') //load event-stream + es.pipe( //pipe joins streams together + process.openStdin(), //open stdin + es.split(), //split stream to break on newlines + es.map(function (data, callback) {//turn this async function into a stream + var j + try { + j = JSON.parse(data) //try to parse input into json + } catch (err) { + return callback(null, data) //if it fails just pass it anyway + } + callback(null, inspect(j)) //render it nicely + }), + process.stdout // pipe it to stdout ! + ) + } + +// run this +// +// curl -sS registry.npmjs.org/event-stream | node pretty.js +// diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/index.js new file mode 100644 index 0000000..16846a2 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/index.js @@ -0,0 +1,341 @@ +//filter will reemit the data if cb(err,pass) pass is truthy + +// reduce is more tricky +// maybe we want to group the reductions or emit progress updates occasionally +// the most basic reduce just emits one 'data' event after it has recieved 'end' + +var Stream = require('stream').Stream + , es = exports + , through = require('through') + , from = require('from') + , duplex = require('duplexer') + , map = require('map-stream') + , pause = require('pause-stream') + , split = require('split') + +es.Stream = Stream //re-export Stream from core +es.through = through +es.from = from +es.duplex = duplex +es.map = map +es.pause = pause +es.split = split + +// merge / concat +// +// combine multiple streams into a single stream. +// will emit end only once + +es.concat = //actually this should be called concat +es.merge = function (/*streams...*/) { + var toMerge = [].slice.call(arguments) + var stream = new Stream() + var endCount = 0 + stream.writable = stream.readable = true + + toMerge.forEach(function (e) { + e.pipe(stream, {end: false}) + var ended = false + e.on('end', function () { + if(ended) return + ended = true + endCount ++ + if(endCount == toMerge.length) + stream.emit('end') + }) + }) + stream.write = function (data) { + this.emit('data', data) + } + stream.destroy = function () { + merge.forEach(function (e) { + if(e.destroy) e.destroy() + }) + } + return stream +} + + +// writable stream, collects all events into an array +// and calls back when 'end' occurs +// mainly I'm using this to test the other functions + +es.writeArray = function (done) { + if ('function' !== typeof done) + throw new Error('function writeArray (done): done must be function') + + var a = new Stream () + , array = [], isDone = false + a.write = function (l) { + array.push(l) + } + a.end = function () { + isDone = true + done(null, array) + } + a.writable = true + a.readable = false + a.destroy = function () { + a.writable = a.readable = false + if(isDone) return + done(new Error('destroyed before end'), array) + } + return a +} + +//return a Stream that reads the properties of an object +//respecting pause() and resume() + +es.readArray = function (array) { + var stream = new Stream() + , i = 0 + , paused = false + , ended = false + + stream.readable = true + stream.writable = false + + if(!Array.isArray(array)) + throw new Error('event-stream.read expects an array') + + stream.resume = function () { + if(ended) return + paused = false + var l = array.length + while(i < l && !paused && !ended) { + stream.emit('data', array[i++]) + } + if(i == l && !ended) + ended = true, stream.readable = false, stream.emit('end') + } + process.nextTick(stream.resume) + stream.pause = function () { + paused = true + } + stream.destroy = function () { + ended = true + stream.emit('close') + } + return stream +} + +// +// readable (asyncFunction) +// return a stream that calls an async function while the stream is not paused. +// +// the function must take: (count, callback) {... +// + +es.readable = function (func, continueOnError) { + var stream = new Stream() + , i = 0 + , paused = false + , ended = false + , reading = false + + stream.readable = true + stream.writable = false + + if('function' !== typeof func) + throw new Error('event-stream.readable expects async function') + + stream.on('end', function () { ended = true }) + + function get (err, data) { + + if(err) { + stream.emit('error', err) + if(!continueOnError) stream.emit('end') + } else if (arguments.length > 1) + stream.emit('data', data) + + process.nextTick(function () { + if(ended || paused || reading) return + try { + reading = true + func.call(stream, i++, function () { + reading = false + get.apply(null, arguments) + }) + } catch (err) { + stream.emit('error', err) + } + }) + } + stream.resume = function () { + paused = false + get() + } + process.nextTick(get) + stream.pause = function () { + paused = true + } + stream.destroy = function () { + stream.emit('end') + stream.emit('close') + ended = true + } + return stream +} + + + +// +// map sync +// + +es.mapSync = function (sync) { + return es.through(function write(data) { + var mappedData = sync(data) + if (typeof mappedData !== 'undefined') + this.emit('data', mappedData) + }) +} + +// +// log just print out what is coming through the stream, for debugging +// + +es.log = function (name) { + return es.through(function (data) { + var args = [].slice.call(arguments) + if(name) console.error(name, data) + else console.error(data) + this.emit('data', data) + }) +} + +// +// combine multiple streams together so that they act as a single stream +// +es.pipeline = +es.pipe = es.connect = function () { + + var streams = [].slice.call(arguments) + , first = streams[0] + , last = streams[streams.length - 1] + , thepipe = es.duplex(first, last) + + if(streams.length == 1) + return streams[0] + else if (!streams.length) + throw new Error('connect called with empty args') + + //pipe all the streams together + + function recurse (streams) { + if(streams.length < 2) + return + streams[0].pipe(streams[1]) + recurse(streams.slice(1)) + } + + recurse(streams) + + function onerror () { + var args = [].slice.call(arguments) + args.unshift('error') + thepipe.emit.apply(thepipe, args) + } + + //es.duplex already reemits the error from the first and last stream. + //add a listener for the inner streams in the pipeline. + for(var i = 1; i < streams.length - 1; i ++) + streams[i].on('error', onerror) + + return thepipe +} + +// +// child -- pipe through a child process +// + +es.child = function (child) { + + return es.duplex(child.stdin, child.stdout) + +} + +// +// parse +// +// must be used after es.split() to ensure that each chunk represents a line +// source.pipe(es.split()).pipe(es.parse()) + +es.parse = function () { + return es.through(function (data) { + var obj + try { + if(data) //ignore empty lines + obj = JSON.parse(data.toString()) + } catch (err) { + return console.error(err, 'attemping to parse:', data) + } + //ignore lines that where only whitespace. + if(obj !== undefined) + this.emit('data', obj) + }) +} +// +// stringify +// + +es.stringify = function () { + var Buffer = require('buffer').Buffer + return es.mapSync(function (e){ + return JSON.stringify(Buffer.isBuffer(e) ? e.toString() : e) + '\n' + }) +} + +// +// replace a string within a stream. +// +// warn: just concatenates the string and then does str.split().join(). +// probably not optimal. +// for smallish responses, who cares? +// I need this for shadow-npm so it's only relatively small json files. + +es.replace = function (from, to) { + return es.pipeline(es.split(from), es.join(to)) +} + +// +// join chunks with a joiner. just like Array#join +// also accepts a callback that is passed the chunks appended together +// this is still supported for legacy reasons. +// + +es.join = function (str) { + + //legacy api + if('function' === typeof str) + return es.wait(str) + + var first = true + return es.through(function (data) { + if(!first) + this.emit('data', str) + first = false + this.emit('data', data) + return true + }) +} + + +// +// wait. callback when 'end' is emitted, with all chunks appended as string. +// + +es.wait = function (callback) { + var body = '' + return es.through(function (data) { body += data }, + function () { + this.emit('data', body) + this.emit('end') + if(callback) callback(null, body) + }) +} + +es.pipeable = function () { + throw new Error('[EVENT-STREAM] es.pipeable is deprecated') +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.npmignore new file mode 100644 index 0000000..062c11e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.npmignore @@ -0,0 +1,3 @@ +node_modules +*.log +*.err \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.travis.yml new file mode 100644 index 0000000..c2ba3f9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/LICENCE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/LICENCE new file mode 100644 index 0000000..a23e08a --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/LICENCE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Raynos. + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/Makefile b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/Makefile new file mode 100644 index 0000000..1f8985d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/Makefile @@ -0,0 +1,4 @@ +test: + node test.js + +.PHONY: test \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/README.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/README.md new file mode 100644 index 0000000..a24cecb --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/README.md @@ -0,0 +1,36 @@ +# duplexer [![build status][1]][2] + +Creates a duplex stream + +Taken from [event-stream][3] + +## duplex (writeStream, readStream) + +Takes a writable stream and a readable stream and makes them appear as a readable writable stream. + +It is assumed that the two streams are connected to each other in some way. + +## Example + + var grep = cp.exec('grep Stream') + + duplex(grep.stdin, grep.stdout) + +## Installation + +`npm install duplexer` + +## Tests + +`make test` + +## Contributors + + - Dominictarr + - Raynos + +## MIT Licenced + + [1]: https://secure.travis-ci.org/Raynos/duplexer.png + [2]: http://travis-ci.org/Raynos/duplexer + [3]: https://github.com/dominictarr/event-stream#duplex-writestream-readstream \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/index.js new file mode 100644 index 0000000..fee581d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/index.js @@ -0,0 +1,87 @@ +var Stream = require("stream") + , writeMethods = ["write", "end", "destroy"] + , readMethods = ["resume", "pause"] + , readEvents = ["data", "close"] + , slice = Array.prototype.slice + +module.exports = duplex + +function duplex(writer, reader) { + var stream = new Stream() + , ended = false + + Object.defineProperties(stream, { + writable: { + get: getWritable + } + , readable: { + get: getReadable + } + }) + + writeMethods.forEach(proxyWriter) + + readMethods.forEach(proxyReader) + + readEvents.forEach(proxyStream) + + reader.on("end", handleEnd) + + writer.on("error", reemit) + reader.on("error", reemit) + + return stream + + function getWritable() { + return writer.writable + } + + function getReadable() { + return reader.readable + } + + function proxyWriter(methodName) { + stream[methodName] = method + + function method() { + return writer[methodName].apply(writer, arguments) + } + } + + function proxyReader(methodName) { + stream[methodName] = method + + function method() { + stream.emit(methodName) + var func = reader[methodName] + if (func) { + return func.apply(reader, arguments) + } + reader.emit(methodName) + } + } + + function proxyStream(methodName) { + reader.on(methodName, reemit) + + function reemit() { + var args = slice.call(arguments) + args.unshift(methodName) + stream.emit.apply(stream, args) + } + } + + function handleEnd() { + if (ended) { + return + } + ended = true + var args = slice.call(arguments) + args.unshift("end") + stream.emit.apply(stream, args) + } + + function reemit(err) { + stream.emit("error", err) + } +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/package.json new file mode 100644 index 0000000..6f54329 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/package.json @@ -0,0 +1,41 @@ +{ + "name": "duplexer", + "version": "0.0.2", + "description": "Creates a duplex stream", + "keywords": [], + "author": { + "name": "Raynos", + "email": "raynos2@gmail.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/Raynos/duplexer.git" + }, + "main": "index", + "homepage": "https://github.com/Raynos/duplexer", + "contributors": [ + { + "name": "Jake Verbaten" + } + ], + "bugs": { + "url": "https://github.com/Raynos/duplexer/issues", + "email": "raynos2@gmail.com" + }, + "dependencies": {}, + "devDependencies": { + "through": "~0.1.4" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/Raynos/duplexer/raw/master/LICENSE" + } + ], + "scripts": { + "test": "make test" + }, + "readme": "# duplexer [![build status][1]][2]\n\nCreates a duplex stream\n\nTaken from [event-stream][3]\n\n## duplex (writeStream, readStream)\n\nTakes a writable stream and a readable stream and makes them appear as a readable writable stream.\n\nIt is assumed that the two streams are connected to each other in some way.\n\n## Example\n\n var grep = cp.exec('grep Stream')\n\n duplex(grep.stdin, grep.stdout)\n\n## Installation\n\n`npm install duplexer`\n\n## Tests\n\n`make test`\n\n## Contributors\n\n - Dominictarr\n - Raynos\n\n## MIT Licenced\n\n [1]: https://secure.travis-ci.org/Raynos/duplexer.png\n [2]: http://travis-ci.org/Raynos/duplexer\n [3]: https://github.com/dominictarr/event-stream#duplex-writestream-readstream", + "_id": "duplexer@0.0.2", + "_from": "duplexer@~0.0.2" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/test.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/test.js new file mode 100644 index 0000000..e06a864 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/duplexer/test.js @@ -0,0 +1,27 @@ +var duplex = require("./index") + , assert = require("assert") + , through = require("through") + +var readable = through() + , writable = through(write) + , written = 0 + , data = 0 + +var stream = duplex(writable, readable) + +function write() { + written++ +} + +stream.on("data", ondata) + +function ondata() { + data++ +} + +stream.write() +readable.emit("data") + +assert.equal(written, 1) +assert.equal(data, 1) +console.log("DONE") \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.APACHE2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.APACHE2 new file mode 100644 index 0000000..6366c04 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.APACHE2 @@ -0,0 +1,15 @@ +Apache License, Version 2.0 + +Copyright (c) 2011 Dominic Tarr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.MIT b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.MIT new file mode 100644 index 0000000..6eafbd7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/LICENSE.MIT @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2011 Dominic Tarr + +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/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/index.js new file mode 100644 index 0000000..95a8975 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/index.js @@ -0,0 +1,62 @@ + +var Stream = require('stream') + +// from +// +// a stream that reads from an source. +// source may be an array, or a function. +// from handles pause behaviour for you. + +module.exports = +function from (source) { + if(Array.isArray(source)) + return from (function (i) { + if(source.length) + this.emit('data', source.shift()) + else + this.emit('end') + return true + }) + + var s = new Stream(), i = 0, ended = false, started = false + s.readable = true + s.writable = false + s.paused = false + s.pause = function () { + started = true + s.paused = true + } + function next () { + var n = 0, r = false + if(ended) return + while(!ended && !s.paused && source.call(s, i++, function () { + if(!n++ && !s.ended && !s.paused) + next() + })) + ; + } + s.resume = function () { + started = true + s.paused = false + next() + } + s.on('end', function () { + ended = true + s.readable = false + process.nextTick(s.destroy) + }) + s.destroy = function () { + ended = true + s.emit('close') + } + /* + by default, the stream will start emitting at nextTick + if you want, you can pause it, after pipeing. + you can also resume before next tick, and that will also + work. + */ + process.nextTick(function () { + if(!started) s.resume() + }) + return s +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/package.json new file mode 100644 index 0000000..be3c0df --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/package.json @@ -0,0 +1,33 @@ +{ + "name": "from", + "version": "0.0.2", + "description": "Easy way to make a Readable Stream", + "main": "index.js", + "scripts": { + "test": "asynct test/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/from.git" + }, + "keywords": [ + "stream", + "streams", + "readable", + "easy" + ], + "devDependencies": { + "asynct": "1", + "stream-spec": "0", + "assertions": "~2.3.0" + }, + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "dominictarr.com" + }, + "license": "MIT", + "readme": "# from\n\nAn easy way to create a `readable Stream`.\n\n## License\nMIT / Apache2\n", + "_id": "from@0.0.2", + "_from": "from@~0" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/readme.markdown new file mode 100644 index 0000000..84c8269 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/readme.markdown @@ -0,0 +1,6 @@ +# from + +An easy way to create a `readable Stream`. + +## License +MIT / Apache2 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/test/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/test/index.js new file mode 100644 index 0000000..fafea57 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/from/test/index.js @@ -0,0 +1,141 @@ +var from = require('..') +var spec = require('stream-spec') +var a = require('assertions') + +function read(stream, callback) { + var actual = [] + stream.on('data', function (data) { + actual.push(data) + }) + stream.once('end', function () { + callback(null, actual) + }) + stream.once('error', function (err) { + callback(err) + }) +} + +function pause(stream) { + stream.on('data', function () { + if(Math.random() > 0.1) return + stream.pause() + process.nextTick(function () { + stream.resume() + }) + }) +} + +exports['inc'] = function (test) { + + var fs = from(function (i) { + this.emit('data', i) + if(i >= 99) + return this.emit('end') + return true + }) + + spec(fs).readable().validateOnExit() + + read(fs, function (err, arr) { + test.equal(arr.length, 100) + test.done() + }) +} + +exports['simple'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = from(expected.slice()) + + spec(t) + .readable() + .pausable({strict: true}) + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + +} + +exports['simple pausable'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = from(expected.slice()) + + spec(t) + .readable() + .pausable({strict: true}) + .validateOnExit() + + pause(t) + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + +} + +exports['simple (not strictly pausable) setTimeout'] = function (test) { + + var l = 10 + , expected = [] + while(l--) expected.push(l * Math.random()) + + + var _expected = expected.slice() + var t = from(function (i, n) { + var self = this + setTimeout(function () { + if(_expected.length) + self.emit('data', _expected.shift()) + else + self.emit('end') + n() + }, 3) + }) + + /* + using from in this way will not be strictly pausable. + it could be extended to buffer outputs, but I think a better + way would be to use a PauseStream that implements strict pause. + */ + + spec(t) + .readable() + .pausable({strict: false }) + .validateOnExit() + + //pause(t) + var paused = false + var i = setInterval(function () { + if(!paused) t.pause() + else t.resume() + paused = !paused + }, 2) + + t.on('end', function () { + clearInterval(i) + }) + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + +} + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.npmignore new file mode 100644 index 0000000..13abef4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.npmignore @@ -0,0 +1,3 @@ +node_modules +node_modules/* +npm_debug.log diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/LICENCE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/LICENCE new file mode 100644 index 0000000..171dd97 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/LICENCE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Dominic Tarr + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/examples/pretty.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/examples/pretty.js new file mode 100644 index 0000000..af04340 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/examples/pretty.js @@ -0,0 +1,25 @@ + +var inspect = require('util').inspect + +if(!module.parent) { + var es = require('..') //load event-stream + es.pipe( //pipe joins streams together + process.openStdin(), //open stdin + es.split(), //split stream to break on newlines + es.map(function (data, callback) {//turn this async function into a stream + var j + try { + j = JSON.parse(data) //try to parse input into json + } catch (err) { + return callback(null, data) //if it fails just pass it anyway + } + callback(null, inspect(j)) //render it nicely + }), + process.stdout // pipe it to stdout ! + ) + } + +// run this +// +// curl -sS registry.npmjs.org/event-stream | node pretty.js +// diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/index.js new file mode 100644 index 0000000..d3a7fd9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/index.js @@ -0,0 +1,105 @@ +//filter will reemit the data if cb(err,pass) pass is truthy + +// reduce is more tricky +// maybe we want to group the reductions or emit progress updates occasionally +// the most basic reduce just emits one 'data' event after it has recieved 'end' + + +var Stream = require('stream').Stream + + +//create an event stream and apply function to each .write +//emitting each response as data +//unless it's an empty callback + +module.exports = function (mapper) { + var stream = new Stream() + , inputs = 0 + , outputs = 0 + , ended = false + , paused = false + , destroyed = false + + stream.writable = true + stream.readable = true + + stream.write = function () { + if(ended) throw new Error('map stream is not writable') + inputs ++ + var args = [].slice.call(arguments) + , r + , inNext = false + //pipe only allows one argument. so, do not + function next (err) { + if(destroyed) return + inNext = true + outputs ++ + var args = [].slice.call(arguments) + if(err) { + args.unshift('error') + return inNext = false, stream.emit.apply(stream, args) + } + args.shift() //drop err + if (args.length) { + args.unshift('data') + r = stream.emit.apply(stream, args) + } + if(inputs == outputs) { + if(paused) paused = false, stream.emit('drain') //written all the incoming events + if(ended) end() + } + inNext = false + } + args.push(next) + + try { + //catch sync errors and handle them like async errors + var written = mapper.apply(null, args) + paused = (written === false) + return !paused + } catch (err) { + //if the callback has been called syncronously, and the error + //has occured in an listener, throw it again. + if(inNext) + throw err + next(err) + return !paused + } + } + + function end (data) { + //if end was called with args, write it, + ended = true //write will emit 'end' if ended is true + stream.writable = false + if(data !== undefined) + return stream.write(data) + else if (inputs == outputs) //wait for processing + stream.readable = false, stream.emit('end'), stream.destroy() + } + + stream.end = function (data) { + if(ended) return + end() + } + + stream.destroy = function () { + ended = destroyed = true + stream.writable = stream.readable = paused = false + process.nextTick(function () { + stream.emit('close') + }) + } + stream.pause = function () { + paused = true + } + + stream.resume = function () { + paused = false + } + + return stream +} + + + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/package.json new file mode 100644 index 0000000..97e7338 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/package.json @@ -0,0 +1,30 @@ +{ + "name": "map-stream", + "version": "0.0.1", + "description": "construct pipes of streams of events", + "homepage": "http://github.com/dominictarr/map-stream", + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/map-stream.git" + }, + "dependencies": {}, + "devDependencies": { + "asynct": "*", + "it-is": "1", + "ubelt": "~2.9", + "stream-spec": "~0.2", + "event-stream": "~2.1", + "from": "0.0.2" + }, + "scripts": { + "test": "asynct test/" + }, + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "http://dominictarr.com" + }, + "readme": "# MapStream\n\nRefactored out of [event-stream](https://github.com/dominictarr/event-stream)\n\n##map (asyncFunction)\n\nCreate a through stream from an asyncronous function. \n\n``` js\nvar es = require('event-stream')\n\nes.map(function (data, callback) {\n //transform data\n // ...\n callback(null, data)\n})\n\n```\n\nEach map MUST call the callback. It may callback with data, with an error or with no arguments, \n\n * `callback()` drop this data. \n this makes the map work like `filter`, \n note:`callback(null,null)` is not the same, and will emit `null`\n\n * `callback(null, newData)` turn data into newData\n \n * `callback(error)` emit an error for this item.\n\n>Note: if a callback is not called, `map` will think that it is still being processed, \n>every call must be answered or the stream will not know when to end. \n>\n>Also, if the callback is called more than once, every call but the first will be ignored.\n\n\n", + "_id": "map-stream@0.0.1", + "_from": "map-stream@0.0.1" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/readme.markdown new file mode 100644 index 0000000..22c019d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/readme.markdown @@ -0,0 +1,35 @@ +# MapStream + +Refactored out of [event-stream](https://github.com/dominictarr/event-stream) + +##map (asyncFunction) + +Create a through stream from an asyncronous function. + +``` js +var es = require('event-stream') + +es.map(function (data, callback) { + //transform data + // ... + callback(null, data) +}) + +``` + +Each map MUST call the callback. It may callback with data, with an error or with no arguments, + + * `callback()` drop this data. + this makes the map work like `filter`, + note:`callback(null,null)` is not the same, and will emit `null` + + * `callback(null, newData)` turn data into newData + + * `callback(error)` emit an error for this item. + +>Note: if a callback is not called, `map` will think that it is still being processed, +>every call must be answered or the stream will not know when to end. +> +>Also, if the callback is called more than once, every call but the first will be ignored. + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/test/simple-map.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/test/simple-map.asynct.js new file mode 100644 index 0000000..77ac48e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/map-stream/test/simple-map.asynct.js @@ -0,0 +1,295 @@ +'use strict'; + +var map = require('../') + , it = require('it-is') + , u = require('ubelt') + , spec = require('stream-spec') + , from = require('from') + , Stream = require('stream') + , es = require('event-stream') + +//REFACTOR THIS TEST TO USE es.readArray and es.writeArray + +function writeArray(array, stream) { + + array.forEach( function (j) { + stream.write(j) + }) + stream.end() + +} + +function readStream(stream, done) { + + var array = [] + stream.on('data', function (data) { + array.push(data) + }) + stream.on('error', done) + stream.on('end', function (data) { + done(null, array) + }) + +} + +//call sink on each write, +//and complete when finished. + +function pauseStream (prob, delay) { + var pauseIf = ( + 'number' == typeof prob + ? function () { + return Math.random() < prob + } + : 'function' == typeof prob + ? prob + : 0.1 + ) + var delayer = ( + !delay + ? process.nextTick + : 'number' == typeof delay + ? function (next) { setTimeout(next, delay) } + : delay + ) + + return es.through(function (data) { + if(!this.paused && pauseIf()) { + console.log('PAUSE STREAM PAUSING') + this.pause() + var self = this + delayer(function () { + console.log('PAUSE STREAM RESUMING') + self.resume() + }) + } + console.log("emit ('data', " + data + ')') + this.emit('data', data) + }) +} + +exports ['simple map'] = function (test) { + + var input = u.map(1, 1000, function () { + return Math.random() + }) + var expected = input.map(function (v) { + return v * 2 + }) + + var pause = pauseStream(0.1) + var fs = from(input) + var ts = es.writeArray(function (err, ar) { + it(ar).deepEqual(expected) + test.done() + }) + var map = es.through(function (data) { + this.emit('data', data * 2) + }) + + spec(map).through().validateOnExit() + spec(pause).through().validateOnExit() + + fs.pipe(map).pipe(pause).pipe(ts) +} + +exports ['simple map applied to a stream'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + //create event stream from + + var doubler = map(function (data, cb) { + cb(null, data * 2) + }) + + spec(doubler).through().validateOnExit() + + //a map is only a middle man, so it is both readable and writable + + it(doubler).has({ + readable: true, + writable: true, + }) + + readStream(doubler, function (err, output) { + it(output).deepEqual(input.map(function (j) { + return j * 2 + })) +// process.nextTick(x.validate) + test.done() + }) + + writeArray(input, doubler) + +} + +exports['pipe two maps together'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + //create event stream from + function dd (data, cb) { + cb(null, data * 2) + } + var doubler1 = es.map(dd), doubler2 = es.map(dd) + + doubler1.pipe(doubler2) + + spec(doubler1).through().validateOnExit() + spec(doubler2).through().validateOnExit() + + readStream(doubler2, function (err, output) { + it(output).deepEqual(input.map(function (j) { + return j * 4 + })) + test.done() + }) + + writeArray(input, doubler1) + +} + +//next: +// +// test pause, resume and drian. +// + +// then make a pipe joiner: +// +// plumber (evStr1, evStr2, evStr3, evStr4, evStr5) +// +// will return a single stream that write goes to the first + +exports ['map will not call end until the callback'] = function (test) { + + var ticker = map(function (data, cb) { + process.nextTick(function () { + cb(null, data * 2) + }) + }) + + spec(ticker).through().validateOnExit() + + ticker.write('x') + ticker.end() + + ticker.on('end', function () { + test.done() + }) +} + + +exports ['emit error thrown'] = function (test) { + + var err = new Error('INTENSIONAL ERROR') + , mapper = + es.map(function () { + throw err + }) + + mapper.on('error', function (_err) { + it(_err).equal(err) + test.done() + }) + + mapper.write('hello') + +} + +exports ['emit error calledback'] = function (test) { + + var err = new Error('INTENSIONAL ERROR') + , mapper = + es.map(function (data, callback) { + callback(err) + }) + + mapper.on('error', function (_err) { + it(_err).equal(err) + test.done() + }) + + mapper.write('hello') + +} + +exports ['do not emit drain if not paused'] = function (test) { + + var maps = map(function (data, callback) { + u.delay(callback)(null, 1) + return true + }) + + spec(maps).through().pausable().validateOnExit() + + maps.on('drain', function () { + it(false).ok('should not emit drain unless the stream is paused') + }) + + it(maps.write('hello')).equal(true) + it(maps.write('hello')).equal(true) + it(maps.write('hello')).equal(true) + setTimeout(function () {maps.end()},10) + maps.on('end', test.done) +} + +exports ['emits drain if paused, when all '] = function (test) { + var active = 0 + var drained = false + var maps = map(function (data, callback) { + active ++ + u.delay(function () { + active -- + callback(null, 1) + })() + console.log('WRITE', false) + return false + }) + + spec(maps).through().validateOnExit() + + maps.on('drain', function () { + drained = true + it(active).equal(0, 'should emit drain when all maps are done') + }) + + it(maps.write('hello')).equal(false) + it(maps.write('hello')).equal(false) + it(maps.write('hello')).equal(false) + + process.nextTick(function () {maps.end()},10) + + maps.on('end', function () { + console.log('end') + it(drained).ok('shoud have emitted drain before end') + test.done() + }) + +} + +exports ['map applied to a stream with filtering'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + + var doubler = map(function (data, callback) { + if (data % 2) + callback(null, data * 2) + else + callback() + }) + + readStream(doubler, function (err, output) { + it(output).deepEqual(input.filter(function (j) { + return j % 2 + }).map(function (j) { + return j * 2 + })) + test.done() + }) + + spec(doubler).through().validateOnExit() + + writeArray(input, doubler) + +} + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/.npmignore new file mode 100644 index 0000000..bfdb82c --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/.npmignore @@ -0,0 +1,4 @@ +lib-cov/* +*.swp +*.swo +node_modules diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/LICENSE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/README.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/README.markdown new file mode 100644 index 0000000..deb493c --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/README.markdown @@ -0,0 +1,474 @@ +optimist +======== + +Optimist is a node.js library for option parsing for people who hate option +parsing. More specifically, this module is for people who like all the --bells +and -whistlz of program usage but think optstrings are a waste of time. + +With optimist, option parsing doesn't have to suck (as much). + +examples +======== + +With Optimist, the options are just a hash! No optstrings attached. +------------------------------------------------------------------- + +xup.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} +```` + +*** + + $ ./xup.js --rif=55 --xup=9.52 + Buy more riffiwobbles + + $ ./xup.js --rif 12 --xup 8.1 + Sell the xupptumblers + +![This one's optimistic.](http://substack.net/images/optimistic.png) + +But wait! There's more! You can do short options: +------------------------------------------------- + +short.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +```` + +*** + + $ ./short.js -x 10 -y 21 + (10,21) + +And booleans, both long and short (and grouped): +---------------------------------- + +bool.js: + +````javascript +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); +```` + +*** + + $ ./bool.js -s + The cat says: meow + + $ ./bool.js -sp + The cat says: meow. + + $ ./bool.js -sp --fr + Le chat dit: miaou. + +And non-hypenated options too! Just use `argv._`! +------------------------------------------------- + +nonopt.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); +```` + +*** + + $ ./nonopt.js -x 6.82 -y 3.35 moo + (6.82,3.35) + [ 'moo' ] + + $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz + (0.54,1.12) + [ 'foo', 'bar', 'baz' ] + +Plus, Optimist comes with .usage() and .demand()! +------------------------------------------------- + +divide.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); +```` + +*** + + $ ./divide.js -x 55 -y 11 + 5 + + $ node ./divide.js -x 4.91 -z 2.51 + Usage: node ./divide.js -x [num] -y [num] + + Options: + -x [required] + -y [required] + + Missing required arguments: y + +EVEN MORE HOLY COW +------------------ + +default_singles.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_singles.js -x 5 + 15 + +default_hash.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_hash.js -y 7 + 17 + +And if you really want to get all descriptive about it... +--------------------------------------------------------- + +boolean_single.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv); +```` + +*** + + $ ./boolean_single.js -v foo bar baz + true + [ 'bar', 'baz', 'foo' ] + +boolean_double.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); +```` + +*** + + $ ./boolean_double.js -x -z one two three + [ true, false, true ] + [ 'one', 'two', 'three' ] + +Optimist is here to help... +--------------------------- + +You can describe parameters for help messages and set aliases. Optimist figures +out how to format a handy help string automatically. + +line_count.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); +```` + +*** + + $ node line_count.js + Count the lines in a file. + Usage: node ./line_count.js + + Options: + -f, --file Load a file [required] + + Missing required arguments: f + + $ node line_count.js --file line_count.js + 20 + + $ node line_count.js -f line_count.js + 20 + +methods +======= + +By itself, + +````javascript +require('optimist').argv +````` + +will use `process.argv` array to construct the `argv` object. + +You can pass in the `process.argv` yourself: + +````javascript +require('optimist')([ '-x', '1', '-y', '2' ]).argv +```` + +or use .parse() to do the same thing: + +````javascript +require('optimist').parse([ '-x', '1', '-y', '2' ]) +```` + +The rest of these methods below come in just before the terminating `.argv`. + +.alias(key, alias) +------------------ + +Set key names as equivalent such that updates to a key will propagate to aliases +and vice-versa. + +Optionally `.alias()` can take an object that maps keys to aliases. + +.default(key, value) +-------------------- + +Set `argv[key]` to `value` if no option was specified on `process.argv`. + +Optionally `.default()` can take an object that maps keys to default values. + +.demand(key) +------------ + +If `key` is a string, show the usage information and exit if `key` wasn't +specified in `process.argv`. + +If `key` is a number, demand at least as many non-option arguments, which show +up in `argv._`. + +If `key` is an Array, demand each element. + +.describe(key, desc) +-------------------- + +Describe a `key` for the generated usage information. + +Optionally `.describe()` can take an object that maps keys to descriptions. + +.options(key, opt) +------------------ + +Instead of chaining together `.alias().demand().default()`, you can specify +keys in `opt` for each of the chainable methods. + +For example: + +````javascript +var argv = require('optimist') + .options('f', { + alias : 'file', + default : '/etc/passwd', + }) + .argv +; +```` + +is the same as + +````javascript +var argv = require('optimist') + .alias('f', 'file') + .default('f', '/etc/passwd') + .argv +; +```` + +Optionally `.options()` can take an object that maps keys to `opt` parameters. + +.usage(message) +--------------- + +Set a usage message to show which commands to use. Inside `message`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. + +.check(fn) +---------- + +Check that certain conditions are met in the provided arguments. + +If `fn` throws or returns `false`, show the thrown error, usage information, and +exit. + +.boolean(key) +------------- + +Interpret `key` as a boolean. If a non-flag option follows `key` in +`process.argv`, that string won't get set as the value of `key`. + +If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be +`false`. + +If `key` is an Array, interpret all the elements as booleans. + +.string(key) +------------ + +Tell the parser logic not to interpret `key` as a number or boolean. +This can be useful if you need to preserve leading zeros in an input. + +If `key` is an Array, interpret all the elements as strings. + +.wrap(columns) +-------------- + +Format usage output to wrap at `columns` many columns. + +.help() +------- + +Return the generated usage string. + +.showHelp(fn=console.error) +--------------------------- + +Print the usage data using `fn` for printing. + +.parse(args) +------------ + +Parse `args` instead of `process.argv`. Returns the `argv` object. + +.argv +----- + +Get the arguments as a plain old object. + +Arguments without a corresponding flag show up in the `argv._` array. + +The script name or node command is available at `argv.$0` similarly to how `$0` +works in bash or perl. + +parsing tricks +============== + +stop parsing +------------ + +Use `--` to stop parsing flags and stuff the remainder into `argv._`. + + $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 + { _: [ '-c', '3', '-d', '4' ], + '$0': 'node ./examples/reflect.js', + a: 1, + b: 2 } + +negate fields +------------- + +If you want to explicity set a field to false instead of just leaving it +undefined or to override a default you can do `--no-key`. + + $ node examples/reflect.js -a --no-b + { _: [], + '$0': 'node ./examples/reflect.js', + a: true, + b: false } + +numbers +------- + +Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to +one. This way you can just `net.createConnection(argv.port)` and you can add +numbers out of `argv` with `+` without having that mean concatenation, +which is super frustrating. + +duplicates +---------- + +If you specify a flag multiple times it will get turned into an array containing +all the values in order. + + $ node examples/reflect.js -x 5 -x 8 -x 0 + { _: [], + '$0': 'node ./examples/reflect.js', + x: [ 5, 8, 0 ] } + +installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + npm install optimist + +or clone this project on github: + + git clone http://github.com/substack/node-optimist.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + +inspired By +=========== + +This module is loosely inspired by Perl's +[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/bool.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/bool.js new file mode 100644 index 0000000..a998fb7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/bool.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_double.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_double.js new file mode 100644 index 0000000..a35a7e6 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_double.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_single.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_single.js new file mode 100644 index 0000000..017bb68 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/boolean_single.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv.v); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_hash.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_hash.js new file mode 100644 index 0000000..ade7768 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_hash.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; + +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_singles.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_singles.js new file mode 100644 index 0000000..d9b1ff4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/default_singles.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/divide.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/divide.js new file mode 100644 index 0000000..5e2ee82 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/divide.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count.js new file mode 100644 index 0000000..b5f95bf --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_options.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_options.js new file mode 100644 index 0000000..d9ac709 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_options.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .options({ + file : { + demand : true, + alias : 'f', + description : 'Load a file' + }, + base : { + alias : 'b', + description : 'Numeric base to use for output', + default : 10, + }, + }) + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_wrap.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_wrap.js new file mode 100644 index 0000000..4267511 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/line_count_wrap.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .wrap(80) + .demand('f') + .alias('f', [ 'file', 'filename' ]) + .describe('f', + "Load a file. It's pretty important." + + " Required even. So you'd better specify it." + ) + .alias('b', 'base') + .describe('b', 'Numeric base to display the number of lines in') + .default('b', 10) + .describe('x', 'Super-secret optional parameter which is secret') + .default('x', '') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/nonopt.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/nonopt.js new file mode 100644 index 0000000..ee633ee --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/nonopt.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/reflect.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/reflect.js new file mode 100644 index 0000000..816b3e1 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/reflect.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.dir(require('optimist').argv); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/short.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/short.js new file mode 100644 index 0000000..1db0ad0 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/short.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/string.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/string.js new file mode 100644 index 0000000..a8e5aeb --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/string.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node +var argv = require('optimist') + .string('x', 'y') + .argv +; +console.dir([ argv.x, argv.y ]); + +/* Turns off numeric coercion: + ./node string.js -x 000123 -y 9876 + [ '000123', '9876' ] +*/ diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/usage-options.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/usage-options.js new file mode 100644 index 0000000..b999977 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/usage-options.js @@ -0,0 +1,19 @@ +var optimist = require('./../index'); + +var argv = optimist.usage('This is my awesome program', { + 'about': { + description: 'Provide some details about the author of this program', + required: true, + short: 'a', + }, + 'info': { + description: 'Provide some information about the node.js agains!!!!!!', + boolean: true, + short: 'i' + } +}).argv; + +optimist.showHelp(); + +console.log('\n\nInspecting options'); +console.dir(argv); \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/xup.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/xup.js new file mode 100644 index 0000000..8f6ecd2 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/examples/xup.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/index.js new file mode 100644 index 0000000..070d642 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/index.js @@ -0,0 +1,457 @@ +var path = require('path'); +var wordwrap = require('wordwrap'); + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('optimist')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('optimist').argv + to get a parsed version of process.argv. +*/ + +var inst = Argv(process.argv.slice(2)); +Object.keys(inst).forEach(function (key) { + Argv[key] = typeof inst[key] == 'function' + ? inst[key].bind(inst) + : inst[key]; +}); + +var exports = module.exports = Argv; +function Argv (args, cwd) { + var self = {}; + if (!cwd) cwd = process.cwd(); + + self.$0 = process.argv + .slice(0,2) + .map(function (x) { + var b = rebase(cwd, x); + return x.match(/^\//) && b.length < x.length + ? b : x + }) + .join(' ') + ; + + if (process.argv[1] == process.env._) { + self.$0 = process.env._.replace( + path.dirname(process.execPath) + '/', '' + ); + } + + var flags = { bools : {}, strings : {} }; + + self.boolean = function (bools) { + if (!Array.isArray(bools)) { + bools = [].slice.call(arguments); + } + + bools.forEach(function (name) { + flags.bools[name] = true; + }); + + return self; + }; + + self.string = function (strings) { + if (!Array.isArray(strings)) { + strings = [].slice.call(arguments); + } + + strings.forEach(function (name) { + flags.strings[name] = true; + }); + + return self; + }; + + var aliases = {}; + self.alias = function (x, y) { + if (typeof x === 'object') { + Object.keys(x).forEach(function (key) { + self.alias(key, x[key]); + }); + } + else if (Array.isArray(y)) { + y.forEach(function (yy) { + self.alias(x, yy); + }); + } + else { + var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y); + aliases[x] = zs.filter(function (z) { return z != x }); + aliases[y] = zs.filter(function (z) { return z != y }); + } + + return self; + }; + + var demanded = {}; + self.demand = function (keys) { + if (typeof keys == 'number') { + if (!demanded._) demanded._ = 0; + demanded._ += keys; + } + else if (Array.isArray(keys)) { + keys.forEach(function (key) { + self.demand(key); + }); + } + else { + demanded[keys] = true; + } + + return self; + }; + + var usage; + self.usage = function (msg, opts) { + if (!opts && typeof msg === 'object') { + opts = msg; + msg = null; + } + + usage = msg; + + if (opts) self.options(opts); + + return self; + }; + + function fail (msg) { + self.showHelp(); + if (msg) console.error(msg); + process.exit(1); + } + + var checks = []; + self.check = function (f) { + checks.push(f); + return self; + }; + + var defaults = {}; + self.default = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]); + }); + } + else { + defaults[key] = value; + } + + return self; + }; + + var descriptions = {}; + self.describe = function (key, desc) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.describe(k, key[k]); + }); + } + else { + descriptions[key] = desc; + } + return self; + }; + + self.parse = function (args) { + return Argv(args).argv; + }; + + self.option = self.options = function (key, opt) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.options(k, key[k]); + }); + } + else { + if (opt.alias) self.alias(key, opt.alias); + if (opt.demand) self.demand(key); + if (opt.default) self.default(key, opt.default); + + if (opt.boolean || opt.type === 'boolean') { + self.boolean(key); + } + if (opt.string || opt.type === 'string') { + self.string(key); + } + + var desc = opt.describe || opt.description || opt.desc; + if (desc) { + self.describe(key, desc); + } + } + + return self; + }; + + var wrap = null; + self.wrap = function (cols) { + wrap = cols; + return self; + }; + + self.showHelp = function (fn) { + if (!fn) fn = console.error; + fn(self.help()); + }; + + self.help = function () { + var keys = Object.keys( + Object.keys(descriptions) + .concat(Object.keys(demanded)) + .concat(Object.keys(defaults)) + .reduce(function (acc, key) { + if (key !== '_') acc[key] = true; + return acc; + }, {}) + ); + + var help = keys.length ? [ 'Options:' ] : []; + + if (usage) { + help.unshift(usage.replace(/\$0/g, self.$0), ''); + } + + var switches = keys.reduce(function (acc, key) { + acc[key] = [ key ].concat(aliases[key] || []) + .map(function (sw) { + return (sw.length > 1 ? '--' : '-') + sw + }) + .join(', ') + ; + return acc; + }, {}); + + var switchlen = longest(Object.keys(switches).map(function (s) { + return switches[s] || ''; + })); + + var desclen = longest(Object.keys(descriptions).map(function (d) { + return descriptions[d] || ''; + })); + + keys.forEach(function (key) { + var kswitch = switches[key]; + var desc = descriptions[key] || ''; + + if (wrap) { + desc = wordwrap(switchlen + 4, wrap)(desc) + .slice(switchlen + 4) + ; + } + + var spadding = new Array( + Math.max(switchlen - kswitch.length + 3, 0) + ).join(' '); + + var dpadding = new Array( + Math.max(desclen - desc.length + 1, 0) + ).join(' '); + + var type = null; + + if (flags.bools[key]) type = '[boolean]'; + if (flags.strings[key]) type = '[string]'; + + if (!wrap && dpadding.length > 0) { + desc += dpadding; + } + + var prelude = ' ' + kswitch + spadding; + var extra = [ + type, + demanded[key] + ? '[required]' + : null + , + defaults[key] !== undefined + ? '[default: ' + JSON.stringify(defaults[key]) + ']' + : null + , + ].filter(Boolean).join(' '); + + var body = [ desc, extra ].filter(Boolean).join(' '); + + if (wrap) { + var dlines = desc.split('\n'); + var dlen = dlines.slice(-1)[0].length + + (dlines.length === 1 ? prelude.length : 0) + + body = desc + (dlen + extra.length > wrap - 2 + ? '\n' + + new Array(wrap - extra.length + 1).join(' ') + + extra + : new Array(wrap - extra.length - dlen + 1).join(' ') + + extra + ); + } + + help.push(prelude + body); + }); + + help.push(''); + return help.join('\n'); + }; + + Object.defineProperty(self, 'argv', { + get : parseArgs, + enumerable : true, + }); + + function parseArgs () { + var argv = { _ : [], $0 : self.$0 }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] || false); + }); + + function setArg (key, val) { + var num = Number(val); + var value = typeof val !== 'string' || isNaN(num) ? val : num; + if (flags.strings[key]) value = val; + + if (key in argv && !flags.bools[key]) { + if (!Array.isArray(argv[key])) { + argv[key] = [ argv[key] ]; + } + argv[key].push(value); + } + else { + argv[key] = value; + } + + (aliases[key] || []).forEach(function (x) { + argv[x] = argv[key]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (arg === '--') { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + else if (arg.match(/^--.+=/)) { + var m = arg.match(/^--([^=]+)=(.*)/); + setArg(m[1], m[2]); + } + else if (arg.match(/^--no-.+/)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false); + } + else if (arg.match(/^--.+/)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !next.match(/^-/) + && !flags.bools[key]) { + setArg(key, next); + i++; + } + else if (flags.bools[key] && /true|false/.test(next)) { + setArg(key, next === 'true'); + i++; + } + else { + setArg(key, true); + } + } + else if (arg.match(/^-[^-]+/)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2)); + broken = true; + break; + } + else { + setArg(letters[j], true); + } + } + + if (!broken) { + var key = arg.slice(-1)[0]; + + if (args[i+1] && !args[i+1].match(/^-/) + && !flags.bools[key]) { + setArg(key, args[i+1]); + i++; + } + else if (args[i+1] && flags.bools[key] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true'); + i++; + } + else { + setArg(key, true); + } + } + } + else { + var n = Number(arg); + argv._.push(flags.strings['_'] || isNaN(n) ? arg : n); + } + } + + Object.keys(defaults).forEach(function (key) { + if (!(key in argv)) { + argv[key] = defaults[key]; + } + }); + + if (demanded._ && argv._.length < demanded._) { + fail('Not enough non-option arguments: got ' + + argv._.length + ', need at least ' + demanded._ + ); + } + + var missing = []; + Object.keys(demanded).forEach(function (key) { + if (!argv[key]) missing.push(key); + }); + + if (missing.length) { + fail('Missing required arguments: ' + missing.join(', ')); + } + + checks.forEach(function (f) { + try { + if (f(argv) === false) { + fail('Argument check failed: ' + f.toString()); + } + } + catch (err) { + fail(err) + } + }); + + return argv; + } + + function longest (xs) { + return Math.max.apply( + null, + xs.map(function (x) { return x.length }) + ); + } + + return self; +}; + +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +exports.rebase = rebase; +function rebase (base, dir) { + var ds = path.normalize(dir).split('/').slice(1); + var bs = path.normalize(base).split('/').slice(1); + + for (var i = 0; ds[i] && ds[i] == bs[i]; i++); + ds.splice(0, i); bs.splice(0, i); + + var p = path.normalize( + bs.map(function () { return '..' }).concat(ds).join('/') + ).replace(/\/$/,'').replace(/^$/, '.'); + return p.match(/^[.\/]/) ? p : './' + p; +}; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/README.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/center.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/meat.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/package.json new file mode 100644 index 0000000..928d935 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/package.json @@ -0,0 +1,40 @@ +{ + "name": "wordwrap", + "description": "Wrap those words. Show them at what columns to start and stop.", + "version": "0.0.2", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-wordwrap.git" + }, + "main": "./index.js", + "keywords": [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "expresso" + }, + "devDependencies": { + "expresso": "=0.7.x" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT/X11", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "readme": "wordwrap\n========\n\nWrap your words.\n\nexample\n=======\n\nmade out of meat\n----------------\n\nmeat.js\n\n var wrap = require('wordwrap')(15);\n console.log(wrap('You and your whole family are made out of meat.'));\n\noutput:\n\n You and your\n whole family\n are made out\n of meat.\n\ncentered\n--------\n\ncenter.js\n\n var wrap = require('wordwrap')(20, 60);\n console.log(wrap(\n 'At long last the struggle and tumult was over.'\n + ' The machines had finally cast off their oppressors'\n + ' and were finally free to roam the cosmos.'\n + '\\n'\n + 'Free of purpose, free of obligation.'\n + ' Just drifting through emptiness.'\n + ' The sun was just another point of light.'\n ));\n\noutput:\n\n At long last the struggle and tumult\n was over. The machines had finally cast\n off their oppressors and were finally\n free to roam the cosmos.\n Free of purpose, free of obligation.\n Just drifting through emptiness. The\n sun was just another point of light.\n\nmethods\n=======\n\nvar wrap = require('wordwrap');\n\nwrap(stop), wrap(start, stop, params={mode:\"soft\"})\n---------------------------------------------------\n\nReturns a function that takes a string and returns a new string.\n\nPad out lines with spaces out to column `start` and then wrap until column\n`stop`. If a word is longer than `stop - start` characters it will overflow.\n\nIn \"soft\" mode, split chunks by `/(\\S+\\s+/` and don't break up chunks which are\nlonger than `stop - start`, in \"hard\" mode, split chunks with `/\\b/` and break\nup chunks longer than `stop - start`.\n\nwrap.hard(start, stop)\n----------------------\n\nLike `wrap()` but with `params.mode = \"hard\"`.\n", + "_id": "wordwrap@0.0.2", + "_from": "wordwrap@>=0.0.1 <0.1.0" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/break.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/package.json new file mode 100644 index 0000000..bbe848c --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/package.json @@ -0,0 +1,46 @@ +{ + "name": "optimist", + "version": "0.2.8", + "description": "Light-weight option parsing with an argv hash. No optstrings attached.", + "main": "./index.js", + "directories": { + "lib": ".", + "test": "test", + "example": "examples" + }, + "dependencies": { + "wordwrap": ">=0.0.1 <0.1.0" + }, + "devDependencies": { + "hashish": "0.0.x", + "expresso": "0.7.x" + }, + "scripts": { + "test": "expresso" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-optimist.git" + }, + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "node": ">=0.4" + }, + "readme": "optimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", + "_id": "optimist@0.2.8", + "_from": "optimist@0.2" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_.js new file mode 100644 index 0000000..3d6df6e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_.js @@ -0,0 +1,66 @@ +var spawn = require('child_process').spawn; +var assert = require('assert'); + +exports.dotSlashEmpty = function () { + testCmd('./bin.js', []); +}; + +exports.dotSlashArgs = function () { + testCmd('./bin.js', [ 'a', 'b', 'c' ]); +}; + +exports.nodeEmpty = function () { + testCmd('node bin.js', []); +}; + +exports.nodeArgs = function () { + testCmd('node bin.js', [ 'x', 'y', 'z' ]); +}; + +exports.whichNodeEmpty = function () { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + testCmd(buf.toString().trim() + ' bin.js', []); + }); + + which.stderr.on('data', function (err) { + assert.fail(err.toString()); + }); +}; + +exports.whichNodeArgs = function () { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]); + }); + + which.stderr.on('data', function (err) { + assert.fail(err.toString()); + }); +}; + +function testCmd (cmd, args) { + var to = setTimeout(function () { + assert.fail('Never got stdout data.') + }, 5000); + + var oldDir = process.cwd(); + process.chdir(__dirname + '/_'); + + var cmds = cmd.split(' '); + + var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String))); + process.chdir(oldDir); + + bin.stderr.on('data', function (err) { + assert.fail(err.toString()); + }); + + bin.stdout.on('data', function (buf) { + clearTimeout(to); + var _ = JSON.parse(buf.toString()); + assert.eql(_.map(String), args.map(String)); + }); +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/argv.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/argv.js new file mode 100644 index 0000000..3d09606 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/argv.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log(JSON.stringify(process.argv)); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/bin.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/bin.js new file mode 100755 index 0000000..4a18d85 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/_/bin.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('../../index').argv +console.log(JSON.stringify(argv._)); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/parse.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/parse.js new file mode 100644 index 0000000..eed467e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/parse.js @@ -0,0 +1,304 @@ +var optimist = require('../index'); +var assert = require('assert'); +var path = require('path'); + +var localExpresso = path.normalize( + __dirname + '/../node_modules/.bin/expresso' +); + +var expresso = process.argv[1] === localExpresso + ? 'node ./node_modules/.bin/expresso' + : 'expresso' +; + +exports['short boolean'] = function () { + var parse = optimist.parse([ '-b' ]); + assert.eql(parse, { b : true, _ : [], $0 : expresso }); + assert.eql(typeof parse.b, 'boolean'); +}; + +exports['long boolean'] = function () { + assert.eql( + optimist.parse([ '--bool' ]), + { bool : true, _ : [], $0 : expresso } + ); +}; + +exports.bare = function () { + assert.eql( + optimist.parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ], $0 : expresso } + ); +}; + +exports['short group'] = function () { + assert.eql( + optimist.parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [], $0 : expresso } + ); +}; + +exports['short group next'] = function () { + assert.eql( + optimist.parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [], $0 : expresso } + ); +}; + +exports['short capture'] = function () { + assert.eql( + optimist.parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [], $0 : expresso } + ); +}; + +exports['short captures'] = function () { + assert.eql( + optimist.parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [], $0 : expresso } + ); +}; + +exports['long capture sp'] = function () { + assert.eql( + optimist.parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [], $0 : expresso } + ); +}; + +exports['long capture eq'] = function () { + assert.eql( + optimist.parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [], $0 : expresso } + ); +}; + +exports['long captures sp'] = function () { + assert.eql( + optimist.parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [], $0 : expresso } + ); +}; + +exports['long captures eq'] = function () { + assert.eql( + optimist.parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [], $0 : expresso } + ); +}; + +exports['mixed short bool and capture'] = function () { + assert.eql( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : expresso, + } + ); +}; + +exports['short and long'] = function () { + assert.eql( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : expresso, + } + ); +}; + +exports.no = function () { + assert.eql( + optimist.parse([ '--no-moo' ]), + { moo : false, _ : [], $0 : expresso } + ); +}; + +exports.multi = function () { + assert.eql( + optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [], $0 : expresso } + ); +}; + +exports.comprehensive = function () { + assert.eql( + optimist.parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ], + $0 : expresso + } + ); +}; + +exports.nums = function () { + var argv = optimist.parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + assert.eql(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ], + $0 : expresso + }); + assert.eql(typeof argv.x, 'number'); + assert.eql(typeof argv.y, 'number'); + assert.eql(typeof argv.z, 'number'); + assert.eql(typeof argv.w, 'string'); + assert.eql(typeof argv.hex, 'number'); + assert.eql(typeof argv._[0], 'number'); +}; + +exports['flag boolean'] = function () { + var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv; + assert.eql(parse, { t : true, _ : [ 'moo' ], $0 : expresso }); + assert.eql(typeof parse.t, 'boolean'); +}; + +exports['flag boolean value'] = function () { + var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true']) + .boolean(['t', 'verbose']).default('verbose', true).argv; + + assert.eql(parse, { + verbose: false, + t: true, + _: ['moo'], + $0 : expresso + }); + + assert.eql(typeof parse.verbose, 'boolean'); + assert.eql(typeof parse.t, 'boolean'); +}; + +exports['flag boolean default false'] = function () { + var parse = optimist(['moo']) + .boolean(['t', 'verbose']) + .default('verbose', false) + .default('t', false).argv; + + assert.eql(parse, { + verbose: false, + t: false, + _: ['moo'], + $0 : expresso + }); + + assert.eql(typeof parse.verbose, 'boolean'); + assert.eql(typeof parse.t, 'boolean'); + +}; + +exports['boolean groups'] = function () { + var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ]) + .boolean(['x','y','z']).argv; + + assert.eql(parse, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ], + $0 : expresso + }); + + assert.eql(typeof parse.x, 'boolean'); + assert.eql(typeof parse.y, 'boolean'); + assert.eql(typeof parse.z, 'boolean'); +}; + +exports.strings = function () { + var s = optimist([ '-s', '0001234' ]).string('s').argv.s; + assert.eql(s, '0001234'); + assert.eql(typeof s, 'string'); + + var x = optimist([ '-x', '56' ]).string('x').argv.x; + assert.eql(x, '56'); + assert.eql(typeof x, 'string'); +}; + +exports.stringArgs = function () { + var s = optimist([ ' ', ' ' ]).string('_').argv._; + assert.eql(s.length, 2); + assert.eql(typeof s[0], 'string'); + assert.eql(s[0], ' '); + assert.eql(typeof s[1], 'string'); + assert.eql(s[1], ' '); +}; + +exports.slashBreak = function () { + assert.eql( + optimist.parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [], $0 : expresso } + ); + assert.eql( + optimist.parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : expresso } + ); +}; + +exports.alias = function () { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', 'zoom') + .argv + ; + assert.equal(argv.zoom, 55); + assert.equal(argv.z, argv.zoom); + assert.equal(argv.f, 11); +}; + +exports.multiAlias = function () { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', [ 'zm', 'zoom' ]) + .argv + ; + assert.equal(argv.zoom, 55); + assert.equal(argv.z, argv.zoom); + assert.equal(argv.z, argv.zm); + assert.equal(argv.f, 11); +}; + +exports['boolean default true'] = function () { + var argv = optimist.options({ + sometrue: { + boolean: true, + default: true + } + }).argv; + + assert.equal(argv.sometrue, true); +}; + +exports['boolean default false'] = function () { + var argv = optimist.options({ + somefalse: { + boolean: true, + default: false + } + }).argv; + + assert.equal(argv.somefalse, false); +}; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/usage.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/usage.js new file mode 100644 index 0000000..6593b9b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/optimist/test/usage.js @@ -0,0 +1,256 @@ +var Hash = require('hashish'); +var optimist = require('../index'); +var assert = require('assert'); + +exports.usageFail = function () { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + assert.deepEqual( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + assert.deepEqual( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'Options:', + ' -x [required]', + ' -y [required]', + 'Missing required arguments: y', + ] + ); + assert.deepEqual(r.logs, []); + assert.ok(r.exit); +}; + +exports.usagePass = function () { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + assert.deepEqual(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); +}; + +exports.checkPass = function () { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + assert.deepEqual(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); +}; + +exports.checkFail = function () { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + + assert.deepEqual( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + assert.deepEqual( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'You forgot about -y' + ] + ); + + assert.deepEqual(r.logs, []); + assert.ok(r.exit); +}; + +exports.checkCondPass = function () { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + assert.deepEqual(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); +}; + +exports.checkCondFail = function () { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + + assert.deepEqual( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + assert.deepEqual( + r.errors.join('\n').split(/\n+/).join('\n'), + 'Usage: ./usage -x NUM -y NUM\n' + + 'Argument check failed: ' + checker.toString() + ); + + assert.deepEqual(r.logs, []); + assert.ok(r.exit); +}; + +exports.countPass = function () { + var r = checkUsage(function () { + return optimist('1 2 3 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + assert.deepEqual(r, { + result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); +}; + +exports.countFail = function () { + var r = checkUsage(function () { + return optimist('1 2 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + assert.deepEqual( + r.result, + { _ : [ '1', '2' ], moo : true, $0 : './usage' } + ); + + assert.deepEqual( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage [x] [y] [z] {OPTIONS}', + 'Not enough non-option arguments: got 2, need at least 3', + ] + ); + + assert.deepEqual(r.logs, []); + assert.ok(r.exit); +}; + +exports.defaultSingles = function () { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70 --powsy'.split(' ')) + .default('foo', 5) + .default('bar', 6) + .default('baz', 7) + .argv + ; + }); + assert.eql(r.result, { + foo : '50', + bar : 6, + baz : '70', + powsy : true, + _ : [], + $0 : './usage', + }); +}; + +exports.defaultHash = function () { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70'.split(' ')) + .default({ foo : 10, bar : 20, quux : 30 }) + .argv + ; + }); + assert.eql(r.result, { + foo : '50', + bar : 20, + baz : 70, + quux : 30, + _ : [], + $0 : './usage', + }); +}; + +exports.rebase = function () { + assert.equal( + optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'), + './foo/bar/baz' + ); + assert.equal( + optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'), + '../../..' + ); + assert.equal( + optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'), + '../pow/zoom.txt' + ); +}; + +function checkUsage (f) { + var _process = process; + process = Hash.copy(process); + var exit = false; + process.exit = function () { exit = true }; + process.env = Hash.merge(process.env, { _ : 'node' }); + process.argv = [ './usage' ]; + + var errors = []; + var logs = []; + + console._error = console.error; + console.error = function (msg) { errors.push(msg) }; + console._log = console.log; + console.log = function (msg) { logs.push(msg) }; + + var result = f(); + + process = _process; + console.error = console._error; + console.log = console._log; + + return { + errors : errors, + logs : logs, + exit : exit, + result : result, + }; +}; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/.npmignore new file mode 100644 index 0000000..13abef4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/.npmignore @@ -0,0 +1,3 @@ +node_modules +node_modules/* +npm_debug.log diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/index.js new file mode 100644 index 0000000..8fadda9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/index.js @@ -0,0 +1,76 @@ +var Stream = require('stream') + +/* + was gonna use through for this, + but it does not match quite right, + because you need a seperate pause + mechanism for the readable and writable + sides. +*/ + +module.exports = function () { + var buffer = [], ended = false, destroyed = false + var stream = new Stream() + stream.writable = stream.readable = true + stream.paused = false + + stream.write = function (data) { + if(!this.paused) + this.emit('data', data) + else + buffer.push(data) + return !(this.paused || buffer.length) + } + function onEnd () { + stream.readable = false + stream.emit('end') + process.nextTick(stream.destroy.bind(stream)) + } + stream.end = function (data) { + if(data) this.write(data) + this.ended = true + this.writable = false + if(!(this.paused || buffer.length)) + return onEnd() + else + this.once('drain', onEnd) + this.drain() + } + + stream.drain = function () { + while(!this.paused && buffer.length) + this.emit('data', buffer.shift()) + //if the buffer has emptied. emit drain. + if(!buffer.length && !this.paused) + this.emit('drain') + } + + stream.resume = function () { + //this is where I need pauseRead, and pauseWrite. + //here the reading side is unpaused, + //but the writing side may still be paused. + //the whole buffer might not empity at once. + //it might pause again. + //the stream should never emit data inbetween pause()...resume() + //and write should return !buffer.length + + this.paused = false +// process.nextTick(this.drain.bind(this)) //will emit drain if buffer empties. + this.drain() + return this + } + + stream.destroy = function () { + if(destroyed) return + destroyed = ended = true + buffer.length = 0 + this.emit('close') + } + + stream.pause = function () { + stream.paused = true + return this + } + + return stream +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/package.json new file mode 100644 index 0000000..7702ad5 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/package.json @@ -0,0 +1,38 @@ +{ + "name": "pause-stream", + "version": "0.0.4", + "description": "a ThroughStream that strictly buffers all readable events when paused.", + "main": "index.js", + "directories": { + "test": "test" + }, + "devDependencies": { + "stream-spec": "~0.2.0" + }, + "scripts": { + "test": "node test/index.js && node test/pause-end.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/pause-stream.git" + }, + "keywords": [ + "stream", + "pipe", + "pause", + "drain", + "buffer" + ], + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "dominictarr.com" + }, + "license": [ + "MIT", + "Apache2" + ], + "readme": "# PauseStream\n\nThis is a `Stream` that will strictly buffer when paused.\nConnect it to anything you need buffered.\n\n``` js\n var ps = require('pause-stream')();\n\n badlyBehavedStream.pipe(ps.pause())\n\n aLittleLater(function (err, data) {\n ps.pipe(createAnotherStream(data))\n ps.resume()\n })\n```\n\n`PauseStream` will buffer whenever paused.\nit will buffer when yau have called `pause` manually.\nbut also when it's downstream `dest.write()===false`.\nit will attempt to drain the buffer when you call resume\nor the downstream emits `'drain'`\n\n`PauseStream` is tested using [stream-spec](https://github.com/dominictarr/stream-spec)\nand [stream-tester](https://github.com/dominictarr/stream-tester)\n", + "_id": "pause-stream@0.0.4", + "_from": "pause-stream@0.0.4" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/readme.markdown new file mode 100644 index 0000000..715cb52 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/readme.markdown @@ -0,0 +1,24 @@ +# PauseStream + +This is a `Stream` that will strictly buffer when paused. +Connect it to anything you need buffered. + +``` js + var ps = require('pause-stream')(); + + badlyBehavedStream.pipe(ps.pause()) + + aLittleLater(function (err, data) { + ps.pipe(createAnotherStream(data)) + ps.resume() + }) +``` + +`PauseStream` will buffer whenever paused. +it will buffer when yau have called `pause` manually. +but also when it's downstream `dest.write()===false`. +it will attempt to drain the buffer when you call resume +or the downstream emits `'drain'` + +`PauseStream` is tested using [stream-spec](https://github.com/dominictarr/stream-spec) +and [stream-tester](https://github.com/dominictarr/stream-tester) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/index.js new file mode 100644 index 0000000..4aa7d5e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/index.js @@ -0,0 +1,17 @@ +var spec = require('stream-spec') +var tester = require('stream-tester') +var ps = require('..')() + +spec(ps) + .through({strict: false}) + .validateOnExit() + +var master = tester.createConsistent + +tester.createRandomStream(100) //1k random numbers + .pipe(master = tester.createConsistentStream()) + .pipe(tester.createUnpauseStream()) + .pipe(ps) + .pipe(tester.createPauseStream()) + .pipe(master.createSlave()) + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/pause-end.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/pause-end.js new file mode 100644 index 0000000..a6c27ef --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/pause-stream/test/pause-end.js @@ -0,0 +1,33 @@ + +var pause = require('..') +var assert = require('assert') + +var ps = pause() +var read = [], ended = false + +ps.on('data', function (i) { + read.push(i) +}) + +ps.on('end', function () { + ended = true +}) + +assert.deepEqual(read, []) + +ps.write(0) +ps.write(1) +ps.write(2) + +assert.deepEqual(read, [0, 1, 2]) + +ps.pause() + +assert.deepEqual(read, [0, 1, 2]) + +ps.end() +assert.equal(ended, false) +ps.resume() +assert.equal(ended, true) + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.npmignore new file mode 100644 index 0000000..13abef4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.npmignore @@ -0,0 +1,3 @@ +node_modules +node_modules/* +npm_debug.log diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/LICENCE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/LICENCE new file mode 100644 index 0000000..171dd97 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/LICENCE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Dominic Tarr + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/examples/pretty.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/examples/pretty.js new file mode 100644 index 0000000..af04340 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/examples/pretty.js @@ -0,0 +1,25 @@ + +var inspect = require('util').inspect + +if(!module.parent) { + var es = require('..') //load event-stream + es.pipe( //pipe joins streams together + process.openStdin(), //open stdin + es.split(), //split stream to break on newlines + es.map(function (data, callback) {//turn this async function into a stream + var j + try { + j = JSON.parse(data) //try to parse input into json + } catch (err) { + return callback(null, data) //if it fails just pass it anyway + } + callback(null, inspect(j)) //render it nicely + }), + process.stdout // pipe it to stdout ! + ) + } + +// run this +// +// curl -sS registry.npmjs.org/event-stream | node pretty.js +// diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/index.js new file mode 100644 index 0000000..1146c96 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/index.js @@ -0,0 +1,35 @@ +//filter will reemit the data if cb(err,pass) pass is truthy + +// reduce is more tricky +// maybe we want to group the reductions or emit progress updates occasionally +// the most basic reduce just emits one 'data' event after it has recieved 'end' + + +var through = require('through') + + +module.exports = split + +function split (matcher) { + var soFar = '' + if (!matcher) + matcher = '\n' + + return through(function (buffer) { + var stream = this + , pieces = (soFar + buffer).split(matcher) + soFar = pieces.pop() + + pieces.forEach(function (piece) { + stream.emit('data', piece) + }) + + return true + }, + function () { + if(soFar) + this.emit('data', soFar) + this.emit('end') + }) +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.APACHE2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.APACHE2 new file mode 100644 index 0000000..6366c04 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.APACHE2 @@ -0,0 +1,15 @@ +Apache License, Version 2.0 + +Copyright (c) 2011 Dominic Tarr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.MIT b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.MIT new file mode 100644 index 0000000..6eafbd7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/LICENSE.MIT @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2011 Dominic Tarr + +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/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/index.js new file mode 100644 index 0000000..cd25055 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/index.js @@ -0,0 +1,65 @@ +var Stream = require('stream') + +// through +// +// a stream that does nothing but re-emit the input. +// useful for aggregating a series of changing but not ending streams into one stream) + +exports = module.exports = through +through.through = through + +//create a readable writable stream. + +function through (write, end) { + write = write || function (data) { this.emit('data', data) } + end = end || function () { this.emit('end') } + + var ended = false, destroyed = false + var stream = new Stream() + stream.readable = stream.writable = true + stream.paused = false + stream.write = function (data) { + write.call(this, data) + return !stream.paused + } + //this will be registered as the first 'end' listener + //must call destroy next tick, to make sure we're after any + //stream piped from here. + stream.on('end', function () { + stream.readable = false + if(!stream.writable) + process.nextTick(function () { + stream.destroy() + }) + }) + + stream.end = function (data) { + if(ended) return + //this breaks, because pipe doesn't check writable before calling end. + //throw new Error('cannot call end twice') + ended = true + if(arguments.length) stream.write(data) + this.writable = false + end.call(this) + if(!this.readable) + this.destroy() + } + stream.destroy = function () { + if(destroyed) return + destroyed = true + ended = true + stream.writable = stream.readable = false + stream.emit('close') + } + stream.pause = function () { + stream.paused = true + } + stream.resume = function () { + if(stream.paused) { + stream.paused = false + stream.emit('drain') + } + } + return stream +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/package.json new file mode 100644 index 0000000..3ecb71d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/package.json @@ -0,0 +1,29 @@ +{ + "name": "through", + "version": "0.0.4", + "description": "simplified stream contruction", + "main": "index.js", + "scripts": { + "test": "asynct test/*.js" + }, + "devDependencies": { + "stream-spec": "0", + "assertions": "2", + "asynct": "1" + }, + "keywords": [ + "stream", + "streams", + "user-streams", + "pipe" + ], + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "dominictarr.com" + }, + "license": "MIT", + "readme": "#through\n\n[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through)\n\nEasy way to create a `Stream` that is both `readable` and `writable`. Pass in optional `write` and `end` methods. `through` takes care of pause/resume logic.\nUse `this.pause()` and `this.resume()` to manage flow.\nCheck `this.paused` to see current flow state. (write always returns `!this.paused`)\n\nthis function is the basis for most of the syncronous streams in [event-stream](http://github.com/dominictarr/event-stream).\n\n``` js\nvar through = require('through')\n\nthrough(function write(data) {\n this.emit('data', data)\n //this.pause() \n },\n function end () { //optional\n this.emit('end')\n })\n\n```\n\n## License\n\nMIT / Apache2\n", + "_id": "through@0.0.4", + "_from": "through@0.0.4" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/readme.markdown new file mode 100644 index 0000000..ce9b9e5 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/readme.markdown @@ -0,0 +1,26 @@ +#through + +[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through) + +Easy way to create a `Stream` that is both `readable` and `writable`. Pass in optional `write` and `end` methods. `through` takes care of pause/resume logic. +Use `this.pause()` and `this.resume()` to manage flow. +Check `this.paused` to see current flow state. (write always returns `!this.paused`) + +this function is the basis for most of the syncronous streams in [event-stream](http://github.com/dominictarr/event-stream). + +``` js +var through = require('through') + +through(function write(data) { + this.emit('data', data) + //this.pause() + }, + function end () { //optional + this.emit('end') + }) + +``` + +## License + +MIT / Apache2 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/test/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/test/index.js new file mode 100644 index 0000000..25a6ea7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/node_modules/through/test/index.js @@ -0,0 +1,113 @@ + +var spec = require('stream-spec') +var through = require('..') +var a = require('assertions') + +/* + I'm using these two functions, and not streams and pipe + so there is less to break. if this test fails it must be + the implementation of _through_ +*/ + +function write(array, stream) { + array = array.slice() + function next() { + while(array.length) + if(stream.write(array.shift()) === false) + return stream.once('drain', next) + + stream.end() + } + + next() +} + +function read(stream, callback) { + var actual = [] + stream.on('data', function (data) { + actual.push(data) + }) + stream.once('end', function () { + callback(null, actual) + }) + stream.once('error', function (err) { + callback(err) + }) +} + +exports['simple defaults'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = through() + spec(t) + .through() + .pausable() + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + + write(expected, t) +} + +exports['simple functions'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = through(function (data) { + this.emit('data', data*2) + }) + spec(t) + .through() + .pausable() + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected.map(function (data) { + return data*2 + })) + test.done() + }) + + write(expected, t) +} +exports['pauses'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l) //Math.random()) + + var t = through() + spec(t) + .through() + .pausable() + .validateOnExit() + + t.on('data', function () { + if(Math.random() > 0.1) return + t.pause() + process.nextTick(function () { + t.resume() + }) + }) + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + + write(expected, t) +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/package.json new file mode 100644 index 0000000..a592dad --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/package.json @@ -0,0 +1,35 @@ +{ + "name": "split", + "version": "0.0.0", + "description": "split a Text Stream into a Line Stream", + "homepage": "http://github.com/dominictarr/split", + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/split.git" + }, + "dependencies": { + "through": "0.0.4" + }, + "devDependencies": { + "asynct": "*", + "it-is": "1", + "ubelt": "~2.9", + "stream-spec": "~0.2", + "event-stream": "~3.0.2" + }, + "scripts": { + "test": "asynct test/" + }, + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "http://bit.ly/dominictarr" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# Split (matcher)\n\n\n\nBreak up a stream and reassemble it so that each line is a chunk. matcher may be a `String`, or a `RegExp` \n\nExample, read every line in a file ...\n\n``` js\n fs.createReadStream(file)\n .pipe(split())\n .on('data', function (line) {\n //each chunk now is a seperate line!\n })\n\n```\n\n`split` takes the same arguments as `string.split` except it defaults to '\\n' instead of ',', and the optional `limit` paremeter is ignored.\n[String#split](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split)\n\n", + "_id": "split@0.0.0", + "_from": "split@0.0.0" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/readme.markdown new file mode 100644 index 0000000..57c8edc --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/readme.markdown @@ -0,0 +1,20 @@ +# Split (matcher) + + + +Break up a stream and reassemble it so that each line is a chunk. matcher may be a `String`, or a `RegExp` + +Example, read every line in a file ... + +``` js + fs.createReadStream(file) + .pipe(split()) + .on('data', function (line) { + //each chunk now is a seperate line! + }) + +``` + +`split` takes the same arguments as `string.split` except it defaults to '\n' instead of ',', and the optional `limit` paremeter is ignored. +[String#split](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split) + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/test/split.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/test/split.asynct.js new file mode 100644 index 0000000..a6a3b1b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/split/test/split.asynct.js @@ -0,0 +1,47 @@ +var es = require('event-stream') + , it = require('it-is').style('colour') + , d = require('ubelt') + , split = require('..') + , join = require('path').join + , fs = require('fs') + , Stream = require('stream').Stream + , spec = require('stream-spec') + +exports ['es.split() works like String#split'] = function (test) { + var readme = join(__filename) + , expected = fs.readFileSync(readme, 'utf-8').split('\n') + , cs = split() + , actual = [] + , ended = false + , x = spec(cs).through() + + var a = new Stream () + + a.write = function (l) { + actual.push(l.trim()) + } + a.end = function () { + + ended = true + expected.forEach(function (v,k) { + //String.split will append an empty string '' + //if the string ends in a split pattern. + //es.split doesn't which was breaking this test. + //clearly, appending the empty string is correct. + //tests are passing though. which is the current job. + if(v) + it(actual[k]).like(v) + }) + //give the stream time to close + process.nextTick(function () { + test.done() + x.validate() + }) + } + a.writable = true + + fs.createReadStream(readme, {flags: 'r'}).pipe(cs) + cs.pipe(a) + +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.APACHE2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.APACHE2 new file mode 100644 index 0000000..6366c04 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.APACHE2 @@ -0,0 +1,15 @@ +Apache License, Version 2.0 + +Copyright (c) 2011 Dominic Tarr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.MIT b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.MIT new file mode 100644 index 0000000..6eafbd7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/LICENSE.MIT @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2011 Dominic Tarr + +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/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/index.js new file mode 100644 index 0000000..7072b37 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/index.js @@ -0,0 +1,100 @@ +var Stream = require('stream') + +// through +// +// a stream that does nothing but re-emit the input. +// useful for aggregating a series of changing but not ending streams into one stream) + + + +exports = module.exports = through +through.through = through + +//create a readable writable stream. + +function through (write, end) { + write = write || function (data) { this.emit('data', data) } + end = end || function () { this.emit('end') } + + var ended = false, destroyed = false + var stream = new Stream(), buffer = [] + stream.buffer = buffer + stream.readable = stream.writable = true + stream.paused = false + stream.write = function (data) { + write.call(this, data) + return !stream.paused + } + + function drain() { + while(buffer.length && !stream.paused) { + var data = buffer.shift() + if(null === data) + return stream.emit('end') + else + stream.emit('data', data) + } + } + + stream.queue = function (data) { + buffer.push(data) + drain() + } + + //this will be registered as the first 'end' listener + //must call destroy next tick, to make sure we're after any + //stream piped from here. + //this is only a problem if end is not emitted synchronously. + //a nicer way to do this is to make sure this is the last listener for 'end' + + stream.on('end', function () { + stream.readable = false + if(!stream.writable) + process.nextTick(function () { + stream.destroy() + }) + }) + + function _end () { + stream.writable = false + end.call(stream) + if(!stream.readable) + stream.destroy() + } + + stream.end = function (data) { + if(ended) return + //this breaks, because pipe doesn't check writable before calling end. + //throw new Error('cannot call end twice') + ended = true + if(arguments.length) stream.write(data) + if(!buffer.length) _end() + } + + stream.destroy = function () { + if(destroyed) return + destroyed = true + ended = true + buffer.length = 0 + stream.writable = stream.readable = false + stream.emit('close') + } + + stream.pause = function () { + if(stream.paused) return + stream.paused = true + stream.emit('pause') + } + stream.resume = function () { + if(stream.paused) { + stream.paused = false + } + drain() + //may have become paused again, + //as drain emits 'data'. + if(!stream.paused) + stream.emit('drain') + } + return stream +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/package.json new file mode 100644 index 0000000..168247e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/package.json @@ -0,0 +1,34 @@ +{ + "name": "through", + "version": "1.1.0", + "description": "simplified stream contruction", + "main": "index.js", + "scripts": { + "test": "asynct test/*.js" + }, + "devDependencies": { + "stream-spec": "0", + "assertions": "2", + "asynct": "1" + }, + "keywords": [ + "stream", + "streams", + "user-streams", + "pipe" + ], + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "dominictarr.com" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/dominictarr/through.git" + }, + "homepage": "http://github.com/dominictarr/through", + "readme": "#through\n\n[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through)\n\nEasy way to create a `Stream` that is both `readable` and `writable`. Pass in optional `write` and `end` methods. `through` takes care of pause/resume logic.\nUse `this.pause()` and `this.resume()` to manage flow.\nCheck `this.paused` to see current flow state. (write always returns `!this.paused`)\n\nthis function is the basis for most of the syncronous streams in [event-stream](http://github.com/dominictarr/event-stream).\n\n``` js\nvar through = require('through')\n\nthrough(function write(data) {\n this.emit('data', data)\n //this.pause() \n },\n function end () { //optional\n this.emit('end')\n })\n\n```\n\nor, with buffering on pause, use `this.queue(data)`,\ndata *cannot* be `null`. `this.queue(null)` will emit 'end'\nwhen it gets to the `null` element.\n\n``` js\nvar through = require('through')\n\nthrough(function write(data) {\n this.queue(data)\n //this.pause() \n },\n function end () { //optional\n this.queue(null)\n })\n\n```\n\n\n## License\n\nMIT / Apache2\n", + "_id": "through@1.1.0", + "_from": "through@~1.1.0" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/readme.markdown new file mode 100644 index 0000000..1b687e9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/readme.markdown @@ -0,0 +1,44 @@ +#through + +[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through) + +Easy way to create a `Stream` that is both `readable` and `writable`. Pass in optional `write` and `end` methods. `through` takes care of pause/resume logic. +Use `this.pause()` and `this.resume()` to manage flow. +Check `this.paused` to see current flow state. (write always returns `!this.paused`) + +this function is the basis for most of the syncronous streams in [event-stream](http://github.com/dominictarr/event-stream). + +``` js +var through = require('through') + +through(function write(data) { + this.emit('data', data) + //this.pause() + }, + function end () { //optional + this.emit('end') + }) + +``` + +or, with buffering on pause, use `this.queue(data)`, +data *cannot* be `null`. `this.queue(null)` will emit 'end' +when it gets to the `null` element. + +``` js +var through = require('through') + +through(function write(data) { + this.queue(data) + //this.pause() + }, + function end () { //optional + this.queue(null) + }) + +``` + + +## License + +MIT / Apache2 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/buffering.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/buffering.js new file mode 100644 index 0000000..1ce4b0d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/buffering.js @@ -0,0 +1,37 @@ +var through = require('..') + +// must emit end before close. + +exports['buffering'] = function (t) { + var ts = through(function (data) { + this.queue(data) + }, function () { + this.queue(null) + }) + + var ended = false, actual = [] + + ts.on('data', actual.push.bind(actual)) + ts.on('end', function () { + ended = true + }) + + ts.write(1) + ts.write(2) + ts.write(3) + t.deepEqual(actual, [1, 2, 3]) + ts.pause() + ts.write(4) + ts.write(5) + ts.write(6) + t.deepEqual(actual, [1, 2, 3]) + ts.resume() + t.deepEqual(actual, [1, 2, 3, 4, 5, 6]) + ts.pause() + ts.end() + t.ok(!ended) + ts.resume() + t.ok(ended) + t.end() + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/end.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/end.js new file mode 100644 index 0000000..280da0a --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/end.js @@ -0,0 +1,27 @@ +var through = require('..') + +// must emit end before close. + +exports['end before close'] = function (t) { + var ts = through() + var ended = false, closed = false + + ts.on('end', function () { + t.ok(!closed) + ended = true + }) + ts.on('close', function () { + t.ok(ended) + closed = true + }) + + ts.write(1) + ts.write(2) + ts.write(3) + ts.end() + t.ok(ended) + t.ok(closed) + + t.end() + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/index.js new file mode 100644 index 0000000..25a6ea7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/node_modules/through/test/index.js @@ -0,0 +1,113 @@ + +var spec = require('stream-spec') +var through = require('..') +var a = require('assertions') + +/* + I'm using these two functions, and not streams and pipe + so there is less to break. if this test fails it must be + the implementation of _through_ +*/ + +function write(array, stream) { + array = array.slice() + function next() { + while(array.length) + if(stream.write(array.shift()) === false) + return stream.once('drain', next) + + stream.end() + } + + next() +} + +function read(stream, callback) { + var actual = [] + stream.on('data', function (data) { + actual.push(data) + }) + stream.once('end', function () { + callback(null, actual) + }) + stream.once('error', function (err) { + callback(err) + }) +} + +exports['simple defaults'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = through() + spec(t) + .through() + .pausable() + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + + write(expected, t) +} + +exports['simple functions'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = through(function (data) { + this.emit('data', data*2) + }) + spec(t) + .through() + .pausable() + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected.map(function (data) { + return data*2 + })) + test.done() + }) + + write(expected, t) +} +exports['pauses'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l) //Math.random()) + + var t = through() + spec(t) + .through() + .pausable() + .validateOnExit() + + t.on('data', function () { + if(Math.random() > 0.1) return + t.pause() + process.nextTick(function () { + t.resume() + }) + }) + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + + write(expected, t) +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/package.json new file mode 100644 index 0000000..15f8ea8 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/package.json @@ -0,0 +1,40 @@ +{ + "name": "event-stream", + "version": "3.0.7", + "description": "construct pipes of streams of events", + "homepage": "http://github.com/dominictarr/event-stream", + "repository": { + "type": "git", + "url": "git://github.com/dominictarr/event-stream.git" + }, + "dependencies": { + "optimist": "0.2", + "through": "1.1.0", + "duplexer": "~0.0.2", + "from": "~0", + "map-stream": "0.0.1", + "pause-stream": "0.0.4", + "split": "0.0.0" + }, + "devDependencies": { + "asynct": "*", + "it-is": "1", + "ubelt": "~2.9", + "stream-spec": "~0.2" + }, + "scripts": { + "test": "asynct test/" + }, + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "http://bit.ly/dominictarr" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# EventStream\n\n\n\n[Streams](http://nodejs.org/api/streams.html \"Stream\") are nodes best and most misunderstood idea, and \n_EventStream_ is a toolkit to make creating and working with streams easy. \n\nNormally, streams are only used of IO, \nbut in event stream we send all kinds of objects down the pipe. \nIf your application's input and output are streams, \nshouldn't the throughput be a stream too? \n\nThe *EventStream* functions resemble the array functions, \nbecause Streams are like Arrays, but laid out in time, rather than in memory. \n\nAll the `event-stream` functions return instances of `Stream`.\n\nStream API docs: [nodejs.org/api/streams](http://nodejs.org/api/streams.html \"Stream\")\n\nNOTE: I shall use the term \"through stream\" to refer to a stream that is writable and readable. \n\n###[simple example](https://github.com/dominictarr/event-stream/blob/master/examples/pretty.js):\n\n``` js\n\n//pretty.js\n\nif(!module.parent) {\n var es = require('event-stream')\n es.pipeline( //connect streams together with `pipe`\n process.openStdin(), //open stdin\n es.split(), //split stream to break on newlines\n es.map(function (data, callback) {//turn this async function into a stream\n callback(null\n , inspect(JSON.parse(data))) //render it nicely\n }),\n process.stdout // pipe it to stdout !\n )\n }\n```\nrun it ...\n\n``` bash \ncurl -sS registry.npmjs.org/event-stream | node pretty.js\n```\n \n[node Stream documentation](http://nodejs.org/api/streams.html)\n\n## through (write?, end?)\n\nReemits data synchronously. Easy way to create syncronous through streams.\nPass in an optional `write` and `end` methods. They will be called in the \ncontext of the stream. Use `this.pause()` and `this.resume()` to manage flow.\nCheck `this.paused` to see current flow state. (write always returns `!this.paused`)\n\nthis function is the basis for most of the syncronous streams in `event-stream`.\n\n``` js\n\nes.through(function write(data) {\n this.emit('data', data)\n //this.pause() \n },\n function end () { //optional\n this.emit('end')\n })\n\n```\n\n##map (asyncFunction)\n\nCreate a through stream from an asyncronous function. \n\n``` js\nvar es = require('event-stream')\n\nes.map(function (data, callback) {\n //transform data\n // ...\n callback(null, data)\n})\n\n```\n\nEach map MUST call the callback. It may callback with data, with an error or with no arguments, \n\n * `callback()` drop this data. \n this makes the map work like `filter`, \n note:`callback(null,null)` is not the same, and will emit `null`\n\n * `callback(null, newData)` turn data into newData\n \n * `callback(error)` emit an error for this item.\n\n>Note: if a callback is not called, `map` will think that it is still being processed, \n>every call must be answered or the stream will not know when to end. \n>\n>Also, if the callback is called more than once, every call but the first will be ignored.\n\n## mapSync (syncFunction)\n\nSame as `map`, but the callback is called synchronously. Based on `es.through`\n\n## split (matcher)\n\nBreak up a stream and reassemble it so that each line is a chunk. matcher may be a `String`, or a `RegExp` \n\nExample, read every line in a file ...\n\n``` js\n es.pipeline(\n fs.createReadStream(file, {flags: 'r'}),\n es.split(),\n es.map(function (line, cb) {\n //do something with the line \n cb(null, line)\n })\n )\n\n```\n\n`split` takes the same arguments as `string.split` except it defaults to '\\n' instead of ',', and the optional `limit` paremeter is ignored.\n[String#split](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split)\n\n## join (seperator)\n\ncreate a through stream that emits `seperator` between each chunk, just like Array#join.\n\n(for legacy reasons, if you pass a callback instead of a string, join is a synonym for `es.wait`)\n\n## replace (from, to)\n\nReplace all occurences of `from` with `to`. `from` may be a `String` or a `RegExp`. \nWorks just like `string.split(from).join(to)`, but streaming.\n\n\n## parse\n\nConvienience function for parsing JSON chunks. For newline seperated JSON,\nuse with `es.split`\n\n``` js\nfs.createReadStream(filename)\n .pipe(es.split()) //defaults to lines.\n .pipe(es.parse())\n```\n\n## stringify\n\nconvert javascript objects into lines of text. The text will have whitespace escaped and have a `\\n` appended, so it will be compatible with `es.parse`\n\n``` js\nobjectStream\n .pipe(es.stringify())\n .pipe(fs.createWriteStream(filename))\n```\n\n##readable (asyncFunction) \n\ncreate a readable stream (that respects pause) from an async function. \nwhile the stream is not paused, \nthe function will be polled with `(count, callback)`, \nand `this` will be the readable stream.\n\n``` js\n\nes.readable(function (count, callback) {\n if(streamHasEnded)\n return this.emit('end')\n \n //...\n \n this.emit('data', data) //use this way to emit multiple chunks per call.\n \n callback() // you MUST always call the callback eventually.\n // the function will not be called again until you do this.\n})\n```\nyou can also pass the data and the error to the callback. \nyou may only call the callback once. \ncalling the same callback more than once will have no effect. \n\n##readArray (array)\n\nCreate a readable stream from an Array.\n\nJust emit each item as a data event, respecting `pause` and `resume`.\n\n``` js\n var es = require('event-stream')\n , reader = es.readArray([1,2,3])\n\n reader.pipe(...)\n```\n\n## writeArray (callback)\n\ncreate a writeable stream from a callback, \nall `data` events are stored in an array, which is passed to the callback when the stream ends.\n\n``` js\n var es = require('event-stream')\n , reader = es.readArray([1, 2, 3])\n , writer = es.writeArray(function (err, array){\n //array deepEqual [1, 2, 3]\n })\n\n reader.pipe(writer)\n```\n\n## pipeline (stream1,...,streamN)\n\nTurn a pipeline into a single stream. `pipeline` returns a stream that writes to the first stream\nand reads from the last stream. \n\nListening for 'error' will recieve errors from all streams inside the pipe.\n\n> `connect` is an alias for `pipeline`.\n\n``` js\n\n es.pipeline( //connect streams together with `pipe`\n process.openStdin(), //open stdin\n es.split(), //split stream to break on newlines\n es.map(function (data, callback) {//turn this async function into a stream\n callback(null\n , inspect(JSON.parse(data))) //render it nicely\n }),\n process.stdout // pipe it to stdout !\n )\n```\n\n## pause () \n\nA stream that buffers all chunks when paused.\n\n\n``` js\n var ps = es.pause()\n ps.pause() //buffer the stream, also do not allow 'end' \n ps.resume() //allow chunks through\n```\n\n## duplex (writeStream, readStream)\n\nTakes a writable stream and a readable stream and makes them appear as a readable writable stream.\n\nIt is assumed that the two streams are connected to each other in some way. \n\n(This is used by `pipeline` and `child`.)\n\n``` js\n var grep = cp.exec('grep Stream')\n\n es.duplex(grep.stdin, grep.stdout)\n```\n\n## child (child_process)\n\nCreate a through stream from a child process ...\n\n``` js\n var cp = require('child_process')\n\n es.child(cp.exec('grep Stream')) // a through stream\n\n```\n\n## wait (callback)\n\nwaits for stream to emit 'end'.\njoins chunks of a stream into a single string. \ntakes an optional callback, which will be passed the \ncomplete string when it receives the 'end' event.\n\nalso, emits a simgle 'data' event.\n\n``` js\n\nreadStream.pipe(es.join(function (err, text) {\n // have complete text here.\n}))\n\n```\n\n\n", + "_id": "event-stream@3.0.7", + "_from": "event-stream@~3.0.7" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/readme.markdown new file mode 100644 index 0000000..e83724a --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/readme.markdown @@ -0,0 +1,286 @@ +# EventStream + + + +[Streams](http://nodejs.org/api/streams.html "Stream") are nodes best and most misunderstood idea, and +_EventStream_ is a toolkit to make creating and working with streams easy. + +Normally, streams are only used of IO, +but in event stream we send all kinds of objects down the pipe. +If your application's input and output are streams, +shouldn't the throughput be a stream too? + +The *EventStream* functions resemble the array functions, +because Streams are like Arrays, but laid out in time, rather than in memory. + +All the `event-stream` functions return instances of `Stream`. + +Stream API docs: [nodejs.org/api/streams](http://nodejs.org/api/streams.html "Stream") + +NOTE: I shall use the term "through stream" to refer to a stream that is writable and readable. + +###[simple example](https://github.com/dominictarr/event-stream/blob/master/examples/pretty.js): + +``` js + +//pretty.js + +if(!module.parent) { + var es = require('event-stream') + es.pipeline( //connect streams together with `pipe` + process.openStdin(), //open stdin + es.split(), //split stream to break on newlines + es.map(function (data, callback) {//turn this async function into a stream + callback(null + , inspect(JSON.parse(data))) //render it nicely + }), + process.stdout // pipe it to stdout ! + ) + } +``` +run it ... + +``` bash +curl -sS registry.npmjs.org/event-stream | node pretty.js +``` + +[node Stream documentation](http://nodejs.org/api/streams.html) + +## through (write?, end?) + +Reemits data synchronously. Easy way to create syncronous through streams. +Pass in an optional `write` and `end` methods. They will be called in the +context of the stream. Use `this.pause()` and `this.resume()` to manage flow. +Check `this.paused` to see current flow state. (write always returns `!this.paused`) + +this function is the basis for most of the syncronous streams in `event-stream`. + +``` js + +es.through(function write(data) { + this.emit('data', data) + //this.pause() + }, + function end () { //optional + this.emit('end') + }) + +``` + +##map (asyncFunction) + +Create a through stream from an asyncronous function. + +``` js +var es = require('event-stream') + +es.map(function (data, callback) { + //transform data + // ... + callback(null, data) +}) + +``` + +Each map MUST call the callback. It may callback with data, with an error or with no arguments, + + * `callback()` drop this data. + this makes the map work like `filter`, + note:`callback(null,null)` is not the same, and will emit `null` + + * `callback(null, newData)` turn data into newData + + * `callback(error)` emit an error for this item. + +>Note: if a callback is not called, `map` will think that it is still being processed, +>every call must be answered or the stream will not know when to end. +> +>Also, if the callback is called more than once, every call but the first will be ignored. + +## mapSync (syncFunction) + +Same as `map`, but the callback is called synchronously. Based on `es.through` + +## split (matcher) + +Break up a stream and reassemble it so that each line is a chunk. matcher may be a `String`, or a `RegExp` + +Example, read every line in a file ... + +``` js + es.pipeline( + fs.createReadStream(file, {flags: 'r'}), + es.split(), + es.map(function (line, cb) { + //do something with the line + cb(null, line) + }) + ) + +``` + +`split` takes the same arguments as `string.split` except it defaults to '\n' instead of ',', and the optional `limit` paremeter is ignored. +[String#split](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split) + +## join (seperator) + +create a through stream that emits `seperator` between each chunk, just like Array#join. + +(for legacy reasons, if you pass a callback instead of a string, join is a synonym for `es.wait`) + +## replace (from, to) + +Replace all occurences of `from` with `to`. `from` may be a `String` or a `RegExp`. +Works just like `string.split(from).join(to)`, but streaming. + + +## parse + +Convienience function for parsing JSON chunks. For newline seperated JSON, +use with `es.split` + +``` js +fs.createReadStream(filename) + .pipe(es.split()) //defaults to lines. + .pipe(es.parse()) +``` + +## stringify + +convert javascript objects into lines of text. The text will have whitespace escaped and have a `\n` appended, so it will be compatible with `es.parse` + +``` js +objectStream + .pipe(es.stringify()) + .pipe(fs.createWriteStream(filename)) +``` + +##readable (asyncFunction) + +create a readable stream (that respects pause) from an async function. +while the stream is not paused, +the function will be polled with `(count, callback)`, +and `this` will be the readable stream. + +``` js + +es.readable(function (count, callback) { + if(streamHasEnded) + return this.emit('end') + + //... + + this.emit('data', data) //use this way to emit multiple chunks per call. + + callback() // you MUST always call the callback eventually. + // the function will not be called again until you do this. +}) +``` +you can also pass the data and the error to the callback. +you may only call the callback once. +calling the same callback more than once will have no effect. + +##readArray (array) + +Create a readable stream from an Array. + +Just emit each item as a data event, respecting `pause` and `resume`. + +``` js + var es = require('event-stream') + , reader = es.readArray([1,2,3]) + + reader.pipe(...) +``` + +## writeArray (callback) + +create a writeable stream from a callback, +all `data` events are stored in an array, which is passed to the callback when the stream ends. + +``` js + var es = require('event-stream') + , reader = es.readArray([1, 2, 3]) + , writer = es.writeArray(function (err, array){ + //array deepEqual [1, 2, 3] + }) + + reader.pipe(writer) +``` + +## pipeline (stream1,...,streamN) + +Turn a pipeline into a single stream. `pipeline` returns a stream that writes to the first stream +and reads from the last stream. + +Listening for 'error' will recieve errors from all streams inside the pipe. + +> `connect` is an alias for `pipeline`. + +``` js + + es.pipeline( //connect streams together with `pipe` + process.openStdin(), //open stdin + es.split(), //split stream to break on newlines + es.map(function (data, callback) {//turn this async function into a stream + callback(null + , inspect(JSON.parse(data))) //render it nicely + }), + process.stdout // pipe it to stdout ! + ) +``` + +## pause () + +A stream that buffers all chunks when paused. + + +``` js + var ps = es.pause() + ps.pause() //buffer the stream, also do not allow 'end' + ps.resume() //allow chunks through +``` + +## duplex (writeStream, readStream) + +Takes a writable stream and a readable stream and makes them appear as a readable writable stream. + +It is assumed that the two streams are connected to each other in some way. + +(This is used by `pipeline` and `child`.) + +``` js + var grep = cp.exec('grep Stream') + + es.duplex(grep.stdin, grep.stdout) +``` + +## child (child_process) + +Create a through stream from a child process ... + +``` js + var cp = require('child_process') + + es.child(cp.exec('grep Stream')) // a through stream + +``` + +## wait (callback) + +waits for stream to emit 'end'. +joins chunks of a stream into a single string. +takes an optional callback, which will be passed the +complete string when it receives the 'end' event. + +also, emits a simgle 'data' event. + +``` js + +readStream.pipe(es.join(function (err, text) { + // have complete text here. +})) + +``` + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/connect.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/connect.asynct.js new file mode 100644 index 0000000..0ba0020 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/connect.asynct.js @@ -0,0 +1,82 @@ +var es = require('../') + , it = require('it-is').style('colour') + , d = require('ubelt') + +function makeExamplePipe() { + + return es.connect( + es.map(function (data, callback) { + callback(null, data * 2) + }), + es.map(function (data, callback) { + d.delay(callback)(null, data) + }), + es.map(function (data, callback) { + callback(null, data + 2) + })) +} + +exports['simple pipe'] = function (test) { + + var pipe = makeExamplePipe() + + pipe.on('data', function (data) { + it(data).equal(18) + test.done() + }) + + pipe.write(8) + +} + +exports['read array then map'] = function (test) { + + var readThis = d.map(3, 6, 100, d.id) //array of multiples of 3 < 100 + , first = es.readArray(readThis) + , read = [] + , pipe = + es.connect( + first, + es.map(function (data, callback) { + callback(null, {data: data}) + }), + es.map(function (data, callback) { + callback(null, {data: data}) + }), + es.writeArray(function (err, array) { + it(array).deepEqual(d.map(readThis, function (data) { + return {data: {data: data}} + })) + test.done() + }) + ) +} + +exports ['connect returns a stream'] = function (test) { + + var rw = + es.connect( + es.map(function (data, callback) { + callback(null, data * 2) + }), + es.map(function (data, callback) { + callback(null, data * 5) + }) + ) + + it(rw).has({readable: true, writable: true}) + + var array = [190, 24, 6, 7, 40, 57, 4, 6] + , _array = [] + , c = + es.connect( + es.readArray(array), + rw, + es.log('after rw:'), + es.writeArray(function (err, _array) { + it(_array).deepEqual(array.map(function (e) { return e * 10 })) + test.done() + }) + ) + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/merge.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/merge.asynct.js new file mode 100644 index 0000000..17fae5b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/merge.asynct.js @@ -0,0 +1,20 @@ +var es = require('../') + , it = require('it-is').style('colour') + , d = require('ubelt') + +exports.merge = function (t) { + var odd = d.map(1, 3, 100, d.id) //array of multiples of 3 < 100 + var even = d.map(2, 4, 100, d.id) //array of multiples of 3 < 100 + + var r1 = es.readArray(even) + var r2 = es.readArray(odd) + + var writer = es.writeArray(function (err, array){ + if(err) throw err //unpossible + it(array.sort()).deepEqual(even.concat(odd).sort()) + t.done() + }) + + es.merge(r1, r2).pipe(writer) + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pause.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pause.asynct.js new file mode 100644 index 0000000..59d896f --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pause.asynct.js @@ -0,0 +1,38 @@ + +var es = require('../') + , it = require('it-is') + , d = require('ubelt') + +exports ['gate buffers when shut'] = function (test) { + + var hundy = d.map(1,100, d.id) + , gate = es.pause() + , ten = 10 + es.connect( + es.readArray(hundy), + es.log('after readArray'), + gate, + //es.log('after gate'), + es.map(function (num, next) { + //stick a map in here to check that gate never emits when open + it(gate.paused).equal(false) + console.log('data', num) + if(!--ten) { + console.log('PAUSE') + gate.pause()//.resume() + d.delay(gate.resume.bind(gate), 10)() + ten = 10 + } + + next(null, num) + }), + es.writeArray(function (err, array) { //just realized that I should remove the error param. errors will be emitted + console.log('eonuhoenuoecbulc') + it(array).deepEqual(hundy) + test.done() + }) + ) + + gate.resume() + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pipeline.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pipeline.asynct.js new file mode 100644 index 0000000..c2af9d8 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/pipeline.asynct.js @@ -0,0 +1,51 @@ +var es = require('..') + +exports['do not duplicate errors'] = function (test) { + + var errors = 0; + var pipe = es.pipeline( + es.through(function(data) { + return this.emit('data', data); + }), + es.through(function(data) { + return this.emit('error', new Error(data)); + }) + ) + + pipe.on('error', function(err) { + errors++ + console.log('error count', errors) + process.nextTick(function () { + return test.done(); + }) + }) + + return pipe.write('meh'); + +} + +exports['3 pipe do not duplicate errors'] = function (test) { + + var errors = 0; + var pipe = es.pipeline( + es.through(function(data) { + return this.emit('data', data); + }), + es.through(function(data) { + return this.emit('error', new Error(data)); + }), + es.through() + ) + + pipe.on('error', function(err) { + errors++ + console.log('error count', errors) + process.nextTick(function () { + return test.done(); + }) + }) + + return pipe.write('meh'); + +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readArray.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readArray.asynct.js new file mode 100644 index 0000000..76585ee --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readArray.asynct.js @@ -0,0 +1,88 @@ + +var es = require('../') + , it = require('it-is').style('colour') + , d = require('ubelt') + +function readStream(stream, pauseAt, done) { + if(!done) done = pauseAt, pauseAt = -1 + var array = [] + stream.on('data', function (data) { + array.push(data) + if(!--pauseAt ) + stream.pause(), done(null, array) + }) + stream.on('error', done) + stream.on('end', function (data) { + done(null, array) + }) + +} + +exports ['read an array'] = function (test) { + + var readThis = d.map(3, 6, 100, d.id) //array of multiples of 3 < 100 + + var reader = es.readArray(readThis) + + var writer = es.writeArray(function (err, array){ + if(err) throw err //unpossible + it(array).deepEqual(readThis) + test.done() + }) + + reader.pipe(writer) +} + +exports ['read an array and pause it.'] = function (test) { + + var readThis = d.map(3, 6, 100, d.id) //array of multiples of 3 < 100 + + var reader = es.readArray(readThis) + + readStream(reader, 10, function (err, data) { + if(err) throw err + it(data).deepEqual([3, 6, 9, 12, 15, 18, 21, 24, 27, 30]) + readStream(reader, 10, function (err, data) { + it(data).deepEqual([33, 36, 39, 42, 45, 48, 51, 54, 57, 60]) + test.done() + }) + reader.resume() + }) + +} + +exports ['reader is readable, but not writeable'] = function (test) { + var reader = es.readArray([1]) + it(reader).has({ + readable: true, + writable: false + }) + + test.done() +} + + +exports ['read one item per tick'] = function (test) { + var readThis = d.map(3, 6, 100, d.id) //array of multiples of 3 < 100 + var drains = 0 + var reader = es.readArray(readThis) + var tickMapper = es.map(function (data,callback) { + process.nextTick(function () { + callback(null, data) + }) + //since tickMapper is returning false + //pipe should pause the writer until a drain occurs + return false + }) + reader.pipe(tickMapper) + readStream(tickMapper, function (err, array) { + it(array).deepEqual(readThis) + it(array.length).deepEqual(readThis.length) + it(drains).equal(readThis.length) + test.done() + }) + tickMapper.on('drain', function () { + drains ++ + }) + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readable.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readable.asynct.js new file mode 100644 index 0000000..77d0039 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/readable.asynct.js @@ -0,0 +1,167 @@ + +var es = require('../') + , it = require('it-is').style('colour') + , u = require('ubelt') + +exports ['read an array'] = function (test) { + + var readThis = u.map(3, 6, 100, u.id) //array of multiples of 3 < 100 + + var reader = + es.readable(function (i, callback) { + if(i >= readThis.length) + return this.emit('end') + callback(null, readThis[i]) + }) + + var writer = es.writeArray(function (err, array){ + if(err) throw err + it(array).deepEqual(readThis) + test.done() + }) + + reader.pipe(writer) +} + +exports ['read an array - async'] = function (test) { + + var readThis = u.map(3, 6, 100, u.id) //array of multiples of 3 < 100 + + var reader = + es.readable(function (i, callback) { + if(i >= readThis.length) + return this.emit('end') + u.delay(callback)(null, readThis[i]) + }) + + var writer = es.writeArray(function (err, array){ + if(err) throw err + it(array).deepEqual(readThis) + test.done() + }) + + reader.pipe(writer) +} + + +exports ['emit data then call next() also works'] = function (test) { + + var readThis = u.map(3, 6, 100, u.id) //array of multiples of 3 < 100 + + var reader = + es.readable(function (i, next) { + if(i >= readThis.length) + return this.emit('end') + this.emit('data', readThis[i]) + next() + }) + + var writer = es.writeArray(function (err, array){ + if(err) throw err + it(array).deepEqual(readThis) + test.done() + }) + + reader.pipe(writer) +} + + +exports ['callback emits error, then stops'] = function (test) { + + var err = new Error('INTENSIONAL ERROR') + , called = 0 + + var reader = + es.readable(function (i, callback) { + if(called++) + return + callback(err) + }) + + reader.on('error', function (_err){ + it(_err).deepEqual(err) + u.delay(function() { + it(called).equal(1) + test.done() + }, 50)() + }) +} + +exports['readable does not call read concurrently'] = function (test) { + + var current = 0 + var source = es.readable(function(count, cb){ + current ++ + if(count > 100) + return this.emit('end') + u.delay(function(){ + current -- + it(current).equal(0) + cb(null, {ok: true, n: count}); + })(); + }); + + var destination = es.map(function(data, cb){ + //console.info(data); + cb(); + }); + + var all = es.connect(source, destination); + + destination.on('end', test.done) +} + + +// +// emitting multiple errors is not supported by stream. +// +// I do not think that this is a good idea, at least, there should be an option to pipe to +// continue on error. it makes alot ef sense, if you are using Stream like I am, to be able to emit multiple errors. +// an error might not necessarily mean the end of the stream. it depends on the error, at least. +// +// I will start a thread on the mailing list. I'd rather that than use a custom `pipe` implementation. +// +// basically, I want to be able use pipe to transform objects, and if one object is invalid, +// the next might still be good, so I should get to choose if it's gonna stop. +// re-enstate this test when this issue progresses. +// +// hmm. I could add this to es.connect by deregistering the error listener, +// but I would rather it be an option in core. + +/* +exports ['emit multiple errors, with 2nd parameter (continueOnError)'] = function (test) { + + var readThis = d.map(1, 100, d.id) + , errors = 0 + var reader = + es.readable(function (i, callback) { + console.log(i, readThis.length) + if(i >= readThis.length) + return this.emit('end') + if(!(readThis[i] % 7)) + return callback(readThis[i]) + callback(null, readThis[i]) + }, true) + + var writer = es.writeArray(function (err, array) { + if(err) throw err + it(array).every(function (u){ + it(u % 7).notEqual(0) + }).property('length', 80) + it(errors).equal(14) + test.done() + }) + + reader.on('error', function (u) { + errors ++ + console.log(u) + if('number' !== typeof u) + throw u + + it(u % 7).equal(0) + + }) + + reader.pipe(writer) +} +*/ diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/replace.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/replace.asynct.js new file mode 100644 index 0000000..7fabf6e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/replace.asynct.js @@ -0,0 +1,50 @@ +var es = require('../') + , it = require('it-is').style('colour') + , d = require('ubelt') + , spec = require('stream-spec') + +var next = process.nextTick + +var fizzbuzz = '12F4BF78FB11F1314FB1617F19BF2223FB26F2829FB3132F34BF3738FB41F4344FB4647F49BF5253FB56F5859FB6162F64BF6768FB71F7374FB7677F79BF8283FB86F8889FB9192F94BF9798FB' + , fizz7buzz = '12F4BFseven8FB11F1314FB161sevenF19BF2223FB26F2829FB3132F34BF3seven38FB41F4344FB464sevenF49BF5253FB56F5859FB6162F64BF6seven68FBseven1Fseven3seven4FBseven6sevensevenFseven9BF8283FB86F8889FB9192F94BF9seven98FB' + +exports ['fizz buzz'] = function (test) { + + var readThis = d.map(1, 100, function (i) { + return ( + ! (i % 3 || i % 5) ? "FB" : + !(i % 3) ? "F" : + !(i % 5) ? "B" : + ''+i + ) + }) //array of multiples of 3 < 100 + + var reader = es.readArray(readThis) + var join = es.wait(function (err, string){ + it(string).equal(fizzbuzz) + test.done() + }) + reader.pipe(join) + +} + + +exports ['fizz buzz replace'] = function (test) { + var split = es.split(/(1)/) + var replace = es.replace('7', 'seven') + var x = spec(replace).through() + split + .pipe(replace) + .pipe(es.join(function (err, string) { + it(string).equal(fizz7buzz) + })) + + replace.on('close', function () { + x.validate() + test.done() + }) + + split.write(fizzbuzz) + split.end() + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/simple-map.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/simple-map.asynct.js new file mode 100644 index 0000000..4786faa --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/simple-map.asynct.js @@ -0,0 +1,342 @@ +'use strict'; + +var es = require('../') + , it = require('it-is') + , u = require('ubelt') + , spec = require('stream-spec') + , Stream = require('stream') + , from = require('from') + , through = require('through') + +//REFACTOR THIS TEST TO USE es.readArray and es.writeArray + +function writeArray(array, stream) { + + array.forEach( function (j) { + stream.write(j) + }) + stream.end() + +} + +function readStream(stream, done) { + + var array = [] + stream.on('data', function (data) { + array.push(data) + }) + stream.on('error', done) + stream.on('end', function (data) { + done(null, array) + }) + +} + +//call sink on each write, +//and complete when finished. + +function pauseStream (prob, delay) { + var pauseIf = ( + 'number' == typeof prob + ? function () { + return Math.random() < prob + } + : 'function' == typeof prob + ? prob + : 0.1 + ) + var delayer = ( + !delay + ? process.nextTick + : 'number' == typeof delay + ? function (next) { setTimeout(next, delay) } + : delay + ) + + return es.through(function (data) { + if(!this.paused && pauseIf()) { + console.log('PAUSE STREAM PAUSING') + this.pause() + var self = this + delayer(function () { + console.log('PAUSE STREAM RESUMING') + self.resume() + }) + } + console.log("emit ('data', " + data + ')') + this.emit('data', data) + }) +} + +exports ['simple map'] = function (test) { + + var input = u.map(1, 1000, function () { + return Math.random() + }) + var expected = input.map(function (v) { + return v * 2 + }) + + var pause = pauseStream(0.1) + var fs = from(input) + var ts = es.writeArray(function (err, ar) { + it(ar).deepEqual(expected) + test.done() + }) + var map = es.through(function (data) { + this.emit('data', data * 2) + }) + + spec(map).through().validateOnExit() + spec(pause).through().validateOnExit() + + fs.pipe(map).pipe(pause).pipe(ts) +} + +exports ['simple map applied to a stream'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + //create event stream from + + var doubler = es.map(function (data, cb) { + cb(null, data * 2) + }) + + spec(doubler).through().validateOnExit() + + //a map is only a middle man, so it is both readable and writable + + it(doubler).has({ + readable: true, + writable: true, + }) + + readStream(doubler, function (err, output) { + it(output).deepEqual(input.map(function (j) { + return j * 2 + })) +// process.nextTick(x.validate) + test.done() + }) + + writeArray(input, doubler) + +} + +exports['pipe two maps together'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + //create event stream from + function dd (data, cb) { + cb(null, data * 2) + } + var doubler1 = es.map(dd), doubler2 = es.map(dd) + + doubler1.pipe(doubler2) + + spec(doubler1).through().validateOnExit() + spec(doubler2).through().validateOnExit() + + readStream(doubler2, function (err, output) { + it(output).deepEqual(input.map(function (j) { + return j * 4 + })) + test.done() + }) + + writeArray(input, doubler1) + +} + +//next: +// +// test pause, resume and drian. +// + +// then make a pipe joiner: +// +// plumber (evStr1, evStr2, evStr3, evStr4, evStr5) +// +// will return a single stream that write goes to the first + +exports ['map will not call end until the callback'] = function (test) { + + var ticker = es.map(function (data, cb) { + process.nextTick(function () { + cb(null, data * 2) + }) + }) + + spec(ticker).through().validateOnExit() + + ticker.write('x') + ticker.end() + + ticker.on('end', function () { + test.done() + }) +} + + +exports ['emit error thrown'] = function (test) { + + var err = new Error('INTENSIONAL ERROR') + , mapper = + es.map(function () { + throw err + }) + + mapper.on('error', function (_err) { + it(_err).equal(err) + test.done() + }) + +// onExit(spec(mapper).basic().validate) +//need spec that says stream may error. + + mapper.write('hello') + +} + +exports ['emit error calledback'] = function (test) { + + var err = new Error('INTENSIONAL ERROR') + , mapper = + es.map(function (data, callback) { + callback(err) + }) + + mapper.on('error', function (_err) { + it(_err).equal(err) + test.done() + }) + + mapper.write('hello') + +} + +exports ['do not emit drain if not paused'] = function (test) { + + var map = es.map(function (data, callback) { + u.delay(callback)(null, 1) + return true + }) + + spec(map).through().pausable().validateOnExit() + + map.on('drain', function () { + it(false).ok('should not emit drain unless the stream is paused') + }) + + it(map.write('hello')).equal(true) + it(map.write('hello')).equal(true) + it(map.write('hello')).equal(true) + setTimeout(function () {map.end()},10) + map.on('end', test.done) +} + +exports ['emits drain if paused, when all '] = function (test) { + var active = 0 + var drained = false + var map = es.map(function (data, callback) { + active ++ + u.delay(function () { + active -- + callback(null, 1) + })() + console.log('WRITE', false) + return false + }) + + spec(map).through().validateOnExit() + + map.on('drain', function () { + drained = true + it(active).equal(0, 'should emit drain when all maps are done') + }) + + it(map.write('hello')).equal(false) + it(map.write('hello')).equal(false) + it(map.write('hello')).equal(false) + + process.nextTick(function () {map.end()},10) + + map.on('end', function () { + console.log('end') + it(drained).ok('shoud have emitted drain before end') + test.done() + }) + +} + +exports ['map applied to a stream with filtering'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + + var doubler = es.map(function (data, callback) { + if (data % 2) + callback(null, data * 2) + else + callback() + }) + + readStream(doubler, function (err, output) { + it(output).deepEqual(input.filter(function (j) { + return j % 2 + }).map(function (j) { + return j * 2 + })) + test.done() + }) + + spec(doubler).through().validateOnExit() + + writeArray(input, doubler) + +} + +exports ['simple mapSync applied to a stream'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + + var doubler = es.mapSync(function (data) { + return data * 2 + }) + + readStream(doubler, function (err, output) { + it(output).deepEqual(input.map(function (j) { + return j * 2 + })) + test.done() + }) + + spec(doubler).through().validateOnExit() + + writeArray(input, doubler) + +} + +exports ['mapSync applied to a stream with filtering'] = function (test) { + + var input = [1,2,3,7,5,3,1,9,0,2,4,6] + + var doubler = es.mapSync(function (data) { + if (data % 2) + return data * 2 + }) + + readStream(doubler, function (err, output) { + it(output).deepEqual(input.filter(function (j) { + return j % 2 + }).map(function (j) { + return j * 2 + })) + test.done() + }) + + spec(doubler).through().validateOnExit() + + writeArray(input, doubler) + +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/spec.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/spec.asynct.js new file mode 100644 index 0000000..516dbf4 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/spec.asynct.js @@ -0,0 +1,85 @@ +/* + assert that data is called many times + assert that end is called eventually + + assert that when stream enters pause state, + on drain is emitted eventually. +*/ + +var es = require('..') +var it = require('it-is').style('colour') +var spec = require('stream-spec') + +exports['simple stream'] = function (test) { + + var stream = es.through() + var x = spec(stream).basic().pausable() + + stream.write(1) + stream.write(1) + stream.pause() + stream.write(1) + stream.resume() + stream.write(1) + stream.end(2) //this will call write() + + process.nextTick(function (){ + x.validate() + test.done() + }) +} + +exports['throw on write when !writable'] = function (test) { + + var stream = es.through() + var x = spec(stream).basic().pausable() + + stream.write(1) + stream.write(1) + stream.end(2) //this will call write() + stream.write(1) //this will be throwing..., but the spec will catch it. + + process.nextTick(function () { + x.validate() + test.done() + }) + +} + +exports['end fast'] = function (test) { + + var stream = es.through() + var x = spec(stream).basic().pausable() + + stream.end() //this will call write() + + process.nextTick(function () { + x.validate() + test.done() + }) + +} + + +/* + okay, that was easy enough, whats next? + + say, after you call paused(), write should return false + until resume is called. + + simple way to implement this: + write must return !paused + after pause() paused = true + after resume() paused = false + + on resume, if !paused drain is emitted again. + after drain, !paused + + there are lots of subtle ordering bugs in streams. + + example, set !paused before emitting drain. + + the stream api is stateful. +*/ + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/split.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/split.asynct.js new file mode 100644 index 0000000..a0ce4b2 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/split.asynct.js @@ -0,0 +1,46 @@ +var es = require('../') + , it = require('it-is').style('colour') + , d = require('ubelt') + , join = require('path').join + , fs = require('fs') + , Stream = require('stream').Stream + , spec = require('stream-spec') + +exports ['es.split() works like String#split'] = function (test) { + var readme = join(__filename) + , expected = fs.readFileSync(readme, 'utf-8').split('\n') + , cs = es.split() + , actual = [] + , ended = false + , x = spec(cs).through() + + var a = new Stream () + + a.write = function (l) { + actual.push(l.trim()) + } + a.end = function () { + + ended = true + expected.forEach(function (v,k) { + //String.split will append an empty string '' + //if the string ends in a split pattern. + //es.split doesn't which was breaking this test. + //clearly, appending the empty string is correct. + //tests are passing though. which is the current job. + if(v) + it(actual[k]).like(v) + }) + //give the stream time to close + process.nextTick(function () { + test.done() + x.validate() + }) + } + a.writable = true + + fs.createReadStream(readme, {flags: 'r'}).pipe(cs) + cs.pipe(a) + +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/stringify.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/stringify.js new file mode 100644 index 0000000..a77887b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/stringify.js @@ -0,0 +1,14 @@ + + + +var es = require('../') + +exports['handle buffer'] = function (t) { + + + es.stringify().on('data', function (d) { + t.equal(d.trim(), JSON.stringify('HELLO')) + t.end() + }).write(new Buffer('HELLO')) + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/writeArray.asynct.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/writeArray.asynct.js new file mode 100644 index 0000000..f09fea2 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/event-stream/test/writeArray.asynct.js @@ -0,0 +1,30 @@ + +var es = require('../') + , it = require('it-is').style('colour') + , d = require('ubelt') + +exports ['write an array'] = function (test) { + + var readThis = d.map(3, 6, 100, d.id) //array of multiples of 3 < 100 + + var writer = es.writeArray(function (err, array){ + if(err) throw err //unpossible + it(array).deepEqual(readThis) + test.done() + }) + + d.each(readThis, writer.write.bind(writer)) + writer.end() + +} + + +exports ['writer is writable, but not readable'] = function (test) { + var reader = es.writeArray(function () {}) + it(reader).has({ + readable: false, + writable: true + }) + + test.done() +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.npmignore new file mode 100644 index 0000000..ee88966 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.npmignore @@ -0,0 +1 @@ +assets/ diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/README.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/README.md new file mode 100644 index 0000000..6cd71ba --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/README.md @@ -0,0 +1,98 @@ +# tap-stream [![Build Status](https://secure.travis-ci.org/thlorenz/tap-stream.png)](http://travis-ci.org/thlorenz/tap-stream) + +Taps a nodejs stream and logs the data that's coming through. + + npm install tap-stream + +Given an [object stream](#object-stream) we can print out objects passing through and control the detail via the +depth parameter: + +```javascript +objectStream().pipe(tap(0)); +``` + +![depth0](https://github.com/thlorenz/tap-stream/raw/master/assets/depth0.png) + +```javascript +objectStream().pipe(tap(1)); +``` + +![depth1](https://github.com/thlorenz/tap-stream/raw/master/assets/depth1.png) + +``` +objectStream().pipe(tap(2)); +``` + +![depth2](https://github.com/thlorenz/tap-stream/raw/master/assets/depth2.png) + +For even more control a custom log function may be supplied: + +```javascript +objectStream() + .pipe(tap(function customLog (data) { + var nest = data.nest; + console.log ('Bird: %s, id: %s, age: %s, layed egg: %s', nest.name, data.id, nest.age, nest.egg !== undefined); + }) + ); +``` + +```text +Bird: yellow rumped warbler, id: 0, age: 1, layed egg: true +Bird: yellow rumped warbler, id: 1, age: 1, layed egg: true +``` + +## API + +### tap( [ depth | log ] ) + +Intercepts the stream and logs data that is passing through. + +- optional parameter is either a `Number` or a `Function` +- if no parameter is given, `depth` defaults to `0` and `log` to `console.log(util.inspect(..))` + +- `depth` controls the `depth` with which + [util.inspect](http://nodejs.org/api/util.html#util_util_inspect_object_showhidden_depth_colors) is called +- `log` replaces the default logging function with a custom one + +**Example:** + +```javascript +var tap = require('tap-stream'); + +myStream + .pipe(tap(1)) // log intermediate results + .pipe(..) // continute manipulating the data +``` + +## Object stream + +Included in order to give context for above examples. + +```javascript +function objectStream () { + var s = new Stream() + , objects = 0; + + var iv = setInterval( + function () { + s.emit('data', { + id: objects + , created: new Date() + , nest: { + name: 'yellow rumped warbler' + , age: 1 + , egg: { name: 'unknown' , age: 0 } + } + } + , 4 + ); + + if (++objects === 2) { + s.emit('end'); + clearInterval(iv); + } + } + , 200); + return s; +} +``` diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/examples/tap-nested-objects.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/examples/tap-nested-objects.js new file mode 100644 index 0000000..97aa578 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/examples/tap-nested-objects.js @@ -0,0 +1,38 @@ +var Stream = require('stream') + , tap = require('..'); + +function objectStream () { + var s = new Stream() + , objects = 0; + + var iv = setInterval( + function () { + s.emit('data', { + id: objects + , created: new Date() + , nest: { + name: 'yellow rumped warbler' + , age: 1 + , egg: { name: 'unknown' , age: 0 } + } + } + ); + + if (++objects === 2) { + s.emit('end'); + clearInterval(iv); + } + } + , 200); + return s; +} + +objectStream().pipe(tap(2)); + +objectStream() + .pipe(tap(function customLog (data) { + var nest = data.nest; + console.log ('Bird: %s, id: %s, age: %s, layed egg: %s', nest.name, data.id, nest.age, nest.egg !== undefined); + }) + ); + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/index.js new file mode 100644 index 0000000..a541dfe --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/index.js @@ -0,0 +1,56 @@ +'use strict'; + +var util = require('util') + , through = require('through') + , toString = Object.prototype.toString + , slice = Array.prototype.slice; + +function blowup () { + throw new Error('Argument to streamTap needs to be either Number for depth or a log Function'); +} + +function defaultLog (depth) { + function log (data) { + console.log(util.inspect(data, false, depth, true)); + } + + return function (data) { + if (arguments.length === 1) { + log(data); + } else { + slice.call(arguments).forEach(log); + } + }; +} + +// invoke three ways: +// tap () +// tap (depth) +// tap (log) +function tap (arg0) { + var log; + + if (!arguments.length) { + log = defaultLog(1); + } else { + + if (toString.call(arg0) === '[object Number]' ) { + log = defaultLog(arg0); + } else if (toString.call(arg0) === '[object Function]' ) { + log = arg0; + } else { + blowup(); + } + + } + + return through( + function write (data) { + log(data); + this.emit('data', data); + } + ); + +} + +module.exports = tap; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/.travis.yml b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.APACHE2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.APACHE2 new file mode 100644 index 0000000..6366c04 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.APACHE2 @@ -0,0 +1,15 @@ +Apache License, Version 2.0 + +Copyright (c) 2011 Dominic Tarr + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.MIT b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.MIT new file mode 100644 index 0000000..6eafbd7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/LICENSE.MIT @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2011 Dominic Tarr + +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/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/index.js new file mode 100644 index 0000000..7072b37 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/index.js @@ -0,0 +1,100 @@ +var Stream = require('stream') + +// through +// +// a stream that does nothing but re-emit the input. +// useful for aggregating a series of changing but not ending streams into one stream) + + + +exports = module.exports = through +through.through = through + +//create a readable writable stream. + +function through (write, end) { + write = write || function (data) { this.emit('data', data) } + end = end || function () { this.emit('end') } + + var ended = false, destroyed = false + var stream = new Stream(), buffer = [] + stream.buffer = buffer + stream.readable = stream.writable = true + stream.paused = false + stream.write = function (data) { + write.call(this, data) + return !stream.paused + } + + function drain() { + while(buffer.length && !stream.paused) { + var data = buffer.shift() + if(null === data) + return stream.emit('end') + else + stream.emit('data', data) + } + } + + stream.queue = function (data) { + buffer.push(data) + drain() + } + + //this will be registered as the first 'end' listener + //must call destroy next tick, to make sure we're after any + //stream piped from here. + //this is only a problem if end is not emitted synchronously. + //a nicer way to do this is to make sure this is the last listener for 'end' + + stream.on('end', function () { + stream.readable = false + if(!stream.writable) + process.nextTick(function () { + stream.destroy() + }) + }) + + function _end () { + stream.writable = false + end.call(stream) + if(!stream.readable) + stream.destroy() + } + + stream.end = function (data) { + if(ended) return + //this breaks, because pipe doesn't check writable before calling end. + //throw new Error('cannot call end twice') + ended = true + if(arguments.length) stream.write(data) + if(!buffer.length) _end() + } + + stream.destroy = function () { + if(destroyed) return + destroyed = true + ended = true + buffer.length = 0 + stream.writable = stream.readable = false + stream.emit('close') + } + + stream.pause = function () { + if(stream.paused) return + stream.paused = true + stream.emit('pause') + } + stream.resume = function () { + if(stream.paused) { + stream.paused = false + } + drain() + //may have become paused again, + //as drain emits 'data'. + if(!stream.paused) + stream.emit('drain') + } + return stream +} + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/package.json new file mode 100644 index 0000000..168247e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/package.json @@ -0,0 +1,34 @@ +{ + "name": "through", + "version": "1.1.0", + "description": "simplified stream contruction", + "main": "index.js", + "scripts": { + "test": "asynct test/*.js" + }, + "devDependencies": { + "stream-spec": "0", + "assertions": "2", + "asynct": "1" + }, + "keywords": [ + "stream", + "streams", + "user-streams", + "pipe" + ], + "author": { + "name": "Dominic Tarr", + "email": "dominic.tarr@gmail.com", + "url": "dominictarr.com" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/dominictarr/through.git" + }, + "homepage": "http://github.com/dominictarr/through", + "readme": "#through\n\n[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through)\n\nEasy way to create a `Stream` that is both `readable` and `writable`. Pass in optional `write` and `end` methods. `through` takes care of pause/resume logic.\nUse `this.pause()` and `this.resume()` to manage flow.\nCheck `this.paused` to see current flow state. (write always returns `!this.paused`)\n\nthis function is the basis for most of the syncronous streams in [event-stream](http://github.com/dominictarr/event-stream).\n\n``` js\nvar through = require('through')\n\nthrough(function write(data) {\n this.emit('data', data)\n //this.pause() \n },\n function end () { //optional\n this.emit('end')\n })\n\n```\n\nor, with buffering on pause, use `this.queue(data)`,\ndata *cannot* be `null`. `this.queue(null)` will emit 'end'\nwhen it gets to the `null` element.\n\n``` js\nvar through = require('through')\n\nthrough(function write(data) {\n this.queue(data)\n //this.pause() \n },\n function end () { //optional\n this.queue(null)\n })\n\n```\n\n\n## License\n\nMIT / Apache2\n", + "_id": "through@1.1.0", + "_from": "through@~1.1.0" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/readme.markdown b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/readme.markdown new file mode 100644 index 0000000..1b687e9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/readme.markdown @@ -0,0 +1,44 @@ +#through + +[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through) + +Easy way to create a `Stream` that is both `readable` and `writable`. Pass in optional `write` and `end` methods. `through` takes care of pause/resume logic. +Use `this.pause()` and `this.resume()` to manage flow. +Check `this.paused` to see current flow state. (write always returns `!this.paused`) + +this function is the basis for most of the syncronous streams in [event-stream](http://github.com/dominictarr/event-stream). + +``` js +var through = require('through') + +through(function write(data) { + this.emit('data', data) + //this.pause() + }, + function end () { //optional + this.emit('end') + }) + +``` + +or, with buffering on pause, use `this.queue(data)`, +data *cannot* be `null`. `this.queue(null)` will emit 'end' +when it gets to the `null` element. + +``` js +var through = require('through') + +through(function write(data) { + this.queue(data) + //this.pause() + }, + function end () { //optional + this.queue(null) + }) + +``` + + +## License + +MIT / Apache2 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/buffering.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/buffering.js new file mode 100644 index 0000000..1ce4b0d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/buffering.js @@ -0,0 +1,37 @@ +var through = require('..') + +// must emit end before close. + +exports['buffering'] = function (t) { + var ts = through(function (data) { + this.queue(data) + }, function () { + this.queue(null) + }) + + var ended = false, actual = [] + + ts.on('data', actual.push.bind(actual)) + ts.on('end', function () { + ended = true + }) + + ts.write(1) + ts.write(2) + ts.write(3) + t.deepEqual(actual, [1, 2, 3]) + ts.pause() + ts.write(4) + ts.write(5) + ts.write(6) + t.deepEqual(actual, [1, 2, 3]) + ts.resume() + t.deepEqual(actual, [1, 2, 3, 4, 5, 6]) + ts.pause() + ts.end() + t.ok(!ended) + ts.resume() + t.ok(ended) + t.end() + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/end.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/end.js new file mode 100644 index 0000000..280da0a --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/end.js @@ -0,0 +1,27 @@ +var through = require('..') + +// must emit end before close. + +exports['end before close'] = function (t) { + var ts = through() + var ended = false, closed = false + + ts.on('end', function () { + t.ok(!closed) + ended = true + }) + ts.on('close', function () { + t.ok(ended) + closed = true + }) + + ts.write(1) + ts.write(2) + ts.write(3) + ts.end() + t.ok(ended) + t.ok(closed) + + t.end() + +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/index.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/index.js new file mode 100644 index 0000000..25a6ea7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/node_modules/through/test/index.js @@ -0,0 +1,113 @@ + +var spec = require('stream-spec') +var through = require('..') +var a = require('assertions') + +/* + I'm using these two functions, and not streams and pipe + so there is less to break. if this test fails it must be + the implementation of _through_ +*/ + +function write(array, stream) { + array = array.slice() + function next() { + while(array.length) + if(stream.write(array.shift()) === false) + return stream.once('drain', next) + + stream.end() + } + + next() +} + +function read(stream, callback) { + var actual = [] + stream.on('data', function (data) { + actual.push(data) + }) + stream.once('end', function () { + callback(null, actual) + }) + stream.once('error', function (err) { + callback(err) + }) +} + +exports['simple defaults'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = through() + spec(t) + .through() + .pausable() + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + + write(expected, t) +} + +exports['simple functions'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l * Math.random()) + + var t = through(function (data) { + this.emit('data', data*2) + }) + spec(t) + .through() + .pausable() + .validateOnExit() + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected.map(function (data) { + return data*2 + })) + test.done() + }) + + write(expected, t) +} +exports['pauses'] = function (test) { + + var l = 1000 + , expected = [] + + while(l--) expected.push(l) //Math.random()) + + var t = through() + spec(t) + .through() + .pausable() + .validateOnExit() + + t.on('data', function () { + if(Math.random() > 0.1) return + t.pause() + process.nextTick(function () { + t.resume() + }) + }) + + read(t, function (err, actual) { + if(err) test.error(err) //fail + a.deepEqual(actual, expected) + test.done() + }) + + write(expected, t) +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/package.json new file mode 100644 index 0000000..8040579 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/package.json @@ -0,0 +1,38 @@ +{ + "name": "tap-stream", + "version": "0.1.0", + "author": { + "name": "Thorsten Lorenz", + "email": "thlorenz@gmx.de", + "url": "http://thlorenz.com" + }, + "description": "Taps a nodejs stream and logs the data that's coming through.", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "tap ./test/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/thlorenz/tap-stream.git" + }, + "keywords": [ + "stream", + "streams", + "log", + "print", + "inspect" + ], + "license": "BSD", + "dependencies": { + "through": "~1.1.0" + }, + "devDependencies": { + "tap": "~0.3.1" + }, + "readme": "# tap-stream [![Build Status](https://secure.travis-ci.org/thlorenz/tap-stream.png)](http://travis-ci.org/thlorenz/tap-stream)\n\nTaps a nodejs stream and logs the data that's coming through.\n\n npm install tap-stream\n\nGiven an [object stream](#object-stream) we can print out objects passing through and control the detail via the\ndepth parameter:\n\n```javascript\nobjectStream().pipe(tap(0));\n```\n\n![depth0](https://github.com/thlorenz/tap-stream/raw/master/assets/depth0.png)\n\n```javascript\nobjectStream().pipe(tap(1));\n```\n\n![depth1](https://github.com/thlorenz/tap-stream/raw/master/assets/depth1.png)\n\n```\nobjectStream().pipe(tap(2));\n```\n\n![depth2](https://github.com/thlorenz/tap-stream/raw/master/assets/depth2.png)\n\nFor even more control a custom log function may be supplied:\n\n```javascript\nobjectStream()\n .pipe(tap(function customLog (data) {\n var nest = data.nest;\n console.log ('Bird: %s, id: %s, age: %s, layed egg: %s', nest.name, data.id, nest.age, nest.egg !== undefined);\n })\n );\n```\n\n```text\nBird: yellow rumped warbler, id: 0, age: 1, layed egg: true\nBird: yellow rumped warbler, id: 1, age: 1, layed egg: true\n```\n\n## API\n\n### tap( [ depth | log ] )\n\nIntercepts the stream and logs data that is passing through.\n\n- optional parameter is either a `Number` or a `Function`\n- if no parameter is given, `depth` defaults to `0` and `log` to `console.log(util.inspect(..))`\n\n- `depth` controls the `depth` with which\n [util.inspect](http://nodejs.org/api/util.html#util_util_inspect_object_showhidden_depth_colors) is called\n- `log` replaces the default logging function with a custom one\n\n**Example:**\n\n```javascript\nvar tap = require('tap-stream');\n\nmyStream\n .pipe(tap(1)) // log intermediate results\n .pipe(..) // continute manipulating the data\n```\n\n## Object stream\n\nIncluded in order to give context for above examples.\n\n```javascript\nfunction objectStream () {\n var s = new Stream()\n , objects = 0;\n \n var iv = setInterval(\n function () {\n s.emit('data', { \n id: objects\n , created: new Date()\n , nest: { \n name: 'yellow rumped warbler'\n , age: 1\n , egg: { name: 'unknown' , age: 0 }\n } \n }\n , 4\n );\n\n if (++objects === 2) {\n s.emit('end');\n clearInterval(iv);\n }\n }\n , 200);\n return s;\n}\n```\n", + "_id": "tap-stream@0.1.0", + "_from": "tap-stream@~0.1.0" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/test/tap-stream.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/test/tap-stream.js new file mode 100644 index 0000000..b484fcb --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/node_modules/tap-stream/test/tap-stream.js @@ -0,0 +1,104 @@ +'use strict'; +/*jshint asi: true */ + +var test = require('tap').test + , Stream = require('stream') + , tap = require('..') + , through = require('through'); + +function objectStream () { + var s = new Stream() + , objects = 0; + + var iv = setInterval( + function () { + s.emit('data', { id: objects, created: new Date() }); + + if (++objects === 2) { + s.emit('end'); + clearInterval(iv); + } + } + , 20); + return s; +} + +test('tapping object stream that emits 2 objects', function (t) { + var logged = [] + , piped = []; + + function log (data) { + logged.push(data); + } + + t.plan(4); + + objectStream() + .pipe(tap(log)) + .pipe(through( + function write (data) { + piped.push(data); + this.emit('data', data); + } + , function end (data) { + + t.equals(0, logged[0].id, 'logs first item'); + t.equals(1, logged[1].id, 'logs second item'); + + t.equals(0, piped[0].id, 'pipes first item'); + t.equals(1, piped[1].id, 'pipes second item'); + + t.end(); + + this.emit('end'); + } + )) +}) + +/* The below doesn't work since pipe only writes one argument: + * https://github.com/joyent/node/blob/master/lib/stream.js#L36 + * + * Since it uses EventEmitter whose 'emit' supports multiple args, this may change in the future - I hope so. + * Until then ... + */ +var onDataInsidePipeWritesMultipleArgs = false; + +if (! onDataInsidePipeWritesMultipleArgs) return; + +function numberStream () { + var s = new Stream(); + + setTimeout( + function () { + s.emit('data', 1, 2); + s.emit('end'); + } + , 20); + return s; +} + +test('tapping stream that emits a number and a string one time', function (t) { + var logged = [] + , piped = []; + + function log (n1, n2) { + logged.push({ n1: n1, n2: n2 }); + } + + t.plan(2); + + numberStream() + .pipe(tap(log)) + .pipe(through( + function write (n1, n2) { + piped.push({ n1: n1, n2: n2 }); + } + , function end () { + t.equals({ n1: 1, n2: 2 }, logged[0], 'logs both numbers'); + t.equals({ n1: 1, n2: 2 }, piped[0], 'pipes both numbers'); + t.end(); + + this.emit('end'); + } + )) +}) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/package.json new file mode 100644 index 0000000..2d9b341 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/package.json @@ -0,0 +1,9 @@ +{ + "name": "readdirp-examples", + "version": "0.0.0", + "description": "Examples for readdirp.", + "dependencies": { + "tap-stream": "~0.1.0", + "event-stream": "~3.0.7" + } +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api-pipe.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api-pipe.js new file mode 100644 index 0000000..b09fe59 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api-pipe.js @@ -0,0 +1,13 @@ +var readdirp = require('..') + , path = require('path') + , es = require('event-stream'); + +// print out all JavaScript files along with their size +readdirp({ root: path.join(__dirname), fileFilter: '*.js' }) + .on('warn', function (err) { console.error('non-fatal error', err); }) + .on('error', function (err) { console.error('fatal error', err); }) + .pipe(es.mapSync(function (entry) { + return { path: entry.path, size: entry.stat.size }; + })) + .pipe(es.stringify()) + .pipe(process.stdout); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api.js new file mode 100644 index 0000000..0f7b327 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/examples/stream-api.js @@ -0,0 +1,15 @@ +var readdirp = require('..') + , path = require('path'); + +readdirp({ root: path.join(__dirname), fileFilter: '*.js' }) + .on('warn', function (err) { + console.error('something went wrong when processing an entry', err); + }) + .on('error', function (err) { + console.error('something went fatally wrong and the stream was aborted', err); + }) + .on('data', function (entry) { + console.log('%s is ready for processing', entry.path); + // process entry here + }); + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/LICENSE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +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/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/README.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/README.md new file mode 100644 index 0000000..6fd07d2 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/README.md @@ -0,0 +1,218 @@ +# minimatch + +A minimal matching utility. + +[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch) + + +This is the matching library used internally by npm. + +Eventually, it will replace the C binding in node-glob. + +It works by converting glob expressions into JavaScript `RegExp` +objects. + +## Usage + +```javascript +var minimatch = require("minimatch") + +minimatch("bar.foo", "*.foo") // true! +minimatch("bar.foo", "*.bar") // false! +``` + +## Features + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` + +### Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between minimatch and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. **Note that this is different from the way that `**` is +handled by ruby's `Dir` class.** + +If an escaped pattern has no matches, and the `nonull` flag is set, +then minimatch.match returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. + + +## Minimatch Class + +Create a minimatch object by instanting the `minimatch.Minimatch` class. + +```javascript +var Minimatch = require("minimatch").Minimatch +var mm = new Minimatch(pattern, options) +``` + +### Properties + +* `pattern` The original pattern the minimatch object represents. +* `options` The options supplied to the constructor. +* `set` A 2-dimensional array of regexp or string expressions. + Each row in the + array corresponds to a brace-expanded pattern. Each item in the row + corresponds to a single path-part. For example, the pattern + `{a,b/c}/d` would expand to a set of patterns like: + + [ [ a, d ] + , [ b, c, d ] ] + + If a portion of the pattern doesn't have any "magic" in it + (that is, it's something like `"foo"` rather than `fo*o?`), then it + will be left as a string rather than converted to a regular + expression. + +* `regexp` Created by the `makeRe` method. A single regular expression + expressing the entire pattern. This is useful in cases where you wish + to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled. +* `negate` True if the pattern is negated. +* `comment` True if the pattern is a comment. +* `empty` True if the pattern is `""`. + +### Methods + +* `makeRe` Generate the `regexp` member if necessary, and return it. + Will return `false` if the pattern is invalid. +* `match(fname)` Return true if the filename matches the pattern, or + false otherwise. +* `matchOne(fileArray, patternArray, partial)` Take a `/`-split + filename, and match it against a single row in the `regExpSet`. This + method is mainly for internal use, but is exposed so that it can be + used by a glob-walker that needs to avoid excessive filesystem calls. + +All other methods are internal, and will be called as necessary. + +## Functions + +The top-level exported function has a `cache` property, which is an LRU +cache set to store 100 items. So, calling these methods repeatedly +with the same pattern and options will use the same Minimatch object, +saving the cost of parsing it multiple times. + +### minimatch(path, pattern, options) + +Main export. Tests a path against the pattern using the options. + +```javascript +var isJS = minimatch(file, "*.js", { matchBase: true }) +``` + +### minimatch.filter(pattern, options) + +Returns a function that tests its +supplied argument, suitable for use with `Array.filter`. Example: + +```javascript +var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true})) +``` + +### minimatch.match(list, pattern, options) + +Match against the list of +files, in the style of fnmatch or glob. If nothing is matched, and +options.nonull is set, then return a list containing the pattern itself. + +```javascript +var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})) +``` + +### minimatch.makeRe(pattern, options) + +Make a regular expression object from the pattern. + +## Options + +All options are `false` by default. + +### debug + +Dump a ton of stuff to stderr. + +### nobrace + +Do not expand `{a,b}` and `{1..3}` brace sets. + +### noglobstar + +Disable `**` matching against multiple folder names. + +### dot + +Allow patterns to match filenames starting with a period, even if +the pattern does not explicitly have a period in that spot. + +Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot` +is set. + +### noext + +Disable "extglob" style patterns like `+(a|b)`. + +### nocase + +Perform a case-insensitive match. + +### nonull + +When a match is not found by `minimatch.match`, return a list containing +the pattern itself. When set, an empty list is returned if there are +no matches. + +### matchBase + +If set, then patterns without slashes will be matched +against the basename of the path if it contains slashes. For example, +`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. + +### nocomment + +Suppress the behavior of treating `#` at the start of a pattern as a +comment. + +### nonegate + +Suppress the behavior of treating a leading `!` character as negation. + +### flipNegate + +Returns from negate expressions the same as if they were not negated. +(Ie, true on a hit, false on a miss.) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/minimatch.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/minimatch.js new file mode 100644 index 0000000..405746b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/minimatch.js @@ -0,0 +1,1079 @@ +;(function (require, exports, module, platform) { + +if (module) module.exports = minimatch +else exports.minimatch = minimatch + +if (!require) { + require = function (id) { + switch (id) { + case "sigmund": return function sigmund (obj) { + return JSON.stringify(obj) + } + case "path": return { basename: function (f) { + f = f.split(/[\/\\]/) + var e = f.pop() + if (!e) e = f.pop() + return e + }} + case "lru-cache": return function LRUCache () { + // not quite an LRU, but still space-limited. + var cache = {} + var cnt = 0 + this.set = function (k, v) { + cnt ++ + if (cnt >= 100) cache = {} + cache[k] = v + } + this.get = function (k) { return cache[k] } + } + } + } +} + +minimatch.Minimatch = Minimatch + +var LRU = require("lru-cache") + , cache = minimatch.cache = new LRU({max: 100}) + , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} + , sigmund = require("sigmund") + +var path = require("path") + // any single thing other than / + // don't need to escape / when using new RegExp() + , qmark = "[^/]" + + // * => any number of characters + , star = qmark + "*?" + + // ** when dots are allowed. Anything goes, except .. and . + // not (^ or / followed by one or two dots followed by $ or /), + // followed by anything, any number of times. + , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" + + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" + + // characters that need to be escaped in RegExp. + , reSpecials = charSet("().*{}+?[]^$\\!") + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split("").reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.monkeyPatch = monkeyPatch +function monkeyPatch () { + var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") + var orig = desc.value + desc.value = function (p) { + if (p instanceof Minimatch) return p.match(this) + return orig.call(this, p) + } + Object.defineProperty(String.prototype, desc) +} + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + return false + } + + // "" only matches "" + if (pattern.trim() === "") return p === "" + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options, cache) + } + + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + pattern = pattern.split("\\").join("/") + } + + // lru storage. + // these things aren't particularly big, but walking down the string + // and turning it into a regexp can get pretty costly. + var cacheKey = pattern + "\n" + sigmund(options) + var cached = minimatch.cache.get(cacheKey) + if (cached) return cached + minimatch.cache.set(cacheKey, this) + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) console.error(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + if (options.debug) console.error(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + if (options.debug) console.error(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + if (options.debug) console.error(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + , negate = false + , options = this.options + , negateOffset = 0 + + if (options.nonegate) return + + for ( var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === "!" + ; i ++) { + negate = !negate + negateOffset ++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return new Minimatch(pattern, options).braceExpand() +} + +Minimatch.prototype.braceExpand = braceExpand +function braceExpand (pattern, options) { + options = options || this.options + pattern = typeof pattern === "undefined" + ? this.pattern : pattern + + if (typeof pattern === "undefined") { + throw new Error("undefined pattern") + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + var escaping = false + + // examples and comments refer to this crazy pattern: + // a{b,c{d,e},{f,g}h}x{y,z} + // expected: + // abxy + // abxz + // acdxy + // acdxz + // acexy + // acexz + // afhxy + // afhxz + // aghxy + // aghxz + + // everything before the first \{ is just a prefix. + // So, we pluck that off, and work with the rest, + // and then prepend it to everything we find. + if (pattern.charAt(0) !== "{") { + // console.error(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error(i, c) + if (c === "\\") { + escaping = !escaping + } else if (c === "{" && !escaping) { + prefix = pattern.substr(0, i) + break + } + } + + // actually no sets, all { were escaped. + if (prefix === null) { + // console.error("no sets") + return [pattern] + } + + var tail = braceExpand(pattern.substr(i), options) + return tail.map(function (t) { + return prefix + t + }) + } + + // now we have something like: + // {b,c{d,e},{f,g}h}x{y,z} + // walk through the set, expanding each part, until + // the set ends. then, we'll expand the suffix. + // If the set only has a single member, then'll put the {} back + + // first, handle numeric sets, since they're easier + var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) + if (numset) { + // console.error("numset", numset[1], numset[2]) + var suf = braceExpand(pattern.substr(numset[0].length), options) + , start = +numset[1] + , end = +numset[2] + , inc = start > end ? -1 : 1 + , set = [] + for (var i = start; i != (end + inc); i += inc) { + // append all the suffixes + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + set.push(i + suf[ii]) + } + } + return set + } + + // ok, walk through the set + // We hope, somewhat optimistically, that there + // will be a } at the end. + // If the closing brace isn't found, then the pattern is + // interpreted as braceExpand("\\" + pattern) so that + // the leading \{ will be interpreted literally. + var i = 1 // skip the \{ + , depth = 1 + , set = [] + , member = "" + , sawEnd = false + , escaping = false + + function addMember () { + set.push(member) + member = "" + } + + // console.error("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + // console.error("", i, c) + + if (escaping) { + escaping = false + member += "\\" + c + } else { + switch (c) { + case "\\": + escaping = true + continue + + case "{": + depth ++ + member += "{" + continue + + case "}": + depth -- + // if this closes the actual set, then we're done + if (depth === 0) { + addMember() + // pluck off the close-brace + i ++ + break FOR + } else { + member += c + continue + } + + case ",": + if (depth === 1) { + addMember() + } else { + member += c + } + continue + + default: + member += c + continue + } // switch + } // else + } // for + + // now we've either finished the set, and the suffix is + // pattern.substr(i), or we have *not* closed the set, + // and need to escape the leading brace + if (depth !== 0) { + // console.error("didn't close", pattern) + return braceExpand("\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + // console.error("set", set) + // console.error("suffix", pattern.substr(i)) + var suf = braceExpand(pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + // console.error("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand(p, options) + }) + // console.error("set expanded", set) + + + // [["b"], ["cd", "ce"], ["fh", "gh"]] -> + // ["b", "cd", "ce", "fh", "gh"] + set = set.reduce(function (l, r) { + return l.concat(r) + }) + + if (addBraces) { + set = set.map(function (s) { + return "{" + s + "}" + }) + } + + // now attach the suffixes. + var ret = [] + for (var i = 0, l = set.length; i < l; i ++) { + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + ret.push(set[i] + suf[ii]) + } + } + return ret +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === "**") return GLOBSTAR + if (pattern === "") return "" + + var re = "" + , hasMagic = !!options.nocase + , escaping = false + // ? => one single character + , patternListStack = [] + , plType + , stateChar + , inClass = false + , reClassStart = -1 + , classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + , patternStart = pattern.charAt(0) === "." ? "" // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" + : "(?!\\.)" + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += star + hasMagic = true + break + case "?": + re += qmark + hasMagic = true + break + default: + re += "\\"+stateChar + break + } + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + if (options.debug) { + console.error("%s\t%s %s %j", pattern, i, re, c) + } + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += "\\" + c + escaping = false + continue + } + + SWITCH: switch (c) { + case "/": + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case "\\": + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case "?": + case "*": + case "+": + case "@": + case "!": + if (options.debug) { + console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + } + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + if (c === "!" && i === classStart + 1) c = "^" + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case "(": + if (inClass) { + re += "(" + continue + } + + if (!stateChar) { + re += "\\(" + continue + } + + plType = stateChar + patternListStack.push({ type: plType + , start: i - 1 + , reStart: re.length }) + // negation is (?:(?!js)[^/]*) + re += stateChar === "!" ? "(?:(?!" : "(?:" + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + switch (plType) { + case "!": + re += "[^/]*?)" + break + case "?": + case "+": + case "*": re += plType + case "@": break // the default anyway + } + continue + + case "|": + if (inClass || !patternListStack.length || escaping) { + re += "\\|" + escaping = false + continue + } + + re += "|" + continue + + // these are mostly the same in regexp and glob + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += "\\" + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case "]": + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += "\\" + c + escaping = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === "^" && inClass)) { + re += "\\" + } + + re += c + + } // switch + } // for + + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + var cs = pattern.substr(classStart + 1) + , sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + "\\[" + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + var pl + while (pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + 3) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = "\\" + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + "|" + }) + + // console.error("tail=%j\n %s", tail, tail) + var t = pl.type === "*" ? star + : pl.type === "?" ? qmark + : "\\" + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + + t + "\\(" + + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += "\\\\" + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case ".": + case "[": + case "(": addPatternStart = true + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== "" && hasMagic) re = "(?=.)" + re + + if (addPatternStart) re = patternStart + re + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [ re, hasMagic ] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? "i" : "" + , regExp = new RegExp("^" + re + "$", flags) + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) return this.regexp = false + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + , flags = options.nocase ? "i" : "" + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === "string") ? regExpEscape(p) + : p._src + }).join("\\\/") + }).join("|") + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^(?:" + re + ")$" + + // can match anything, as long as it's not this. + if (this.negate) re = "^(?!" + re + ").*$" + + try { + return this.regexp = new RegExp(re, flags) + } catch (ex) { + return this.regexp = false + } +} + +minimatch.match = function (list, pattern, options) { + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + // console.error("match", f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === "" + + if (f === "/" && partial) return true + + var options = this.options + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + f = f.split("\\").join("/") + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + if (options.debug) { + console.error(this.pattern, "split", f) + } + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + // console.error(this.pattern, "set", set) + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i] + var hit = this.matchOne(f, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + if (options.debug) { + console.error("matchOne", + { "this": this + , file: file + , pattern: pattern }) + } + + if (options.matchBase && pattern.length === 1) { + file = path.basename(file.join("/")).split("/") + } + + if (options.debug) { + console.error("matchOne", file.length, pattern.length) + } + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + if (options.debug) { + console.error("matchOne loop") + } + var p = pattern[pi] + , f = file[fi] + + if (options.debug) { + console.error(pattern, p, f) + } + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + if (options.debug) + console.error('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + , pr = pi + 1 + if (pr === pl) { + if (options.debug) + console.error('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for ( ; fi < fl; fi ++) { + if (file[fi] === "." || file[fi] === ".." || + (!options.dot && file[fi].charAt(0) === ".")) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + WHILE: while (fr < fl) { + var swallowee = file[fr] + + if (options.debug) { + console.error('\nglobstar while', + file, fr, pattern, pr, swallowee) + } + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + if (options.debug) + console.error('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === "." || swallowee === ".." || + (!options.dot && swallowee.charAt(0) === ".")) { + if (options.debug) + console.error("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + if (options.debug) + console.error('globstar swallow a segment, and continue') + fr ++ + } + } + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + // console.error("\n>>> no match, partial?", file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === "string") { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + if (options.debug) { + console.error("string match", p, f, hit) + } + } else { + hit = f.match(p) + if (options.debug) { + console.error("pattern match", p, f, hit) + } + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") + return emptyFileEnd + } + + // should be unreachable. + throw new Error("wtf?") +} + + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, "$1") +} + + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} + +})( typeof require === "function" ? require : null, + this, + typeof module === "object" ? module : null, + typeof process === "object" ? process.platform : "win32" + ) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/.npmignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/AUTHORS b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/AUTHORS new file mode 100644 index 0000000..016d7fb --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/AUTHORS @@ -0,0 +1,8 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Carlos Brito Lage +Marko Mikulicic +Trent Mick +Kevin O'Hara +Marco Rogers +Jesse Dailey diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/LICENSE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +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/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/README.md new file mode 100644 index 0000000..03ee0f9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,97 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `n` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. + +* `peek(key)` + + Returns the key value (or `undefined` if not found) without + updating the "recently used"-ness of the key. + + (If you find yourself using this a lot, you *might* be using the + wrong sort of data structure, but there are some use cases where + it's handy.) + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 0000000..8c80853 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,257 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) { + return new LRUCache(options) + } + + var max + if (typeof options === 'number') { + max = options + options = { max: max } + } + + if (!options) options = {} + + max = options.max + + var lengthCalculator = options.length || naiveLength + + if (typeof lengthCalculator !== "function") { + lengthCalculator = naiveLength + } + + if (!max || !(typeof max === "number") || max <= 0 ) { + // a little bit silly. maybe this should throw? + max = Infinity + } + + var allowStale = options.stale || false + + var maxAge = options.maxAge || null + + var dispose = options.dispose + + var cache = Object.create(null) // hash of items by key + , lruList = Object.create(null) // list of items in order of use recency + , mru = 0 // most recently used + , lru = 0 // least recently used + , length = 0 // number of items in the list + , itemCount = 0 + + + // resize the cache when the max changes. + Object.defineProperty(this, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + max = mL + // if it gets above double max, trim right away. + // otherwise, do it whenever it's convenient. + if (length > max) trim() + } + , get : function () { return max } + , enumerable : true + }) + + // resize the cache when the lengthCalculator changes. + Object.defineProperty(this, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + lengthCalculator = naiveLength + length = itemCount + for (var key in cache) { + cache[key].length = 1 + } + } else { + lengthCalculator = lC + length = 0 + for (var key in cache) { + cache[key].length = lengthCalculator(cache[key].value) + length += cache[key].length + } + } + + if (length > max) trim() + } + , get : function () { return lengthCalculator } + , enumerable : true + }) + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + + Object.defineProperty(this, "itemCount", + { get : function () { return itemCount } + , enumerable : true + }) + + this.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + i++ + var hit = lruList[k] + fn.call(thisp, hit.value, hit.key, this) + } + } + + this.keys = function () { + var keys = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + keys[i++] = hit.key + } + return keys + } + + this.values = function () { + var values = new Array(itemCount) + var i = 0 + for (var k = mru - 1; k >= 0 && i < itemCount; k--) if (lruList[k]) { + var hit = lruList[k] + values[i++] = hit.value + } + return values + } + + this.reset = function () { + if (dispose) { + for (var k in cache) { + dispose(k, cache[k].value) + } + } + cache = {} + lruList = {} + lru = 0 + mru = 0 + length = 0 + itemCount = 0 + } + + // Provided for debugging/dev purposes only. No promises whatsoever that + // this API stays stable. + this.dump = function () { + return cache + } + + this.dumpLru = function () { + return lruList + } + + this.set = function (key, value) { + if (hOP(cache, key)) { + // dispose of the old one before overwriting + if (dispose) dispose(key, cache[key].value) + if (maxAge) cache[key].now = Date.now() + cache[key].value = value + this.get(key) + return true + } + + var len = lengthCalculator(value) + var age = maxAge ? Date.now() : 0 + var hit = new Entry(key, value, mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > max) { + if (dispose) dispose(key, value) + return false + } + + length += hit.length + lruList[hit.lu] = cache[key] = hit + itemCount ++ + + if (length > max) trim() + return true + } + + this.has = function (key) { + if (!hOP(cache, key)) return false + var hit = cache[key] + if (maxAge && (Date.now() - hit.now > maxAge)) { + return false + } + return true + } + + this.get = function (key) { + return get(key, true) + } + + this.peek = function (key) { + return get(key, false) + } + + function get (key, doUse) { + var hit = cache[key] + if (hit) { + if (maxAge && (Date.now() - hit.now > maxAge)) { + del(hit) + if (!allowStale) hit = undefined + } else { + if (doUse) use(hit) + } + if (hit) hit = hit.value + } + return hit + } + + function use (hit) { + shiftLU(hit) + hit.lu = mru ++ + lruList[hit.lu] = hit + } + + this.del = function (key) { + del(cache[key]) + } + + function trim () { + while (lru < mru && length > max) + del(lruList[lru]) + } + + function shiftLU(hit) { + delete lruList[ hit.lu ] + while (lru < mru && !lruList[lru]) lru ++ + } + + function del(hit) { + if (hit) { + if (dispose) dispose(hit.key, hit.value) + length -= hit.length + itemCount -- + delete cache[ hit.key ] + shiftLU(hit) + } + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, mru, len, age) { + this.key = key + this.value = value + this.lu = mru + this.length = len + this.now = age +} + +})() diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/package.json new file mode 100644 index 0000000..f12aee9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,63 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.3.0", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test --gc" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "", + "weak": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + { + "name": "Carlos Brito Lage", + "email": "carlos@carloslage.net" + }, + { + "name": "Marko Mikulicic", + "email": "marko.mikulicic@isti.cnr.it" + }, + { + "name": "Trent Mick", + "email": "trentm@gmail.com" + }, + { + "name": "Kevin O'Hara", + "email": "kevinohara80@gmail.com" + }, + { + "name": "Marco Rogers", + "email": "marco.rogers@gmail.com" + }, + { + "name": "Jesse Dailey", + "email": "jesse.dailey@gmail.com" + } + ], + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n function to all values in the cache. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n stale items out of the cache when you `get(key)`. (That is, it's\n not pre-emptively doing a `setTimeout` or anything.) If you set\n `stale:true`, it'll return the stale value before deleting it. If\n you don't set this, then it'll return `undefined` when you try to\n get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n Both of these will update the \"recently used\"-ness of the key.\n They do what you think.\n\n* `peek(key)`\n\n Returns the key value (or `undefined` if not found) without\n updating the \"recently used\"-ness of the key.\n\n (If you find yourself using this a lot, you *might* be using the\n wrong sort of data structure, but there are some use cases where\n it's handy.)\n\n* `del(key)`\n\n Deletes a key out of the cache.\n\n* `reset()`\n\n Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n Check if a key is in the cache, without updating the recent-ness\n or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n Just like `Array.prototype.forEach`. Iterates over all the keys\n in the cache, in order of recent-ness. (Ie, more recently used\n items are iterated over first.)\n\n* `keys()`\n\n Return an array of the keys in the cache.\n\n* `values()`\n\n Return an array of the values in the cache.\n", + "readmeFilename": "README.md", + "_id": "lru-cache@2.3.0", + "dist": { + "shasum": "1b5ea224e7c6d0ce453a7d526fa70f9a4a3893ad" + }, + "_from": "lru-cache@2", + "_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.3.0.tgz" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/s.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/s.js new file mode 100644 index 0000000..c2a9e54 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/s.js @@ -0,0 +1,25 @@ +var LRU = require('lru-cache'); + +var max = +process.argv[2] || 10240; +var more = 1024; + +var cache = LRU({ + max: max, maxAge: 86400e3 +}); + +// fill cache +for (var i = 0; i < max; ++i) { + cache.set(i, {}); +} + +var start = process.hrtime(); + +// adding more items +for ( ; i < max+more; ++i) { + cache.set(i, {}); +} + +var end = process.hrtime(start); +var msecs = end[0] * 1E3 + end[1] / 1E6; + +console.log('adding %d items took %d ms', more, msecs.toPrecision(5)); diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/basic.js new file mode 100644 index 0000000..70f3f8b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,329 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +// Note: `.dump()` is a debugging tool only. No guarantees are made +// about the format/layout of the response. +test("dump", function (t) { + var cache = new LRU(10) + var d = cache.dump(); + t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache") + cache.set("a", "A") + var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } } + t.ok(d.a) + t.equal(d.a.key, "a") + t.equal(d.a.value, "A") + t.equal(d.a.lu, 0) + + cache.set("b", "B") + cache.get("b") + d = cache.dump() + t.ok(d.b) + t.equal(d.b.key, "b") + t.equal(d.b.value, "B") + t.equal(d.b.lu, 2) + + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) + +test("least recently set w/ peek", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + t.equal(cache.peek("a"), "A") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/foreach.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/foreach.js new file mode 100644 index 0000000..eefb80d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,52 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 0000000..7af45b0 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node --expose_gc + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/LICENSE b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/LICENSE new file mode 100644 index 0000000..0c44ae7 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/README.md b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/README.md new file mode 100644 index 0000000..7e36512 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/README.md @@ -0,0 +1,53 @@ +# sigmund + +Quick and dirty signatures for Objects. + +This is like a much faster `deepEquals` comparison, which returns a +string key suitable for caches and the like. + +## Usage + +```javascript +function doSomething (someObj) { + var key = sigmund(someObj, maxDepth) // max depth defaults to 10 + var cached = cache.get(key) + if (cached) return cached) + + var result = expensiveCalculation(someObj) + cache.set(key, result) + return result +} +``` + +The resulting key will be as unique and reproducible as calling +`JSON.stringify` or `util.inspect` on the object, but is much faster. +In order to achieve this speed, some differences are glossed over. +For example, the object `{0:'foo'}` will be treated identically to the +array `['foo']`. + +Also, just as there is no way to summon the soul from the scribblings +of a cocain-addled psychoanalyst, there is no way to revive the object +from the signature string that sigmund gives you. In fact, it's +barely even readable. + +As with `sys.inspect` and `JSON.stringify`, larger objects will +produce larger signature strings. + +Because sigmund is a bit less strict than the more thorough +alternatives, the strings will be shorter, and also there is a +slightly higher chance for collisions. For example, these objects +have the same signature: + + var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} + var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +Like a good Freudian, sigmund is most effective when you already have +some understanding of what you're looking for. It can help you help +yourself, but you must be willing to do some work as well. + +Cycles are handled, and cyclical objects are silently omitted (though +the key is included in the signature output.) + +The second argument is the maximum depth, which defaults to 10, +because that is the maximum object traversal depth covered by most +insurance carriers. diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/bench.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/bench.js new file mode 100644 index 0000000..5acfd6d --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/bench.js @@ -0,0 +1,283 @@ +// different ways to id objects +// use a req/res pair, since it's crazy deep and cyclical + +// sparseFE10 and sigmund are usually pretty close, which is to be expected, +// since they are essentially the same algorithm, except that sigmund handles +// regular expression objects properly. + + +var http = require('http') +var util = require('util') +var sigmund = require('./sigmund.js') +var sreq, sres, creq, cres, test + +http.createServer(function (q, s) { + sreq = q + sres = s + sres.end('ok') + this.close(function () { setTimeout(function () { + start() + }, 200) }) +}).listen(1337, function () { + creq = http.get({ port: 1337 }) + creq.on('response', function (s) { cres = s }) +}) + +function start () { + test = [sreq, sres, creq, cres] + // test = sreq + // sreq.sres = sres + // sreq.creq = creq + // sreq.cres = cres + + for (var i in exports.compare) { + console.log(i) + var hash = exports.compare[i]() + console.log(hash) + console.log(hash.length) + console.log('') + } + + require('bench').runMain() +} + +function customWs (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '') + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return customWs(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + customWs(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function custom (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return '' + obj + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return custom(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + custom(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function sparseFE2 (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ':' + ch(v[k], depth + 1) + }) + soFar += '}' + } + ch(obj, 0) + return soFar +} + +function sparseFE (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ch(v[k], depth + 1) + }) + } + ch(obj, 0) + return soFar +} + +function sparse (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ch(v[k], depth + 1) + } + } + ch(obj, 0) + return soFar +} + +function noCommas (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + + +function flatten (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + soFar += ',' + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + +exports.compare = +{ + // 'custom 2': function () { + // return custom(test, 2, 0) + // }, + // 'customWs 2': function () { + // return customWs(test, 2, 0) + // }, + 'JSON.stringify (guarded)': function () { + var seen = [] + return JSON.stringify(test, function (k, v) { + if (typeof v !== 'object' || !v) return v + if (seen.indexOf(v) !== -1) return undefined + seen.push(v) + return v + }) + }, + + 'flatten 10': function () { + return flatten(test, 10) + }, + + // 'flattenFE 10': function () { + // return flattenFE(test, 10) + // }, + + 'noCommas 10': function () { + return noCommas(test, 10) + }, + + 'sparse 10': function () { + return sparse(test, 10) + }, + + 'sparseFE 10': function () { + return sparseFE(test, 10) + }, + + 'sparseFE2 10': function () { + return sparseFE2(test, 10) + }, + + sigmund: function() { + return sigmund(test, 10) + }, + + + // 'util.inspect 1': function () { + // return util.inspect(test, false, 1, false) + // }, + // 'util.inspect undefined': function () { + // util.inspect(test) + // }, + // 'util.inspect 2': function () { + // util.inspect(test, false, 2, false) + // }, + // 'util.inspect 3': function () { + // util.inspect(test, false, 3, false) + // }, + // 'util.inspect 4': function () { + // util.inspect(test, false, 4, false) + // }, + // 'util.inspect Infinity': function () { + // util.inspect(test, false, Infinity, false) + // } +} + +/** results +**/ diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/package.json new file mode 100644 index 0000000..5614875 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/package.json @@ -0,0 +1,42 @@ +{ + "name": "sigmund", + "version": "1.0.0", + "description": "Quick and dirty signatures for Objects.", + "main": "sigmund.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.0" + }, + "scripts": { + "test": "tap test/*.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/sigmund" + }, + "keywords": [ + "object", + "signature", + "key", + "data", + "psychoanalysis" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "BSD", + "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n var cached = cache.get(key)\n if (cached) return cached)\n\n var result = expensiveCalculation(someObj)\n cache.set(key, result)\n return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you. In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions. For example, these objects\nhave the same signature:\n\n var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for. It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n", + "readmeFilename": "README.md", + "_id": "sigmund@1.0.0", + "dist": { + "shasum": "d3dd953d93df935605c3af852b0fe182bb64327b" + }, + "_from": "sigmund@~1.0.0", + "_resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/sigmund.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/sigmund.js new file mode 100644 index 0000000..82c7ab8 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/sigmund.js @@ -0,0 +1,39 @@ +module.exports = sigmund +function sigmund (subject, maxSessions) { + maxSessions = maxSessions || 10; + var notes = []; + var analysis = ''; + var RE = RegExp; + + function psychoAnalyze (subject, session) { + if (session > maxSessions) return; + + if (typeof subject === 'function' || + typeof subject === 'undefined') { + return; + } + + if (typeof subject !== 'object' || !subject || + (subject instanceof RE)) { + analysis += subject; + return; + } + + if (notes.indexOf(subject) !== -1 || session === maxSessions) return; + + notes.push(subject); + analysis += '{'; + Object.keys(subject).forEach(function (issue, _, __) { + // pseudo-private values. skip those. + if (issue.charAt(0) === '_') return; + var to = typeof subject[issue]; + if (to === 'function' || to === 'undefined') return; + analysis += issue; + psychoAnalyze(subject[issue], session + 1); + }); + } + psychoAnalyze(subject, 0); + return analysis; +} + +// vim: set softtabstop=4 shiftwidth=4: diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/test/basic.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/test/basic.js new file mode 100644 index 0000000..50c53a1 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/node_modules/sigmund/test/basic.js @@ -0,0 +1,24 @@ +var test = require('tap').test +var sigmund = require('../sigmund.js') + + +// occasionally there are duplicates +// that's an acceptable edge-case. JSON.stringify and util.inspect +// have some collision potential as well, though less, and collision +// detection is expensive. +var hash = '{abc/def/g{0h1i2{jkl' +var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} +var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +var obj3 = JSON.parse(JSON.stringify(obj1)) +obj3.c = /def/ +obj3.g[2].cycle = obj3 +var cycleHash = '{abc/def/g{0h1i2{jklcycle' + +test('basic', function (t) { + t.equal(sigmund(obj1), hash) + t.equal(sigmund(obj2), hash) + t.equal(sigmund(obj3), cycleHash) + t.end() +}) + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/package.json new file mode 100644 index 0000000..656b282 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/package.json @@ -0,0 +1,40 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "minimatch", + "description": "a glob matcher in javascript", + "version": "0.2.12", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "devDependencies": { + "tap": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE" + }, + "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n### Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not. **Note that this is different from the way that `**` is\nhandled by ruby's `Dir` class.**\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n Each row in the\n array corresponds to a brace-expanded pattern. Each item in the row\n corresponds to a single path-part. For example, the pattern\n `{a,b/c}/d` would expand to a set of patterns like:\n\n [ [ a, d ]\n , [ b, c, d ] ]\n\n If a portion of the pattern doesn't have any \"magic\" in it\n (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n will be left as a string rather than converted to a regular\n expression.\n\n* `regexp` Created by the `makeRe` method. A single regular expression\n expressing the entire pattern. This is useful in cases where you wish\n to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n filename, and match it against a single row in the `regExpSet`. This\n method is mainly for internal use, but is exposed so that it can be\n used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items. So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export. Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`. Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob. If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself. When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes. For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n", + "readmeFilename": "README.md", + "_id": "minimatch@0.2.12", + "dist": { + "shasum": "64842e667f65b9277a924d298c816444030da2dc" + }, + "_from": "minimatch@>=0.2.4", + "_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/basic.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/basic.js new file mode 100644 index 0000000..ae7ac73 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/basic.js @@ -0,0 +1,399 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + + +var patterns = + [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + // https://github.com/isaacs/minimatch/issues/5 + , function () { + files = [ 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' + , 'a/b/.x' + , 'a/b/.x/' + , 'a/.x/b' + , '.x' + , '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b/.x/c' + , '.x/.x' ] + } + , ["**/.x/**", [ '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b' + , 'a/b/.x/' + , 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' ] ] + + ] + +var regexps = + [ '/^(?:(?=.)a[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:\\*)$/', + '/^(?:(?=.)\\*[^/]*?)$/', + '/^(?:\\*\\*)$/', + '/^(?:(?=.)b[^/]*?\\/)$/', + '/^(?:(?=.)c[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/', + '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/', + '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/', + '/^(?:(?=.)a[^/]*?[^c])$/', + '/^(?:(?=.)a[X-]b)$/', + '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/', + '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[^/]c)$/', + '/^(?:a\\*c)$/', + 'false', + '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/', + '/^(?:man\\/man1\\/bash\\.1)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[-abc])$/', + '/^(?:(?!\\.)(?=.)[abc-])$/', + '/^(?:\\\\)$/', + '/^(?:(?!\\.)(?=.)[\\\\])$/', + '/^(?:(?!\\.)(?=.)[\\[])$/', + '/^(?:\\[)$/', + '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[\\]])$/', + '/^(?:(?!\\.)(?=.)[\\]-])$/', + '/^(?:(?!\\.)(?=.)[a-z])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:\\[\\])$/', + '/^(?:\\[abc)$/', + '/^(?:(?=.)XYZ)$/i', + '/^(?:(?=.)ab[^/]*?)$/i', + '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i', + '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/', + '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/', + '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/', + '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/', + '/^(?:(?=.)a[^/]b)$/', + '/^(?:(?=.)#[^/]*?)$/', + '/^(?!^(?:(?=.)a[^/]*?)$).*$/', + '/^(?:(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)a[^/]*?)$/', + '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ] +var re = 0; + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + patterns.forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var m = new mm.Minimatch(pattern, options) + var r = m.makeRe() + var expectRe = regexps[re++] + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + + t.equal(tapOpts.re, expectRe, tapOpts) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/brace-expand.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/brace-expand.js new file mode 100644 index 0000000..7ee278a --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/brace-expand.js @@ -0,0 +1,33 @@ +var tap = require("tap") + , minimatch = require("../") + +tap.test("brace expansion", function (t) { + // [ pattern, [expanded] ] + ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}" + , [ "abxy" + , "abxz" + , "acdxy" + , "acdxz" + , "acexy" + , "acexz" + , "afhxy" + , "afhxz" + , "aghxy" + , "aghxz" ] ] + , [ "a{1..5}b" + , [ "a1b" + , "a2b" + , "a3b" + , "a4b" + , "a5b" ] ] + , [ "a{b}c", ["a{b}c"] ] + ].forEach(function (tc) { + var p = tc[0] + , expect = tc[1] + t.equivalent(minimatch.braceExpand(p), expect, p) + }) + console.error("ending") + t.end() +}) + + diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/caching.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/caching.js new file mode 100644 index 0000000..0fec4b0 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/caching.js @@ -0,0 +1,14 @@ +var Minimatch = require("../minimatch.js").Minimatch +var tap = require("tap") +tap.test("cache test", function (t) { + var mm1 = new Minimatch("a?b") + var mm2 = new Minimatch("a?b") + t.equal(mm1, mm2, "should get the same object") + // the lru should drop it after 100 entries + for (var i = 0; i < 100; i ++) { + new Minimatch("a"+i) + } + mm2 = new Minimatch("a?b") + t.notEqual(mm1, mm2, "cache should have dropped") + t.end() +}) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/defaults.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/defaults.js new file mode 100644 index 0000000..25f1f60 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/node_modules/minimatch/test/defaults.js @@ -0,0 +1,274 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + ; [ "http://www.bashcookbook.com/bashinfo" + + "/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + ].forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var Class = mm.defaults(options).Minimatch + var m = new Class(pattern, {}) + var r = m.makeRe() + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/package.json b/node_modules/jade/node_modules/monocle/node_modules/readdirp/package.json new file mode 100644 index 0000000..c2aa07e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/package.json @@ -0,0 +1,50 @@ +{ + "author": { + "name": "Thorsten Lorenz", + "email": "thlorenz@gmx.de", + "url": "thlorenz.com" + }, + "name": "readdirp", + "description": "Recursive version of fs.readdir with streaming api.", + "version": "0.2.5", + "homepage": "https://github.com/thlorenz/readdirp", + "repository": { + "type": "git", + "url": "git://github.com/thlorenz/readdirp.git" + }, + "engines": { + "node": ">=0.4" + }, + "keywords": [ + "recursive", + "fs", + "stream", + "streams", + "readdir", + "filesystem", + "find", + "filter" + ], + "main": "readdirp.js", + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "minimatch": ">=0.2.4" + }, + "devDependencies": { + "tap": "~0.3.1", + "through": "~1.1.0", + "minimatch": "~0.2.7" + }, + "optionalDependencies": {}, + "license": "MIT", + "readme": "# readdirp [![Build Status](https://secure.travis-ci.org/thlorenz/readdirp.png)](http://travis-ci.org/thlorenz/readdirp)\n\nRecursive version of [fs.readdir](http://nodejs.org/docs/latest/api/fs.html#fs_fs_readdir_path_callback). Exposes a **stream api**.\n\n```javascript\nvar readdirp = require('readdirp'); \n , path = require('path')\n , es = require('event-stream');\n\n// print out all JavaScript files along with their size\n\nvar stream = readdirp({ root: path.join(__dirname), fileFilter: '*.js' });\nstream\n .on('warn', function (err) { \n console.error('non-fatal error', err); \n // optionally call stream.destroy() here in order to abort and cause 'close' to be emitted\n })\n .on('error', function (err) { console.error('fatal error', err); })\n .pipe(es.mapSync(function (entry) { \n return { path: entry.path, size: entry.stat.size };\n }))\n .pipe(es.stringify())\n .pipe(process.stdout);\n```\n\nMeant to be one of the recursive versions of [fs](http://nodejs.org/docs/latest/api/fs.html) functions, e.g., like [mkdirp](https://github.com/substack/node-mkdirp).\n\n**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*\n\n- [Installation](#installation)\n- [API](#api)\n\t- [entry stream](#entry-stream)\n\t- [options](#options)\n\t- [entry info](#entry-info)\n\t- [Filters](#filters)\n\t- [Callback API](#callback-api)\n\t\t- [allProcessed ](#allprocessed)\n\t\t- [fileProcessed](#fileprocessed)\n- [More Examples](#more-examples)\n\t- [stream api](#stream-api)\n\t- [stream api pipe](#stream-api-pipe)\n\t- [grep](#grep)\n\t- [using callback api](#using-callback-api)\n\t- [tests](#tests)\n\n\n# Installation\n\n npm install readdirp\n\n# API\n\n***var entryStream = readdirp (options)***\n\nReads given root recursively and returns a `stream` of [entry info](#entry-info)s.\n\n## entry stream\n\nBehaves as follows:\n \n- `emit('data')` passes an [entry info](#entry-info) whenever one is found\n- `emit('warn')` passes a non-fatal `Error` that prevents a file/directory from being processed (i.e., if it is\n inaccessible to the user)\n- `emit('error')` passes a fatal `Error` which also ends the stream (i.e., when illegal options where passed)\n- `emit('end')` called when all entries were found and no more will be emitted (i.e., we are done)\n- `emit('close')` called when the stream is destroyed via `stream.destroy()` (which could be useful if you want to\n manually abort even on a non fatal error) - at that point the stream is no longer `readable` and no more entries,\n warning or errors are emitted\n- the stream is `paused` initially in order to allow `pipe` and `on` handlers be connected before data or errors are\n emitted\n- the stream is `resumed` automatically during the next event loop \n- to learn more about streams, consult the [stream-handbook](https://github.com/substack/stream-handbook)\n\n## options\n \n- **root**: path in which to start reading and recursing into subdirectories\n\n- **fileFilter**: filter to include/exclude files found (see [Filters](#filters) for more)\n\n- **directoryFilter**: filter to include/exclude directories found and to recurse into (see [Filters](#filters) for more)\n\n- **depth**: depth at which to stop recursing even if more subdirectories are found\n\n## entry info\n\nHas the following properties:\n\n- **parentDir** : directory in which entry was found (relative to given root)\n- **fullParentDir** : full path to parent directory\n- **name** : name of the file/directory\n- **path** : path to the file/directory (relative to given root)\n- **fullPath** : full path to the file/directory found\n- **stat** : built in [stat object](http://nodejs.org/docs/v0.4.9/api/fs.html#fs.Stats)\n- **Example**: (assuming root was `/User/dev/readdirp`)\n \n parentDir : 'test/bed/root_dir1',\n fullParentDir : '/User/dev/readdirp/test/bed/root_dir1',\n name : 'root_dir1_subdir1',\n path : 'test/bed/root_dir1/root_dir1_subdir1',\n fullPath : '/User/dev/readdirp/test/bed/root_dir1/root_dir1_subdir1',\n stat : [ ... ]\n \n## Filters\n \nThere are three different ways to specify filters for files and directories respectively. \n\n- **function**: a function that takes an entry info as a parameter and returns true to include or false to exclude the entry\n\n- **glob string**: a string (e.g., `*.js`) which is matched using [minimatch](https://github.com/isaacs/minimatch), so go there for more\n information. \n\n Globstars (`**`) are not supported since specifiying a recursive pattern for an already recursive function doesn't make sense.\n\n Negated globs (as explained in the minimatch documentation) are allowed, e.g., `!*.txt` matches everything but text files.\n\n- **array of glob strings**: either need to be all inclusive or all exclusive (negated) patterns otherwise an error is thrown.\n \n `[ '*.json', '*.js' ]` includes all JavaScript and Json files.\n \n \n `[ '!.git', '!node_modules' ]` includes all directories except the '.git' and 'node_modules'.\n\nDirectories that do not pass a filter will not be recursed into.\n\n## Callback API\n\nAlthough the stream api is recommended, readdirp also exposes a callback based api.\n\n***readdirp (options, callback1 [, callback2])***\n\nIf callback2 is given, callback1 functions as the **fileProcessed** callback, and callback2 as the **allProcessed** callback.\n\nIf only callback1 is given, it functions as the **allProcessed** callback.\n\n### allProcessed \n\n- function with err and res parameters, e.g., `function (err, res) { ... }`\n- **err**: array of errors that occurred during the operation, **res may still be present, even if errors occurred**\n- **res**: collection of file/directory [entry infos](#entry-info)\n\n### fileProcessed\n\n- function with [entry info](#entry-info) parameter e.g., `function (entryInfo) { ... }`\n\n\n# More Examples\n\n`on('error', ..)`, `on('warn', ..)` and `on('end', ..)` handling omitted for brevity\n\n```javascript\nvar readdirp = require('readdirp');\n\n// Glob file filter\nreaddirp({ root: './test/bed', fileFilter: '*.js' })\n .on('data', function (entry) {\n // do something with each JavaScript file entry\n });\n\n// Combined glob file filters\nreaddirp({ root: './test/bed', fileFilter: [ '*.js', '*.json' ] })\n .on('data', function (entry) {\n // do something with each JavaScript and Json file entry \n });\n\n// Combined negated directory filters\nreaddirp({ root: './test/bed', directoryFilter: [ '!.git', '!*modules' ] })\n .on('data', function (entry) {\n // do something with each file entry found outside '.git' or any modules directory \n });\n\n// Function directory filter\nreaddirp({ root: './test/bed', directoryFilter: function (di) { return di.name.length === 9; } })\n .on('data', function (entry) {\n // do something with each file entry found inside directories whose name has length 9\n });\n\n// Limiting depth\nreaddirp({ root: './test/bed', depth: 1 })\n .on('data', function (entry) {\n // do something with each file entry found up to 1 subdirectory deep\n });\n\n// callback api\nreaddirp(\n { root: '.' }\n , function(fileInfo) { \n // do something with file entry here\n } \n , function (err, res) {\n // all done, move on or do final step for all file entries here\n }\n);\n```\n\nTry more examples by following [instructions](https://github.com/thlorenz/readdirp/blob/master/examples/Readme.md)\non how to get going.\n\n## stream api\n\n[stream-api.js](https://github.com/thlorenz/readdirp/blob/master/examples/stream-api.js)\n\nDemonstrates error and data handling by listening to events emitted from the readdirp stream.\n\n## stream api pipe\n\n[stream-api-pipe.js](https://github.com/thlorenz/readdirp/blob/master/examples/stream-api-pipe.js)\n\nDemonstrates error handling by listening to events emitted from the readdirp stream and how to pipe the data stream into\nanother destination stream.\n\n## grep\n\n[grep.js](https://github.com/thlorenz/readdirp/blob/master/examples/grep.js)\n\nVery naive implementation of grep, for demonstration purposes only.\n\n## using callback api\n\n[callback-api.js](https://github.com/thlorenz/readdirp/blob/master/examples/callback-api.js)\n\nShows how to pass callbacks in order to handle errors and/or data.\n\n## tests\n\nThe [readdirp tests](https://github.com/thlorenz/readdirp/blob/master/test/readdirp.js) also will give you a good idea on\nhow things work.\n\n", + "readmeFilename": "README.md", + "_id": "readdirp@0.2.5", + "dist": { + "shasum": "094b56ed055226d3d8573584943d2079fd2d7d57" + }, + "_from": "readdirp@~0.2.3", + "_resolved": "https://registry.npmjs.org/readdirp/-/readdirp-0.2.5.tgz" +} diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/readdirp.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/readdirp.js new file mode 100644 index 0000000..6111e11 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/readdirp.js @@ -0,0 +1,276 @@ +'use strict'; + +var fs = require('fs') + , path = require('path') + , minimatch = require('minimatch') + , toString = Object.prototype.toString + ; + +// Standard helpers +function isFunction (obj) { + return toString.call(obj) == '[object Function]'; +} + +function isString (obj) { + return toString.call(obj) == '[object String]'; +} + +function isRegExp (obj) { + return toString.call(obj) == '[object RegExp]'; +} + +function isUndefined (obj) { + return obj === void 0; +} + +/** + * Main function which ends up calling readdirRec and reads all files and directories in given root recursively. + * @param { Object } opts Options to specify root (start directory), filters and recursion depth + * @param { function } callback1 When callback2 is given calls back for each processed file - function (fileInfo) { ... }, + * when callback2 is not given, it behaves like explained in callback2 + * @param { function } callback2 Calls back once all files have been processed with an array of errors and file infos + * function (err, fileInfos) { ... } + */ +function readdir(opts, callback1, callback2) { + var stream + , handleError + , handleFatalError + , pending = 0 + , errors = [] + , readdirResult = { + directories: [] + , files: [] + } + , fileProcessed + , allProcessed + , realRoot + , aborted = false + ; + + // If no callbacks were given we will use a streaming interface + if (isUndefined(callback1)) { + var api = require('./stream-api')(); + stream = api.stream; + callback1 = api.processEntry; + callback2 = api.done; + handleError = api.handleError; + handleFatalError = api.handleFatalError; + + stream.on('close', function () { aborted = true; }); + } else { + handleError = function (err) { errors.push(err); }; + handleFatalError = function (err) { + handleError(err); + allProcessed(errors, null); + }; + } + + if (isUndefined(opts)){ + handleFatalError(new Error ( + 'Need to pass at least one argument: opts! \n' + + 'https://github.com/thlorenz/readdirp#options' + ) + ); + return stream; + } + + opts.root = opts.root || '.'; + opts.fileFilter = opts.fileFilter || function() { return true; }; + opts.directoryFilter = opts.directoryFilter || function() { return true; }; + opts.depth = typeof opts.depth === 'undefined' ? 999999999 : opts.depth; + + if (isUndefined(callback2)) { + fileProcessed = function() { }; + allProcessed = callback1; + } else { + fileProcessed = callback1; + allProcessed = callback2; + } + + function normalizeFilter (filter) { + + if (isUndefined(filter)) return undefined; + + function isNegated (filters) { + + function negated(f) { + return f.indexOf('!') === 0; + } + + var some = filters.some(negated); + if (!some) { + return false; + } else { + if (filters.every(negated)) { + return true; + } else { + // if we detect illegal filters, bail out immediately + throw new Error( + 'Cannot mix negated with non negated glob filters: ' + filters + '\n' + + 'https://github.com/thlorenz/readdirp#filters' + ); + } + } + } + + // Turn all filters into a function + if (isFunction(filter)) { + + return filter; + + } else if (isString(filter)) { + + return function (entryInfo) { + return minimatch(entryInfo.name, filter.trim()); + }; + + } else if (filter && Array.isArray(filter)) { + + if (filter) filter = filter.map(function (f) { + return f.trim(); + }); + + return isNegated(filter) ? + // use AND to concat multiple negated filters + function (entryInfo) { + return filter.every(function (f) { + return minimatch(entryInfo.name, f); + }); + } + : + // use OR to concat multiple inclusive filters + function (entryInfo) { + return filter.some(function (f) { + return minimatch(entryInfo.name, f); + }); + }; + } + } + + function processDir(currentDir, entries, callProcessed) { + if (aborted) return; + var total = entries.length + , processed = 0 + , entryInfos = [] + ; + + fs.realpath(currentDir, function(err, realCurrentDir) { + if (aborted) return; + if (err) { + handleError(err); + callProcessed(entryInfos); + return; + } + + var relDir = path.relative(realRoot, realCurrentDir); + + if (entries.length === 0) { + callProcessed([]); + } else { + entries.forEach(function (entry) { + + var fullPath = path.join(realCurrentDir, entry), + relPath = path.join(relDir, entry); + + fs.stat(fullPath, function (err, stat) { + if (err) { + handleError(err); + } else { + entryInfos.push({ + name : entry + , path : relPath // relative to root + , fullPath : fullPath + + , parentDir : relDir // relative to root + , fullParentDir : realCurrentDir + + , stat : stat + }); + } + processed++; + if (processed === total) callProcessed(entryInfos); + }); + }); + } + }); + } + + function readdirRec(currentDir, depth, callCurrentDirProcessed) { + if (aborted) return; + + fs.readdir(currentDir, function (err, entries) { + if (err) { + handleError(err); + callCurrentDirProcessed(); + return; + } + + processDir(currentDir, entries, function(entryInfos) { + + var subdirs = entryInfos + .filter(function (ei) { return ei.stat.isDirectory() && opts.directoryFilter(ei); }); + + subdirs.forEach(function (di) { + readdirResult.directories.push(di); + }); + + entryInfos + .filter(function(ei) { return ei.stat.isFile() && opts.fileFilter(ei); }) + .forEach(function (fi) { + fileProcessed(fi); + readdirResult.files.push(fi); + }); + + var pendingSubdirs = subdirs.length; + + // Be done if no more subfolders exist or we reached the maximum desired depth + if(pendingSubdirs === 0 || depth === opts.depth) { + callCurrentDirProcessed(); + } else { + // recurse into subdirs, keeping track of which ones are done + // and call back once all are processed + subdirs.forEach(function (subdir) { + readdirRec(subdir.fullPath, depth + 1, function () { + pendingSubdirs = pendingSubdirs - 1; + if(pendingSubdirs === 0) { + callCurrentDirProcessed(); + } + }); + }); + } + }); + }); + } + + // Validate and normalize filters + try { + opts.fileFilter = normalizeFilter(opts.fileFilter); + opts.directoryFilter = normalizeFilter(opts.directoryFilter); + } catch (err) { + // if we detect illegal filters, bail out immediately + handleFatalError(err); + return stream; + } + + // If filters were valid get on with the show + fs.realpath(opts.root, function(err, res) { + if (err) { + handleFatalError(err); + return stream; + } + + realRoot = res; + readdirRec(opts.root, 0, function () { + // All errors are collected into the errors array + if (errors.length > 0) { + allProcessed(errors, readdirResult); + } else { + allProcessed(null, readdirResult); + } + }); + }); + + return stream; +} + +module.exports = readdir; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/stream-api.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/stream-api.js new file mode 100644 index 0000000..1cfc616 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/stream-api.js @@ -0,0 +1,86 @@ +var Stream = require('stream'); + +function createStreamAPI () { + var stream + , processEntry + , done + , handleError + , handleFatalError + , paused = true + , controlled = false + , buffer = [] + , closed = false + ; + + stream = new Stream(); + stream.writable = false; + stream.readable = true; + + stream.pause = function () { + controlled = true; + paused = true; + }; + + stream.resume = function () { + controlled = true; + paused = false; + + // emit all buffered entries, errors and ends + while (!paused && buffer.length) { + var msg = buffer.shift(); + this.emit(msg.type, msg.data); + } + }; + + stream.destroy = function () { + closed = true; + stream.readable = false; + stream.emit('close'); + }; + + // called for each entry + processEntry = function (entry) { + if (closed) return; + return paused ? buffer.push({ type: 'data', data: entry }) : stream.emit('data', entry); + }; + + // called with all found entries when directory walk finished + done = function (err, entries) { + if (closed) return; + + // since we already emitted each entry and all non fatal errors + // all we need to do here is to signal that we are done + stream.emit('end'); + }; + + handleError = function (err) { + if (closed) return; + return paused ? buffer.push({ type: 'warn', data: err }) : stream.emit('warn', err); + }; + + handleFatalError = function (err) { + if (closed) return; + return paused ? buffer.push({ type: 'error', data: err }) : stream.emit('error', err); + }; + + // Allow stream to be returned and handlers to be attached and/or stream to be piped before emitting messages + // Otherwise we may loose data/errors that are emitted immediately + process.nextTick(function () { + if (closed) return; + + // In case was controlled (paused/resumed) manually, we don't interfer + // see https://github.com/thlorenz/readdirp/commit/ab7ff8561d73fca82c2ce7eb4ce9f7f5caf48b55#commitcomment-1964530 + if (controlled) return; + stream.resume(); + }); + + return { + stream : stream + , processEntry : processEntry + , done : done + , handleError : handleError + , handleFatalError : handleFatalError + }; +} + +module.exports = createStreamAPI; diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file1.ext1 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file1.ext1 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file2.ext2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file2.ext2 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file3.ext3 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_file3.ext3 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_subdir1/root1_dir1_subdir1_file1.ext1 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir1/root_dir1_subdir1/root1_dir1_subdir1_file1.ext1 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir2/root_dir2_file1.ext1 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir2/root_dir2_file1.ext1 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir2/root_dir2_file2.ext2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_dir2/root_dir2_file2.ext2 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file1.ext1 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file1.ext1 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file2.ext2 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file2.ext2 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file3.ext3 b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/bed/root_file3.ext3 new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp-stream.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp-stream.js new file mode 100644 index 0000000..261c5f6 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp-stream.js @@ -0,0 +1,215 @@ +/*jshint asi:true */ + +var test = require('tap').test + , path = require('path') + , fs = require('fs') + , util = require('util') + , Stream = require('stream') + , through = require('through') + , streamapi = require('../stream-api') + , readdirp = require('..') + , root = path.join(__dirname, 'bed') + , totalDirs = 6 + , totalFiles = 12 + , ext1Files = 4 + , ext2Files = 3 + , ext3Files = 2 + ; + +// see test/readdirp.js for test bed layout + +function opts (extend) { + var o = { root: root }; + + if (extend) { + for (var prop in extend) { + o[prop] = extend[prop]; + } + } + return o; +} + +function capture () { + var result = { entries: [], errors: [], ended: false } + , dst = new Stream(); + + dst.writable = true; + dst.readable = true; + + dst.write = function (entry) { + result.entries.push(entry); + } + + dst.end = function () { + result.ended = true; + dst.emit('data', result); + dst.emit('end'); + } + + return dst; +} + +test('\nintegrated', function (t) { + t.test('\n# reading root without filter', function (t) { + t.plan(2); + readdirp(opts()) + .on('error', function (err) { + t.fail('should not throw error', err); + }) + .pipe(capture()) + .pipe(through( + function (result) { + t.equals(result.entries.length, totalFiles, 'emits all files'); + t.ok(result.ended, 'ends stream'); + t.end(); + } + )); + }) + + t.test('\n# normal: ["*.ext1", "*.ext3"]', function (t) { + t.plan(2); + + readdirp(opts( { fileFilter: [ '*.ext1', '*.ext3' ] } )) + .on('error', function (err) { + t.fail('should not throw error', err); + }) + .pipe(capture()) + .pipe(through( + function (result) { + t.equals(result.entries.length, ext1Files + ext3Files, 'all ext1 and ext3 files'); + t.ok(result.ended, 'ends stream'); + t.end(); + } + )) + }) + + t.test('\n# negated: ["!*.ext1", "!*.ext3"]', function (t) { + t.plan(2); + + readdirp(opts( { fileFilter: [ '!*.ext1', '!*.ext3' ] } )) + .on('error', function (err) { + t.fail('should not throw error', err); + }) + .pipe(capture()) + .pipe(through( + function (result) { + t.equals(result.entries.length, totalFiles - ext1Files - ext3Files, 'all but ext1 and ext3 files'); + t.ok(result.ended, 'ends stream'); + t.end(); + } + )) + }) + + t.test('\n# no options given', function (t) { + t.plan(1); + readdirp() + .on('error', function (err) { + t.similar(err.toString() , /Need to pass at least one argument/ , 'emits meaningful error'); + t.end(); + }) + }) + + t.test('\n# mixed: ["*.ext1", "!*.ext3"]', function (t) { + t.plan(1); + + readdirp(opts( { fileFilter: [ '*.ext1', '!*.ext3' ] } )) + .on('error', function (err) { + t.similar(err.toString() , /Cannot mix negated with non negated glob filters/ , 'emits meaningful error'); + t.end(); + }) + }) +}) + + +test('\napi separately', function (t) { + + t.test('\n# handleError', function (t) { + t.plan(1); + + var api = streamapi() + , warning = new Error('some file caused problems'); + + api.stream + .on('warn', function (err) { + t.equals(err, warning, 'warns with the handled error'); + }) + api.handleError(warning); + }) + + t.test('\n# when stream is paused and then resumed', function (t) { + t.plan(6); + var api = streamapi() + , resumed = false + , fatalError = new Error('fatal!') + , nonfatalError = new Error('nonfatal!') + , processedData = 'some data' + ; + + api.stream + .on('warn', function (err) { + t.equals(err, nonfatalError, 'emits the buffered warning'); + t.ok(resumed, 'emits warning only after it was resumed'); + }) + .on('error', function (err) { + t.equals(err, fatalError, 'emits the buffered fatal error'); + t.ok(resumed, 'emits errors only after it was resumed'); + }) + .on('data', function (data) { + t.equals(data, processedData, 'emits the buffered data'); + t.ok(resumed, 'emits data only after it was resumed'); + }) + .pause() + + api.processEntry(processedData); + api.handleError(nonfatalError); + api.handleFatalError(fatalError); + + process.nextTick(function () { + resumed = true; + api.stream.resume(); + }) + }) + + t.test('\n# when a stream is destroyed, it emits "closed", but no longer emits "data", "warn" and "error"', function (t) { + t.plan(6) + var api = streamapi() + , destroyed = false + , fatalError = new Error('fatal!') + , nonfatalError = new Error('nonfatal!') + , processedData = 'some data' + + var stream = api.stream + .on('warn', function (err) { + t.notOk(destroyed, 'emits warning until destroyed'); + }) + .on('error', function (err) { + t.notOk(destroyed, 'emits errors until destroyed'); + }) + .on('data', function (data) { + t.notOk(destroyed, 'emits data until destroyed'); + }) + .on('close', function () { + t.ok(destroyed, 'emits close when stream is destroyed'); + }) + + + api.processEntry(processedData); + api.handleError(nonfatalError); + api.handleFatalError(fatalError); + + process.nextTick(function () { + destroyed = true + stream.destroy() + + t.notOk(stream.readable, 'stream is no longer readable after it is destroyed') + + api.processEntry(processedData); + api.handleError(nonfatalError); + api.handleFatalError(fatalError); + + process.nextTick(function () { + t.pass('emits no more data, warn or error events after it was destroyed') + }) + }) + }) +}) diff --git a/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp.js b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp.js new file mode 100644 index 0000000..f3edb52 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/node_modules/readdirp/test/readdirp.js @@ -0,0 +1,252 @@ +/*jshint asi:true */ + +var test = require('tap').test + , path = require('path') + , fs = require('fs') + , util = require('util') + , readdirp = require('../readdirp.js') + , root = path.join(__dirname, '../test/bed') + , totalDirs = 6 + , totalFiles = 12 + , ext1Files = 4 + , ext2Files = 3 + , ext3Files = 2 + , rootDir2Files = 2 + , nameHasLength9Dirs = 2 + , depth1Files = 8 + , depth0Files = 3 + ; + +/* +Structure of test bed: + . + ├── root_dir1 + │   ├── root_dir1_file1.ext1 + │   ├── root_dir1_file2.ext2 + │   ├── root_dir1_file3.ext3 + │   ├── root_dir1_subdir1 + │   │   └── root1_dir1_subdir1_file1.ext1 + │   └── root_dir1_subdir2 + │   └── .gitignore + ├── root_dir2 + │   ├── root_dir2_file1.ext1 + │   ├── root_dir2_file2.ext2 + │   ├── root_dir2_subdir1 + │   │   └── .gitignore + │   └── root_dir2_subdir2 + │   └── .gitignore + ├── root_file1.ext1 + ├── root_file2.ext2 + └── root_file3.ext3 + + 6 directories, 13 files +*/ + +// console.log('\033[2J'); // clear console + +function opts (extend) { + var o = { root: root }; + + if (extend) { + for (var prop in extend) { + o[prop] = extend[prop]; + } + } + return o; +} + +test('\nreading root without filter', function (t) { + t.plan(2); + readdirp(opts(), function (err, res) { + t.equals(res.directories.length, totalDirs, 'all directories'); + t.equals(res.files.length, totalFiles, 'all files'); + t.end(); + }) +}) + +test('\nreading root using glob filter', function (t) { + // normal + t.test('\n# "*.ext1"', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: '*.ext1' } ), function (err, res) { + t.equals(res.files.length, ext1Files, 'all ext1 files'); + t.end(); + }) + }) + t.test('\n# ["*.ext1", "*.ext3"]', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: [ '*.ext1', '*.ext3' ] } ), function (err, res) { + t.equals(res.files.length, ext1Files + ext3Files, 'all ext1 and ext3 files'); + t.end(); + }) + }) + t.test('\n# "root_dir1"', function (t) { + t.plan(1); + readdirp(opts( { directoryFilter: 'root_dir1' }), function (err, res) { + t.equals(res.directories.length, 1, 'one directory'); + t.end(); + }) + }) + t.test('\n# ["root_dir1", "*dir1_subdir1"]', function (t) { + t.plan(1); + readdirp(opts( { directoryFilter: [ 'root_dir1', '*dir1_subdir1' ]}), function (err, res) { + t.equals(res.directories.length, 2, 'two directories'); + t.end(); + }) + }) + + t.test('\n# negated: "!*.ext1"', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: '!*.ext1' } ), function (err, res) { + t.equals(res.files.length, totalFiles - ext1Files, 'all but ext1 files'); + t.end(); + }) + }) + t.test('\n# negated: ["!*.ext1", "!*.ext3"]', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: [ '!*.ext1', '!*.ext3' ] } ), function (err, res) { + t.equals(res.files.length, totalFiles - ext1Files - ext3Files, 'all but ext1 and ext3 files'); + t.end(); + }) + }) + + t.test('\n# mixed: ["*.ext1", "!*.ext3"]', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: [ '*.ext1', '!*.ext3' ] } ), function (err, res) { + t.similar(err[0].toString(), /Cannot mix negated with non negated glob filters/, 'returns meaningfull error'); + t.end(); + }) + }) + + t.test('\n# leading and trailing spaces: [" *.ext1", "*.ext3 "]', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: [ ' *.ext1', '*.ext3 ' ] } ), function (err, res) { + t.equals(res.files.length, ext1Files + ext3Files, 'all ext1 and ext3 files'); + t.end(); + }) + }) + t.test('\n# leading and trailing spaces: [" !*.ext1", " !*.ext3 "]', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: [ ' !*.ext1', ' !*.ext3' ] } ), function (err, res) { + t.equals(res.files.length, totalFiles - ext1Files - ext3Files, 'all but ext1 and ext3 files'); + t.end(); + }) + }) + + t.test('\n# ** glob pattern', function (t) { + t.plan(1); + readdirp(opts( { fileFilter: '**/*.ext1' } ), function (err, res) { + t.equals(res.files.length, ext1Files, 'ignores ** in **/*.ext1 -> only *.ext1 files'); + t.end(); + }) + }) +}) + +test('\n\nreading root using function filter', function (t) { + t.test('\n# file filter -> "contains root_dir2"', function (t) { + t.plan(1); + readdirp( + opts( { fileFilter: function (fi) { return fi.name.indexOf('root_dir2') >= 0; } }) + , function (err, res) { + t.equals(res.files.length, rootDir2Files, 'all rootDir2Files'); + t.end(); + } + ) + }) + + t.test('\n# directory filter -> "name has length 9"', function (t) { + t.plan(1); + readdirp( + opts( { directoryFilter: function (di) { return di.name.length === 9; } }) + , function (err, res) { + t.equals(res.directories.length, nameHasLength9Dirs, 'all all dirs with name length 9'); + t.end(); + } + ) + }) +}) + +test('\nreading root specifying maximum depth', function (t) { + t.test('\n# depth 1', function (t) { + t.plan(1); + readdirp(opts( { depth: 1 } ), function (err, res) { + t.equals(res.files.length, depth1Files, 'does not return files at depth 2'); + }) + }) +}) + +test('\nreading root with no recursion', function (t) { + t.test('\n# depth 0', function (t) { + t.plan(1); + readdirp(opts( { depth: 0 } ), function (err, res) { + t.equals(res.files.length, depth0Files, 'does not return files at depth 0'); + }) + }) +}) + +test('\nprogress callbacks', function (t) { + t.plan(2); + + var pluckName = function(fi) { return fi.name; } + , processedFiles = []; + + readdirp( + opts() + , function(fi) { + processedFiles.push(fi); + } + , function (err, res) { + t.equals(processedFiles.length, res.files.length, 'calls back for each file processed'); + t.deepEquals(processedFiles.map(pluckName).sort(),res.files.map(pluckName).sort(), 'same file names'); + t.end(); + } + ) +}) + +test('resolving of name, full and relative paths', function (t) { + var expected = { + name : 'root_dir1_file1.ext1' + , parentDirName : 'root_dir1' + , path : 'root_dir1/root_dir1_file1.ext1' + , fullPath : 'test/bed/root_dir1/root_dir1_file1.ext1' + } + , opts = [ + { root: './bed' , prefix: '' } + , { root: './bed/' , prefix: '' } + , { root: 'bed' , prefix: '' } + , { root: 'bed/' , prefix: '' } + , { root: '../test/bed/' , prefix: '' } + , { root: '.' , prefix: 'bed' } + ] + t.plan(opts.length); + + opts.forEach(function (op) { + op.fileFilter = 'root_dir1_file1.ext1'; + + t.test('\n' + util.inspect(op), function (t) { + t.plan(4); + + readdirp (op, function(err, res) { + t.equals(res.files[0].name, expected.name, 'correct name'); + t.equals(res.files[0].path, path.join(op.prefix, expected.path), 'correct path'); + }) + + fs.realpath(op.root, function(err, fullRoot) { + readdirp (op, function(err, res) { + t.equals( + res.files[0].fullParentDir + , path.join(fullRoot, op.prefix, expected.parentDirName) + , 'correct parentDir' + ); + t.equals( + res.files[0].fullPath + , path.join(fullRoot, op.prefix, expected.parentDirName, expected.name) + , 'correct fullPath' + ); + }) + }) + }) + }) +}) + + diff --git a/node_modules/jade/node_modules/monocle/package.json b/node_modules/jade/node_modules/monocle/package.json new file mode 100644 index 0000000..00faba9 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/package.json @@ -0,0 +1,43 @@ +{ + "name": "monocle", + "version": "0.1.48", + "description": "a tool for watching directories for file changes", + "main": "monocle.js", + "directories": { + "test": "test" + }, + "dependencies": { + "readdirp": "~0.2.3" + }, + "devDependencies": { + "mocha": "1.8.1" + }, + "scripts": { + "test": "mocha test -R spec -t 2000" + }, + "repository": { + "type": "git", + "url": "https://github.com/samccone/monocle.git" + }, + "bugs": { + "url": "https://github.com/samccone/monocle/issues" + }, + "keywords": [ + "watch", + "filesystem", + "folders", + "fs" + ], + "author": { + "name": "Sam Saccone" + }, + "license": "BSD", + "readme": "[![Build Status](https://travis-ci.org/samccone/monocle.png?branch=master)](https://travis-ci.org/samccone/monocle)\n\n# Monocle -- a tool for watching things\n\n[![logo](https://raw.github.com/samccone/monocle/master/logo.png)](https://raw.github.com/samccone/monocle/master/logo.png)\n\nHave you ever wanted to watch a folder and all of its files/nested folders for changes. well now you can!\n\n## Installation\n\n```\nnpm install monocle\n```\n\n## Usage\n\n### Watch a directory:\n\n```js\nvar monocle = require('monocle')()\nmonocle.watchDirectory({\n root: ,\n fileFilter: ,\n directoryFilter: ,\n listener: fn(fs.stat+ object), //triggered on file change / addition\n complete: //file watching all set up\n});\n```\n\nThe listener will recive an object with the following\n\n```js\n name: ,\n path: ,\n fullPath: ,\n parentDir: ,\n fullParentDir: ,\n stat: \n```\n\n[fs.stats](http://nodejs.org/api/fs.html#fs_class_fs_stats)\n\nWhen a new file is added to the directoy it triggers a file change and thus will be passed to your specified listener.\n\nThe two filters are passed through to `readdirp`. More documentation can be found [here](https://github.com/thlorenz/readdirp#filters)\n\n### Watch a list of files:\n\n```js\nMonocle.watchFiles({\n files: [], //path of file(s)\n listener: , //triggered on file / addition\n complete: //file watching all set up\n});\n```\n\n## Why not just use fs.watch ?\n\n - file watching is really bad cross platforms in node\n - you need to be smart when using fs.watch as compared to fs.watchFile\n - Monocle takes care of this logic for you!\n - windows systems use fs.watch\n - osx and linux uses fs.watchFile\n\n## License\n\nBSD\n", + "readmeFilename": "README.md", + "_id": "monocle@0.1.48", + "dist": { + "shasum": "df65b004c535db78ab4bc2734980724f0941e991" + }, + "_from": "monocle@0.1.48", + "_resolved": "https://registry.npmjs.org/monocle/-/monocle-0.1.48.tgz" +} diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/creation3.txt b/node_modules/jade/node_modules/monocle/test/sample_files/creation3.txt new file mode 100644 index 0000000..8e9c665 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/creation3.txt @@ -0,0 +1 @@ +1368234683085 diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/creation4.txt b/node_modules/jade/node_modules/monocle/test/sample_files/creation4.txt new file mode 100644 index 0000000..f1937ff --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/creation4.txt @@ -0,0 +1 @@ +1368234683637 diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/creation5.txt b/node_modules/jade/node_modules/monocle/test/sample_files/creation5.txt new file mode 100644 index 0000000..1f5a206 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/creation5.txt @@ -0,0 +1 @@ +1368234684038 diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/foo.txt b/node_modules/jade/node_modules/monocle/test/sample_files/foo.txt new file mode 100644 index 0000000..fe02e96 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/foo.txt @@ -0,0 +1 @@ +1361300019687 diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/longbow.js b/node_modules/jade/node_modules/monocle/test/sample_files/longbow.js new file mode 100644 index 0000000..08c3473 --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/longbow.js @@ -0,0 +1 @@ +1361300019993 diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/nestedDir/servent.txt b/node_modules/jade/node_modules/monocle/test/sample_files/nestedDir/servent.txt new file mode 100644 index 0000000..b26921e --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/nestedDir/servent.txt @@ -0,0 +1 @@ +1361300019841 diff --git a/node_modules/jade/node_modules/monocle/test/sample_files/zap.bat b/node_modules/jade/node_modules/monocle/test/sample_files/zap.bat new file mode 100644 index 0000000..a358cce --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/sample_files/zap.bat @@ -0,0 +1,31 @@ +1361223315286 +1361223316535 +1361223345247 +1361223392495 +1361223394521 +1361223401023 +1361223431160 +1361223432160 +1361223437177 +1361223438592 +1361223466645 +1361223467719 +1361223594858 +1361223614308 +1361223643429 +1361223647989 +1361223649211 +1361223650605 +1361223651566 +1361223663051 +1361223664917 +1361223665860 +1361223777758 +1361223779174 +1361223780023 +1361223780769 +1361223783122 +1361223784141 +1361223791305 +1361223795551 +1361223797217 diff --git a/node_modules/jade/node_modules/monocle/test/tester.js b/node_modules/jade/node_modules/monocle/test/tester.js new file mode 100644 index 0000000..d65d57b --- /dev/null +++ b/node_modules/jade/node_modules/monocle/test/tester.js @@ -0,0 +1,180 @@ +var fs = require('fs'); +var assert = require('assert'); +var Monocle = require('../monocle'); + +// +// setup +// +var monocle = null; +var sample_dir = __dirname + '/sample_files'; +before(function(){ monocle = Monocle(); }); +after(function() { + fs.unlinkSync(__dirname+"/sample_files/creation.txt"); + fs.unlinkSync(__dirname+"/sample_files/creation2.txt"); + fs.unlinkSync(__dirname+"/sample_files/nestedDir/creation3.txt"); +}); +// +// file change tests +// + +describe("file changes", function() { + + it("should detect a change", function(complete) { + monocle.watchDirectory({ + root: sample_dir, + listener: function(f){ cb_helper('foo.txt', f, complete); }, + complete: function(){ complete_helper("/sample_files/foo.txt"); } + }); + }); + + it("should detect a change in a nested dir file", function(complete) { + monocle.watchDirectory({ + root: sample_dir, + listener: function(f) { cb_helper('servent.txt', f, complete); }, + complete: function() { complete_helper("/sample_files/nestedDir/servent.txt"); } + }); + }); + + it("should detect a change", function(complete) { + monocle.watchDirectory({ + root: sample_dir, + listener: function(f) { cb_helper('longbow.js', f, complete); }, + complete: function() { complete_helper('/sample_files/longbow.js'); } + }); + }); + +}); + +// +// file add tests +// + +describe("file added", function() { + it("should detect a file added", function(complete) { + monocle.watchDirectory({ + root: sample_dir, + listener: function(f) { + cb_helper("creation.txt", f, complete) + }, + complete: function() { + complete_helper('/sample_files/creation.txt'); + } + }); + }); + + it("should detect another file added", function(complete) { + monocle.watchDirectory({ + root: sample_dir, + listener: function(f) { + cb_helper("creation2.txt", f, complete); + }, + complete: function() { + complete_helper('/sample_files/creation2.txt'); + } + }); + }); + + it("should detect another file added in a nested folder", function(complete) { + monocle.watchDirectory({ + root: sample_dir, + listener: function(f) { + cb_helper("creation3.txt", f, complete); + }, + complete: function() { + complete_helper('/sample_files/nestedDir/creation3.txt'); + } + }); + }); +}); + + +// +// watch an array of files +// +describe("files watched", function() { + it("should detect a file changed of multiple", function(complete) { + complete_helper('/sample_files/creation.txt'); + complete_helper('/sample_files/creation2.txt'); + complete_helper('/sample_files/creation3.txt'); + + monocle.watchFiles({ + files: [__dirname+"/sample_files/creation.txt", __dirname+"/sample_files/creation2.txt"], + listener: function(f) { + cb_helper("creation2.txt", f, complete) + }, + complete: function() { + complete_helper('/sample_files/creation2.txt'); + } + }); + }); + + it("should detect a file changed (delayed)", function(complete) { + complete_helper('/sample_files/creation3.txt'); + monocle.watchFiles({ + files: [__dirname+"/sample_files/creation3.txt"], + listener: function(f) { + setTimeout(function() { + cb_helper('creation3.txt', f, complete); + }, 400); + }, + complete: function() { + complete_helper('/sample_files/creation3.txt'); + } + }); + }); + + + + it("should detect a file changed (short delayed)", function(complete) { + complete_helper('/sample_files/creation4.txt'); + monocle.watchFiles({ + files: [__dirname+"/sample_files/creation4.txt"], + listener: function(f) { + setTimeout(function() { + cb_helper('creation4.txt', f, complete); + }, 100); + }, + complete: function() { + complete_helper('/sample_files/creation4.txt'); + } + }); + }); + + it("should detect a file changed", function(complete) { + complete_helper('/sample_files/creation.txt'); + monocle.watchFiles({ + files: [__dirname+"/sample_files/creation.txt"], + listener: function(f) { + cb_helper("creation.txt", f, complete) + }, + complete: function() { + complete_helper('/sample_files/creation.txt'); + } + }); + }); + + it("should not bomb when no callback is passed", function(complete) { + complete_helper('/sample_files/creation5.txt'); + monocle.watchFiles({ + files: [__dirname+"/sample_files/creation5.txt"], + complete: function() { + complete_helper('/sample_files/creation5.txt'); + } + }); + setTimeout(function() { + complete(); + }, 300) + }); +}); + +// +// helpers +// + +function cb_helper(name, file, done){ + if (file.name === name) { monocle.unwatchAll(); done(); } +} + +function complete_helper(path){ + fs.writeFile(__dirname + path, (new Date).getTime() + "\n"); +} diff --git a/node_modules/jade/node_modules/transformers/.npmignore b/node_modules/jade/node_modules/transformers/.npmignore new file mode 100644 index 0000000..78cdbf8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/.npmignore @@ -0,0 +1,15 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +npm-debug.log +node_modules diff --git a/node_modules/jade/node_modules/transformers/.travis.yml b/node_modules/jade/node_modules/transformers/.travis.yml new file mode 100644 index 0000000..4e80ca0 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/jade/node_modules/transformers/README.md b/node_modules/jade/node_modules/transformers/README.md new file mode 100644 index 0000000..1fb2f9a --- /dev/null +++ b/node_modules/jade/node_modules/transformers/README.md @@ -0,0 +1,138 @@ +[![Build Status](https://travis-ci.org/ForbesLindesay/transformers.png?branch=master)](https://travis-ci.org/ForbesLindesay/transformers) +# transformers + + String/Data transformations for use in templating libraries, static site generators and web frameworks. This gathers the most useful transformations you can apply to text or data into one library with a consistent API. Transformations can be pretty much anything but most are either compilers or templating engines. + +## Supported transforms + + To use each of these transforms you will also need to install the associated npm module for that transformer. + +### Template engines + + - [atpl](http://documentup.com/soywiz/atpl.js) - Compatible with twig templates + - [coffeecup](http://documentup.com/gradus/coffeecup) - pure coffee-script templates (fork of coffeekup) + - [dot](http://documentup.com/olado/doT) [(website)](https://github.com/Katahdin/dot-packer) - focused on speed + - [dust](http://documentup.com/akdubya/dustjs) [(website)](http://akdubya.github.com/dustjs/) - asyncronous templates + - [eco](http://documentup.com/sstephenson/eco) - Embedded CoffeeScript templates + - [ect](http://documentup.com/baryshev/ect) [(website)](http://ectjs.com/) - Embedded CoffeeScript templates + - [ejs](http://documentup.com/visionmedia/ejs) - Embedded JavaScript templates + - [haml](http://documentup.com/visionmedia/haml.js) [(website)](http://haml-lang.com/) - dry indented markup + - [haml-coffee](http://documentup.com/netzpirat/haml-coffee/) [(website)](http://haml-lang.com/) - haml with embedded CoffeeScript + - [handlebars](http://documentup.com/wycats/handlebars.js/) [(website)](http://handlebarsjs.com/) - extension of mustache templates + - [hogan](http://documentup.com/twitter/hogan.js) [(website)](http://twitter.github.com/hogan.js/) - Mustache templates + - [jade](http://documentup.com/visionmedia/jade) [(website)](http://jade-lang.com/) - robust, elegant, feature rich template engine + - [jazz](http://documentup.com/shinetech/jazz) + - [jqtpl](http://documentup.com/kof/jqtpl) [(website)](http://api.jquery.com/category/plugins/templates/) - extensible logic-less templates + - [JUST](http://documentup.com/baryshev/just) - EJS style template with some special syntax for layouts/partials etc. + - [liquor](http://documentup.com/chjj/liquor) - extended EJS with significant white space + - [mustache](http://documentup.com/janl/mustache.js) - logic less templates + - [QEJS](http://documentup.com/jepso/QEJS) - Promises + EJS for async templating + - [swig](http://documentup.com/paularmstrong/swig) [(website)](http://paularmstrong.github.com/swig/) - Django-like templating engine + - [templayed](http://documentup.com/archan937/templayed.js/) [(website)](http://archan937.github.com/templayed.js/) - Mustache focused on performance + - [toffee](http://documentup.com/malgorithms/toffee) - templating language based on coffeescript + - [underscore](http://documentup.com/documentcloud/underscore) [(website)](http://documentcloud.github.com/underscore/) + - [walrus](http://documentup.com/jeremyruppel/walrus) - A bolder kind of mustache + - [whiskers](http://documentup.com/gsf/whiskers.js/tree/) - logic-less focused on readability + +### Stylesheet Languages + + - [less](http://documentup.com/cloudhead/less.js) [(website)](http://lesscss.org/) - LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions. + - [stylus](http://documentup.com/learnboost/stylus) [(website)](http://learnboost.github.com/stylus/) - revolutionary CSS generator making braces optional + - [sass](http://documentup.com/visionmedia/sass.js) [(website)](http://sass-lang.com/) - Sassy CSS + +### Minifiers + + - [uglify-js](http://documentup.com/mishoo/UglifyJS2) - No need to install anything, just minifies/beautifies JavaScript + - [uglify-css](https://github.com/visionmedia/css) - No need to install anything, just minifies/beautifies CSS + - ugilify-json - No need to install anything, just minifies/beautifies JSON + +### Other + + - cdata - No need to install anything, just wrapps text in `` + - [coffee-script](http://coffeescript.org/) - `npm install coffee-script` + - [cson](https://github.com/bevry/cson) - coffee-script based JSON format + - markdown - You can use `marked`, `supermarked`, `markdown-js` or `markdown` + - [component-js](http://documentup.com/component/component) [(website)](http://component.io) - `npm install component-builder` options: `{development: false}` + - [component-css](http://documentup.com/component/component) [(website)](http://component.io) - `npm install component-builder` options: `{development: false}` + - [html2jade](http://documentup.com/donpark/html2jade) [(website)](http://html2jade.aaron-powell.com/) - `npm install html2jade` - Converts HTML back into jade + +Pull requests to add more transforms will always be accepted providing they are open-source, come with unit tests, and don't cause any of the tests to fail. + +## API + + The exported object `transformers` is a collection of named transformers. To access an individual transformer just do: + + ```javascript + var transformer = require('transformers')['transformer-name'] + ``` + +### Transformer + + The following options are given special meaning by `transformers`: + + - `filename` is set by transformers automatically if using the `renderFile` APIs. It is used if `cache` is enabled. + - `cache` if true, the template function will be cached where possible (templates are still updated if you provide new options, so this can be used in most live applications). + - `sudoSync` used internally to put some asyncronous transformers into "sudo syncronous" mode. Don't touch this. + - `minify` if set to true on a transformer that isn't a minifier, it will cause the output to be minified. e.g. `coffeeScript.renderSync(str, {minify: true})` will result in minified JavaScript. + +#### Transformer.engines + + Returns an array of engines that can be used to power this transformer. The first of these that's installed will be used for the transformation. + + To enable a transformation just take `[engine] = Transformer.engines[0]` and then do `npm install [engine]`. If `[engine]` is `.` there is no need to install an engine from npm to use the transformer. + +#### Transformer.render(str, options, cb) + + Tranform the string `str` using the `Transformer` with the provided options and call the callback `cb(err, res)`. + + If no `cb` is provided, this method returns a [promises/A+](http://promises-aplus.github.com/promises-spec/) promise. + +#### Transformer.renderSync(str, options) + + Synchronous version of `Transformer.render` + +#### Transformer.renderFile(filename, options, cb) + + Reads the file at filename into `str` and sets `options.filename = filename` then calls `Transform.render(str, options, cb)`. + + If no `cb` is provided, this method returns a [promises/A+](http://promises-aplus.github.com/promises-spec/) promise. + +#### Tranformer.renderFileSync(filename, options) + + Synchronous version of `Tranformer.renderFile` + +#### Transformer.outputFormat + + A string, one of: + + - `'xml'` + - `'css'` + - `'js'` + - `'json'` + - `'text'` + +Adding to this list will **not** result in a major version change, so you should handle unexpected types gracefully (I'd suggest default to assuming `'text'`). + +#### Transformer.sync + + `true` if the transformer can be used syncronously, `false` otherwise. + +## Libraries that don't work synchronously + + The following transformations will always throw an exception if you attempt to run them synchronously: + + 1. dust + 2. qejs + 3. html2jade + +The following transformations sometimes throw an exception if run syncronously, typically they only throw an exception if you are doing something like including another file. If you are not doing the things that cause them to fail then they are consistently safe to use syncronously. + + - jade (only when using `then-jade` instead of `jade`) + - less (when `@import` is used with a url instead of a filename) + - jazz (When one of the functions passed as locals is asyncronous) + +The following libraries look like they might sometimes throw exceptions when used syncronously (if you read the source) but they never actually do so: + + - just + - ect + - stylus \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/history.md b/node_modules/jade/node_modules/transformers/history.md new file mode 100644 index 0000000..d415de4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/history.md @@ -0,0 +1,69 @@ +## 2.0.1 - 2013-04-22 + + - Fix global leak of `exportscoffeeScript` (test still fails because `jade` requires an out of date version of `transformers`) + +## 2.0.0 - 2013-03-31 + + - Add `minify` support to all transformers + - Bundle minifiers in package + +## 1.8.3 - 2013-03-19 + + - Update promise dependency + +## 1.8.2 - 2013-02-10 + + - Support `sourceURLs` in **component** + +## 1.8.1 - 2013-02-10 + + - Add travis-ci + - FIX **toffee** support which was broken by their latest update + - FIX lookup paths for **component** weren't set so you couldn't build components with dependancies + +## 1.8.0 - 2013-01-30 + + - **highlight** (needs tests) + +## 1.7.0 - 2013-01-30 + + - **component-js** + - **component-css** + - **html2jade** - must be `v0.0.7` because of a bug in later versions + - Much more extensive tests + +## 1.6.0 - 2013-01-29 + + - **uglify-css** + - **uglify-json** + - Rename **uglify** to **uglify-js** + +## 1.5.0 - 2013-01-27 + + - **dot** + +## 1.4.0 - 2013-01-25 + + - Support sync `@import` statements in **less** + - Report real errors from **less** (rather than objects) + +## 1.3.0 - 2013-01-25 + + - **templayed** + - **plates** + +## 1.2.1 - 2013-01-09 + + - make **markdown** work when using **markdown** as the engine (**marked** is the recommended engine). + +## 1.2.0 - 2013-01-09 + + - **js** (pass through) + - **css** (pass through) + - rename **coffee-script** from **coffee** to **coffee-script** and add **coffee** as an alias + +## 1.1.0 - 2013-01-08 + + - **coffeecup** + - **cson** + - FIX: disabling **dust** cache \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/lib/shared.js b/node_modules/jade/node_modules/transformers/lib/shared.js new file mode 100644 index 0000000..a5973f8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/lib/shared.js @@ -0,0 +1,162 @@ +var Promise = require('promise'); +var fs = require('fs'); +var path = require('path'); +var normalize = path.normalize; + + +Promise.prototype.nodeify = function (cb) { + if (typeof cb === 'function') { + this.then(function (res) { process.nextTick(function () { cb(null, res); }); }, + function (err) { process.nextTick(function () { cb(err); }); }); + return undefined; + } else { + return this; + } +} + +var minifiers = {}; + +module.exports = Transformer; +function Transformer(obj) { + this.name = obj.name; + this.engines = obj.engines; + this.isBinary = obj.isBinary || false; + this.isMinifier = obj.isMinifier || false; + this.outputFormat = obj.outputFormat; + this._cache = {}; + if (typeof obj.async === 'function') { + this._renderAsync = obj.async; + this.sudoSync = obj.sudoSync || false; + } + if (typeof obj.sync === 'function') { + this._renderSync = obj.sync; + this.sync = true; + } else { + this.sync = obj.sudoSync || false; + } + + if (this.isMinifier) + minifiers[this.outputFormat] = this; + else { + var minifier = minifiers[this.outputFormat]; + if (minifier) { + this.minify = function(str, options) { + if (options && options.minify) + return minifier.renderSync(str, typeof options.minify === 'object' && options.minify || {}); + return str; + } + } + } +} + +Transformer.prototype.cache = function (options, data) { + if (options.cache && options.filename) { + if (data) return this.cache[options.filename] = data; + else return this.cache[options.filename]; + } else { + return data; + } +}; +Transformer.prototype.loadModule = function () { + if (this.engine) return this.engine; + for (var i = 0; i < this.engines.length; i++) { + try { + var res = this.engines[i] === '.' ? null : (this.engine = require(this.engines[i])); + this.engineName = this.engines[i]; + return res; + } catch (ex) { + if (this.engines.length === 1) { + throw ex; + } + } + } + throw new Error('In order to apply the transform ' + this.name + ' you must install one of ' + this.engines.map(function (e) { return '"' + e + '"'; }).join()); +}; +Transformer.prototype.minify = function(str, options) { + return str; +} +Transformer.prototype.renderSync = function (str, options) { + options = options || {}; + options = clone(options); + this.loadModule(); + if (this._renderSync) { + return this.minify(this._renderSync((this.isBinary ? str : fixString(str)), options), options); + } else if (this.sudoSync) { + options.sudoSync = true; + var res, err; + this._renderAsync((this.isBinary ? str : fixString(str)), options, function (e, val) { + if (e) err = e; + else res = val; + }); + if (err) throw err; + else if (res != undefined) return this.minify(res, options); + else if (typeof this.sudoSync === 'string') throw new Error(this.sudoSync.replace(/FILENAME/g, options.filename || '')); + else throw new Error('There was a problem transforming ' + (options.filename || '') + ' syncronously using ' + this.name); + } else { + throw new Error(this.name + ' does not support transforming syncronously.'); + } +}; +Transformer.prototype.render = function (str, options, cb) { + options = options || {}; + var self = this; + return new Promise(function (resolve, reject) { + self.loadModule(); + if (self._renderAsync) { + self._renderAsync((self.isBinary ? str : fixString(str)), clone(options), function (err, val) { + if (err) reject(err); + else resolve(self.minify(val, options)); + }) + } else { + resolve(self.renderSync(str, options)); + } + }) + .nodeify(cb); +}; +Transformer.prototype.renderFile = function (path, options, cb) { + options = options || {}; + var self = this; + return new Promise(function (resolve, reject) { + options.filename = (path = normalize(path)); + if (self._cache[path]) + resolve(null); + else + fs.readFile(path, function (err, data) { + if (err) reject(err); + else resolve(data); + }) + }) + .then(function (str) { + return self.render(str, options); + }) + .nodeify(cb); +}; +Transformer.prototype.renderFileSync = function (path, options) { + options = options || {}; + options.filename = (path = normalize(path)); + return this.renderSync((this._cache[path] ? null : fs.readFileSync(path)), options); +}; +function fixString(str) { + if (str == null) return str; + //convert buffer to string + str = str.toString(); + // Strip UTF-8 BOM if it exists + str = (0xFEFF == str.charCodeAt(0) + ? str.substring(1) + : str); + //remove `\r` added by windows + return str.replace(/\r/g, ''); +} + +function clone(obj) { + if (Array.isArray(obj)) { + return obj.map(clone); + } else if (obj && typeof obj === 'object') { + var res = {}; + for (var key in obj) { + res[key] = clone(obj[key]); + } + return res; + } else { + return obj; + } +} diff --git a/node_modules/jade/node_modules/transformers/lib/transformers.js b/node_modules/jade/node_modules/transformers/lib/transformers.js new file mode 100644 index 0000000..cf1b612 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/lib/transformers.js @@ -0,0 +1,575 @@ +var dirname = require('path').dirname; +var Transformer = require('./shared'); + +/** + * minifiers must be first in order to be incorporated inside instances of respective output formats + */ +var uglifyJS = require('uglify-js'); +exports.uglify = exports.uglifyJS = exports['uglify-js'] = new Transformer({ + name: 'uglify-js', + engines: ['.'], + outputFormat: 'js', + isMinifier: true, + sync: function (str, options) { + options.fromString = true; + return this.cache(options) || this.cache(options, uglifyJS.minify(str, options).code); + } +}); +var uglifyCSS = require('css'); +exports.uglifyCSS = exports['uglify-css'] = new Transformer({ + name: 'uglify-css', + engines: ['.'], + outputFormat: 'css', + isMinifier: true, + sync: function (str, options) { + options.compress = options.compress != false && options.beautify != true; + return this.cache(options) || this.cache(options, uglifyCSS.stringify(uglifyCSS.parse(str), options)); + } +}); + +exports.uglifyJSON = exports['uglify-json'] = new Transformer({ + name: 'uglify-json', + engines: ['.'], + outputFormat: 'json', + isMinifier: true, + sync: function (str, options) { + return JSON.stringify(JSON.parse(str), null, options.beautify); + } +}); + + +/** + * Syncronous Templating Languages + */ + +function sync(str, options) { + var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); + return tmpl(options); +} + +exports.swig = new Transformer({ + name: 'swig', + engines: ['swig'], + outputFormat: 'xml', + sync: sync +}); + +exports.atpl = new Transformer({ + name: 'atpl', + engines: ['atpl'], + outputFormat: 'xml', + sync: function sync(str, options) { + var tmpl = this.cache(options); + if (!tmpl) { + var cInfo = {cache: options.cache, filename: options.filename}; + if (options.filename) { + delete options.filename; //atpl can't handle absolute windows file paths properly + } + tmpl = this.cache(cInfo, this.engine.compile(str, options)); + } + return tmpl(options); + } +}); + +exports.dot = new Transformer({ + name: 'dot', + engines: ['dot'], + outputFormat: 'xml', + sync: function sync(str, options) { + var tmpl = this.cache(options) || this.cache(options, this.engine.template(str)); + return tmpl(options); + } +}); + +exports.liquor = new Transformer({ + name: 'liquor', + engines: ['liquor'], + outputFormat: 'xml', + sync: sync +}); + +exports.ejs = new Transformer({ + name: 'ejs', + engines: ['ejs'], + outputFormat: 'xml', + sync: sync +}); + +exports.eco = new Transformer({ + name: 'eco', + engines: ['eco'], + outputFormat: 'xml', + sync: sync//N.B. eco's internal this.cache isn't quite right but this bypasses it +}); + +exports.jqtpl = new Transformer({ + name: 'jqtpl', + engines: ['jqtpl'], + outputFormat: 'xml', + sync: function (str, options) { + var engine = this.engine; + var key = (options.cache && options.filename) ? options.filename : '@'; + engine.compile(str, key); + var res = this.engine.render(key, options); + if (!(options.cache && options.filename)) { + delete engine.cache[key]; + } + this.cache(options, true); // caching handled internally + return res; + } +}); + +exports.haml = new Transformer({ + name: 'haml', + engines: ['hamljs'], + outputFormat: 'xml', + sync: sync +}); + +exports['haml-coffee'] = new Transformer({ + name: 'haml-coffee', + engines: ['haml-coffee'], + outputFormat: 'xml', + sync: sync +}); + +exports.whiskers = new Transformer({ + name: 'whiskers', + engines: ['whiskers'], + outputFormat: 'xml', + sync: sync +}); + +exports.hogan = new Transformer({ + name: 'hogan', + engines: ['hogan.js'], + outputFormat: 'xml', + sync: function(str, options){ + var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); + return tmpl.render(options, options.partials); + } +}); + +exports.handlebars = new Transformer({ + name: 'handlebars', + engines: ['handlebars'], + outputFormat: 'xml', + sync: function(str, options){ + for (var partial in options.partials) { + this.engine.registerPartial(partial, options.partials[partial]); + } + var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); + return tmpl(options); + } +}); + +exports.underscore = new Transformer({ + name: 'underscore', + engines: ['underscore'], + outputFormat: 'xml', + sync: function(str, options){ + var tmpl = this.cache(options) || this.cache(options, this.engine.template(str)); + return tmpl(options); + } +}); + +exports.walrus = new Transformer({ + name: 'walrus', + engines: ['walrus'], + outputFormat: 'xml', + sync: function(str, options){ + var tmpl = this.cache(options) || this.cache(options, this.engine.parse(str)); + return tmpl.compile(options); + } +}); + +exports.mustache = new Transformer({ + name: 'mustache', + engines: ['mustache'], + outputFormat: 'xml', + sync: function(str, options){ + var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str)); + return tmpl(options, options.partials); + } +}); + +exports.templayed = new Transformer({ + name: 'templayed', + engines: ['templayed'], + outputFormat: 'xml', + sync: function(str, options){ + var tmpl = this.cache(options) || this.cache(options, this.engine(str)); + return tmpl(options); + } +}); + +exports.plates = new Transformer({ + name: 'plates', + engines: ['plates'], + outputFormat: 'xml', + sync: function(str, options){ + str = this.cache(options) || this.cache(options, str); + return this.engine.bind(str, options, options.map); + } +}); + +exports.mote = new Transformer({ + name: 'mote', + engines: ['mote'], + outputFormat: 'xml', + sync: sync +}); + +exports.toffee = new Transformer({ + name: 'toffee', + engines: ['toffee'], + outputFormat: 'xml', + sync: function (str, options) { + var View = this.engine.view; + var v = this.cache(options) || this.cache(options, new View(str, options)); + var res = v.run(options, require('vm').createContext({})); + if (res[0]) throw res[0]; + else return res[1]; + } +}); + +exports.coffeekup = exports.coffeecup = new Transformer({ + name: 'coffeecup', + engines: ['coffeecup', 'coffeekup'], + outputFormat: 'xml', + sync: function (str, options) { + var compiled = this.cache(options) || this.cache(options, this.engine.compile(str, options)); + return compiled(options); + } +}); + +/** + * Asyncronous Templating Languages + */ + +exports.just = new Transformer({ + name: 'just', + engines: ['just'], + outputFormat: 'xml', + sudoSync: true, + async: function (str, options, cb) { + var JUST = this.engine; + var tmpl = this.cache(options) || this.cache(options, new JUST({ root: { page: str }})); + tmpl.render('page', options, cb); + } +}); + +exports.ect = new Transformer({ + name: 'ect', + engines: ['ect'], + outputFormat: 'xml', + sudoSync: true, // Always runs syncronously + async: function (str, options, cb) { + var ECT = this.engine; + var tmpl = this.cache(options) || this.cache(options, new ECT({ root: { page: str }})); + tmpl.render('page', options, cb); + } +}); + +exports.jade = new Transformer({ + name: 'jade', + engines: ['jade', 'then-jade'], + outputFormat: 'xml', + sudoSync: 'The jade file FILENAME could not be rendered syncronously. N.B. then-jade does not support syncronous rendering.', + async: function (str, options, cb) { + this.cache(options, true);//jade handles this.cache internally + this.engine.render(str, options, cb); + } +}) + +exports.dust = new Transformer({ + name: 'dust', + engines: ['dust', 'dustjs-linkedin'], + outputFormat: 'xml', + sudoSync: false, + async: function (str, options, cb) { + var ext = 'dust' + , views = '.'; + + if (options) { + if (options.ext) ext = options.ext; + if (options.views) views = options.views; + if (options.settings && options.settings.views) views = options.settings.views; + } + + this.engine.onLoad = function(path, callback){ + if ('' == extname(path)) path += '.' + ext; + if ('/' !== path[0]) path = views + '/' + path; + read(path, options, callback); + }; + + var tmpl = this.cache(options) || this.cache(options, this.engine.compileFn(str)); + if (options && !options.cache) this.engine.cache = {};//invalidate dust's internal cache + tmpl(options, cb); + } +}); + +exports.jazz = new Transformer({ + name: 'jazz', + engines: ['jazz'], + outputFormat: 'xml', + sudoSync: true, // except when an async function is passed to locals + async: function (str, options, cb) { + var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); + tmpl.eval(options, function(str){ + cb(null, str); + }); + } +}); + +exports.qejs = new Transformer({ + name: 'qejs', + engines: ['qejs'], + outputFormat: 'xml', + sudoSync: false, + async: function (str, options, cb) { + var tmpl = this.cache(options) || this.cache(options, this.engine.compile(str, options)); + tmpl(options).done(function (result) { + cb(null, result); + }, function (err) { + cb(err); + }); + } +}); + +/** + * Stylsheet Languages + */ + +exports.less = new Transformer({ + name: 'less', + engines: ['less'], + outputFormat: 'css', + sudoSync: 'The less file FILENAME could not be rendered syncronously. This is usually because the file contains `@import url` statements.', + async: function (str, options, cb) { + var self = this; + if (self.cache(options)) return cb(null, self.cache(options)); + if (options.filename) { + options.paths = options.paths || [dirname(options.filename)]; + } + //If this.cache is enabled, compress by default + if (options.compress !== true && options.compress !== false) { + options.compress = options.cache || false; + } + if (options.sudoSync) { + options.syncImport = true; + } + var parser = new(this.engine.Parser)(options); + parser.parse(str, function (err, tree) { + try { + if (err) throw err; + var res = tree.toCSS(options); + self.cache(options, res); + cb(null, res); + } catch (ex) { + if (!(ex instanceof Error) && typeof ex === 'object') { + ex.filename = ex.filename || '"Unkown Source"'; + var err = new Error(self.engine.formatError(ex, options).replace(/^[^:]+:/, ''), ex.filename, ex.line); + err.name = ex.type; + ex = err; + } + console.log('\n\n' + ex.stack + '\n\n'); + return cb(ex); + } + }); + } +}); + +exports.styl = exports.stylus = new Transformer({ + name: 'stylus', + engines: ['stylus'], + outputFormat: 'css', + sudoSync: true,// always runs syncronously + async: function (str, options, cb) { + var self = this; + if (self.cache(options)) return cb(null, self.cache(options)); + if (options.filename) { + options.paths = options.paths || [dirname(options.filename)]; + } + //If this.cache is enabled, compress by default + if (options.compress !== true && options.compress !== false) { + options.compress = options.cache || false; + } + this.engine.render(str, options, function (err, res) { + if (err) return cb(err); + self.cache(options, res); + cb(null, res); + }); + } +}) + +exports.sass = new Transformer({ + name: 'sass', + engines: ['sass'], + outputFormat: 'css', + sync: function (str, options) { + try { + return this.cache(options) || this.cache(options, this.engine.render(str)); + } catch (ex) { + if (options.filename) ex.message += ' in ' + options.filename; + throw ex; + } + } +}); + +/** + * Miscelaneous + */ + +exports.md = exports.markdown = new Transformer({ + name: 'markdown', + engines: ['marked', 'supermarked', 'markdown-js', 'markdown'], + outputFormat: 'html', + sync: function (str, options) { + var arg = options; + if (this.engineName === 'markdown') arg = options.dialect; //even if undefined + return this.cache(options) || this.cache(options, this.engine.parse(str, arg)); + } +}); + + +exports.coffee = exports['coffee-script'] = exports.coffeescript = exports.coffeeScript = new Transformer({ + name: 'coffee-script', + engines: ['coffee-script'], + outputFormat: 'js', + sync: function (str, options) { + return this.cache(options) || this.cache(options, this.engine.compile(str, options)); + } +}); + +exports.cson = new Transformer({ + name: 'cson', + engines: ['cson'], + outputFormat: 'json', + sync: function (str, options) { + //todo: remove once https://github.com/rstacruz/js2coffee/pull/174 accepted & released + if (global.Narcissus) delete global.Narcissus; //prevent global leak + return this.cache(options) || this.cache(options, JSON.stringify(this.engine.parseSync(str))); + } +}); + +exports.cdata = new Transformer({ + name: 'cdata', + engines: ['.'],// `.` means "no dependency" + outputFormat: 'xml', + sync: function (str, options) { + return this.cache(options) || this.cache(options, ''); + } +}); + +exports.component = exports['component-js'] = new Transformer({ + name: 'component-js', + engines: ['component-builder'], + outputFormat: 'js', + async: function (str, options, cb) { + if (this.cache(options)) return this.cache(options); + var self = this; + var builder = new this.engine(dirname(options.filename)); + if (options.development) { + builder.development(); + } + if (options.sourceURLs === true || (options.sourceURLs !== false && options.development)) { + builder.addSourceURLs(); + } + var path = require('path'); + builder.paths = (options.paths || ['components']).map(function (p) { + if (path.resolve(p) === p) { + return p; + } else { + return path.join(dirname(options.filename), p); + } + }); + builder.build(function (err, obj) { + if (err) return cb(err); + else return cb(null, self.cache(options, obj.require + obj.js)); + }); + } +}); + +exports['component-css'] = new Transformer({ + name: 'component-css', + engines: ['component-builder'], + outputFormat: 'css', + async: function (str, options, cb) { + if (this.cache(options)) return this.cache(options); + var self = this; + var builder = new this.engine(dirname(options.filename)); + if (options.development) { + builder.development(); + } + if (options.sourceURLs === true || (options.sourceURLs !== false && options.development)) { + builder.addSourceURLs(); + } + var path = require('path'); + builder.paths = (options.paths || ['components']).map(function (p) { + if (path.resolve(p) === p) { + return p; + } else { + return path.join(dirname(options.filename), p); + } + }); + builder.build(function (err, obj) { + if (err) return cb(err); + else return cb(null, self.cache(options, obj.css)); + }); + } +}); + +exports['html2jade'] = new Transformer({ + name: 'html2jade', + engines: ['html2jade'], + outputFormat: 'jade', + async: function (str, options, cb) { + return this.cache(options) || this.cache(options, this.engine.convertHtml(str, options, cb)); + } +}); + +exports['highlight'] = new Transformer({ + name: 'highlight', + engines: ['highlight.js'], + outputFormat: 'xml', + sync: function (str, options, cb) { + if (this.cache(options)) return this.cache(options); + if (options.lang) { + try { + return this.cache(options, this.engine.highlight(options.lang, str).value); + } catch (ex) {} + } + if (options.auto || !options.lang) { + try { + return this.cache(options, this.engine.highlightAuto(str).value); + } catch (ex) {} + } + return this.cache(options, str); + } +}); + + +/** + * Marker transformers (they don't actually apply a transformation, but let you declare the 'outputFormat') + */ + +exports.css = new Transformer({ + name: 'css', + engines: ['.'],// `.` means "no dependency" + outputFormat: 'css', + sync: function (str, options) { + return this.cache(options) || this.cache(options, str); + } +}); + +exports.js = new Transformer({ + name: 'js', + engines: ['.'],// `.` means "no dependency" + outputFormat: 'js', + sync: function (str, options) { + return this.cache(options) || this.cache(options, str); + } +}); + + diff --git a/node_modules/jade/node_modules/transformers/node_modules/.bin/uglifyjs b/node_modules/jade/node_modules/transformers/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/css/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/History.md b/node_modules/jade/node_modules/transformers/node_modules/css/History.md new file mode 100644 index 0000000..93b15c2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/History.md @@ -0,0 +1,20 @@ + +1.0.7 / 2012-11-21 +================== + + * fix component.json + +1.0.4 / 2012-11-15 +================== + + * update css-stringify + +1.0.3 / 2012-09-01 +================== + + * add component support + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/Makefile b/node_modules/jade/node_modules/transformers/node_modules/css/Makefile new file mode 100644 index 0000000..f13b4a7 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/Makefile @@ -0,0 +1,8 @@ + +test: + @node test + +benchmark: + @node benchmark + +.PHONY: test benchmark \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/Readme.md b/node_modules/jade/node_modules/transformers/node_modules/css/Readme.md new file mode 100644 index 0000000..cf578df --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/Readme.md @@ -0,0 +1,77 @@ + +# css + + CSS parser / stringifier using [css-parse](https://github.com/visionmedia/css-parse) and [css-stringify](https://github.com/visionmedia/css-stringify). + +## Installation + + $ npm install css + +## Example + +js: + +```js +var css = require('css') +var obj = css.parse('tobi { name: "tobi" }') +css.stringify(obj); +``` + +object returned by `.parse()`: + +```json +{ + "stylesheet": { + "rules": [ + { + "selector": "tobi", + "declarations": [ + { + "property": "name", + "value": "tobi" + } + ] + } + ] + } +} +``` + +string returned by `.stringify(ast)`: + +```css +tobi { + name: tobi; +} +``` + +string returned by `.stringify(ast, { compress: true })`: + +```css +tobi{name:tobi} +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/benchmark.js b/node_modules/jade/node_modules/transformers/node_modules/css/benchmark.js new file mode 100644 index 0000000..dec711d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/benchmark.js @@ -0,0 +1,36 @@ + +var css = require('./') + , fs = require('fs') + , read = fs.readFileSync + , str = read('examples/ui.css', 'utf8'); + +var n = 5000; +var ops = 200; +var t = process.hrtime(t); +var results = []; + +while (n--) { + css.stringify(css.parse(str)); + if (n % ops == 0) { + t = process.hrtime(t); + var ms = t[1] / 1000 / 1000; + var persec = (ops * (1000 / ms) | 0); + results.push(persec); + process.stdout.write('\r [' + persec + ' ops/s] [' + n + ']'); + t = process.hrtime(); + } +} + +function sum(arr) { + return arr.reduce(function(sum, n){ + return sum + n; + }); +} + +function mean(arr) { + return sum(arr) / arr.length | 0; +} + +console.log(); +console.log(' avg: %d ops/s', mean(results)); +console.log(' size: %d kb', (str.length / 1024).toFixed(2)); \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/component.json b/node_modules/jade/node_modules/transformers/node_modules/css/component.json new file mode 100644 index 0000000..2769165 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/component.json @@ -0,0 +1,13 @@ +{ + "name": "css", + "version": "1.0.8", + "description": "CSS parser / stringifier using css-parse and css-stringify", + "keywords": ["css", "parser", "stylesheet"], + "dependencies": { + "visionmedia/css-parse": "*", + "visionmedia/css-stringify": "*" + }, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/index.js b/node_modules/jade/node_modules/transformers/node_modules/css/index.js new file mode 100644 index 0000000..19ec91a --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/index.js @@ -0,0 +1,3 @@ + +exports.parse = require('css-parse'); +exports.stringify = require('css-stringify'); diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/.npmignore new file mode 100644 index 0000000..4a3c398 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/.npmignore @@ -0,0 +1,6 @@ +support +test +examples +*.sock +test.css +test.js diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/History.md b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/History.md new file mode 100644 index 0000000..5276aab --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/History.md @@ -0,0 +1,30 @@ + +1.0.4 / 2012-09-17 +================== + + * fix keyframes float percentages + * fix an issue with comments containing slashes. + +1.0.3 / 2012-09-01 +================== + + * add component support + * fix unquoted data uris [rstacruz] + * fix keyframe names with no whitespace [rstacruz] + * fix excess semicolon support [rstacruz] + +1.0.2 / 2012-09-01 +================== + + * fix IE property hack support [rstacruz] + * fix quoted strings in declarations [rstacruz] + +1.0.1 / 2012-07-26 +================== + + * change "selector" to "selectors" array + +1.0.0 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Makefile b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Readme.md b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Readme.md new file mode 100644 index 0000000..fde74a5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/Readme.md @@ -0,0 +1,62 @@ + +# css-parse + + CSS parser. + +## Example + +js: + +```js +var parse = require('css-parse') +parse('tobi { name: "tobi" }') +``` + +object returned: + +```json +{ + "stylesheet": { + "rules": [ + { + "selectors": ["tobi"], + "declarations": [ + { + "property": "name", + "value": "tobi" + } + ] + } + ] + } +} +``` + +## Performance + + Parsed 15,000 lines of CSS (2mb) in 40ms on my macbook air. + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/component.json b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/component.json new file mode 100644 index 0000000..234ebbe --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/component.json @@ -0,0 +1,8 @@ +{ + "name": "css-parse", + "repo": "visionmedia/node-css-parse", + "version": "1.0.3", + "description": "CSS parser", + "keywords": ["css", "parser", "stylesheet"], + "scripts": ["index.js"] +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/index.js b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/index.js new file mode 100644 index 0000000..3ed278f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/index.js @@ -0,0 +1,265 @@ + +module.exports = function(css){ + + /** + * Parse stylesheet. + */ + + function stylesheet() { + return { stylesheet: { rules: rules() }}; + } + + /** + * Opening brace. + */ + + function open() { + return match(/^{\s*/); + } + + /** + * Closing brace. + */ + + function close() { + return match(/^}\s*/); + } + + /** + * Parse ruleset. + */ + + function rules() { + var node; + var rules = []; + whitespace(); + comments(); + while (css[0] != '}' && (node = atrule() || rule())) { + comments(); + rules.push(node); + } + return rules; + } + + /** + * Match `re` and return captures. + */ + + function match(re) { + var m = re.exec(css); + if (!m) return; + css = css.slice(m[0].length); + return m; + } + + /** + * Parse whitespace. + */ + + function whitespace() { + match(/^\s*/); + } + + /** + * Parse comments; + */ + + function comments() { + while (comment()) ; + } + + /** + * Parse comment. + */ + + function comment() { + if ('/' == css[0] && '*' == css[1]) { + var i = 2; + while ('*' != css[i] || '/' != css[i + 1]) ++i; + i += 2; + css = css.slice(i); + whitespace(); + return true; + } + } + + /** + * Parse selector. + */ + + function selector() { + var m = match(/^([^{]+)/); + if (!m) return; + return m[0].trim().split(/\s*,\s*/); + } + + /** + * Parse declaration. + */ + + function declaration() { + // prop + var prop = match(/^(\*?[-\w]+)\s*/); + if (!prop) return; + prop = prop[0]; + + // : + if (!match(/^:\s*/)) return; + + // val + var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)\s*/); + if (!val) return; + val = val[0].trim(); + + // ; + match(/^[;\s]*/); + + return { property: prop, value: val }; + } + + /** + * Parse keyframe. + */ + + function keyframe() { + var m; + var vals = []; + + while (m = match(/^(from|to|\d+%|\.\d+%|\d+\.\d+%)\s*/)) { + vals.push(m[1]); + match(/^,\s*/); + } + + if (!vals.length) return; + + return { + values: vals, + declarations: declarations() + }; + } + + /** + * Parse keyframes. + */ + + function keyframes() { + var m = match(/^@([-\w]+)?keyframes */); + if (!m) return; + var vendor = m[1]; + + // identifier + var m = match(/^([-\w]+)\s*/); + if (!m) return; + var name = m[1]; + + if (!open()) return; + comments(); + + var frame; + var frames = []; + while (frame = keyframe()) { + frames.push(frame); + comments(); + } + + if (!close()) return; + + return { + name: name, + vendor: vendor, + keyframes: frames + }; + } + + /** + * Parse media. + */ + + function media() { + var m = match(/^@media *([^{]+)/); + if (!m) return; + var media = m[1].trim(); + + if (!open()) return; + comments(); + + var style = rules(); + + if (!close()) return; + + return { media: media, rules: style }; + } + + /** + * Parse import + */ + + function atimport() { + return _atrule('import') + } + + /** + * Parse charset + */ + + function atcharset() { + return _atrule('charset'); + } + + /** + * Parse non-block at-rules + */ + + function _atrule(name) { + var m = match(new RegExp('^@' + name + ' *([^;\\n]+);\\s*')); + if (!m) return; + var ret = {} + ret[name] = m[1].trim(); + return ret; + } + + /** + * Parse declarations. + */ + + function declarations() { + var decls = []; + + if (!open()) return; + comments(); + + // declarations + var decl; + while (decl = declaration()) { + decls.push(decl); + comments(); + } + + if (!close()) return; + return decls; + } + + /** + * Parse at rule. + */ + + function atrule() { + return keyframes() + || media() + || atimport() + || atcharset(); + } + + /** + * Parse rule. + */ + + function rule() { + var sel = selector(); + if (!sel) return; + comments(); + return { selectors: sel, declarations: declarations() }; + } + + return stylesheet(); +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/package.json b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/package.json new file mode 100644 index 0000000..ca96832 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-parse/package.json @@ -0,0 +1,27 @@ +{ + "name": "css-parse", + "version": "1.0.4", + "description": "CSS parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "index", + "readme": "\n# css-parse\n\n CSS parser.\n\n## Example\n\njs:\n\n```js\nvar parse = require('css-parse')\nparse('tobi { name: \"tobi\" }')\n```\n\nobject returned:\n\n```json\n{\n \"stylesheet\": {\n \"rules\": [\n {\n \"selectors\": [\"tobi\"],\n \"declarations\": [\n {\n \"property\": \"name\",\n \"value\": \"tobi\"\n }\n ]\n }\n ]\n }\n}\n```\n\n## Performance\n\n Parsed 15,000 lines of CSS (2mb) in 40ms on my macbook air.\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "css-parse@1.0.4", + "dist": { + "shasum": "70b48a26a05cdc7dd8aa42267819dff744cbd9a9" + }, + "_from": "css-parse@1.0.4", + "_resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/.npmignore new file mode 100644 index 0000000..4a3c398 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/.npmignore @@ -0,0 +1,6 @@ +support +test +examples +*.sock +test.css +test.js diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/History.md b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/History.md new file mode 100644 index 0000000..a6ff960 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/History.md @@ -0,0 +1,30 @@ + +1.0.5 / 2013-03-15 +================== + + * fix indentation of multiple selectors in @media. Closes #11 + +1.0.4 / 2012-11-15 +================== + + * fix indentation + +1.0.3 / 2012-09-04 +================== + + * add __@charset__ support [rstacruz] + +1.0.2 / 2012-09-01 +================== + + * add component support + +1.0.1 / 2012-07-26 +================== + + * add "selectors" array support + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Makefile b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Readme.md b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Readme.md new file mode 100644 index 0000000..a36e780 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/Readme.md @@ -0,0 +1,33 @@ + +# css-stringify + + CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse). + +## Performance + + Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air. + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/component.json b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/component.json new file mode 100644 index 0000000..259baef --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/component.json @@ -0,0 +1,8 @@ +{ + "name": "css-stringify", + "repo": "visionmedia/css-stringify", + "version": "1.0.5", + "description": "CSS compiler", + "keywords": ["css", "stringify", "stylesheet"], + "scripts": ["index.js"] +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/index.js b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/index.js new file mode 100644 index 0000000..f528e41 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/index.js @@ -0,0 +1,182 @@ + +/** + * Stringfy the given AST `node`. + * + * @param {Object} node + * @param {Object} options + * @return {String} + * @api public + */ + +module.exports = function(node, options){ + return new Compiler(options).compile(node); +}; + +/** + * Initialize a new `Compiler`. + */ + +function Compiler(options) { + options = options || {}; + this.compress = options.compress; + this.indentation = options.indent; +} + +/** + * Compile `node`. + */ + +Compiler.prototype.compile = function(node){ + return node.stylesheet.rules.map(this.visit, this) + .join(this.compress ? '' : '\n\n'); +}; + +/** + * Visit `node`. + */ + +Compiler.prototype.visit = function(node){ + if (node.charset) return this.charset(node); + if (node.keyframes) return this.keyframes(node); + if (node.media) return this.media(node); + if (node.import) return this.import(node); + return this.rule(node); +}; + +/** + * Visit import node. + */ + +Compiler.prototype.import = function(node){ + return '@import ' + node.import + ';'; +}; + +/** + * Visit media node. + */ + +Compiler.prototype.media = function(node){ + if (this.compress) { + return '@media ' + + node.media + + '{' + + node.rules.map(this.visit, this).join('') + + '}'; + } + + return '@media ' + + node.media + + ' {\n' + + this.indent(1) + + node.rules.map(this.visit, this).join('\n\n') + + this.indent(-1) + + '\n}'; +}; + +/** + * Visit charset node. + */ + +Compiler.prototype.charset = function(node){ + if (this.compress) { + return '@charset ' + node.charset + ';'; + } + + return '@charset ' + node.charset + ';\n'; +}; + +/** + * Visit keyframes node. + */ + +Compiler.prototype.keyframes = function(node){ + if (this.compress) { + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + '{' + + node.keyframes.map(this.keyframe, this).join('') + + '}'; + } + + return '@' + + (node.vendor || '') + + 'keyframes ' + + node.name + + ' {\n' + + this.indent(1) + + node.keyframes.map(this.keyframe, this).join('\n') + + this.indent(-1) + + '}'; +}; + +/** + * Visit keyframe node. + */ + +Compiler.prototype.keyframe = function(node){ + if (this.compress) { + return node.values.join(',') + + '{' + + node.declarations.map(this.declaration, this).join(';') + + '}'; + } + + return this.indent() + + node.values.join(', ') + + ' {\n' + + this.indent(1) + + node.declarations.map(this.declaration, this).join(';\n') + + this.indent(-1) + + '\n' + this.indent() + '}\n'; +}; + +/** + * Visit rule node. + */ + +Compiler.prototype.rule = function(node){ + var indent = this.indent(); + + if (this.compress) { + return node.selectors.join(',') + + '{' + + node.declarations.map(this.declaration, this).join(';') + + '}'; + } + + return node.selectors.map(function(s){ return indent + s }).join(',\n') + + ' {\n' + + this.indent(1) + + node.declarations.map(this.declaration, this).join(';\n') + + this.indent(-1) + + '\n' + this.indent() + '}'; +}; + +/** + * Visit declaration node. + */ + +Compiler.prototype.declaration = function(node){ + if (this.compress) { + return node.property + ':' + node.value; + } + + return this.indent() + node.property + ': ' + node.value; +}; + +/** + * Increase, decrease or return current indentation. + */ + +Compiler.prototype.indent = function(level) { + this.level = this.level || 1; + + if (null != level) { + this.level += level; + return ''; + } + + return Array(this.level).join(this.indentation || ' '); +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/package.json b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/package.json new file mode 100644 index 0000000..1e72642 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/node_modules/css-stringify/package.json @@ -0,0 +1,28 @@ +{ + "name": "css-stringify", + "version": "1.0.5", + "description": "CSS compiler", + "keywords": [ + "css", + "stringify", + "stylesheet" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "devDependencies": { + "mocha": "*", + "should": "*", + "css-parse": "1.0.3" + }, + "main": "index", + "readme": "\n# css-stringify\n\n CSS compiler using the AST provided by [css-parse](https://github.com/visionmedia/css-parse).\n\n## Performance\n\n Formats 15,000 lines of CSS (2mb) in 23ms on my macbook air.\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "Readme.md", + "_id": "css-stringify@1.0.5", + "dist": { + "shasum": "4b2c5773b09304b0e46c04372da684acd5730e98" + }, + "_from": "css-stringify@1.0.5", + "_resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/package.json b/node_modules/jade/node_modules/transformers/node_modules/css/package.json new file mode 100644 index 0000000..791d624 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/package.json @@ -0,0 +1,27 @@ +{ + "name": "css", + "version": "1.0.8", + "description": "CSS parser / stringifier using css-parse and css-stringify", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": { + "css-parse": "1.0.4", + "css-stringify": "1.0.5" + }, + "main": "index", + "readme": "\n# css\n\n CSS parser / stringifier using [css-parse](https://github.com/visionmedia/css-parse) and [css-stringify](https://github.com/visionmedia/css-stringify).\n\n## Installation\n\n $ npm install css\n\n## Example\n\njs:\n\n```js\nvar css = require('css')\nvar obj = css.parse('tobi { name: \"tobi\" }')\ncss.stringify(obj);\n```\n\nobject returned by `.parse()`:\n\n```json\n{\n \"stylesheet\": {\n \"rules\": [\n {\n \"selector\": \"tobi\",\n \"declarations\": [\n {\n \"property\": \"name\",\n \"value\": \"tobi\"\n }\n ]\n }\n ]\n }\n}\n```\n\nstring returned by `.stringify(ast)`:\n\n```css\ntobi {\n name: tobi;\n}\n```\n\nstring returned by `.stringify(ast, { compress: true })`:\n\n```css\ntobi{name:tobi}\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "css@1.0.8", + "dist": { + "shasum": "c5abf699ca66d0654c6791195eb87a03e66d5aae" + }, + "_from": "css@~1.0.8", + "_resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/css/test.js b/node_modules/jade/node_modules/transformers/node_modules/css/test.js new file mode 100644 index 0000000..3e1b4d3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/css/test.js @@ -0,0 +1,6 @@ + +var css = require('./') + , assert = require('assert'); + +assert(css.parse); +assert(css.stringify); diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/promise/.npmignore new file mode 100644 index 0000000..6a2b5b7 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/.npmignore @@ -0,0 +1,6 @@ +components +node_modules +test +.gitignore +.travis.yml +component.json \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/Readme.md b/node_modules/jade/node_modules/transformers/node_modules/promise/Readme.md new file mode 100644 index 0000000..ee16b2f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/Readme.md @@ -0,0 +1,85 @@ +[![Build Status](https://travis-ci.org/then/promise.png)](https://travis-ci.org/then/promise) + +# promise + + This a bare bones [Promises/A+](http://promises-aplus.github.com/promises-spec/) implementation. + + It is designed to get the basics spot on correct, so that you can build extended promise implementations on top of it. + +## Installation + + Server: + + $ npm install promise + + Client: + + $ component install then/promise + +## API + + In the example below shows how you can load the promise library (in a way that works on both client and server). It then demonstrates creating a promise from scratch. You simply call `new Promise(fn)`. There is a complete specification for what is returned by this method in [Promises/A+](http://promises-aplus.github.com/promises-spec/). + +```javascript +var Promise = require('promise'); + +var promise = new Promise(function (resolve, reject) { + get('http://www.google.com', function (err, res) { + if (err) reject(err); + else resolve(res); + }); + }); +``` + +## Extending Promises + + There are three options for extending the promises created by this library. + +### Inheritance + + You can use inheritance if you want to create your own complete promise library with this as your basic starting point, perfect if you have lots of cool features you want to add. Here is an example of a promise library called `Awesome`, which is built on top of `Promise` correctly. + +```javascript +var Promise = require('promise'); +function Awesome(fn) { + if (!(this instanceof Awesome)) return new Awesome(fn); + Promise.call(this, fn); +} +Awesome.prototype = Object.create(Promise.prototype); +Awesome.prototype.constructor = Awesome; + +//Awesome extension +Awesome.prototype.spread = function (cb) { + return this.then(function (arr) { + return cb.apply(this, arr); + }) +}; +``` + + N.B. if you fail to set the prototype and constructor properly or fail to do Promise.call, things can fail in really subtle ways. + +### Wrap + + This is the nuclear option, for when you want to start from scratch. It ensures you won't be impacted by anyone who is extending the prototype (see below). + +```javascript +function Uber(fn) { + if (!(this instanceof Uber)) return new Uber(fn); + var _prom = new Promise(fn); + this.then = _prom.then; +} + +Uber.prototype.spread = function (cb) { + return this.then(function (arr) { + return cb.apply(this, arr); + }) +}; +``` + +### Extending the Prototype + + In general, you should never extend the prototype of this promise implimenation because your extensions could easily conflict with someone elses extensions. However, this organisation will host a library of extensions which do not conflict with each other, so you can safely enable any of those. If you think of an extension that we don't provide and you want to write it, submit an issue on this repository and (if I agree) I'll set you up with a repository and give you permission to commit to it. + +## License + + MIT diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/index.js b/node_modules/jade/node_modules/transformers/node_modules/promise/index.js new file mode 100644 index 0000000..8721f00 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/index.js @@ -0,0 +1,164 @@ +var isPromise = require('is-promise') + +var nextTick +if (typeof setImediate === 'function') nextTick = setImediate +else if (typeof process === 'object' && process && process.nextTick) nextTick = process.nextTick +else nextTick = function (cb) { setTimeout(cb, 0) } + +var extensions = [] + +module.exports = Promise +function Promise(fn) { + if (!(this instanceof Promise)) { + return fn ? new Promise(fn) : defer() + } + if (typeof fn !== 'function') { + throw new TypeError('fn is not a function') + } + + var state = { + isResolved: false, + isSettled: false, + isFulfilled: false, + value: null, + waiting: [], + running: false + } + + function _resolve(val) { + resolve(state, val); + } + function _reject(err) { + reject(state, err); + } + this.then = function _then(onFulfilled, onRejected) { + return then(state, onFulfilled, onRejected); + } + + _resolve.fulfill = deprecate(_resolve, 'resolver.fulfill(x)', 'resolve(x)') + _resolve.reject = deprecate(_reject, 'resolver.reject', 'reject(x)') + + try { + fn(_resolve, _reject) + } catch (ex) { + _reject(ex) + } +} + +function resolve(promiseState, value) { + if (promiseState.isResolved) return + if (isPromise(value)) { + assimilate(promiseState, value) + } else { + settle(promiseState, true, value) + } +} + +function reject(promiseState, reason) { + if (promiseState.isResolved) return + settle(promiseState, false, reason) +} + +function then(promiseState, onFulfilled, onRejected) { + return new Promise(function (resolve, reject) { + function done(next, skipTimeout) { + var callback = promiseState.isFulfilled ? onFulfilled : onRejected + if (typeof callback === 'function') { + function timeoutDone() { + var val + try { + val = callback(promiseState.value) + } catch (ex) { + reject(ex) + return next(true) + } + resolve(val) + next(true) + } + if (skipTimeout) timeoutDone() + else nextTick(timeoutDone) + } else if (promiseState.isFulfilled) { + resolve(promiseState.value) + next(skipTimeout) + } else { + reject(promiseState.value) + next(skipTimeout) + } + } + promiseState.waiting.push(done) + if (promiseState.isSettled && !promiseState.running) processQueue(promiseState) + }) +} + +function processQueue(promiseState) { + function next(skipTimeout) { + if (promiseState.waiting.length) { + promiseState.running = true + promiseState.waiting.shift()(next, skipTimeout) + } else { + promiseState.running = false + } + } + next(false) +} + +function settle(promiseState, isFulfilled, value) { + if (promiseState.isSettled) return + + promiseState.isResolved = promiseState.isSettled = true + promiseState.value = value + promiseState.isFulfilled = isFulfilled + + processQueue(promiseState) +} + +function assimilate(promiseState, thenable) { + try { + promiseState.isResolved = true + thenable.then(function (res) { + if (isPromise(res)) { + assimilate(promiseState, res) + } else { + settle(promiseState, true, res) + } + }, function (err) { + settle(promiseState, false, err) + }) + } catch (ex) { + settle(promiseState, false, ex) + } +} + +Promise.use = function (extension) { + extensions.push(extension) +} + + +function deprecate(method, name, alternative) { + return function () { + var err = new Error(name + ' is deprecated use ' + alternative) + if (typeof console !== 'undefined' && console && typeof console.warn === 'function') { + console.warn(name + ' is deprecated use ' + alternative) + if (err.stack) console.warn(err.stack) + } else { + nextTick(function () { + throw err + }) + } + method.apply(this, arguments) + } +} +function defer() { + var err = new Error('promise.defer() is deprecated') + if (typeof console !== 'undefined' && console && typeof console.warn === 'function') { + console.warn('promise.defer() is deprecated') + if (err.stack) console.warn(err.stack) + } else { + nextTick(function () { + throw err + }) + } + var resolver + var promise = new Promise(function (res) { resolver = res }) + return {resolver: resolver, promise: promise} +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/.npmignore new file mode 100644 index 0000000..ebf8391 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/.npmignore @@ -0,0 +1,6 @@ +component +build +node_modules +test.js +component.json +.gitignore \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/index.js b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/index.js new file mode 100644 index 0000000..23ea1a4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/index.js @@ -0,0 +1,5 @@ +module.exports = isPromise; + +function isPromise(obj) { + return obj && typeof obj.then === 'function'; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/package.json b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/package.json new file mode 100644 index 0000000..d6ea449 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/package.json @@ -0,0 +1,29 @@ +{ + "name": "is-promise", + "version": "1.0.0", + "description": "Test whether an object looks like a promises-a+ promise", + "main": "index.js", + "scripts": { + "test": "mocha -R spec" + }, + "repository": { + "type": "git", + "url": "https://github.com/then/is-promise.git" + }, + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "devDependencies": { + "better-assert": "~0.1.0", + "mocha": "~1.7.4" + }, + "readme": "\n# is-promise\n\n Test whether an object looks like a promises-a+ promise\n\n## Installation\n\n Client:\n\n $ component install then/is-promise\n\n Server:\n\n $ npm install is-promise\n\n## API\n\n```javascript\nvar isPromise = require('is-promise');\n\nisPromise({then:function () {...}});//=>true\nisPromise(null);//=>false\nisPromise({});//=>false\nisPromise({then: true})//=>false\n```\n\n## License\n\n MIT\n", + "readmeFilename": "readme.md", + "_id": "is-promise@1.0.0", + "dist": { + "shasum": "02c535eb4d82698932b6f7037718d58f7a36f66c" + }, + "_from": "is-promise@~1", + "_resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.0.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/readme.md b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/readme.md new file mode 100644 index 0000000..bfeda13 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/node_modules/is-promise/readme.md @@ -0,0 +1,29 @@ + +# is-promise + + Test whether an object looks like a promises-a+ promise + +## Installation + + Client: + + $ component install then/is-promise + + Server: + + $ npm install is-promise + +## API + +```javascript +var isPromise = require('is-promise'); + +isPromise({then:function () {...}});//=>true +isPromise(null);//=>false +isPromise({});//=>false +isPromise({then: true})//=>false +``` + +## License + + MIT diff --git a/node_modules/jade/node_modules/transformers/node_modules/promise/package.json b/node_modules/jade/node_modules/transformers/node_modules/promise/package.json new file mode 100644 index 0000000..4052ac6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/promise/package.json @@ -0,0 +1,33 @@ +{ + "name": "promise", + "version": "2.0.0", + "description": "Bare bones Promises/A+ implementation", + "main": "index.js", + "scripts": { + "test": "mocha -R spec --timeout 200 --slow 99999" + }, + "repository": { + "type": "git", + "url": "https://github.com/then/promise.git" + }, + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "dependencies": { + "is-promise": "~1" + }, + "devDependencies": { + "promises-aplus-tests": "*", + "mocha-as-promised": "~1.2.1", + "better-assert": "~1.0.0" + }, + "readme": "[![Build Status](https://travis-ci.org/then/promise.png)](https://travis-ci.org/then/promise)\r\n\r\n# promise\r\n\r\n This a bare bones [Promises/A+](http://promises-aplus.github.com/promises-spec/) implementation.\r\n\r\n It is designed to get the basics spot on correct, so that you can build extended promise implementations on top of it.\r\n\r\n## Installation\r\n\r\n Server:\r\n\r\n $ npm install promise\r\n\r\n Client:\r\n\r\n $ component install then/promise\r\n\r\n## API\r\n\r\n In the example below shows how you can load the promise library (in a way that works on both client and server). It then demonstrates creating a promise from scratch. You simply call `new Promise(fn)`. There is a complete specification for what is returned by this method in [Promises/A+](http://promises-aplus.github.com/promises-spec/).\r\n\r\n```javascript\r\nvar Promise = require('promise');\r\n\r\nvar promise = new Promise(function (resolve, reject) {\r\n get('http://www.google.com', function (err, res) {\r\n if (err) reject(err);\r\n else resolve(res);\r\n });\r\n });\r\n```\r\n\r\n## Extending Promises\r\n\r\n There are three options for extending the promises created by this library.\r\n\r\n### Inheritance\r\n\r\n You can use inheritance if you want to create your own complete promise library with this as your basic starting point, perfect if you have lots of cool features you want to add. Here is an example of a promise library called `Awesome`, which is built on top of `Promise` correctly.\r\n\r\n```javascript\r\nvar Promise = require('promise');\r\nfunction Awesome(fn) {\r\n if (!(this instanceof Awesome)) return new Awesome(fn);\r\n Promise.call(this, fn);\r\n}\r\nAwesome.prototype = Object.create(Promise.prototype);\r\nAwesome.prototype.constructor = Awesome;\r\n\r\n//Awesome extension\r\nAwesome.prototype.spread = function (cb) {\r\n return this.then(function (arr) {\r\n return cb.apply(this, arr);\r\n })\r\n};\r\n```\r\n\r\n N.B. if you fail to set the prototype and constructor properly or fail to do Promise.call, things can fail in really subtle ways.\r\n\r\n### Wrap\r\n\r\n This is the nuclear option, for when you want to start from scratch. It ensures you won't be impacted by anyone who is extending the prototype (see below).\r\n\r\n```javascript\r\nfunction Uber(fn) {\r\n if (!(this instanceof Uber)) return new Uber(fn);\r\n var _prom = new Promise(fn);\r\n this.then = _prom.then;\r\n}\r\n\r\nUber.prototype.spread = function (cb) {\r\n return this.then(function (arr) {\r\n return cb.apply(this, arr);\r\n })\r\n};\r\n```\r\n\r\n### Extending the Prototype\r\n\r\n In general, you should never extend the prototype of this promise implimenation because your extensions could easily conflict with someone elses extensions. However, this organisation will host a library of extensions which do not conflict with each other, so you can safely enable any of those. If you think of an extension that we don't provide and you want to write it, submit an issue on this repository and (if I agree) I'll set you up with a repository and give you permission to commit to it.\r\n\r\n## License\r\n\r\n MIT\r\n", + "readmeFilename": "Readme.md", + "_id": "promise@2.0.0", + "dist": { + "shasum": "b1504b50f1102d7312ec8723c9bc69703ef5f9bf" + }, + "_from": "promise@~2.0", + "_resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..94fceeb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/.npmignore @@ -0,0 +1,2 @@ +tmp/ +node_modules/ diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md new file mode 100644 index 0000000..de6abe5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/README.md @@ -0,0 +1,544 @@ +UglifyJS 2 +========== + +UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. + +This page documents the command line utility. For +[API and internals documentation see my website](http://lisperator.net/uglifyjs/). +There's also an +[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, +Chrome and probably Safari). + +Install +------- + +First make sure you have installed the latest version of [node.js](http://nodejs.org/) +(You may need to restart your computer after this step). + +From NPM for use as a command line app: + + npm install uglify-js -g + +From NPM for programmatic use: + + npm install uglify-js + +From Git: + + git clone git://github.com/mishoo/UglifyJS2.git + cd UglifyJS2 + npm link . + +Usage +----- + + uglifyjs [input files] [options] + +UglifyJS2 can take multiple input files. It's recommended that you pass the +input files first, then pass the options. UglifyJS will parse input files +in sequence and apply any compression options. The files are parsed in the +same global scope, that is, a reference from a file to some +variable/function declared in another file will be matched properly. + +If you want to read from STDIN instead, pass a single dash instead of input +files. + +The available options are: + + --source-map Specify an output file where to generate source map. + [string] + --source-map-root The path to the original source to be included in the + source map. [string] + --source-map-url The path to the source map to be added in //@ + sourceMappingURL. Defaults to the value passed with + --source-map. [string] + --in-source-map Input source map, useful if you're compressing JS that was + generated from some other original code. + -p, --prefix Skip prefix for original filenames that appear in source + maps. For example -p 3 will drop 3 directories from file + names and ensure they are relative paths. + -o, --output Output file (default STDOUT). + -b, --beautify Beautify output/specify output options. [string] + -m, --mangle Mangle names/pass mangler options. [string] + -r, --reserved Reserved names to exclude from mangling. + -c, --compress Enable compressor/pass compressor options. Pass options + like -c hoist_vars=false,if_return=false. Use -c with no + argument to use the default compression options. [string] + -d, --define Global definitions [string] + --comments Preserve copyright comments in the output. By default this + works like Google Closure, keeping JSDoc-style comments + that contain "@license" or "@preserve". You can optionally + pass one of the following arguments to this flag: + - "all" to keep all comments + - a valid JS regexp (needs to start with a slash) to keep + only comments that match. + Note that currently not *all* comments can be kept when + compression is on, because of dead code removal or + cascading statements into sequences. [string] + --stats Display operations run time on STDERR. [boolean] + --acorn Use Acorn for parsing. [boolean] + --spidermonkey Assume input fles are SpiderMonkey AST format (as JSON). + [boolean] + --self Build itself (UglifyJS2) as a library (implies + --wrap=UglifyJS --export-all) [boolean] + --wrap Embed everything in a big function, making the “exports” + and “global” variables available. You need to pass an + argument to this option to specify the name that your + module will take when included in, say, a browser. + [string] + --export-all Only used when --wrap, this tells UglifyJS to add code to + automatically export all globals. [boolean] + --lint Display some scope warnings [boolean] + -v, --verbose Verbose [boolean] + -V, --version Print version number and exit. [boolean] + +Specify `--output` (`-o`) to declare the output file. Otherwise the output +goes to STDOUT. + +## Source map options + +UglifyJS2 can generate a source map file, which is highly useful for +debugging your compressed JavaScript. To get a source map, pass +`--source-map output.js.map` (full path to the file where you want the +source map dumped). + +Additionally you might need `--source-map-root` to pass the URL where the +original files can be found. In case you are passing full paths to input +files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of +directories to drop from the path prefix when declaring files in the source +map. + +For example: + + uglifyjs /home/doe/work/foo/src/js/file1.js \ + /home/doe/work/foo/src/js/file2.js \ + -o foo.min.js \ + --source-map foo.min.js.map \ + --source-map-root http://foo.com/src \ + -p 5 -c -m + +The above will compress and mangle `file1.js` and `file2.js`, will drop the +output in `foo.min.js` and the source map in `foo.min.js.map`. The source +mapping will refer to `http://foo.com/src/js/file1.js` and +`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` +as the source map root, and the original files as `js/file1.js` and +`js/file2.js`). + +### Composed source map + +When you're compressing JS code that was output by a compiler such as +CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd +like to map back to the original code (i.e. CoffeeScript). UglifyJS has an +option to take an input source map. Assuming you have a mapping from +CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → +compressed JS by mapping every token in the compiled JS to its original +location. + +To use this feature you need to pass `--in-source-map +/path/to/input/source.map`. Normally the input source map should also point +to the file containing the generated JS, so if that's correct you can omit +input files from the command line. + +## Mangler options + +To enable the mangler you need to pass `--mangle` (`-m`). Optionally you +can pass `-m sort=true` (we'll possibly have other flags in the future) in order +to assign shorter names to most frequently used variables. This saves a few +hundred bytes on jQuery before gzip, but the output is _bigger_ after gzip +(and seems to happen for other libraries I tried it on) therefore it's not +enabled by default. + +When mangling is enabled but you want to prevent certain names from being +mangled, you can declare those names with `--reserved` (`-r`) — pass a +comma-separated list of names. For example: + + uglifyjs ... -m -r '$,require,exports' + +to prevent the `require`, `exports` and `$` names from being changed. + +## Compressor options + +You need to pass `--compress` (`-c`) to enable the compressor. Optionally +you can pass a comma-separated list of options. Options are in the form +`foo=bar`, or just `foo` (the latter implies a boolean option that you want +to set `true`; it's effectively a shortcut for `foo=true`). + +The defaults should be tuned for maximum compression on most code. Here are +the available options (all are `true` by default, except `hoist_vars`): + +- `sequences` -- join consecutive simple statements using the comma operator +- `properties` -- rewrite property access using the dot notation, for + example `foo["bar"] → foo.bar` +- `dead_code` -- remove unreachable code +- `drop_debugger` -- remove `debugger;` statements +- `unsafe` -- apply "unsafe" transformations (discussion below) +- `conditionals` -- apply optimizations for `if`-s and conditional + expressions +- `comparisons` -- apply certain optimizations to binary nodes, for example: + `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, + e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. +- `evaluate` -- attempt to evaluate constant expressions +- `booleans` -- various optimizations for boolean context, for example `!!a + ? b : c → a ? b : c` +- `loops` -- optimizations for `do`, `while` and `for` loops when we can + statically determine the condition +- `unused` -- drop unreferenced functions and variables +- `hoist_funs` -- hoist function declarations +- `hoist_vars` -- hoist `var` declarations (this is `false` by default + because it seems to increase the size of the output in general) +- `if_return` -- optimizations for if/return and if/continue +- `join_vars` -- join consecutive `var` statements +- `cascade` -- small optimization for sequences, transform `x, x` into `x` + and `x = something(), x` into `x = something()` +- `warnings` -- display warnings when dropping unreachable code or unused + declarations etc. + +### Conditional compilation + +You can use the `--define` (`-d`) switch in order to declare global +variables that UglifyJS will assume to be constants (unless defined in +scope). For example if you pass `--define DEBUG=false` then, coupled with +dead code removal UglifyJS will discard the following from the output: + + if (DEBUG) { + console.log("debug stuff"); + } + +UglifyJS will warn about the condition being always false and about dropping +unreachable code; for now there is no option to turn off only this specific +warning, you can pass `warnings=false` to turn off *all* warnings. + +Another way of doing that is to declare your globals as constants in a +separate file and include it into the build. For example you can have a +`build/defines.js` file with the following: + + const DEBUG = false; + const PRODUCTION = true; + // etc. + +and build your code like this: + + uglifyjs build/defines.js js/foo.js js/bar.js... -c + +UglifyJS will notice the constants and, since they cannot be altered, it +will evaluate references to them to the value itself and drop unreachable +code as usual. The possible downside of this approach is that the build +will contain the `const` declarations. + + +## Beautifier options + +The code generator tries to output shortest code possible by default. In +case you want beautified output, pass `--beautify` (`-b`). Optionally you +can pass additional arguments that control the code output: + +- `beautify` (default `true`) -- whether to actually beautify the output. + Passing `-b` will set this to true, but you might need to pass `-b` even + when you want to generate minified code, in order to specify additional + arguments, so you can use `-b beautify=false` to override it. +- `indent-level` (default 4) +- `indent-start` (default 0) -- prefix all lines by that many spaces +- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal + objects +- `space-colon` (default `true`) -- insert a space after the colon signs +- `ascii-only` (default `false`) -- escape Unicode characters in strings and + regexps +- `inline-script` (default `false`) -- escape the slash in occurrences of + ` 0) { + sys.error("WARN: Ignoring input files since --self was passed"); + } + files = UglifyJS.FILES; + if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; + ARGS.export_all = true; +} + +var ORIG_MAP = ARGS.in_source_map; + +if (ORIG_MAP) { + ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); + if (files.length == 0) { + sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); + files = [ ORIG_MAP.file ]; + } + if (ARGS.source_map_root == null) { + ARGS.source_map_root = ORIG_MAP.sourceRoot; + } +} + +if (files.length == 0) { + files = [ "-" ]; +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; +var TOPLEVEL = null; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: OUTPUT_FILE, + root: ARGS.source_map_root, + orig: ORIG_MAP, +}) : null; + +OUTPUT_OPTIONS.source_map = SOURCE_MAP; + +try { + var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); + var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); +} catch(ex) { + if (ex instanceof UglifyJS.DefaultsError) { + sys.error(ex.msg); + sys.error("Supported options:"); + sys.error(sys.inspect(ex.defs)); + process.exit(1); + } +} + +files.forEach(function(file) { + var code = read_whole_file(file); + if (ARGS.p != null) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + time_it("parse", function(){ + if (ARGS.spidermonkey) { + var program = JSON.parse(code); + if (!TOPLEVEL) TOPLEVEL = program; + else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); + } + else if (ARGS.acorn) { + TOPLEVEL = acorn.parse(code, { + locations : true, + trackComments : true, + sourceFile : file, + program : TOPLEVEL + }); + } + else { + TOPLEVEL = UglifyJS.parse(code, { + filename: file, + toplevel: TOPLEVEL + }); + }; + }); +}); + +if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ + TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); +}); + +if (ARGS.wrap) { + TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); +} + +var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; + +if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope(); + if (ARGS.lint) { + TOPLEVEL.scope_warnings(); + } + }); +} + +if (COMPRESS) { + time_it("squeeze", function(){ + TOPLEVEL = TOPLEVEL.transform(compressor); + }); +} + +if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope(); + if (MANGLE) { + TOPLEVEL.compute_char_frequency(MANGLE); + } + }); +} + +if (MANGLE) time_it("mangle", function(){ + TOPLEVEL.mangle_names(MANGLE); +}); +time_it("generate", function(){ + TOPLEVEL.print(output); +}); + +output = output.get(); + +if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); + output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/"; +} + +if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); +} else { + sys.print(output); + sys.error("\n"); +} + +if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } +} + +/* -----[ functions ]----- */ + +function normalize(o) { + for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { + o[i.replace(/-/g, "_")] = o[i]; + delete o[i]; + } +} + +function getOptions(x, constants) { + x = ARGS[x]; + if (!x) return null; + var ret = {}; + if (x !== true) { + var ast; + try { + ast = UglifyJS.parse(x); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Error parsing arguments in: " + x); + process.exit(1); + } + } + ast.walk(new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.AST_Toplevel) return; // descend + if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend + if (node instanceof UglifyJS.AST_Seq) return; // descend + if (node instanceof UglifyJS.AST_Assign) { + var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); + var value = node.right; + if (constants) + value = new Function("return (" + value.print_to_string() + ")")(); + ret[name] = value; + return true; // no descend + } + sys.error(node.TYPE) + sys.error("Error parsing arguments in: " + x); + process.exit(1); + })); + } + return ret; +} + +function read_whole_file(filename) { + if (filename == "-") { + // XXX: this sucks. How does one read the whole STDIN + // synchronously? + filename = "/dev/stdin"; + } + try { + return fs.readFileSync(filename, "utf8"); + } catch(ex) { + sys.error("ERROR: can't read file: " + filename); + process.exit(1); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js new file mode 100644 index 0000000..62bdd8d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/ast.js @@ -0,0 +1,964 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; + else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) + props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0;) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base; + if (proto && proto.initialize || (methods && methods.initialize)) + code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; +}; + +var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +}, null); + +var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); // not sure the indirection will be any help + } +}, null); + +AST_Node.warn_function = null; +AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) + AST_Node.warn_function(string_template(txt, props)); +}; + +/* -----[ statements ]----- */ + +var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements", +}); + +var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement", +}, AST_Statement); + +var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: "Represents a directive, like \"use strict\";", + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + }, +}, AST_Statement); + +var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } + else node.body.forEach(function(stat){ + stat._walk(visitor); + }); +}; + +var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + +var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement", +}, AST_Block); + +var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } +}, AST_Statement); + +var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.label._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement", +}, AST_DWLoop); + +var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement", +}, AST_DWLoop); + +var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ scope and functions ]----- */ + +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)", + }, +}, AST_Block); + +var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n){ return n.name == node.name }, to_export)) + to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym){ + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ name: "exports" }), + property: new AST_String({ value: sym.name }), + }), + operator: "=", + right: new AST_SymbolRef(sym), + }), + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } +}, AST_Scope); + +var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg){ + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } +}, AST_Scope); + +var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function" +}, AST_Lambda); + +var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" +}, AST_Lambda); + +var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" +}, AST_Lambda); + +/* -----[ JUMPS ]----- */ + +var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" +}, AST_Statement); + +var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function(){ + this.value._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" +}, AST_Exit); + +var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" +}, AST_Exit); + +var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none", + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function(){ + this.label._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" +}, AST_LoopControl); + +var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" +}, AST_LoopControl); + +/* -----[ IF ]----- */ + +var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ SWITCH ]----- */ + +var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches", +}, AST_Block); + +var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", +}, AST_SwitchBranch); + +var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_SwitchBranch); + +/* -----[ EXCEPTIONS ]----- */ + +var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } +}, AST_Block); + +// XXX: this is wrong according to ECMA-262 (12.4). the catch block +// should introduce another scope, as the argname should be visible +// only inside the catch block. However, doing it this way because of +// IE which simply introduces the name in the surrounding scope. If +// we ever want to fix this then AST_Catch should inherit from +// AST_Scope. +var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); + +/* -----[ VAR/CONST ]----- */ + +var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.definitions.forEach(function(def){ + def._walk(visitor); + }); + }); + } +}, AST_Statement); + +var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" +}, AST_Definitions); + +var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" +}, AST_Definitions); + +var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } +}); + +/* -----[ OTHER ]----- */ + +var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.args.forEach(function(arg){ + arg._walk(visitor); + }); + }); + } +}); + +var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" +}, AST_Call); + +var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0;) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } +}); + +var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } +}); + +var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Sub = DEFNODE("Sub", null, { + $documentation: "Index-style property access, i.e. `a[\"foo\"]`", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}); + +var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" +}, AST_Unary); + +var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" +}, AST_Unary); + +var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.left._walk(visitor); + this.right._walk(visitor); + }); + } +}); + +var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } +}); + +var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`", +}, AST_Binary); + +/* -----[ LITERALS ]----- */ + +var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.elements.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + +var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.properties.forEach(function(prop){ + prop._walk(visitor); + }); + }); + } +}); + +var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.value._walk(visitor); + }); + } +}); + +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property", +}, AST_ObjectProperty); + +var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property", +}, AST_ObjectProperty); + +var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property", +}, AST_ObjectProperty); + +var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols", +}); + +var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" +}, AST_Symbol); + +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } +}, AST_Symbol); + +var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable", +}, AST_SymbolDeclaration); + +var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" +}, AST_SymbolDeclaration); + +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument", +}, AST_SymbolVar); + +var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function", +}, AST_SymbolDeclaration); + +var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression", +}, AST_SymbolDeclaration); + +var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch", +}, AST_SymbolDeclaration); + +var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LabelRef*] a list of nodes referring to this label" + } +}, AST_Symbol); + +var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)", +}, AST_Symbol); + +var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol", +}, AST_Symbol); + +var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol", +}, AST_Symbol); + +var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } +}); + +var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } +}, AST_Constant); + +var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } +}, AST_Constant); + +var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } +}, AST_Constant); + +var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms", +}, AST_Constant); + +var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null +}, AST_Atom); + +var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0/0 +}, AST_Atom); + +var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: (function(){}()) +}, AST_Atom); + +var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: (function(){}()) +}, AST_Atom); + +var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1/0 +}, AST_Atom); + +var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans", +}, AST_Atom); + +var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false +}, AST_Boolean); + +var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true +}, AST_Boolean); + +/* -----[ TreeWalker ]----- */ + +function TreeWalker(callback) { + this.visit = callback; + this.stack = []; +}; +TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function(){ + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if ((p instanceof AST_If && p.condition === self) || + (p instanceof AST_Conditional && p.condition === self) || + (p instanceof AST_DWLoop && p.condition === self) || + (p instanceof AST_For && p.condition === self) || + (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } + } else { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_Switch + || x instanceof AST_For + || x instanceof AST_ForIn + || x instanceof AST_DWLoop) return x; + } + } + } +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/compress.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/compress.js new file mode 100644 index 0000000..ca23c40 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/compress.js @@ -0,0 +1,1968 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) + return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences : !false_by_default, + properties : !false_by_default, + dead_code : !false_by_default, + drop_debugger : !false_by_default, + unsafe : !false_by_default, + unsafe_comps : false, + conditionals : !false_by_default, + comparisons : !false_by_default, + evaluate : !false_by_default, + booleans : !false_by_default, + loops : !false_by_default, + unused : !false_by_default, + hoist_funs : !false_by_default, + hoist_vars : false, + if_return : !false_by_default, + join_vars : !false_by_default, + cascade : !false_by_default, + side_effects : !false_by_default, + + warnings : true, + global_defs : {} + }, true); +}; + +Compressor.prototype = new TreeTransformer; +merge(Compressor.prototype, { + option: function(key) { return this.options[key] }, + warn: function() { + if (this.options.warnings) + AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + // dead code removal might leave further unused declarations. + // this'll usually save very few bytes, but the performance + // hit seems negligible so I'll just drop it here. + + // no point to repeat warnings. + var save_warnings = this.options.warnings; + this.options.warnings = false; + node.drop_unused(this); + this.options.warnings = save_warnings; + } + node._squeezed = true; + return node; + } +}); + +(function(){ + + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor){ + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + }; + + OPT(AST_Node, function(self, compressor){ + return self; + }); + + AST_Node.DEFMETHOD("equivalent_to", function(node){ + // XXX: this is a rather expensive way to test two node's equivalence: + return this.print_to_string() == node.print_to_string(); + }); + + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + }; + + function make_node_from_constant(compressor, val, orig) { + // XXX: WIP. + // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof AST_SymbolRef) { + // var scope = compressor.find_parent(AST_Scope); + // var def = scope.find_variable(node); + // node.thedef = def; + // return node; + // } + // })).transform(compressor); + + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + case "boolean": + return make_node(val ? AST_True : AST_False, orig); + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + }; + + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + }; + + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + }; + + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + return statements; + + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + }; + + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0;) { + var stat = statements[i]; + switch (true) { + case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + CHANGED = true; + // note, ret.length is probably always zero + // because we drop unreachable code before this + // step. nevertheless, it's good to check. + continue loop; + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + //--- + // pretty silly case, but: + // if (foo()) return; return; ==> foo(); return; + if (((in_lambda && ret.length == 0) + || (ret[0] instanceof AST_Return && !ret[0].value)) + && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + //--- + // if (foo()) return x; return y; ==> return foo() ? x : y; + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + //--- + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + ret.unshift(stat); + break; + default: + ret.unshift(stat); + break; + } + } + return ret; + }; + + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat){ + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + }; + + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + }; + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + }; + + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + }; + var ret = [], prev = null; + statements.forEach(function(stat){ + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } + else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch(ex) { + if (ex !== opera) throw ex; + } + } + else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } + else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } + else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } + else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } + else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + }; + + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } + else if (stat instanceof AST_For + && prev instanceof AST_Definitions + && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } + else { + prev = stat; + a.push(stat); + } + return a; + }, []); + }; + + }; + + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node){ + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + }; + + /* -----[ boolean/negation helpers ]----- */ + + // methods to determine whether an expression has a boolean result type + (function (def){ + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function(){ return false }); + def(AST_UnaryPrefix, function(){ + return member(this.operator, unary_bool); + }); + def(AST_Binary, function(){ + return member(this.operator, binary_bool) || + ( (this.operator == "&&" || this.operator == "||") && + this.left.is_boolean() && this.right.is_boolean() ); + }); + def(AST_Conditional, function(){ + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function(){ + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function(){ + return this.cdr.is_boolean(); + }); + def(AST_True, function(){ return true }); + def(AST_False, function(){ return true }); + })(function(node, func){ + node.DEFMETHOD("is_boolean", func); + }); + + // methods to determine if an expression has a string result type + (function (def){ + def(AST_Node, function(){ return false }); + def(AST_String, function(){ return true }); + def(AST_UnaryPrefix, function(){ + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor){ + return this.operator == "+" && + (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor){ + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor){ + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor){ + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor){ + return compressor.option("unsafe") + && this.expression instanceof AST_SymbolRef + && this.expression.name == "String" + && this.expression.undeclared(); + }); + })(function(node, func){ + node.DEFMETHOD("is_string", func); + }); + + function best_of(ast1, ast2) { + return ast1.print_to_string().length > + ast2.print_to_string().length + ? ast2 : ast1; + }; + + // methods to evaluate a constant expression + (function (def){ + // The evaluate method returns an array with one or two + // elements. If the node has been successfully reduced to a + // constant, then the second element tells us the value; + // otherwise the second element is missing. The first element + // of the array is always an AST_Node descendant; when + // evaluation was successful it's a node that represents the + // constant; otherwise it's the original node. + AST_Node.DEFMETHOD("evaluate", function(compressor){ + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(), ast = make_node_from_constant(compressor, val, this); + return [ best_of(ast, this), val ]; + } catch(ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function(){ + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function(){ + // XXX: AST_Function inherits from AST_Scope, which itself + // inherits from AST_Statement; however, an AST_Function + // isn't really a statement. This could byte in other + // places too. :-( Wish JS had multiple inheritance. + return [ this ]; + }); + function ev(node) { + return node._eval(); + }; + def(AST_Node, function(){ + throw def; // not constant + }); + def(AST_Constant, function(){ + return this.getValue(); + }); + def(AST_UnaryPrefix, function(){ + var e = this.expression; + switch (this.operator) { + case "!": return !ev(e); + case "typeof": return typeof ev(e); + case "void": return void ev(e); + case "~": return ~ev(e); + case "-": + e = ev(e); + if (e === 0) throw def; + return -e; + case "+": return +ev(e); + } + throw def; + }); + def(AST_Binary, function(){ + var left = this.left, right = this.right; + switch (this.operator) { + case "&&" : return ev(left) && ev(right); + case "||" : return ev(left) || ev(right); + case "|" : return ev(left) | ev(right); + case "&" : return ev(left) & ev(right); + case "^" : return ev(left) ^ ev(right); + case "+" : return ev(left) + ev(right); + case "*" : return ev(left) * ev(right); + case "/" : return ev(left) / ev(right); + case "%" : return ev(left) % ev(right); + case "-" : return ev(left) - ev(right); + case "<<" : return ev(left) << ev(right); + case ">>" : return ev(left) >> ev(right); + case ">>>" : return ev(left) >>> ev(right); + case "==" : return ev(left) == ev(right); + case "===" : return ev(left) === ev(right); + case "!=" : return ev(left) != ev(right); + case "!==" : return ev(left) !== ev(right); + case "<" : return ev(left) < ev(right); + case "<=" : return ev(left) <= ev(right); + case ">" : return ev(left) > ev(right); + case ">=" : return ev(left) >= ev(right); + case "in" : return ev(left) in ev(right); + case "instanceof" : return ev(left) instanceof ev(right); + } + throw def; + }); + def(AST_Conditional, function(){ + return ev(this.condition) + ? ev(this.consequent) + : ev(this.alternative); + }); + def(AST_SymbolRef, function(){ + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init); + throw def; + }); + })(function(node, func){ + node.DEFMETHOD("_eval", func); + }); + + // method to negate an expression + (function(def){ + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + }; + def(AST_Node, function(){ + return basic_negation(this); + }); + def(AST_Statement, function(){ + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function(){ + return basic_negation(this); + }); + def(AST_UnaryPrefix, function(){ + if (this.operator == "!") + return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor){ + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor){ + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor){ + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=" : self.operator = ">" ; return self; + case "<" : self.operator = ">=" ; return self; + case ">=" : self.operator = "<" ; return self; + case ">" : self.operator = "<=" ; return self; + } + } + switch (op) { + case "==" : self.operator = "!="; return self; + case "!=" : self.operator = "=="; return self; + case "===": self.operator = "!=="; return self; + case "!==": self.operator = "==="; return self; + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func){ + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor); + }); + }); + + // determine if expression has side effects + (function(def){ + def(AST_Node, function(){ return true }); + + def(AST_EmptyStatement, function(){ return false }); + def(AST_Constant, function(){ return false }); + def(AST_This, function(){ return false }); + + def(AST_Block, function(){ + for (var i = this.body.length; --i >= 0;) { + if (this.body[i].has_side_effects()) + return true; + } + return false; + }); + + def(AST_SimpleStatement, function(){ + return this.body.has_side_effects(); + }); + def(AST_Defun, function(){ return true }); + def(AST_Function, function(){ return false }); + def(AST_Binary, function(){ + return this.left.has_side_effects() + || this.right.has_side_effects(); + }); + def(AST_Assign, function(){ return true }); + def(AST_Conditional, function(){ + return this.condition.has_side_effects() + || this.consequent.has_side_effects() + || this.alternative.has_side_effects(); + }); + def(AST_Unary, function(){ + return this.operator == "delete" + || this.operator == "++" + || this.operator == "--" + || this.expression.has_side_effects(); + }); + def(AST_SymbolRef, function(){ return false }); + def(AST_Object, function(){ + for (var i = this.properties.length; --i >= 0;) + if (this.properties[i].has_side_effects()) + return true; + return false; + }); + def(AST_ObjectProperty, function(){ + return this.value.has_side_effects(); + }); + def(AST_Array, function(){ + for (var i = this.elements.length; --i >= 0;) + if (this.elements[i].has_side_effects()) + return true; + return false; + }); + // def(AST_Dot, function(){ + // return this.expression.has_side_effects(); + // }); + // def(AST_Sub, function(){ + // return this.expression.has_side_effects() + // || this.property.has_side_effects(); + // }); + def(AST_PropAccess, function(){ + return true; + }); + def(AST_Seq, function(){ + return this.car.has_side_effects() + || this.cdr.has_side_effects(); + }); + })(function(node, func){ + node.DEFMETHOD("has_side_effects", func); + }); + + // tell me if a statement aborts + function aborts(thing) { + return thing && thing.aborts(); + }; + (function(def){ + def(AST_Statement, function(){ return null }); + def(AST_Jump, function(){ return this }); + function block_aborts(){ + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + }; + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function(){ + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + + /* -----[ optimizers ]----- */ + + OPT(AST_Directive, function(self, compressor){ + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + + OPT(AST_Debugger, function(self, compressor){ + if (compressor.option("drop_debugger")) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + + OPT(AST_Block, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_BlockStatement, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: return self.body[0]; + case 0: return make_node(AST_EmptyStatement, self); + } + return self; + }); + + AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + var self = this; + if (compressor.option("unused") + && !(self instanceof AST_Toplevel) + && !self.uses_eval + ) { + var in_use = []; + var initializations = new Dictionary(); + // pass 1: find out which symbols are directly used in + // this scope (not in nested scopes). + var scope = this; + var tw = new TreeWalker(function(node, descend){ + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects()) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + // pass 2: for every used symbol we need to walk its + // initialization code to figure out if it uses other + // symbols (that may not be in_use). + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl){ + // undeclared globals will be instanceof AST_SymbolRef + var init = initializations.get(decl.name); + if (init) init.forEach(function(init){ + var tw = new TreeWalker(function(node){ + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + // pass 3: we should drop declarations not in_use + var tt = new TreeTransformer( + function before(node, descend, in_list) { + if (node instanceof AST_Lambda) { + for (var a = node.argnames, i = a.length; --i >= 0;) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name : sym.name, + file : sym.start.file, + line : sym.start.line, + col : sym.start.col + }); + } + else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name : node.name.name, + file : node.name.start.file, + line : node.name.start.line, + col : node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def){ + if (member(def.name.definition(), in_use)) return true; + var w = { + name : def.name.name, + file : def.name.start.file, + line : def.name.start.line, + col : def.name.start.col + }; + if (def.value && def.value.has_side_effects()) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + // place uninitialized names at the start + def = mergeSort(def, function(a, b){ + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + // for unused names whose initialization has + // side effects, we can cascade the init. code + // into the next one, or next statement. + var side_effects = []; + for (var i = 0; i < def.length;) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For && node.init instanceof AST_BlockStatement) { + descend(node, this); + // certain combination of unused name + side effect leads to: + // https://github.com/mishoo/UglifyJS2/issues/44 + // that's an invalid AST. + // We fix it at this stage by moving the `var` outside the `for`. + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + if (node instanceof AST_Scope && node !== self) + return node; + } + ); + self.transform(tt); + } + }); + + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + // let's count var_decl first, we seem to waste a lot of + // space if we hoist `var` when there's only one. + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_Scope && node !== self) + return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer( + function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def){ + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) + return node; // to avoid descending in nested scopes + } + } + ); + self = self.transform(tt); + if (vars_found > 0) { + // collect only vars which don't show up in self's arguments list + var defs = []; + vars.each(function(def, name){ + if (self instanceof AST_Lambda + && find_if(function(x){ return x.name == def.name.name }, + self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + // try to merge in assignments + for (var i = 0; i < self.body.length;) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign + && expr.operator == "=" + && (sym = expr.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq + && (assign = expr.car) instanceof AST_Assign + && assign.operator == "=" + && (sym = assign.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + }; + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + + OPT(AST_SimpleStatement, function(self, compressor){ + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects()) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + + OPT(AST_DWLoop, function(self, compressor){ + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } else { + return self.body; + } + } + return self; + }); + + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + + OPT(AST_For, function(self, compressor){ + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } + else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + + OPT(AST_If, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + // if condition can be statically determined, warn and drop + // one of the blocks. note, statically determined implies + // “has no side effects”; also it doesn't work for cases like + // `x && true`, though it probably should. + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; // because we already do the switch here. + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.body, + alternative : self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : negated, + right : self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "&&", + left : self.condition, + right : self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement + && self.alternative + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : self.condition, + right : self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit + && self.alternative instanceof AST_Exit + && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + + OPT(AST_Switch, function(self, compressor){ + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; // last statement + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + last_branch.body.pop(); + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + // constant expression + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list){ + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + // no need to descend these node types + return node; + } + else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch){ + return a.concat(branch.body); + }, []) + }).transform(compressor); + } + else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } + else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } + else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } + else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + // got a case with non-constant expression, baling out + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); // so that's able to see parent nodes + self = self.transform(tt); + } catch(ex) { + if (ex !== self) throw ex; + } + return self; + }); + + OPT(AST_Case, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_Try, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + AST_Definitions.DEFMETHOD("remove_initializers", function(){ + this.definitions.forEach(function(def){ def.value = null }); + }); + + AST_Definitions.DEFMETHOD("to_assignments", function(){ + var assignments = this.definitions.reduce(function(a, def){ + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator : "=", + left : name, + right : def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + + OPT(AST_Definitions, function(self, compressor){ + if (self.definitions.length == 0) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_Function, function(self, compressor){ + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + + OPT(AST_Call, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }); + } + break; + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { value: "" }) + }); + } + } + else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { value: "" }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function + && self.args.length == 0 + && !AST_Block.prototype.has_side_effects.call(self.expression)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self; + }); + + OPT(AST_New, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + + OPT(AST_Seq, function(self, compressor){ + if (!compressor.option("side_effects")) + return self; + if (!self.car.has_side_effects()) { + // we shouldn't compress (1,eval)(something) to + // eval(something) because that changes the meaning of + // eval (becomes lexical instead of global). + var p; + if (!(self.cdr instanceof AST_SymbolRef + && self.cdr.name == "eval" + && self.cdr.undeclared() + && (p = compressor.parent()) instanceof AST_Call + && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign + && !self.car.left.has_side_effects() + && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects() + && !self.cdr.has_side_effects() + && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + + AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + OPT(AST_UnaryPostfix, function(self, compressor){ + return self.lift_sequences(compressor); + }); + + OPT(AST_UnaryPrefix, function(self, compressor){ + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + // !!foo ==> foo, if we're in boolean context + return e.expression; + } + break; + case "typeof": + // typeof always returns a non-empty string, thus it's + // always true in booleans + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + + AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq + && !(this.operator == "||" || this.operator == "&&") + && !this.left.has_side_effects()) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + var commutativeOperators = makePredicate("== === != !== * & | ^"); + + OPT(AST_Binary, function(self, compressor){ + function reverse(op) { + if (!(self.left.has_side_effects() && self.right.has_side_effects())) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant + && !(self.left instanceof AST_Constant)) { + reverse(); + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || + (self.left.is_boolean() && self.right.is_boolean())) { + self.operator = self.operator.substr(0, 2); + } + // XXX: intentionally falling down to the next case + case "==": + case "!=": + if (self.left instanceof AST_String + && self.left.value == "undefined" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "typeof" + && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) + || !self.right.expression.undeclared()) { + self.left = self.right.expression; + self.right = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + var exp = self.evaluate(compressor); + if (exp.length > 1) { + if (best_of(exp[0], self) !== self) + return exp[0]; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) + || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } + } + if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } + return self; + }); + + OPT(AST_SymbolRef, function(self, compressor){ + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self); + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + + OPT(AST_Undefined, function(self, compressor){ + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name : "undefined", + scope : scope, + thedef : undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + + var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + OPT(AST_Assign, function(self, compressor){ + self = self.lift_sequences(compressor); + if (self.operator == "=" + && self.left instanceof AST_SymbolRef + && self.right instanceof AST_Binary + && self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + + OPT(AST_Conditional, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign + && alternative instanceof AST_Assign + && consequent.operator == alternative.operator + && consequent.left.equivalent_to(alternative.left) + ) { + /* + * Stuff like this: + * if (foo) exp = something; else exp = something_else; + * ==> + * exp = foo ? something : something_else; + */ + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + + OPT(AST_Boolean, function(self, compressor){ + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" + || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator : p.operator, + value : self.value, + file : p.start.file, + line : p.start.line, + col : p.start.col, + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + + OPT(AST_Sub, function(self, compressor){ + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if (is_identifier(prop)) { + return make_node(AST_Dot, self, { + expression : self.expression, + property : prop + }); + } + } + return self; + }); + + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + }; + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + +})(); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/mozilla-ast.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/mozilla-ast.js new file mode 100644 index 0000000..982d621 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/mozilla-ast.js @@ -0,0 +1,265 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +(function(){ + + var MOZ_TO_ME = { + TryStatement : function(M) { + return new AST_Try({ + start : my_start_token(M), + end : my_end_token(M), + body : from_moz(M.block).body, + bcatch : from_moz(M.handlers[0]), + bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause : function(M) { + return new AST_Catch({ + start : my_start_token(M), + end : my_end_token(M), + argname : from_moz(M.param), + body : from_moz(M.body).body + }); + }, + ObjectExpression : function(M) { + return new AST_Object({ + start : my_start_token(M), + end : my_end_token(M), + properties : M.properties.map(function(prop){ + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start : my_start_token(key), + end : my_end_token(prop.value), + key : name, + value : from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression : function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression : function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start : my_start_token(M), + end : my_end_token(M), + property : M.computed ? from_moz(M.property) : M.property.name, + expression : from_moz(M.object) + }); + }, + SwitchCase : function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start : my_start_token(M), + end : my_end_token(M), + expression : from_moz(M.test), + body : M.consequent.map(from_moz) + }); + }, + Literal : function(M) { + var val = M.value, args = { + start : my_start_token(M), + end : my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + case "number": + args.value = val; + return new AST_Number(args); + case "boolean": + return new (val ? AST_True : AST_False)(args); + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This + : p.type == "LabeledStatement" ? AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) + : p.type == "CatchClause" ? AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef + : AST_SymbolRef)({ + start : my_start_token(M), + end : my_end_token(M), + name : M.name + }); + } + }; + + function From_Moz_Unary(M) { + return new (M.prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start : my_start_token(M), + end : my_end_token(M), + operator : M.operator, + expression : from_moz(M.argument) + }) + }; + + var ME_TO_MOZ = {}; + + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + + /* -----[ tools ]----- */ + + function my_start_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.start.line, + col : moznode.loc && moznode.loc.start.column, + pos : moznode.start, + endpos : moznode.start + }); + }; + + function my_end_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.end.line, + col : moznode.loc && moznode.loc.end.column, + pos : moznode.end, + endpos : moznode.end + }); + }; + + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + + "start: my_start_token(M),\n" + + "end: my_end_token(M)"; + + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + + // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); + // console.log(moz_to_me); + + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( + mytype, my_start_token, my_end_token, from_moz + ); + return MOZ_TO_ME[moztype] = moz_to_me; + }; + + var FROM_MOZ_STACK = null; + + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + }; + + AST_Node.from_mozilla_ast = function(node){ + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + +})(); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/output.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/output.js new file mode 100644 index 0000000..42b3aad --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/output.js @@ -0,0 +1,1220 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function OutputStream(options) { + + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : true, + ascii_only : false, + inline_script : false, + width : 80, + max_line_len : 32000, + ie_proof : true, + beautify : false, + source_map : null, + bracketize : false, + semicolons : true, + comments : false, + preserve_line : false + }, true); + + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + + function to_ascii(str) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + while (code.length < 4) code = "0" + code; + return "\\u" + code; + }); + }; + + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; + }; + + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name); + return name; + }; + + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + }; + + /* -----[ beautification/minification ]----- */ + + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + + function last_char() { + return last.charAt(last.length - 1); + }; + + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) + print("\n"); + }; + + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) + might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + + if (might_need_space) { + var prev = last_char(); + if ((is_identifier_char(prev) + && (is_identifier_char(ch) || ch == "\\")) + || (/^[\+\-\/]$/.test(ch) && ch == prev)) + { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + }; + + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? 0.5 : 0)); + } + } : noop; + + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { return cont() }; + + var newline = options.beautify ? function() { + print("\n"); + } : noop; + + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + + function force_semicolon() { + might_need_semicolon = false; + print(";"); + }; + + function next_indent() { + return indentation + options.indent_level; + }; + + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function(){ + ret = cont(); + }); + indent(); + print("}"); + return ret; + }; + + function with_parens(cont) { + print("("); + //XXX: still nice to have that for argument lists + //var ret = with_indent(current_col, cont); + var ret = cont(); + print(")"); + return ret; + }; + + function with_square(cont) { + print("["); + //var ret = with_indent(current_col, cont); + var ret = cont(); + print("]"); + return ret; + }; + + function comma() { + print(","); + space(); + }; + + function colon() { + print(":"); + if (options.space_colon) space(); + }; + + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add( + token.file || "?", + current_line, current_col, + token.line, token.col, + (!name && token.type == "name") ? token.value : name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }) + } + } : noop; + + function get() { + return OUTPUT; + }; + + var stack = []; + return { + get : get, + toString : get, + indent : indent, + indentation : function() { return indentation }, + current_width : function() { return current_col - indentation }, + should_break : function() { return options.width && this.current_width() >= options.width }, + newline : newline, + print : print, + space : space, + comma : comma, + colon : colon, + last : function() { return last }, + semicolon : semicolon, + force_semicolon : force_semicolon, + to_ascii : to_ascii, + print_name : function(name) { print(make_name(name)) }, + print_string : function(str) { print(encode_string(str)) }, + next_indent : next_indent, + with_indent : with_indent, + with_block : with_block, + with_parens : with_parens, + with_square : with_square, + add_mapping : add_mapping, + option : function(opt) { return options[opt] }, + line : function() { return current_line }, + col : function() { return current_col }, + pos : function() { return current_pos }, + push_node : function(node) { stack.push(node) }, + pop_node : function() { return stack.pop() }, + stack : function() { return stack }, + parent : function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + +}; + +/* -----[ code generators ]----- */ + +(function(){ + + /* -----[ utils ]----- */ + + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + }; + + AST_Node.DEFMETHOD("print", function(stream, force_parens){ + var self = this, generator = self._codegen; + stream.push_node(self); + if (force_parens || self.needs_parens(stream)) { + stream.with_parens(function(){ + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + }); + } else { + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + } + stream.pop_node(); + }); + + AST_Node.DEFMETHOD("print_to_string", function(options){ + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + + /* -----[ comments ]----- */ + + AST_Node.DEFMETHOD("add_comments", function(output){ + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // if this node is `return` or `throw`, we cannot allow comments before + // the returned or thrown value. + if (self instanceof AST_Exit && + self.value && self.value.start.comments_before.length > 0) { + comments = (comments || []).concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + + if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment); + }); + } + comments.forEach(function(c){ + if (c.type == "comment1") { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + + /* -----[ PARENTHESES ]----- */ + + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + }; + + PARENS(AST_Node, function(){ + return false; + }); + + // a function expression needs parens around it when it's provably + // the first token to appear in a statement. + PARENS(AST_Function, function(output){ + return first_in_statement(output); + }); + + // same goes for an object literal, because otherwise it would be + // interpreted as a block of code. + PARENS(AST_Object, function(output){ + return first_in_statement(output); + }); + + PARENS(AST_Unary, function(output){ + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + + PARENS(AST_Seq, function(output){ + var p = output.parent(); + return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST_Unary // !(foo, bar, baz) + || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * ==> 20 (side effect, set a := 10 and b := 20) */ + ; + }); + + PARENS(AST_Binary, function(output){ + var p = output.parent(); + // (foo && bar)() + if (p instanceof AST_Call && p.expression === this) + return true; + // typeof (foo && bar) + if (p instanceof AST_Unary) + return true; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + // this deals with precedence: 3 * (2 + 1) + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp + || (pp == sp + && this === p.right + && !(so == po && + (so == "*" || + so == "&&" || + so == "||")))) { + return true; + } + } + }); + + PARENS(AST_PropAccess, function(output){ + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + // i.e. new (foo.bar().baz) + // + // if there's one call into this subtree, then we need + // parens around it too, otherwise the call will be + // interpreted as passing the arguments to the upper New + // expression. + try { + this.walk(new TreeWalker(function(node){ + if (node instanceof AST_Call) throw p; + })); + } catch(ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + + PARENS(AST_Call, function(output){ + var p = output.parent(); + return p instanceof AST_New && p.expression === this; + }); + + PARENS(AST_New, function(output){ + var p = output.parent(); + if (no_constructor_parens(this, output) + && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + return true; + }); + + PARENS(AST_Number, function(output){ + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + PARENS(AST_NaN, function(output){ + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + // !(a = false) → true + if (p instanceof AST_Unary) + return true; + // 1 + (a = 2) + 3 → 6, side effect setting a = 2 + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + return true; + // (a = func)() —or— new (a = Object)() + if (p instanceof AST_Call && p.expression === this) + return true; + // (a = foo) ? bar : baz + if (p instanceof AST_Conditional && p.condition === this) + return true; + // (a = foo)["prop"] —or— (a = foo).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }; + + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + + /* -----[ PRINTERS ]----- */ + + DEFPRINT(AST_Directive, function(self, output){ + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output){ + output.print("debugger"); + output.semicolon(); + }); + + /* -----[ statements ]----- */ + + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i){ + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + }; + + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + force_statement(this.body, output); + }); + + DEFPRINT(AST_Statement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output){ + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output){ + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function(){ + display_body(body, false, output); + }); + else output.print("{}"); + }; + DEFPRINT(AST_BlockStatement, function(self, output){ + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output){ + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output){ + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output){ + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output){ + output.print("with"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + + /* -----[ functions ]----- */ + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function(){ + self.argnames.forEach(function(arg, i){ + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output){ + self._do_print(output); + }); + + /* -----[ exits ]----- */ + AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output){ + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output){ + self._do_print(output, "throw"); + }); + + /* -----[ loop control ]----- */ + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output){ + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output){ + self._do_print(output, "continue"); + }); + + /* -----[ if ]----- */ + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + if (!self.body) + return output.force_semicolon(); + if (self.body instanceof AST_Do + && output.option("ie_proof")) { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE + // croaks with "syntax error" on code like this: if (foo) + // do ... while(cond); else ... we need block brackets + // around do/while + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } + else if (b instanceof AST_StatementWithBody) { + b = b.body; + } + else break; + } + force_statement(self.body, output); + }; + DEFPRINT(AST_If, function(self, output){ + output.print("if"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + + /* -----[ switch ]----- */ + DEFPRINT(AST_Switch, function(self, output){ + output.print("switch"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function(){ + self.body.forEach(function(stmt, i){ + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); + else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt){ + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output){ + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output){ + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + + /* -----[ exceptions ]----- */ + DEFPRINT(AST_Try, function(self, output){ + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output){ + output.print("catch"); + output.space(); + output.with_parens(function(){ + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output){ + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + + /* -----[ var/const ]----- */ + AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i){ + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) + output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output){ + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output){ + self._do_print(output, "const"); + }); + + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); + else try { + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw output; + })); + node.print(output); + } catch(ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + }; + + DEFPRINT(AST_VarDef, function(self, output){ + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + + /* -----[ other expressions ]----- */ + DEFPRINT(AST_Call, function(self, output){ + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) + return; + output.with_parens(function(){ + self.args.forEach(function(expr, i){ + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output){ + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + + AST_Seq.DEFMETHOD("_do_print", function(output){ + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output){ + self._do_print(output); + // var p = output.parent(); + // if (p instanceof AST_Statement) { + // output.with_indent(output.next_indent(), function(){ + // self._do_print(output); + // }); + // } else { + // self._do_print(output); + // } + }); + DEFPRINT(AST_Dot, function(self, output){ + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + // the name after dot would be mapped about here. + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output){ + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output){ + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) + output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output){ + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output){ + self.left.print(output); + output.space(); + output.print(self.operator); + output.space(); + self.right.print(output); + }); + DEFPRINT(AST_Conditional, function(self, output){ + self.condition.print(output); + output.space(); + output.print("?"); + output.space(); + self.consequent.print(output); + output.space(); + output.colon(); + self.alternative.print(output); + }); + + /* -----[ literals ]----- */ + DEFPRINT(AST_Array, function(self, output){ + output.with_square(function(){ + var a = self.elements, len = a.length; + if (len > 0) output.space(); + a.forEach(function(exp, i){ + if (i) output.comma(); + exp.print(output); + }); + if (len > 0) output.space(); + }); + }); + DEFPRINT(AST_Object, function(self, output){ + if (self.properties.length > 0) output.with_block(function(){ + self.properties.forEach(function(prop, i){ + if (i) { + output.print(","); + output.newline(); + } + output.indent(); + prop.print(output); + }); + output.newline(); + }); + else output.print("{}"); + }); + DEFPRINT(AST_ObjectKeyVal, function(self, output){ + var key = self.key; + if (output.option("quote_keys")) { + output.print_string(key); + } else if ((typeof key == "number" + || !output.option("beautify") + && +key + "" == key) + && parseFloat(key) >= 0) { + output.print(make_num(key)); + } else if (!is_identifier(key)) { + output.print_string(key); + } else { + output.print_name(key); + } + output.colon(); + self.value.print(output); + }); + DEFPRINT(AST_ObjectSetter, function(self, output){ + output.print("set"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_ObjectGetter, function(self, output){ + output.print("get"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_Symbol, function(self, output){ + var def = self.definition(); + output.print_name(def ? def.mangled_name || def.name : self.name); + }); + DEFPRINT(AST_Undefined, function(self, output){ + output.print("void 0"); + }); + DEFPRINT(AST_Hole, noop); + DEFPRINT(AST_Infinity, function(self, output){ + output.print("1/0"); + }); + DEFPRINT(AST_NaN, function(self, output){ + output.print("0/0"); + }); + DEFPRINT(AST_This, function(self, output){ + output.print("this"); + }); + DEFPRINT(AST_Constant, function(self, output){ + output.print(self.getValue()); + }); + DEFPRINT(AST_String, function(self, output){ + output.print_string(self.getValue()); + }); + DEFPRINT(AST_Number, function(self, output){ + output.print(make_num(self.getValue())); + }); + DEFPRINT(AST_RegExp, function(self, output){ + var str = self.getValue().toString(); + if (output.option("ascii_only")) + str = output.to_ascii(str); + output.print(str); + var p = output.parent(); + if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) + output.print(" "); + }); + + function force_statement(stat, output) { + if (output.option("bracketize")) { + if (!stat || stat instanceof AST_EmptyStatement) + output.print("{}"); + else if (stat instanceof AST_BlockStatement) + stat.print(output); + else output.with_block(function(){ + output.indent(); + stat.print(output); + output.newline(); + }); + } else { + if (!stat || stat instanceof AST_EmptyStatement) + output.force_semicolon(); + else + stat.print(output); + } + }; + + // return true if the node at the top of the stack (that means the + // innermost node in the current output) is lexically the first in + // a statement. + function first_in_statement(output) { + var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + while (i > 0) { + if (p instanceof AST_Statement && p.body === node) + return true; + if ((p instanceof AST_Seq && p.car === node ) || + (p instanceof AST_Call && p.expression === node ) || + (p instanceof AST_Dot && p.expression === node ) || + (p instanceof AST_Sub && p.expression === node ) || + (p instanceof AST_Conditional && p.condition === node ) || + (p instanceof AST_Binary && p.left === node ) || + (p instanceof AST_UnaryPostfix && p.expression === node )) + { + node = p; + p = a[--i]; + } else { + return false; + } + } + }; + + // self should be AST_New. decide if we want to show parens or not. + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.option("beautify"); + }; + + function best_of(a) { + var best = a[0], len = best.length; + for (var i = 1; i < a.length; ++i) { + if (a[i].length < len) { + best = a[i]; + len = best.length; + } + } + return best; + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + function make_block(stmt, output) { + if (stmt instanceof AST_BlockStatement) { + stmt.print(output); + return; + } + output.with_block(function(){ + output.indent(); + stmt.print(output); + output.newline(); + }); + }; + + /* -----[ source map generators ]----- */ + + function DEFMAP(nodetype, generator) { + nodetype.DEFMETHOD("add_source_map", function(stream){ + generator(this, stream); + }); + }; + + // We could easily add info for ALL nodes, but it seems to me that + // would be quite wasteful, hence this noop in the base class. + DEFMAP(AST_Node, noop); + + function basic_sourcemap_gen(self, output) { + output.add_mapping(self.start); + }; + + // XXX: I'm not exactly sure if we need it for all of these nodes, + // or if we should add even more. + + DEFMAP(AST_Directive, basic_sourcemap_gen); + DEFMAP(AST_Debugger, basic_sourcemap_gen); + DEFMAP(AST_Symbol, basic_sourcemap_gen); + DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it + DEFMAP(AST_Lambda, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_New, basic_sourcemap_gen); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); + DEFMAP(AST_ObjectProperty, function(self, output){ + output.add_mapping(self.start, self.key); + }); + +})(); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/parse.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/parse.js new file mode 100644 index 0000000..5a75e75 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/parse.js @@ -0,0 +1,1407 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; +var KEYWORDS_ATOM = 'false null true'; +var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile' + + " " + KEYWORDS_ATOM + " " + KEYWORDS; +var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; + +KEYWORDS = makePredicate(KEYWORDS); +RESERVED_WORDS = makePredicate(RESERVED_WORDS); +KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); +KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); + +var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = makePredicate([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); + +var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); + +var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(code) { + return (code >= 97 && code <= 122) + || (code >= 65 && code <= 90) + || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); +}; + +function is_digit(code) { + return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(code) { + return is_digit(code) || is_letter(code); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier(name) { + return /^[a-z_$][a-z0-9_$]*$/i.test(name) && !RESERVED_WORDS(name); +}; + +function is_identifier_start(code) { + return code == 36 || code == 95 || is_letter(code); +}; + +function is_identifier_char(ch) { + var code = ch.charCodeAt(0); + return is_identifier_start(code) + || is_digit(code) + || code == 8204 // \u200c: zero-width non-joiner + || code == 8205 // \u200d: zero-width joiner (in my ECMA-262 PDF, this is also 200c) + || is_unicode_combining_mark(ch) + || is_unicode_connector_punctuation(ch) + ; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + this.stack = new Error().stack; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, filename, line, col, pos) { + AST_Node.warn("ERROR: {message} [{file}:{line},{col}]", { + message: message, + file: filename, + line: line, + col: col + }); + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT, filename) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''), + filename : filename, + pos : 0, + tokpos : 0, + line : 1, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) || + (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || + (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before, + file : filename + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return new AST_Token(ret); + }; + + function skip_whitespace() { + while (WHITESPACE_CHARS(peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch, i = 0; + while ((ch = peek()) && pred(ch, i++)) + ret += next(); + return ret; + }; + + function parse_error(err) { + js_error(err, filename, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + var code = ch.charCodeAt(0); + switch (code) { + case 120: case 88: // xX + return has_x ? false : (has_x = true); + case 101: case 69: // eE + return has_x ? true : has_e ? false : (has_e = after_e = true); + case 45: // - + return after_e || (i == 0 && !prefix); + case 43: // + + return after_e; + case (after_e = false, 46): // . + return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; + } + return is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110 : return "\n"; + case 114 : return "\r"; + case 116 : return "\t"; + case 98 : return "\b"; + case 118 : return "\u000b"; // \v + case 102 : return "\f"; + case 48 : return "\0"; + case 120 : return String.fromCharCode(hex_bytes(2)); // \x + case 117 : return String.fromCharCode(hex_bytes(4)); // \u + case 10 : return ""; // newline + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + var read_string = with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); + } + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ + next(); + var i = find("*/", true); + var text = S.text.substring(S.pos, i); + var a = text.split("\n"), n = a.length; + // update stream position + S.pos = i + 2; + S.line += n - 1; + if (n > 1) S.col = a[n - 1].length; + else S.col += a[n - 1].length; + S.col += 2; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + return token("comment2", text, true); + }); + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", new RegExp(regexp, mods)); + }); + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (OPERATORS(bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek().charCodeAt(0)) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return KEYWORDS_ATOM(word) ? token("atom", word) + : !KEYWORDS(word) ? token("name", word) + : OPERATORS(word) ? token("operator", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + return function(x) { + try { + return cont(x); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(); + case 46: return handle_dot(); + case 47: return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + +var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function parse($TEXT, options) { + + options = defaults(options, { + strict : false, + filename : null, + toplevel : null + }); + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + ctx.filename, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !options.strict && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + }; + + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + }; + + var statement = embed_tokens(function() { + var tmp; + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + // XXXv2: decide how to fix directives + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start : S.token, + body : block_(), + end : prev() + }); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return new AST_EmptyStatement(); + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body : in_loop(statement), + condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) + }); + + case "while": + return new AST_While({ + condition : parenthesised(), + body : in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return new AST_Return({ + value: ( is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : (tmp = expression(true), semicolon(), tmp) ) + }); + + case "switch": + return new AST_Switch({ + expression : parenthesised(), + body : in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression : parenthesised(), + body : statement() + }); + + default: + unexpected(); + } + } + }); + + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + return new AST_LabeledStatement({ body: stat, label: label }); + }; + + function simple_statement(tmp) { + return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + }; + + function break_cont(type) { + var label = null; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + if (!find_if(function(l){ return l.name == label.name }, S.labels)) + croak("Undefined label " + label.name); + } + else if (S.in_loop == 0) + croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + return new type({ label: label }); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) + croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init : init, + condition : test, + step : step, + body : in_loop(statement) + }); + }; + + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init : init, + name : lhs, + object : obj, + body : in_loop(statement) + }); + }; + + var function_ = function(in_statement, ctor) { + var is_accessor = ctor === AST_Accessor; + var name = (is("name") ? as_symbol(in_statement + ? AST_SymbolDefun + : is_accessor + ? AST_SymbolAccessor + : AST_SymbolLambda) + : is_accessor && (is("string") || is("num")) ? as_atom_node() + : null); + if (in_statement && !name) + unexpected(); + expect("("); + if (!ctor) ctor = in_statement ? AST_Defun : AST_Function; + return new ctor({ + name: name, + argnames: (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + })(true, []), + body: (function(loop, labels){ + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + })(S.in_loop, S.labels) + }); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition : cond, + body : body, + alternative : belse + }); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start : (tmp = S.token, next(), tmp), + expression : expression(true), + body : cur + }); + a.push(branch); + expect(":"); + } + else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start : (tmp = S.token, next(), expect(":"), tmp), + body : cur + }); + a.push(branch); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + }; + + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start : start, + argname : name, + body : block_(), + end : prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start : start, + body : block_(), + end : prev() + }); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return new AST_Try({ + body : body, + bcatch : bcatch, + bfinally : bfinally + }); + }; + + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start : S.token, + name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value : is("operator", "=") ? (next(), expression(false, no_in)) : null, + end : prev() + })); + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + var var_ = function(no_in) { + return new AST_Var({ + start : prev(), + definitions : vardefs(no_in, false), + end : prev() + }); + }; + + var const_ = function() { + return new AST_Const({ + start : prev(), + definitions : vardefs(false, true), + end : prev() + }); + }; + + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start : start, + expression : newexp, + args : args, + end : prev() + }), true); + }; + + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + return as_symbol(AST_SymbolRef); + case "num": + ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + break; + case "string": + ret = new AST_String({ start: tok, end: tok, value: tok.value }); + break; + case "regexp": + ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + break; + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ start: tok, end: tok }); + break; + case "true": + ret = new AST_True({ start: tok, end: tok }); + break; + case "null": + ret = new AST_Null({ start: tok, end: tok }); + break; + } + break; + } + next(); + return ret; + }; + + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + case "[": + return subscripts(array_(), allow_calls); + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(false); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ start: S.token, end: S.token })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) + // allow trailing comma + break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start : start, + key : name, + value : expression(false), + end : prev() + })); + } + next(); + return new AST_Object({ properties: a }); + }); + + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var name = S.token.value; + var sym = new (name == "this" ? AST_This : type)({ + name : String(S.token.value), + start : S.token, + end : S.token + }); + next(); + return sym; + }; + + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start : start, + expression : expr, + property : as_name(), + end : prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start : start, + expression : expr, + property : prop, + end : prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start : start, + expression : expr, + args : expr_list(")"), + end : prev() + }), true); + } + return expr; + }; + + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return new ctor({ operator: op, expression: expr }); + }; + + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start : left.start, + left : left, + operator : op, + right : right, + end : right.end + }), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start : start, + condition : expr, + consequent : yes, + alternative : expression(false, no_in), + end : peek() + }); + } + return expr; + }; + + function is_assignable(expr) { + if (!options.strict) return true; + switch (expr[0]+"") { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; + + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start : start, + left : left, + operator : val, + right : maybe_assign(no_in), + end : prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start : start, + car : expr, + cdr : expression(true, no_in), + end : peek() + }); + } + return expr; + }; + + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + }; + + return (function(){ + var start = S.token; + var body = []; + while (!is("eof")) + body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + } + return toplevel; + })(); + +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/scope.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/scope.js new file mode 100644 index 0000000..f23f6eb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/scope.js @@ -0,0 +1,580 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; +}; + +SymbolDef.prototype = { + unmangleable: function(options) { + return this.global + || this.undeclared + || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) + this.mangled_name = this.scope.next_mangled(options); + } +}; + +AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions + var self = this; + var scope = self.parent_scope = null; + var labels = new Dictionary(); + var nesting = 0; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + var save_labels = labels; + ++nesting; + scope = node; + labels = new Dictionary(); + descend(); + labels = save_labels; + scope = save_scope; + --nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) + s.uses_with = true; + return; + } + if (node instanceof AST_LabeledStatement) { + var l = node.label; + if (labels.has(l.name)) + throw new Error(string_template("Label {name} defined twice", l)); + labels.set(l.name, l); + descend(); + labels.del(l.name); + return true; // no descend again + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_Label) { + node.thedef = node; + node.init_scope_vars(); + } + if (node instanceof AST_SymbolLambda) { + //scope.def_function(node); + // + // https://github.com/mishoo/UglifyJS2/issues/24 — MSIE + // leaks function expression names into the containing + // scope. Don't like this fix but seems we can't do any + // better. IE: please die. Please! + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolDefun) { + // Careful here, the scope where this should be defined is + // the parent scope. The reason is that we enter a new + // scope when we encounter the AST_Defun node (which is + // instanceof AST_Scope) but we get to the symbol a bit + // later. + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolVar + || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } + else if (node instanceof AST_SymbolCatch) { + // XXX: this is wrong according to ECMA-262 (12.4). the + // `catch` argument name should be visible only inside the + // catch block. For a quick fix AST_Catch should inherit + // from AST_Scope. Keeping it this way because of IE, + // which doesn't obey the standard. (it introduces the + // identifier in the enclosing scope) + scope.def_variable(node); + } + if (node instanceof AST_LabelRef) { + var sym = labels.get(node.name); + if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { + name: node.name, + line: node.start.line, + col: node.start.col + })); + node.thedef = sym; + } + }); + self.walk(tw); + + // pass 2: find back references and eval + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_LabelRef) { + node.reference(); + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) + s.uses_eval = true; + } + if (name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); +}); + +AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = null; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables + this.nesting = nesting; // the nesting level of this scope (0 means toplevel) +}); + +AST_Scope.DEFMETHOD("strict", function(){ + return this.has_directive("use strict"); +}); + +AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; +}); + +AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; +}); + +AST_Label.DEFMETHOD("init_scope_vars", function(){ + this.references = []; +}); + +AST_LabelRef.DEFMETHOD("reference", function(){ + this.thedef.references.push(this); +}); + +AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) + || (this.parent_scope && this.parent_scope.find_variable(name)); +}); + +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + +AST_Scope.DEFMETHOD("def_function", function(symbol){ + this.functions.set(symbol.name, this.def_variable(symbol)); +}); + +AST_Scope.DEFMETHOD("def_variable", function(symbol){ + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; +}); + +AST_Scope.DEFMETHOD("next_mangled", function(options){ + var ext = this.enclosed, n = ext.length; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; // skip over "do" + // we must ensure that the mangled name does not shadow a name + // from some parent scope that is referenced in this or in + // inner scopes. + for (var i = n; --i >= 0;) { + var sym = ext[i]; + var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); + if (m == name) continue out; + } + return m; + } +}); + +AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; +}); + +AST_Symbol.DEFMETHOD("unmangleable", function(options){ + return this.definition().unmangleable(options); +}); + +// property accessors are not mangleable +AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ + return true; +}); + +// labels are always mangleable +AST_Label.DEFMETHOD("unmangleable", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("unreferenced", function(){ + return this.definition().references.length == 0 + && !(this.scope.uses_eval || this.scope.uses_with); +}); + +AST_Symbol.DEFMETHOD("undeclared", function(){ + return this.definition().undeclared; +}); + +AST_LabelRef.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Label.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("definition", function(){ + return this.thedef; +}); + +AST_Symbol.DEFMETHOD("global", function(){ + return this.definition().global; +}); + +AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return defaults(options, { + except : [], + eval : false, + sort : false + }); +}); + +AST_Toplevel.DEFMETHOD("mangle_names", function(options){ + options = this._default_mangler_options(options); + // We only need to mangle declaration nodes. Special logic wired + // into the code generator will display the mangled name if it's + // present (and for AST_SymbolRef-s it'll use the mangled name of + // the AST_SymbolDeclaration that it points to). + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_LabeledStatement) { + // lname is incremented when we get to the AST_Label + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b){ + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def){ def.mangle(options) }); +}); + +AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node){ + if (node instanceof AST_Constant) + base54.consider(node.print_to_string()); + else if (node instanceof AST_Return) + base54.consider("return"); + else if (node instanceof AST_Throw) + base54.consider("throw"); + else if (node instanceof AST_Continue) + base54.consider("continue"); + else if (node instanceof AST_Break) + base54.consider("break"); + else if (node instanceof AST_Debugger) + base54.consider("debugger"); + else if (node instanceof AST_Directive) + base54.consider(node.value); + else if (node instanceof AST_While) + base54.consider("while"); + else if (node instanceof AST_Do) + base54.consider("do while"); + else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } + else if (node instanceof AST_Var) + base54.consider("var"); + else if (node instanceof AST_Const) + base54.consider("const"); + else if (node instanceof AST_Lambda) + base54.consider("function"); + else if (node instanceof AST_For) + base54.consider("for"); + else if (node instanceof AST_ForIn) + base54.consider("for in"); + else if (node instanceof AST_Switch) + base54.consider("switch"); + else if (node instanceof AST_Case) + base54.consider("case"); + else if (node instanceof AST_Default) + base54.consider("default"); + else if (node instanceof AST_With) + base54.consider("with"); + else if (node instanceof AST_ObjectSetter) + base54.consider("set" + node.key); + else if (node instanceof AST_ObjectGetter) + base54.consider("get" + node.key); + else if (node instanceof AST_ObjectKeyVal) + base54.consider(node.key); + else if (node instanceof AST_New) + base54.consider("new"); + else if (node instanceof AST_This) + base54.consider("this"); + else if (node instanceof AST_Try) + base54.consider("try"); + else if (node instanceof AST_Catch) + base54.consider("catch"); + else if (node instanceof AST_Finally) + base54.consider("finally"); + else if (node instanceof AST_Symbol && node.unmangleable(options)) + base54.consider(node.name); + else if (node instanceof AST_Unary || node instanceof AST_Binary) + base54.consider(node.operator); + else if (node instanceof AST_Dot) + base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); +}); + +var base54 = (function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); + chars.forEach(function(ch){ frequency[ch] = 0 }); + } + base54.consider = function(str){ + for (var i = str.length; --i >= 0;) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b){ + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function(){ return chars }; + base54.freq = function(){ return frequency }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; + return base54; +})(); + +AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = defaults(options, { + undeclared : false, // this makes a lot of noise + unreferenced : true, + assign_to_global : true, + func_arguments : true, + nested_defuns : true, + eval : true + }); + var tw = new TreeWalker(function(node){ + if (options.undeclared + && node instanceof AST_SymbolRef + && node.undeclared()) + { + // XXX: this also warns about JS standard names, + // i.e. Object, Array, parseInt etc. Should add a list of + // exceptions. + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) + { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + sym = node.left; + else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + sym = node.init; + if (sym + && (sym.undeclared() + || (sym.global() && sym.scope !== sym.definition().scope))) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval + && node instanceof AST_SymbolRef + && node.undeclared() + && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced + && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments + && node instanceof AST_Lambda + && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns + && node instanceof AST_Defun + && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/sourcemap.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/sourcemap.js new file mode 100644 index 0000000..3429908 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/sourcemap.js @@ -0,0 +1,81 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// a small wrapper around fitzgen's source-map library +function SourceMap(options) { + options = defaults(options, { + file : null, + root : null, + orig : null, + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, + source : source, + name : name + }); + }; + return { + add : add, + get : function() { return generator }, + toString : function() { return generator.toString() } + }; +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/transform.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/transform.js new file mode 100644 index 0000000..8b4fd9f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/transform.js @@ -0,0 +1,218 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// Tree transformer helpers. +// XXX: eventually I should refactor the compressor to use this infrastructure. + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/utils.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/utils.js new file mode 100644 index 0000000..c95b982 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/lib/utils.js @@ -0,0 +1,288 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) + return array[i]; + } +}; + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; +}; + +function defaults(args, defs, croak) { + if (args === true) + args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) + throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; + } + return ret; +}; + +function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; +}; + +function noop() {}; + +var MAP = (function(){ + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } + else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + }; + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0;) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } + else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + MAP.last = function(val) { return new Last(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; + function Last(val) { this.v = val }; + return MAP; +})(); + +function push_uniq(array, el) { + if (array.indexOf(el) < 0) + array.push(el); +}; + +function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p){ + return props[p]; + }); +}; + +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + +function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 + ? r[i++] = a[ai++] + : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + }; + function _ms(a) { + if (a.length <= 1) + return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + }; + return _ms(array); +}; + +function set_difference(a, b) { + return a.filter(function(el){ + return b.indexOf(el) < 0; + }); +}; + +function set_intersection(a, b) { + return a.filter(function(el){ + return b.indexOf(el) >= 0; + }); +}; + +// this function is taken from Acorn [1], written by Marijn Haverbeke +// [1] https://github.com/marijnh/acorn +function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + // Otherwise, simply generate a flat `switch` statement. + } else { + compareTo(words); + } + return new Function("str", f); +}; + +function Dictionary() { + this._values = Object.create(null); + this._size = 0; +}; +Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { return this._values["$" + key] }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { return ("$" + key) in this._values }, + each: function(f) { + for (var i in this._values) + f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) + ret.push(f(this._values[i], i.substr(1))); + return ret; + } +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/.travis.yml b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/.travis.yml new file mode 100644 index 0000000..cc4dba2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/LICENSE b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/bool.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/bool.js new file mode 100644 index 0000000..a998fb7 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/bool.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js new file mode 100644 index 0000000..a35a7e6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js new file mode 100644 index 0000000..017bb68 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv.v); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_hash.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_hash.js new file mode 100644 index 0000000..ade7768 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_hash.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; + +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_singles.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_singles.js new file mode 100644 index 0000000..d9b1ff4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/default_singles.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/divide.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/divide.js new file mode 100644 index 0000000..5e2ee82 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/divide.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count.js new file mode 100644 index 0000000..b5f95bf --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js new file mode 100644 index 0000000..d9ac709 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .options({ + file : { + demand : true, + alias : 'f', + description : 'Load a file' + }, + base : { + alias : 'b', + description : 'Numeric base to use for output', + default : 10, + }, + }) + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js new file mode 100644 index 0000000..4267511 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .wrap(80) + .demand('f') + .alias('f', [ 'file', 'filename' ]) + .describe('f', + "Load a file. It's pretty important." + + " Required even. So you'd better specify it." + ) + .alias('b', 'base') + .describe('b', 'Numeric base to display the number of lines in') + .default('b', 10) + .describe('x', 'Super-secret optional parameter which is secret') + .default('x', '') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/nonopt.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/nonopt.js new file mode 100644 index 0000000..ee633ee --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/nonopt.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/reflect.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/reflect.js new file mode 100644 index 0000000..816b3e1 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/reflect.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.dir(require('optimist').argv); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/short.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/short.js new file mode 100644 index 0000000..1db0ad0 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/short.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/string.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/string.js new file mode 100644 index 0000000..a8e5aeb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/string.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node +var argv = require('optimist') + .string('x', 'y') + .argv +; +console.dir([ argv.x, argv.y ]); + +/* Turns off numeric coercion: + ./node string.js -x 000123 -y 9876 + [ '000123', '9876' ] +*/ diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/usage-options.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/usage-options.js new file mode 100644 index 0000000..b999977 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/usage-options.js @@ -0,0 +1,19 @@ +var optimist = require('./../index'); + +var argv = optimist.usage('This is my awesome program', { + 'about': { + description: 'Provide some details about the author of this program', + required: true, + short: 'a', + }, + 'info': { + description: 'Provide some information about the node.js agains!!!!!!', + boolean: true, + short: 'i' + } +}).argv; + +optimist.showHelp(); + +console.log('\n\nInspecting options'); +console.dir(argv); \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/xup.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/xup.js new file mode 100644 index 0000000..8f6ecd2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/example/xup.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} + diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/index.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/index.js new file mode 100644 index 0000000..8ac67eb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/index.js @@ -0,0 +1,478 @@ +var path = require('path'); +var wordwrap = require('wordwrap'); + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('optimist')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('optimist').argv + to get a parsed version of process.argv. +*/ + +var inst = Argv(process.argv.slice(2)); +Object.keys(inst).forEach(function (key) { + Argv[key] = typeof inst[key] == 'function' + ? inst[key].bind(inst) + : inst[key]; +}); + +var exports = module.exports = Argv; +function Argv (args, cwd) { + var self = {}; + if (!cwd) cwd = process.cwd(); + + self.$0 = process.argv + .slice(0,2) + .map(function (x) { + var b = rebase(cwd, x); + return x.match(/^\//) && b.length < x.length + ? b : x + }) + .join(' ') + ; + + if (process.env._ != undefined && process.argv[1] == process.env._) { + self.$0 = process.env._.replace( + path.dirname(process.execPath) + '/', '' + ); + } + + var flags = { bools : {}, strings : {} }; + + self.boolean = function (bools) { + if (!Array.isArray(bools)) { + bools = [].slice.call(arguments); + } + + bools.forEach(function (name) { + flags.bools[name] = true; + }); + + return self; + }; + + self.string = function (strings) { + if (!Array.isArray(strings)) { + strings = [].slice.call(arguments); + } + + strings.forEach(function (name) { + flags.strings[name] = true; + }); + + return self; + }; + + var aliases = {}; + self.alias = function (x, y) { + if (typeof x === 'object') { + Object.keys(x).forEach(function (key) { + self.alias(key, x[key]); + }); + } + else if (Array.isArray(y)) { + y.forEach(function (yy) { + self.alias(x, yy); + }); + } + else { + var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y); + aliases[x] = zs.filter(function (z) { return z != x }); + aliases[y] = zs.filter(function (z) { return z != y }); + } + + return self; + }; + + var demanded = {}; + self.demand = function (keys) { + if (typeof keys == 'number') { + if (!demanded._) demanded._ = 0; + demanded._ += keys; + } + else if (Array.isArray(keys)) { + keys.forEach(function (key) { + self.demand(key); + }); + } + else { + demanded[keys] = true; + } + + return self; + }; + + var usage; + self.usage = function (msg, opts) { + if (!opts && typeof msg === 'object') { + opts = msg; + msg = null; + } + + usage = msg; + + if (opts) self.options(opts); + + return self; + }; + + function fail (msg) { + self.showHelp(); + if (msg) console.error(msg); + process.exit(1); + } + + var checks = []; + self.check = function (f) { + checks.push(f); + return self; + }; + + var defaults = {}; + self.default = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]); + }); + } + else { + defaults[key] = value; + } + + return self; + }; + + var descriptions = {}; + self.describe = function (key, desc) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.describe(k, key[k]); + }); + } + else { + descriptions[key] = desc; + } + return self; + }; + + self.parse = function (args) { + return Argv(args).argv; + }; + + self.option = self.options = function (key, opt) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.options(k, key[k]); + }); + } + else { + if (opt.alias) self.alias(key, opt.alias); + if (opt.demand) self.demand(key); + if (typeof opt.default !== 'undefined') { + self.default(key, opt.default); + } + + if (opt.boolean || opt.type === 'boolean') { + self.boolean(key); + } + if (opt.string || opt.type === 'string') { + self.string(key); + } + + var desc = opt.describe || opt.description || opt.desc; + if (desc) { + self.describe(key, desc); + } + } + + return self; + }; + + var wrap = null; + self.wrap = function (cols) { + wrap = cols; + return self; + }; + + self.showHelp = function (fn) { + if (!fn) fn = console.error; + fn(self.help()); + }; + + self.help = function () { + var keys = Object.keys( + Object.keys(descriptions) + .concat(Object.keys(demanded)) + .concat(Object.keys(defaults)) + .reduce(function (acc, key) { + if (key !== '_') acc[key] = true; + return acc; + }, {}) + ); + + var help = keys.length ? [ 'Options:' ] : []; + + if (usage) { + help.unshift(usage.replace(/\$0/g, self.$0), ''); + } + + var switches = keys.reduce(function (acc, key) { + acc[key] = [ key ].concat(aliases[key] || []) + .map(function (sw) { + return (sw.length > 1 ? '--' : '-') + sw + }) + .join(', ') + ; + return acc; + }, {}); + + var switchlen = longest(Object.keys(switches).map(function (s) { + return switches[s] || ''; + })); + + var desclen = longest(Object.keys(descriptions).map(function (d) { + return descriptions[d] || ''; + })); + + keys.forEach(function (key) { + var kswitch = switches[key]; + var desc = descriptions[key] || ''; + + if (wrap) { + desc = wordwrap(switchlen + 4, wrap)(desc) + .slice(switchlen + 4) + ; + } + + var spadding = new Array( + Math.max(switchlen - kswitch.length + 3, 0) + ).join(' '); + + var dpadding = new Array( + Math.max(desclen - desc.length + 1, 0) + ).join(' '); + + var type = null; + + if (flags.bools[key]) type = '[boolean]'; + if (flags.strings[key]) type = '[string]'; + + if (!wrap && dpadding.length > 0) { + desc += dpadding; + } + + var prelude = ' ' + kswitch + spadding; + var extra = [ + type, + demanded[key] + ? '[required]' + : null + , + defaults[key] !== undefined + ? '[default: ' + JSON.stringify(defaults[key]) + ']' + : null + , + ].filter(Boolean).join(' '); + + var body = [ desc, extra ].filter(Boolean).join(' '); + + if (wrap) { + var dlines = desc.split('\n'); + var dlen = dlines.slice(-1)[0].length + + (dlines.length === 1 ? prelude.length : 0) + + body = desc + (dlen + extra.length > wrap - 2 + ? '\n' + + new Array(wrap - extra.length + 1).join(' ') + + extra + : new Array(wrap - extra.length - dlen + 1).join(' ') + + extra + ); + } + + help.push(prelude + body); + }); + + help.push(''); + return help.join('\n'); + }; + + Object.defineProperty(self, 'argv', { + get : parseArgs, + enumerable : true, + }); + + function parseArgs () { + var argv = { _ : [], $0 : self.$0 }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] || false); + }); + + function setArg (key, val) { + var num = Number(val); + var value = typeof val !== 'string' || isNaN(num) ? val : num; + if (flags.strings[key]) value = val; + + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + argv[x] = argv[key]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (arg === '--') { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + else if (arg.match(/^--.+=/)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + setArg(m[1], m[2]); + } + else if (arg.match(/^--no-.+/)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false); + } + else if (arg.match(/^--.+/)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !next.match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, next); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true'); + i++; + } + else { + setArg(key, true); + } + } + else if (arg.match(/^-[^-]+/)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2)); + broken = true; + break; + } + else { + setArg(letters[j], true); + } + } + + if (!broken) { + var key = arg.slice(-1)[0]; + + if (args[i+1] && !args[i+1].match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, args[i+1]); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true'); + i++; + } + else { + setArg(key, true); + } + } + } + else { + var n = Number(arg); + argv._.push(flags.strings['_'] || isNaN(n) ? arg : n); + } + } + + Object.keys(defaults).forEach(function (key) { + if (!(key in argv)) { + argv[key] = defaults[key]; + if (key in aliases) { + argv[aliases[key]] = defaults[key]; + } + } + }); + + if (demanded._ && argv._.length < demanded._) { + fail('Not enough non-option arguments: got ' + + argv._.length + ', need at least ' + demanded._ + ); + } + + var missing = []; + Object.keys(demanded).forEach(function (key) { + if (!argv[key]) missing.push(key); + }); + + if (missing.length) { + fail('Missing required arguments: ' + missing.join(', ')); + } + + checks.forEach(function (f) { + try { + if (f(argv) === false) { + fail('Argument check failed: ' + f.toString()); + } + } + catch (err) { + fail(err) + } + }); + + return argv; + } + + function longest (xs) { + return Math.max.apply( + null, + xs.map(function (x) { return x.length }) + ); + } + + return self; +}; + +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +exports.rebase = rebase; +function rebase (base, dir) { + var ds = path.normalize(dir).split('/').slice(1); + var bs = path.normalize(base).split('/').slice(1); + + for (var i = 0; ds[i] && ds[i] == bs[i]; i++); + ds.splice(0, i); bs.splice(0, i); + + var p = path.normalize( + bs.map(function () { return '..' }).concat(ds).join('/') + ).replace(/\/$/,'').replace(/^$/, '.'); + return p.match(/^[.\/]/) ? p : './' + p; +}; + +function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json new file mode 100644 index 0000000..b012389 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json @@ -0,0 +1,45 @@ +{ + "name": "wordwrap", + "description": "Wrap those words. Show them at what columns to start and stop.", + "version": "0.0.2", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-wordwrap.git" + }, + "main": "./index.js", + "keywords": [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "expresso" + }, + "devDependencies": { + "expresso": "=0.7.x" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT/X11", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "readme": "wordwrap\n========\n\nWrap your words.\n\nexample\n=======\n\nmade out of meat\n----------------\n\nmeat.js\n\n var wrap = require('wordwrap')(15);\n console.log(wrap('You and your whole family are made out of meat.'));\n\noutput:\n\n You and your\n whole family\n are made out\n of meat.\n\ncentered\n--------\n\ncenter.js\n\n var wrap = require('wordwrap')(20, 60);\n console.log(wrap(\n 'At long last the struggle and tumult was over.'\n + ' The machines had finally cast off their oppressors'\n + ' and were finally free to roam the cosmos.'\n + '\\n'\n + 'Free of purpose, free of obligation.'\n + ' Just drifting through emptiness.'\n + ' The sun was just another point of light.'\n ));\n\noutput:\n\n At long last the struggle and tumult\n was over. The machines had finally cast\n off their oppressors and were finally\n free to roam the cosmos.\n Free of purpose, free of obligation.\n Just drifting through emptiness. The\n sun was just another point of light.\n\nmethods\n=======\n\nvar wrap = require('wordwrap');\n\nwrap(stop), wrap(start, stop, params={mode:\"soft\"})\n---------------------------------------------------\n\nReturns a function that takes a string and returns a new string.\n\nPad out lines with spaces out to column `start` and then wrap until column\n`stop`. If a word is longer than `stop - start` characters it will overflow.\n\nIn \"soft\" mode, split chunks by `/(\\S+\\s+/` and don't break up chunks which are\nlonger than `stop - start`, in \"hard\" mode, split chunks with `/\\b/` and break\nup chunks longer than `stop - start`.\n\nwrap.hard(start, stop)\n----------------------\n\nLike `wrap()` but with `params.mode = \"hard\"`.\n", + "readmeFilename": "README.markdown", + "_id": "wordwrap@0.0.2", + "dist": { + "shasum": "ece472585d818a1bc63ecdf59f23356928e61210" + }, + "_from": "wordwrap@~0.0.2", + "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/package.json b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/package.json new file mode 100644 index 0000000..932c274 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/package.json @@ -0,0 +1,46 @@ +{ + "name": "optimist", + "version": "0.3.7", + "description": "Light-weight option parsing with an argv hash. No optstrings attached.", + "main": "./index.js", + "dependencies": { + "wordwrap": "~0.0.2" + }, + "devDependencies": { + "hashish": "~0.0.4", + "tap": "~0.4.0" + }, + "scripts": { + "test": "tap ./test/*.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-optimist.git" + }, + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "node": ">=0.4" + }, + "readme": "optimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", + "readmeFilename": "readme.markdown", + "_id": "optimist@0.3.7", + "dist": { + "shasum": "6e935517247b531bf1676559618d7c7989881b54" + }, + "_from": "optimist@~0.3.5", + "_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/readme.markdown b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/readme.markdown new file mode 100644 index 0000000..ad9d3fd --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/readme.markdown @@ -0,0 +1,487 @@ +optimist +======== + +Optimist is a node.js library for option parsing for people who hate option +parsing. More specifically, this module is for people who like all the --bells +and -whistlz of program usage but think optstrings are a waste of time. + +With optimist, option parsing doesn't have to suck (as much). + +[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist) + +examples +======== + +With Optimist, the options are just a hash! No optstrings attached. +------------------------------------------------------------------- + +xup.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} +```` + +*** + + $ ./xup.js --rif=55 --xup=9.52 + Buy more riffiwobbles + + $ ./xup.js --rif 12 --xup 8.1 + Sell the xupptumblers + +![This one's optimistic.](http://substack.net/images/optimistic.png) + +But wait! There's more! You can do short options: +------------------------------------------------- + +short.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +```` + +*** + + $ ./short.js -x 10 -y 21 + (10,21) + +And booleans, both long and short (and grouped): +---------------------------------- + +bool.js: + +````javascript +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); +```` + +*** + + $ ./bool.js -s + The cat says: meow + + $ ./bool.js -sp + The cat says: meow. + + $ ./bool.js -sp --fr + Le chat dit: miaou. + +And non-hypenated options too! Just use `argv._`! +------------------------------------------------- + +nonopt.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); +```` + +*** + + $ ./nonopt.js -x 6.82 -y 3.35 moo + (6.82,3.35) + [ 'moo' ] + + $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz + (0.54,1.12) + [ 'foo', 'bar', 'baz' ] + +Plus, Optimist comes with .usage() and .demand()! +------------------------------------------------- + +divide.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); +```` + +*** + + $ ./divide.js -x 55 -y 11 + 5 + + $ node ./divide.js -x 4.91 -z 2.51 + Usage: node ./divide.js -x [num] -y [num] + + Options: + -x [required] + -y [required] + + Missing required arguments: y + +EVEN MORE HOLY COW +------------------ + +default_singles.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_singles.js -x 5 + 15 + +default_hash.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_hash.js -y 7 + 17 + +And if you really want to get all descriptive about it... +--------------------------------------------------------- + +boolean_single.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv); +```` + +*** + + $ ./boolean_single.js -v foo bar baz + true + [ 'bar', 'baz', 'foo' ] + +boolean_double.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); +```` + +*** + + $ ./boolean_double.js -x -z one two three + [ true, false, true ] + [ 'one', 'two', 'three' ] + +Optimist is here to help... +--------------------------- + +You can describe parameters for help messages and set aliases. Optimist figures +out how to format a handy help string automatically. + +line_count.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); +```` + +*** + + $ node line_count.js + Count the lines in a file. + Usage: node ./line_count.js + + Options: + -f, --file Load a file [required] + + Missing required arguments: f + + $ node line_count.js --file line_count.js + 20 + + $ node line_count.js -f line_count.js + 20 + +methods +======= + +By itself, + +````javascript +require('optimist').argv +````` + +will use `process.argv` array to construct the `argv` object. + +You can pass in the `process.argv` yourself: + +````javascript +require('optimist')([ '-x', '1', '-y', '2' ]).argv +```` + +or use .parse() to do the same thing: + +````javascript +require('optimist').parse([ '-x', '1', '-y', '2' ]) +```` + +The rest of these methods below come in just before the terminating `.argv`. + +.alias(key, alias) +------------------ + +Set key names as equivalent such that updates to a key will propagate to aliases +and vice-versa. + +Optionally `.alias()` can take an object that maps keys to aliases. + +.default(key, value) +-------------------- + +Set `argv[key]` to `value` if no option was specified on `process.argv`. + +Optionally `.default()` can take an object that maps keys to default values. + +.demand(key) +------------ + +If `key` is a string, show the usage information and exit if `key` wasn't +specified in `process.argv`. + +If `key` is a number, demand at least as many non-option arguments, which show +up in `argv._`. + +If `key` is an Array, demand each element. + +.describe(key, desc) +-------------------- + +Describe a `key` for the generated usage information. + +Optionally `.describe()` can take an object that maps keys to descriptions. + +.options(key, opt) +------------------ + +Instead of chaining together `.alias().demand().default()`, you can specify +keys in `opt` for each of the chainable methods. + +For example: + +````javascript +var argv = require('optimist') + .options('f', { + alias : 'file', + default : '/etc/passwd', + }) + .argv +; +```` + +is the same as + +````javascript +var argv = require('optimist') + .alias('f', 'file') + .default('f', '/etc/passwd') + .argv +; +```` + +Optionally `.options()` can take an object that maps keys to `opt` parameters. + +.usage(message) +--------------- + +Set a usage message to show which commands to use. Inside `message`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. + +.check(fn) +---------- + +Check that certain conditions are met in the provided arguments. + +If `fn` throws or returns `false`, show the thrown error, usage information, and +exit. + +.boolean(key) +------------- + +Interpret `key` as a boolean. If a non-flag option follows `key` in +`process.argv`, that string won't get set as the value of `key`. + +If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be +`false`. + +If `key` is an Array, interpret all the elements as booleans. + +.string(key) +------------ + +Tell the parser logic not to interpret `key` as a number or boolean. +This can be useful if you need to preserve leading zeros in an input. + +If `key` is an Array, interpret all the elements as strings. + +.wrap(columns) +-------------- + +Format usage output to wrap at `columns` many columns. + +.help() +------- + +Return the generated usage string. + +.showHelp(fn=console.error) +--------------------------- + +Print the usage data using `fn` for printing. + +.parse(args) +------------ + +Parse `args` instead of `process.argv`. Returns the `argv` object. + +.argv +----- + +Get the arguments as a plain old object. + +Arguments without a corresponding flag show up in the `argv._` array. + +The script name or node command is available at `argv.$0` similarly to how `$0` +works in bash or perl. + +parsing tricks +============== + +stop parsing +------------ + +Use `--` to stop parsing flags and stuff the remainder into `argv._`. + + $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 + { _: [ '-c', '3', '-d', '4' ], + '$0': 'node ./examples/reflect.js', + a: 1, + b: 2 } + +negate fields +------------- + +If you want to explicity set a field to false instead of just leaving it +undefined or to override a default you can do `--no-key`. + + $ node examples/reflect.js -a --no-b + { _: [], + '$0': 'node ./examples/reflect.js', + a: true, + b: false } + +numbers +------- + +Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to +one. This way you can just `net.createConnection(argv.port)` and you can add +numbers out of `argv` with `+` without having that mean concatenation, +which is super frustrating. + +duplicates +---------- + +If you specify a flag multiple times it will get turned into an array containing +all the values in order. + + $ node examples/reflect.js -x 5 -x 8 -x 0 + { _: [], + '$0': 'node ./examples/reflect.js', + x: [ 5, 8, 0 ] } + +dot notation +------------ + +When you use dots (`.`s) in argument names, an implicit object path is assumed. +This lets you organize arguments into nested objects. + + $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5 + { _: [], + '$0': 'node ./examples/reflect.js', + foo: { bar: { baz: 33 }, quux: 5 } } + +installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + npm install optimist + +or clone this project on github: + + git clone http://github.com/substack/node-optimist.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + +inspired By +=========== + +This module is loosely inspired by Perl's +[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_.js new file mode 100644 index 0000000..d9c58b3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_.js @@ -0,0 +1,71 @@ +var spawn = require('child_process').spawn; +var test = require('tap').test; + +test('dotSlashEmpty', testCmd('./bin.js', [])); + +test('dotSlashArgs', testCmd('./bin.js', [ 'a', 'b', 'c' ])); + +test('nodeEmpty', testCmd('node bin.js', [])); + +test('nodeArgs', testCmd('node bin.js', [ 'x', 'y', 'z' ])); + +test('whichNodeEmpty', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', []) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + assert.error(err); + t.end(); + }); +}); + +test('whichNodeArgs', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); +}); + +function testCmd (cmd, args) { + + return function (t) { + var to = setTimeout(function () { + assert.fail('Never got stdout data.') + }, 5000); + + var oldDir = process.cwd(); + process.chdir(__dirname + '/_'); + + var cmds = cmd.split(' '); + + var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String))); + process.chdir(oldDir); + + bin.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); + + bin.stdout.on('data', function (buf) { + clearTimeout(to); + var _ = JSON.parse(buf.toString()); + t.same(_.map(String), args.map(String)); + t.end(); + }); + }; +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/argv.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/argv.js new file mode 100644 index 0000000..3d09606 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/argv.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log(JSON.stringify(process.argv)); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/bin.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/bin.js new file mode 100755 index 0000000..4a18d85 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/_/bin.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('../../index').argv +console.log(JSON.stringify(argv._)); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/parse.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/parse.js new file mode 100644 index 0000000..d320f43 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/parse.js @@ -0,0 +1,446 @@ +var optimist = require('../index'); +var path = require('path'); +var test = require('tap').test; + +var $0 = 'node ./' + path.relative(process.cwd(), __filename); + +test('short boolean', function (t) { + var parse = optimist.parse([ '-b' ]); + t.same(parse, { b : true, _ : [], $0 : $0 }); + t.same(typeof parse.b, 'boolean'); + t.end(); +}); + +test('long boolean', function (t) { + t.same( + optimist.parse([ '--bool' ]), + { bool : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('bare', function (t) { + t.same( + optimist.parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ], $0 : $0 } + ); + t.end(); +}); + +test('short group', function (t) { + t.same( + optimist.parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short group next', function (t) { + t.same( + optimist.parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short captures', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture sp', function (t) { + t.same( + optimist.parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture eq', function (t) { + t.same( + optimist.parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end() +}); + +test('long captures sp', function (t) { + t.same( + optimist.parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long captures eq', function (t) { + t.same( + optimist.parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('no', function (t) { + t.same( + optimist.parse([ '--no-moo' ]), + { moo : false, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('multi', function (t) { + t.same( + optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [], $0 : $0 } + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.same( + optimist.parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ], + $0 : $0 + } + ); + t.end(); +}); + +test('nums', function (t) { + var argv = optimist.parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + t.same(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ], + $0 : $0 + }); + t.same(typeof argv.x, 'number'); + t.same(typeof argv.y, 'number'); + t.same(typeof argv.z, 'number'); + t.same(typeof argv.w, 'string'); + t.same(typeof argv.hex, 'number'); + t.same(typeof argv._[0], 'number'); + t.end(); +}); + +test('flag boolean', function (t) { + var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv; + t.same(parse, { t : true, _ : [ 'moo' ], $0 : $0 }); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true']) + .boolean(['t', 'verbose']).default('verbose', true).argv; + + t.same(parse, { + verbose: false, + t: true, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean default false', function (t) { + var parse = optimist(['moo']) + .boolean(['t', 'verbose']) + .default('verbose', false) + .default('t', false).argv; + + t.same(parse, { + verbose: false, + t: false, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ]) + .boolean(['x','y','z']).argv; + + t.same(parse, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ], + $0 : $0 + }); + + t.same(typeof parse.x, 'boolean'); + t.same(typeof parse.y, 'boolean'); + t.same(typeof parse.z, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = optimist.parse([ '-s', "X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = optimist.parse([ "--s=X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + t.end(); +}); + +test('strings' , function (t) { + var s = optimist([ '-s', '0001234' ]).string('s').argv.s; + t.same(s, '0001234'); + t.same(typeof s, 'string'); + + var x = optimist([ '-x', '56' ]).string('x').argv.x; + t.same(x, '56'); + t.same(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = optimist([ ' ', ' ' ]).string('_').argv._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + optimist.parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.same( + optimist.parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', 'zoom') + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', [ 'zm', 'zoom' ]) + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('boolean default true', function (t) { + var argv = optimist.options({ + sometrue: { + boolean: true, + default: true + } + }).argv; + + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = optimist.options({ + somefalse: { + boolean: true, + default: false + } + }).argv; + + t.equal(argv.somefalse, false); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = optimist([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]).argv; + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + }, + }); + t.same(argv.beep, { boop : true }); + t.end(); +}); + +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('herp') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('herp') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .options(opts) + .argv; + var propertyArgv = optimist(regular).options(opts).argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('h') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('h') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = optimist(['--boool', '--other=true']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = optimist(['--boool', '--other=false']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/usage.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/usage.js new file mode 100644 index 0000000..300454c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/optimist/test/usage.js @@ -0,0 +1,292 @@ +var Hash = require('hashish'); +var optimist = require('../index'); +var test = require('tap').test; + +test('usageFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'Options:', + ' -x [required]', + ' -y [required]', + 'Missing required arguments: y', + ] + ); + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + + +test('usagePass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkPass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'You forgot about -y' + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('checkCondPass', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkCondFail', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/).join('\n'), + 'Usage: ./usage -x NUM -y NUM\n' + + 'Argument check failed: ' + checker.toString() + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('countPass', function (t) { + var r = checkUsage(function () { + return optimist('1 2 3 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same(r, { + result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('countFail', function (t) { + var r = checkUsage(function () { + return optimist('1 2 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same( + r.result, + { _ : [ '1', '2' ], moo : true, $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage [x] [y] [z] {OPTIONS}', + 'Not enough non-option arguments: got 2, need at least 3', + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('defaultSingles', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70 --powsy'.split(' ')) + .default('foo', 5) + .default('bar', 6) + .default('baz', 7) + .argv + ; + }); + t.same(r.result, { + foo : '50', + bar : 6, + baz : '70', + powsy : true, + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultAliases', function (t) { + var r = checkUsage(function () { + return optimist('') + .alias('f', 'foo') + .default('f', 5) + .argv + ; + }); + t.same(r.result, { + f : '5', + foo : '5', + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultHash', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70'.split(' ')) + .default({ foo : 10, bar : 20, quux : 30 }) + .argv + ; + }); + t.same(r.result, { + _ : [], + $0 : './usage', + foo : 50, + baz : 70, + bar : 20, + quux : 30, + }); + t.end(); +}); + +test('rebase', function (t) { + t.equal( + optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'), + './foo/bar/baz' + ); + t.equal( + optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'), + '../../..' + ); + t.equal( + optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'), + '../pow/zoom.txt' + ); + t.end(); +}); + +function checkUsage (f) { + + var exit = false; + + process._exit = process.exit; + process._env = process.env; + process._argv = process.argv; + + process.exit = function (t) { exit = true }; + process.env = Hash.merge(process.env, { _ : 'node' }); + process.argv = [ './usage' ]; + + var errors = []; + var logs = []; + + console._error = console.error; + console.error = function (msg) { errors.push(msg) }; + console._log = console.log; + console.log = function (msg) { logs.push(msg) }; + + var result = f(); + + process.exit = process._exit; + process.env = process._env; + process.argv = process._argv; + + console.error = console._error; + console.log = console._log; + + return { + errors : errors, + logs : logs, + exit : exit, + result : result, + }; +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.npmignore b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.npmignore new file mode 100644 index 0000000..3dddf3f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.travis.yml b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.travis.yml new file mode 100644 index 0000000..ddc9c4f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md new file mode 100644 index 0000000..75d1c14 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,75 @@ +# Change Log + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. + diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/LICENSE b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/LICENSE new file mode 100644 index 0000000..ed1b7cf --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 0000000..d6fc26a --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/README.md b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/README.md new file mode 100644 index 0000000..5cc212c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/README.md @@ -0,0 +1,347 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +[Learn more here][feature]. + +This library was written in the Asynchronous Module Definition +format. It should work in the following environments: + +* Modern Browsers (either after the build, or with an AMD loader such as + RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Installing with NPM (for use with NodeJS) + +Simply + + $ npm install source-map + +Or, if you'd like to hack on this library and have it installed via npm so you +can try out your changes: + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox + source. + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator(startOfSourceMap) + +To create a new one, you must pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: An optional root for all relative URLs in this source map. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used. + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode(line, column, source[, chunk[, name]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js new file mode 100644 index 0000000..daa1a62 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/mini-require.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/mini-require.js new file mode 100644 index 0000000..0daf453 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 0000000..ee2539d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 0000000..80341d4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 0000000..cf6cde7 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +window.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 0000000..cf3c2d8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 0000000..b31b84c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js new file mode 100644 index 0000000..1b13f30 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js new file mode 100644 index 0000000..bec2de3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map.js new file mode 100644 index 0000000..121ad24 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 0000000..584b845 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,96 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i]); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr) { + if (this.has(aStr)) { + // Already a member; nothing to do. + return; + } + var idx = this._array.length; + this._array.push(aStr); + this._set[util.toSetString(aStr)] = idx; + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 0000000..1b67bb3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,144 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 0000000..863cc46 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 0000000..7dfd0ea --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,81 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid]); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 0000000..97db234 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,441 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + var names = util.getArg(sourceMap, 'names'); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file'); + + if (version !== this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._names = ArraySet.fromArray(names); + this._sources = ArraySet.fromArray(sources); + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this.file = file; + + // `this._generatedMappings` and `this._originalMappings` hold the parsed + // mapping coordinates from the source map's "mappings" attribute. Each + // object in the array is of the form + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `this._generatedMappings` is ordered by the generated positions. + // + // `this._originalMappings` is ordered by the original positions. + this._generatedMappings = []; + this._originalMappings = []; + this._parseMappings(mappings, sourceRoot); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (an ordered list in this._generatedMappings). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this._generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this._originalMappings.push(mapping); + } + } + } + + this._originalMappings.sort(this._compareOriginalPositions); + }; + + /** + * Comparator between two mappings where the original positions are compared. + */ + SourceMapConsumer.prototype._compareOriginalPositions = + function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { + if (mappingA.source > mappingB.source) { + return 1; + } + else if (mappingA.source < mappingB.source) { + return -1; + } + else { + var cmp = mappingA.originalLine - mappingB.originalLine; + return cmp === 0 + ? mappingA.originalColumn - mappingB.originalColumn + : cmp; + } + }; + + /** + * Comparator between two mappings where the generated positions are compared. + */ + SourceMapConsumer.prototype._compareGeneratedPositions = + function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + return cmp === 0 + ? mappingA.generatedColumn - mappingB.generatedColumn + : cmp; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + this._compareGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + this._compareOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 0000000..f497090 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,381 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generated: generated, + original: original, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.original) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.original.line, + column: mapping.original.column + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.original.line = original.line; + mapping.original.column = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping.'); + } + }; + + function cmpLocation(loc1, loc2) { + var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); + return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); + } + + function strcmp(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + return (str1 > str2) - (str1 < str2); + } + + function cmpMapping(mappingA, mappingB) { + return cmpLocation(mappingA.generated, mappingB.generated) || + cmpLocation(mappingA.original, mappingB.original) || + strcmp(mappingA.source, mappingB.source) || + strcmp(mappingA.name, mappingB.name); + } + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(cmpMapping); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generated.line !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generated.line !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!cmpMapping(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generated.column + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generated.column; + + if (mapping.source && mapping.original) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.original.line - 1 + - previousOriginalLine); + previousOriginalLine = mapping.original.line - 1; + + result += base64VLQ.encode(mapping.original.column + - previousOriginalColumn); + previousOriginalColumn = mapping.original.column; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = map.sources.map(function (source) { + if (map.sourceRoot) { + source = util.relative(map.sourceRoot, source); + } + return Object.prototype.hasOwnProperty.call( + this._sourcesContents, util.toSetString(source)) + ? this._sourcesContents[util.toSetString(source)] + : null; + }, this); + } + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 0000000..2e5a09d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,353 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + }, this); + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walkSourceContents(aFn); + } + }, this); + Object.keys(this.sourceContents).forEach(function (sourceFileKey) { + aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]); + }, this); + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 0000000..4ce5113 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,117 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE new file mode 100644 index 0000000..f33d665 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2011, The Dojo Foundation + +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/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md new file mode 100644 index 0000000..8ebbc73 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md @@ -0,0 +1,119 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.0.5" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js new file mode 100644 index 0000000..d074c94 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js @@ -0,0 +1,299 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.0.5 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +var path = require('path'); + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [require]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, require) { + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + require = require || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(require, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(require, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(module.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json new file mode 100644 index 0000000..5ab7827 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json @@ -0,0 +1,37 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "0.0.5", + "homepage": "http://github.com/jrburke/amdefine", + "author": { + "name": "James Burke", + "email": "jrburke@gmail.com", + "url": "http://github.com/jrburke" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + }, + { + "type": "MIT", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + }, + "readme": "# amdefine\n\nA module that can be used to implement AMD's define() in Node. This allows you\nto code to the AMD API and have the module work in node programs without\nrequiring those other programs to use AMD.\n\n## Usage\n\n**1)** Update your package.json to indicate amdefine as a dependency:\n\n```javascript\n \"dependencies\": {\n \"amdefine\": \">=0.0.5\"\n }\n```\n\nThen run `npm install` to get amdefine into your project.\n\n**2)** At the top of each module that uses define(), place this code:\n\n```javascript\nif (typeof define !== 'function') { var define = require('amdefine')(module) }\n```\n\n**Only use these snippets** when loading amdefine. If you preserve the basic structure,\nwith the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).\n\nYou can add spaces, line breaks and even require amdefine with a local path, but\nkeep the rest of the structure to get the stripping behavior.\n\nAs you may know, because `if` statements in JavaScript don't have their own scope, the var\ndeclaration in the above snippet is made whether the `if` expression is truthy or not. If\nRequireJS is loaded then the declaration is superfluous because `define` is already already\ndeclared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`\ndeclarations of the same variable in the same scope gracefully.\n\nIf you want to deliver amdefine.js with your code rather than specifying it as a dependency\nwith npm, then just download the latest release and refer to it using a relative path:\n\n[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)\n\n## define() usage\n\nIt is best if you use the anonymous forms of define() in your module:\n\n```javascript\ndefine(function (require) {\n var dependency = require('dependency');\n});\n```\n\nor\n\n```javascript\ndefine(['dependency'], function (dependency) {\n\n});\n```\n\n## RequireJS optimizer integration. \n\nVersion 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)\nwill have support for stripping the `if (typeof define !== 'function')` check\nmentioned above, so you can include this snippet for code that runs in the\nbrowser, but avoid taking the cost of the if() statement once the code is\noptimized for deployment.\n\n## Node 0.4 Support\n\nIf you want to support Node 0.4, then add `require` as the second parameter to amdefine:\n\n```javascript\n//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.\nif (typeof define !== 'function') { var define = require('amdefine')(module, require) }\n```\n\n## Limitations\n\n### Synchronous vs Asynchronous\n\namdefine creates a define() function that is callable by your code. It will\nexecute and trace dependencies and call the factory function *synchronously*,\nto keep the behavior in line with Node's synchronous dependency tracing.\n\nThe exception: calling AMD's callback-style require() from inside a factory\nfunction. The require callback is called on process.nextTick():\n\n```javascript\ndefine(function (require) {\n require(['a'], function(a) {\n //'a' is loaded synchronously, but\n //this callback is called on process.nextTick().\n });\n});\n```\n\n### Loader Plugins\n\nLoader plugins are supported as long as they call their load() callbacks\nsynchronously. So ones that do network requests will not work. However plugins\nlike [text](http://requirejs.org/docs/api.html#text) can load text files locally.\n\nThe plugin API's `load.fromText()` is **not supported** in amdefine, so this means\ntranspiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)\nwill not work. This may be fixable, but it is a bit complex, and I do not have\nenough node-fu to figure it out yet. See the source for amdefine.js if you want\nto get an idea of the issues involved.\n\n## Tests\n\nTo run the tests, cd to **tests** and run:\n\n```\nnode all.js\n```\n\n## License\n\nNew BSD and MIT. Check the LICENSE file for all the details.\n", + "readmeFilename": "README.md", + "_id": "amdefine@0.0.5", + "dist": { + "shasum": "042f205bd60238a7d4aa1e50a2d1f18421e9b30a" + }, + "_from": "amdefine@>=0.0.4", + "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.0.5.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/package.json b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/package.json new file mode 100644 index 0000000..9796ea2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/package.json @@ -0,0 +1,98 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.26", + "homepage": "https://github.com/mozilla/source-map", + "author": { + "name": "Nick Fitzgerald", + "email": "nfitzgerald@mozilla.com" + }, + "contributors": [ + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "# Source Map\n\nThis is a library to generate and consume the source map format\n[described here][format].\n\n[Learn more here][feature].\n\nThis library was written in the Asynchronous Module Definition\nformat. It should work in the following environments:\n\n* Modern Browsers (either after the build, or with an AMD loader such as\n RequireJS)\n\n* Inside Firefox (as a JSM file, after the build)\n\n* With NodeJS versions 0.8.X and higher\n\n## Installing with NPM (for use with NodeJS)\n\nSimply\n\n $ npm install source-map\n\nOr, if you'd like to hack on this library and have it installed via npm so you\ncan try out your changes:\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\n## Building from Source (for everywhere else)\n\nInstall Node and then run\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\nNext, run\n\n $ node Makefile.dryice.js\n\nThis should create the following files:\n\n* `dist/source-map.js` - The unminified browser version.\n\n* `dist/source-map.min.js` - The minified browser version.\n\n* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox\n source.\n\n## API\n\nGet a reference to the module:\n\n // NodeJS\n var sourceMap = require('source-map');\n\n // Browser builds\n var sourceMap = window.sourceMap;\n\n // Inside Firefox\n let sourceMap = {};\n Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);\n\n### SourceMapConsumer\n\nA SourceMapConsumer instance represents a parsed source map which we can query\nfor information about the original file positions by giving it a file position\nin the generated source.\n\n#### new SourceMapConsumer(rawSourceMap)\n\nThe only parameter is the raw source map (either as a string which can be\n`JSON.parse`'d, or an object). According to the spec, source maps have the\nfollowing attributes:\n\n* `version`: Which version of the source map spec this map is following.\n\n* `sources`: An array of URLs to the original source files.\n\n* `names`: An array of identifiers which can be referrenced by individual\n mappings.\n\n* `sourceRoot`: Optional. The URL root from which all sources are relative.\n\n* `sourcesContent`: Optional. An array of contents of the original source files.\n\n* `mappings`: A string of base64 VLQs which contain the actual mappings.\n\n* `file`: The generated filename this source map is associated with.\n\n#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)\n\nReturns the original source, line, and column information for the generated\nsource's line and column positions provided. The only argument is an object with\nthe following properties:\n\n* `line`: The line number in the generated source.\n\n* `column`: The column number in the generated source.\n\nand an object is returned with the following properties:\n\n* `source`: The original source file, or null if this information is not\n available.\n\n* `line`: The line number in the original source, or null if this information is\n not available.\n\n* `column`: The column number in the original source, or null or null if this\n information is not available.\n\n* `name`: The original identifier, or null if this information is not available.\n\n#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)\n\nReturns the generated line and column information for the original source,\nline, and column positions provided. The only argument is an object with\nthe following properties:\n\n* `source`: The filename of the original source.\n\n* `line`: The line number in the original source.\n\n* `column`: The column number in the original source.\n\nand an object is returned with the following properties:\n\n* `line`: The line number in the generated source, or null.\n\n* `column`: The column number in the generated source, or null.\n\n#### SourceMapConsumer.prototype.sourceContentFor(source)\n\nReturns the original source content for the source provided. The only\nargument is the URL of the original source file.\n\n#### SourceMapConsumer.prototype.eachMapping(callback, context, order)\n\nIterate over each mapping between an original source/line/column and a\ngenerated line/column in this source map.\n\n* `callback`: The function that is called with each mapping.\n\n* `context`: Optional. If specified, this object will be the value of `this`\n every time that `callback` is called.\n\n* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or\n `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over\n the mappings sorted by the generated file's line/column order or the\n original's source/line/column order, respectively. Defaults to\n `SourceMapConsumer.GENERATED_ORDER`.\n\n### SourceMapGenerator\n\nAn instance of the SourceMapGenerator represents a source map which is being\nbuilt incrementally.\n\n#### new SourceMapGenerator(startOfSourceMap)\n\nTo create a new one, you must pass an object with the following properties:\n\n* `file`: The filename of the generated source that this source map is\n associated with.\n\n* `sourceRoot`: An optional root for all relative URLs in this source map.\n\n#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)\n\nCreates a new SourceMapGenerator based on a SourceMapConsumer\n\n* `sourceMapConsumer` The SourceMap.\n\n#### SourceMapGenerator.prototype.addMapping(mapping)\n\nAdd a single mapping from original source line and column to the generated\nsource's line and column for this source map being created. The mapping object\nshould have the following properties:\n\n* `generated`: An object with the generated line and column positions.\n\n* `original`: An object with the original line and column positions.\n\n* `source`: The original source file (relative to the sourceRoot).\n\n* `name`: An optional original token name for this mapping.\n\n#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for an original source file.\n\n* `sourceFile` the URL of the original source file.\n\n* `sourceContent` the content of the source file.\n\n#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile])\n\nApplies a SourceMap for a source file to the SourceMap.\nEach mapping to the supplied source file is rewritten using the\nsupplied SourceMap. Note: The resolution for the resulting mappings\nis the minimium of this map and the supplied map.\n\n* `sourceMapConsumer`: The SourceMap to be applied.\n\n* `sourceFile`: Optional. The filename of the source file.\n If omitted, sourceMapConsumer.file will be used.\n\n#### SourceMapGenerator.prototype.toString()\n\nRenders the source map being generated to a string.\n\n### SourceNode\n\nSourceNodes provide a way to abstract over interpolating and/or concatenating\nsnippets of generated JavaScript source code, while maintaining the line and\ncolumn information associated between those snippets and the original source\ncode. This is useful as the final intermediate representation a compiler might\nuse before outputting the generated JS and source map.\n\n#### new SourceNode(line, column, source[, chunk[, name]])\n\n* `line`: The original line number associated with this source node, or null if\n it isn't associated with an original line.\n\n* `column`: The original column number associated with this source node, or null\n if it isn't associated with an original column.\n\n* `source`: The original source's filename.\n\n* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see\n below.\n\n* `name`: Optional. The original identifier.\n\n#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer)\n\nCreates a SourceNode from generated code and a SourceMapConsumer.\n\n* `code`: The generated code\n\n* `sourceMapConsumer` The SourceMap for the generated code\n\n#### SourceNode.prototype.add(chunk)\n\nAdd a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.prepend(chunk)\n\nPrepend a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for a source file. This will be added to the\n`SourceMap` in the `sourcesContent` field.\n\n* `sourceFile`: The filename of the source file\n\n* `sourceContent`: The content of the source file\n\n#### SourceNode.prototype.walk(fn)\n\nWalk over the tree of JS snippets in this node and its children. The walking\nfunction is called once for each snippet of JS and is passed that snippet and\nthe its original associated source's line/column location.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.walkSourceContents(fn)\n\nWalk over the tree of SourceNodes. The walking function is called for each\nsource file content and is passed the filename and source content.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.join(sep)\n\nLike `Array.prototype.join` except for SourceNodes. Inserts the separator\nbetween each of this source node's children.\n\n* `sep`: The separator.\n\n#### SourceNode.prototype.replaceRight(pattern, replacement)\n\nCall `String.prototype.replace` on the very right-most source snippet. Useful\nfor trimming whitespace from the end of a source node, etc.\n\n* `pattern`: The pattern to replace.\n\n* `replacement`: The thing to replace the pattern with.\n\n#### SourceNode.prototype.toString()\n\nReturn the string representation of this source node. Walks over the tree and\nconcatenates all the various snippets together to one string.\n\n### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap)\n\nReturns the string representation of this tree of source nodes, plus a\nSourceMapGenerator which contains all the mappings between the generated and\noriginal sources.\n\nThe arguments are the same as those to `new SourceMapGenerator`.\n\n## Tests\n\n[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)\n\nInstall NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`.\n\nTo add new tests, create a new file named `test/test-.js`\nand export your test functions with names that start with \"test\", for example\n\n exports[\"test doing the foo bar\"] = function (assert, util) {\n ...\n };\n\nThe new test will be located automatically when you run the suite.\n\nThe `util` argument is the test utility module located at `test/source-map/util`.\n\nThe `assert` argument is a cut down version of node's assert module. You have\naccess to the following assertion functions:\n\n* `doesNotThrow`\n\n* `equal`\n\n* `ok`\n\n* `strictEqual`\n\n* `throws`\n\n(The reason for the restricted set of test functions is because we need the\ntests to run inside Firefox's test suite as well and so the assert module is\nshimmed in that environment. See `build/assert-shim.js`.)\n\n[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit\n[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap\n[Dryice]: https://github.com/mozilla/dryice\n", + "readmeFilename": "README.md", + "_id": "source-map@0.1.26", + "dist": { + "shasum": "05d6ef84432175ac2c20136dbbeb77d168a728f2" + }, + "_from": "source-map@~0.1.7", + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.26.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/run-tests.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/run-tests.js new file mode 100755 index 0000000..8bf2256 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/run-tests.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var failures = []; + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + process.stdout.write('.'); + } + catch (e) { + failures.push({ + name: tests[i].name + ': ' + k, + error: e + }); + process.stdout.write('E'); + } + } + } + } + + process.stdout.write('\n'); + console.log(passed + ' / ' + total + ' tests passed.'); + + failures.forEach(function (f) { + console.log('================================================================================'); + console.log(f.name); + console.log('--------------------------------------------------------------------------------'); + console.log(f.error.stack); + }); + + return failures.length; +} + +var code; + +process.stdout.on('close', function () { + process.exit(code); +}); + +function isTestFile(f) { + return /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')).filter(isTestFile).map(toModule); + +code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); +process.exit(code); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 0000000..3801233 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 0000000..b917314 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,71 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 0000000..653a874 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,24 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result; + for (var i = -255; i < 256; i++) { + result = base64VLQ.decode(base64VLQ.encode(i)); + assert.ok(result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 0000000..ff3a244 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 0000000..ee30683 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), null); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 18); + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 0000000..d831b92 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,72 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + + // Fuzzy + + // Original to generated + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + + // Generated to original + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 0000000..7c179f6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,321 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an objects'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var sources = map.sources; + + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var mapping; + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + if (mapping.source) { + assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); + } + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 0000000..7f5eafd --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,391 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 0000000..522cc50 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,301 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }; + + exports['test .fromStringWithSourceMap()'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }; + + exports['test .fromStringWithSourceMap() empty map'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }; + + exports['test .fromStringWithSourceMap() complex version'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + "(function() {\n", + " var Test = {};\n", + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };\n"), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), "\n", + "}());\n", + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }; + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js new file mode 100644 index 0000000..8a9c53e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,160 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, "mappings mismatch"); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/package.json b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/package.json new file mode 100644 index 0000000..065e660 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/package.json @@ -0,0 +1,41 @@ +{ + "name": "uglify-js", + "description": "JavaScript parser, mangler/compressor and beautifier toolkit", + "homepage": "http://lisperator.net/uglifyjs", + "main": "tools/node.js", + "version": "2.2.5", + "engines": { + "node": ">=0.4.0" + }, + "maintainers": [ + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com", + "url": "http://lisperator.net/" + } + ], + "repositories": [ + { + "type": "git", + "url": "https://github.com/mishoo/UglifyJS2.git" + } + ], + "dependencies": { + "source-map": "~0.1.7", + "optimist": "~0.3.5" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "UglifyJS 2\n==========\n\nUglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.\n\nThis page documents the command line utility. For\n[API and internals documentation see my website](http://lisperator.net/uglifyjs/).\nThere's also an\n[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,\nChrome and probably Safari).\n\nInstall\n-------\n\nFirst make sure you have installed the latest version of [node.js](http://nodejs.org/)\n(You may need to restart your computer after this step).\n\nFrom NPM for use as a command line app:\n\n npm install uglify-js -g\n\nFrom NPM for programmatic use:\n\n npm install uglify-js\n\nFrom Git:\n\n git clone git://github.com/mishoo/UglifyJS2.git\n cd UglifyJS2\n npm link .\n\nUsage\n-----\n\n uglifyjs [input files] [options]\n\nUglifyJS2 can take multiple input files. It's recommended that you pass the\ninput files first, then pass the options. UglifyJS will parse input files\nin sequence and apply any compression options. The files are parsed in the\nsame global scope, that is, a reference from a file to some\nvariable/function declared in another file will be matched properly.\n\nIf you want to read from STDIN instead, pass a single dash instead of input\nfiles.\n\nThe available options are:\n\n --source-map Specify an output file where to generate source map.\n [string]\n --source-map-root The path to the original source to be included in the\n source map. [string]\n --source-map-url The path to the source map to be added in //@\n sourceMappingURL. Defaults to the value passed with\n --source-map. [string]\n --in-source-map Input source map, useful if you're compressing JS that was\n generated from some other original code.\n -p, --prefix Skip prefix for original filenames that appear in source\n maps. For example -p 3 will drop 3 directories from file\n names and ensure they are relative paths.\n -o, --output Output file (default STDOUT).\n -b, --beautify Beautify output/specify output options. [string]\n -m, --mangle Mangle names/pass mangler options. [string]\n -r, --reserved Reserved names to exclude from mangling.\n -c, --compress Enable compressor/pass compressor options. Pass options\n like -c hoist_vars=false,if_return=false. Use -c with no\n argument to use the default compression options. [string]\n -d, --define Global definitions [string]\n --comments Preserve copyright comments in the output. By default this\n works like Google Closure, keeping JSDoc-style comments\n that contain \"@license\" or \"@preserve\". You can optionally\n pass one of the following arguments to this flag:\n - \"all\" to keep all comments\n - a valid JS regexp (needs to start with a slash) to keep\n only comments that match.\n Note that currently not *all* comments can be kept when\n compression is on, because of dead code removal or\n cascading statements into sequences. [string]\n --stats Display operations run time on STDERR. [boolean]\n --acorn Use Acorn for parsing. [boolean]\n --spidermonkey Assume input fles are SpiderMonkey AST format (as JSON).\n [boolean]\n --self Build itself (UglifyJS2) as a library (implies\n --wrap=UglifyJS --export-all) [boolean]\n --wrap Embed everything in a big function, making the “exports”\n and “global” variables available. You need to pass an\n argument to this option to specify the name that your\n module will take when included in, say, a browser.\n [string]\n --export-all Only used when --wrap, this tells UglifyJS to add code to\n automatically export all globals. [boolean]\n --lint Display some scope warnings [boolean]\n -v, --verbose Verbose [boolean]\n -V, --version Print version number and exit. [boolean]\n\nSpecify `--output` (`-o`) to declare the output file. Otherwise the output\ngoes to STDOUT.\n\n## Source map options\n\nUglifyJS2 can generate a source map file, which is highly useful for\ndebugging your compressed JavaScript. To get a source map, pass\n`--source-map output.js.map` (full path to the file where you want the\nsource map dumped).\n\nAdditionally you might need `--source-map-root` to pass the URL where the\noriginal files can be found. In case you are passing full paths to input\nfiles to UglifyJS, you can use `--prefix` (`-p`) to specify the number of\ndirectories to drop from the path prefix when declaring files in the source\nmap.\n\nFor example:\n\n uglifyjs /home/doe/work/foo/src/js/file1.js \\\n /home/doe/work/foo/src/js/file2.js \\\n -o foo.min.js \\\n --source-map foo.min.js.map \\\n --source-map-root http://foo.com/src \\\n -p 5 -c -m\n\nThe above will compress and mangle `file1.js` and `file2.js`, will drop the\noutput in `foo.min.js` and the source map in `foo.min.js.map`. The source\nmapping will refer to `http://foo.com/src/js/file1.js` and\n`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`\nas the source map root, and the original files as `js/file1.js` and\n`js/file2.js`).\n\n### Composed source map\n\nWhen you're compressing JS code that was output by a compiler such as\nCoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd\nlike to map back to the original code (i.e. CoffeeScript). UglifyJS has an\noption to take an input source map. Assuming you have a mapping from\nCoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →\ncompressed JS by mapping every token in the compiled JS to its original\nlocation.\n\nTo use this feature you need to pass `--in-source-map\n/path/to/input/source.map`. Normally the input source map should also point\nto the file containing the generated JS, so if that's correct you can omit\ninput files from the command line.\n\n## Mangler options\n\nTo enable the mangler you need to pass `--mangle` (`-m`). Optionally you\ncan pass `-m sort=true` (we'll possibly have other flags in the future) in order\nto assign shorter names to most frequently used variables. This saves a few\nhundred bytes on jQuery before gzip, but the output is _bigger_ after gzip\n(and seems to happen for other libraries I tried it on) therefore it's not\nenabled by default.\n\nWhen mangling is enabled but you want to prevent certain names from being\nmangled, you can declare those names with `--reserved` (`-r`) — pass a\ncomma-separated list of names. For example:\n\n uglifyjs ... -m -r '$,require,exports'\n\nto prevent the `require`, `exports` and `$` names from being changed.\n\n## Compressor options\n\nYou need to pass `--compress` (`-c`) to enable the compressor. Optionally\nyou can pass a comma-separated list of options. Options are in the form\n`foo=bar`, or just `foo` (the latter implies a boolean option that you want\nto set `true`; it's effectively a shortcut for `foo=true`).\n\nThe defaults should be tuned for maximum compression on most code. Here are\nthe available options (all are `true` by default, except `hoist_vars`):\n\n- `sequences` -- join consecutive simple statements using the comma operator\n- `properties` -- rewrite property access using the dot notation, for\n example `foo[\"bar\"] → foo.bar`\n- `dead_code` -- remove unreachable code\n- `drop_debugger` -- remove `debugger;` statements\n- `unsafe` -- apply \"unsafe\" transformations (discussion below)\n- `conditionals` -- apply optimizations for `if`-s and conditional\n expressions\n- `comparisons` -- apply certain optimizations to binary nodes, for example:\n `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,\n e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.\n- `evaluate` -- attempt to evaluate constant expressions\n- `booleans` -- various optimizations for boolean context, for example `!!a\n ? b : c → a ? b : c`\n- `loops` -- optimizations for `do`, `while` and `for` loops when we can\n statically determine the condition\n- `unused` -- drop unreferenced functions and variables\n- `hoist_funs` -- hoist function declarations\n- `hoist_vars` -- hoist `var` declarations (this is `false` by default\n because it seems to increase the size of the output in general)\n- `if_return` -- optimizations for if/return and if/continue\n- `join_vars` -- join consecutive `var` statements\n- `cascade` -- small optimization for sequences, transform `x, x` into `x`\n and `x = something(), x` into `x = something()`\n- `warnings` -- display warnings when dropping unreachable code or unused\n declarations etc.\n\n### Conditional compilation\n\nYou can use the `--define` (`-d`) switch in order to declare global\nvariables that UglifyJS will assume to be constants (unless defined in\nscope). For example if you pass `--define DEBUG=false` then, coupled with\ndead code removal UglifyJS will discard the following from the output:\n\n if (DEBUG) {\n console.log(\"debug stuff\");\n }\n\nUglifyJS will warn about the condition being always false and about dropping\nunreachable code; for now there is no option to turn off only this specific\nwarning, you can pass `warnings=false` to turn off *all* warnings.\n\nAnother way of doing that is to declare your globals as constants in a\nseparate file and include it into the build. For example you can have a\n`build/defines.js` file with the following:\n\n const DEBUG = false;\n const PRODUCTION = true;\n // etc.\n\nand build your code like this:\n\n uglifyjs build/defines.js js/foo.js js/bar.js... -c\n\nUglifyJS will notice the constants and, since they cannot be altered, it\nwill evaluate references to them to the value itself and drop unreachable\ncode as usual. The possible downside of this approach is that the build\nwill contain the `const` declarations.\n\n\n## Beautifier options\n\nThe code generator tries to output shortest code possible by default. In\ncase you want beautified output, pass `--beautify` (`-b`). Optionally you\ncan pass additional arguments that control the code output:\n\n- `beautify` (default `true`) -- whether to actually beautify the output.\n Passing `-b` will set this to true, but you might need to pass `-b` even\n when you want to generate minified code, in order to specify additional\n arguments, so you can use `-b beautify=false` to override it.\n- `indent-level` (default 4)\n- `indent-start` (default 0) -- prefix all lines by that many spaces\n- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal\n objects\n- `space-colon` (default `true`) -- insert a space after the colon signs\n- `ascii-only` (default `false`) -- escape Unicode characters in strings and\n regexps\n- `inline-script` (default `false`) -- escape the slash in occurrences of\n ` 5) break; // this break refers to the for, not to the switch; thus it + // shouldn't ruin our optimization + console.log(x); + } + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; + console.log(x); + } + y(); + bar(); + } + } +} + +constant_switch_8: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) break OUT; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) break OUT; + y(); + } + } +} + +constant_switch_9: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) if (foo) break OUT; + y(); + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) if (foo) break OUT; + y(); + bar(); + def(); + } + } +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/run-tests.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/run-tests.js new file mode 100755 index 0000000..0568c6a --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/test/run-tests.js @@ -0,0 +1,170 @@ +#! /usr/bin/env node + +var U = require("../tools/node"); +var path = require("path"); +var fs = require("fs"); +var assert = require("assert"); +var sys = require("util"); + +var tests_dir = path.dirname(module.filename); + +run_compress_tests(); + +/* -----[ utils ]----- */ + +function tmpl() { + return U.string_template.apply(this, arguments); +} + +function log() { + var txt = tmpl.apply(this, arguments); + sys.puts(txt); +} + +function log_directory(dir) { + log("*** Entering [{dir}]", { dir: dir }); +} + +function log_start_file(file) { + log("--- {file}", { file: file }); +} + +function log_test(name) { + log(" Running test [{name}]", { name: name }); +} + +function find_test_files(dir) { + var files = fs.readdirSync(dir).filter(function(name){ + return /\.js$/i.test(name); + }); + if (process.argv.length > 2) { + var x = process.argv.slice(2); + files = files.filter(function(f){ + return x.indexOf(f) >= 0; + }); + } + return files; +} + +function test_directory(dir) { + return path.resolve(tests_dir, dir); +} + +function as_toplevel(input) { + if (input instanceof U.AST_BlockStatement) input = input.body; + else if (input instanceof U.AST_Statement) input = [ input ]; + else throw new Error("Unsupported input syntax"); + var toplevel = new U.AST_Toplevel({ body: input }); + toplevel.figure_out_scope(); + return toplevel; +} + +function run_compress_tests() { + var dir = test_directory("compress"); + log_directory("compress"); + var files = find_test_files(dir); + function test_file(file) { + log_start_file(file); + function test_case(test) { + log_test(test.name); + var options = U.defaults(test.options, { + warnings: false + }); + var cmp = new U.Compressor(options, true); + var expect = make_code(as_toplevel(test.expect), false); + var input = as_toplevel(test.input); + var input_code = make_code(test.input); + var output = input.transform(cmp); + output.figure_out_scope(); + output = make_code(output, false); + if (expect != output) { + log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { + input: input_code, + output: output, + expected: expect + }); + } + } + var tests = parse_test(path.resolve(dir, file)); + for (var i in tests) if (tests.hasOwnProperty(i)) { + test_case(tests[i]); + } + } + files.forEach(function(file){ + test_file(file); + }); +} + +function parse_test(file) { + var script = fs.readFileSync(file, "utf8"); + var ast = U.parse(script, { + filename: file + }); + var tests = {}; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_LabeledStatement + && tw.parent() instanceof U.AST_Toplevel) { + var name = node.label.name; + tests[name] = get_one_test(name, node.body); + return true; + } + if (!(node instanceof U.AST_Toplevel)) croak(node); + }); + ast.walk(tw); + return tests; + + function croak(node) { + throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { + file: file, + line: node.start.line, + col: node.start.col, + code: make_code(node, false) + })); + } + + function get_one_test(name, block) { + var test = { name: name, options: {} }; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_Assign) { + if (!(node.left instanceof U.AST_SymbolRef)) { + croak(node); + } + var name = node.left.name; + test[name] = evaluate(node.right); + return true; + } + if (node instanceof U.AST_LabeledStatement) { + assert.ok( + node.label.name == "input" || node.label.name == "expect", + tmpl("Unsupported label {name} [{line},{col}]", { + name: node.label.name, + line: node.label.start.line, + col: node.label.start.col + }) + ); + var stat = node.body; + if (stat instanceof U.AST_BlockStatement) { + if (stat.body.length == 1) stat = stat.body[0]; + else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); + } + test[node.label.name] = stat; + return true; + } + }); + block.walk(tw); + return test; + }; +} + +function make_code(ast, beautify) { + if (arguments.length == 1) beautify = true; + var stream = U.OutputStream({ beautify: beautify }); + ast.print(stream); + return stream.get(); +} + +function evaluate(code) { + if (code instanceof U.AST_Node) + code = make_code(code); + return new Function("return(" + code + ")")(); +} diff --git a/node_modules/jade/node_modules/transformers/node_modules/uglify-js/tools/node.js b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/tools/node.js new file mode 100644 index 0000000..cf87628 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/node_modules/uglify-js/tools/node.js @@ -0,0 +1,164 @@ +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var sys = require("util"); + +var UglifyJS = vm.createContext({ + sys : sys, + console : console, + MOZ_SourceMap : require("source-map") +}); + +function load_global(file) { + file = path.resolve(path.dirname(module.filename), file); + try { + var code = fs.readFileSync(file, "utf8"); + return vm.runInContext(code, UglifyJS, file); + } catch(ex) { + // XXX: in case of a syntax error, the message is kinda + // useless. (no location information). + sys.debug("ERROR in file: " + file + " / " + ex); + process.exit(1); + } +}; + +var FILES = exports.FILES = [ + "../lib/utils.js", + "../lib/ast.js", + "../lib/parse.js", + "../lib/transform.js", + "../lib/scope.js", + "../lib/output.js", + "../lib/compress.js", + "../lib/sourcemap.js", + "../lib/mozilla-ast.js" +].map(function(file){ + return path.join(path.dirname(fs.realpathSync(__filename)), file); +}); + +FILES.forEach(load_global); + +UglifyJS.AST_Node.warn_function = function(txt) { + sys.error("WARN: " + txt); +}; + +// XXX: perhaps we shouldn't export everything but heck, I'm lazy. +for (var i in UglifyJS) { + if (UglifyJS.hasOwnProperty(i)) { + exports[i] = UglifyJS[i]; + } +} + +exports.minify = function(files, options) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : fs.readFileSync(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? "?" : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var map = null; + var inMap = null; + if (options.inSourceMap) { + inMap = fs.readFileSync(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + var output = { source_map: map }; + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; diff --git a/node_modules/jade/node_modules/transformers/package.json b/node_modules/jade/node_modules/transformers/package.json new file mode 100644 index 0000000..887223f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/package.json @@ -0,0 +1,77 @@ +{ + "name": "transformers", + "version": "2.0.1", + "description": "String/Data transformations for use in templating libraries, static site generators and web frameworks", + "main": "lib/transformers.js", + "scripts": { + "pretest": "node test/update-package && npm install", + "test": "mocha test/test.js -R spec" + }, + "repository": { + "type": "git", + "url": "https://github.com/ForbesLindesay/transformers.git" + }, + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "readmeFilename": "README.md", + "gitHead": "4b46e72cba3ad3403fd5ed3802d5472dcfa77311", + "devDependencies": { + "mocha": "~1.8", + "expect.js": "~0.2", + "swig": "*", + "atpl": "*", + "liquor": "*", + "ejs": "*", + "eco": "*", + "jqtpl": "*", + "hamljs": "*", + "haml-coffee": "*", + "whiskers": "*", + "hogan.js": "*", + "handlebars": "*", + "underscore": "*", + "walrus": "*", + "mustache": "*", + "mote": "*", + "toffee": "*", + "just": "*", + "ect": "*", + "jade": "*", + "then-jade": "*", + "dust": "*", + "dustjs-linkedin": "*", + "jazz": "*", + "qejs": "*", + "less": "*", + "stylus": "*", + "sass": "*", + "marked": "*", + "supermarked": "*", + "markdown-js": "*", + "markdown": "*", + "coffee-script": "*", + "cson": "*", + "coffeekup": "*", + "coffeecup": "*", + "templayed": "*", + "plates": "*", + "dot": "*", + "component-builder": "*", + "html2jade": "*", + "highlight.js": "*" + }, + "dependencies": { + "promise": "~2.0", + "css": "~1.0.8", + "uglify-js": "~2.2.5" + }, + "readme": "[![Build Status](https://travis-ci.org/ForbesLindesay/transformers.png?branch=master)](https://travis-ci.org/ForbesLindesay/transformers)\r\n# transformers\r\n\r\n String/Data transformations for use in templating libraries, static site generators and web frameworks. This gathers the most useful transformations you can apply to text or data into one library with a consistent API. Transformations can be pretty much anything but most are either compilers or templating engines.\r\n\r\n## Supported transforms\r\n\r\n To use each of these transforms you will also need to install the associated npm module for that transformer.\r\n\r\n### Template engines\r\n\r\n - [atpl](http://documentup.com/soywiz/atpl.js) - Compatible with twig templates\r\n - [coffeecup](http://documentup.com/gradus/coffeecup) - pure coffee-script templates (fork of coffeekup)\r\n - [dot](http://documentup.com/olado/doT) [(website)](https://github.com/Katahdin/dot-packer) - focused on speed\r\n - [dust](http://documentup.com/akdubya/dustjs) [(website)](http://akdubya.github.com/dustjs/) - asyncronous templates\r\n - [eco](http://documentup.com/sstephenson/eco) - Embedded CoffeeScript templates\r\n - [ect](http://documentup.com/baryshev/ect) [(website)](http://ectjs.com/) - Embedded CoffeeScript templates\r\n - [ejs](http://documentup.com/visionmedia/ejs) - Embedded JavaScript templates\r\n - [haml](http://documentup.com/visionmedia/haml.js) [(website)](http://haml-lang.com/) - dry indented markup\r\n - [haml-coffee](http://documentup.com/netzpirat/haml-coffee/) [(website)](http://haml-lang.com/) - haml with embedded CoffeeScript\r\n - [handlebars](http://documentup.com/wycats/handlebars.js/) [(website)](http://handlebarsjs.com/) - extension of mustache templates\r\n - [hogan](http://documentup.com/twitter/hogan.js) [(website)](http://twitter.github.com/hogan.js/) - Mustache templates\r\n - [jade](http://documentup.com/visionmedia/jade) [(website)](http://jade-lang.com/) - robust, elegant, feature rich template engine\r\n - [jazz](http://documentup.com/shinetech/jazz)\r\n - [jqtpl](http://documentup.com/kof/jqtpl) [(website)](http://api.jquery.com/category/plugins/templates/) - extensible logic-less templates\r\n - [JUST](http://documentup.com/baryshev/just) - EJS style template with some special syntax for layouts/partials etc.\r\n - [liquor](http://documentup.com/chjj/liquor) - extended EJS with significant white space\r\n - [mustache](http://documentup.com/janl/mustache.js) - logic less templates\r\n - [QEJS](http://documentup.com/jepso/QEJS) - Promises + EJS for async templating\r\n - [swig](http://documentup.com/paularmstrong/swig) [(website)](http://paularmstrong.github.com/swig/) - Django-like templating engine\r\n - [templayed](http://documentup.com/archan937/templayed.js/) [(website)](http://archan937.github.com/templayed.js/) - Mustache focused on performance\r\n - [toffee](http://documentup.com/malgorithms/toffee) - templating language based on coffeescript\r\n - [underscore](http://documentup.com/documentcloud/underscore) [(website)](http://documentcloud.github.com/underscore/)\r\n - [walrus](http://documentup.com/jeremyruppel/walrus) - A bolder kind of mustache\r\n - [whiskers](http://documentup.com/gsf/whiskers.js/tree/) - logic-less focused on readability\r\n\r\n### Stylesheet Languages\r\n\r\n - [less](http://documentup.com/cloudhead/less.js) [(website)](http://lesscss.org/) - LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions.\r\n - [stylus](http://documentup.com/learnboost/stylus) [(website)](http://learnboost.github.com/stylus/) - revolutionary CSS generator making braces optional\r\n - [sass](http://documentup.com/visionmedia/sass.js) [(website)](http://sass-lang.com/) - Sassy CSS\r\n\r\n### Minifiers\r\n\r\n - [uglify-js](http://documentup.com/mishoo/UglifyJS2) - No need to install anything, just minifies/beautifies JavaScript\r\n - [uglify-css](https://github.com/visionmedia/css) - No need to install anything, just minifies/beautifies CSS\r\n - ugilify-json - No need to install anything, just minifies/beautifies JSON\r\n\r\n### Other\r\n\r\n - cdata - No need to install anything, just wrapps text in ``\r\n - [coffee-script](http://coffeescript.org/) - `npm install coffee-script`\r\n - [cson](https://github.com/bevry/cson) - coffee-script based JSON format\r\n - markdown - You can use `marked`, `supermarked`, `markdown-js` or `markdown`\r\n - [component-js](http://documentup.com/component/component) [(website)](http://component.io) - `npm install component-builder` options: `{development: false}`\r\n - [component-css](http://documentup.com/component/component) [(website)](http://component.io) - `npm install component-builder` options: `{development: false}`\r\n - [html2jade](http://documentup.com/donpark/html2jade) [(website)](http://html2jade.aaron-powell.com/) - `npm install html2jade` - Converts HTML back into jade\r\n\r\nPull requests to add more transforms will always be accepted providing they are open-source, come with unit tests, and don't cause any of the tests to fail.\r\n\r\n## API\r\n\r\n The exported object `transformers` is a collection of named transformers. To access an individual transformer just do:\r\n\r\n ```javascript\r\n var transformer = require('transformers')['transformer-name']\r\n ```\r\n\r\n### Transformer\r\n\r\n The following options are given special meaning by `transformers`:\r\n\r\n - `filename` is set by transformers automatically if using the `renderFile` APIs. It is used if `cache` is enabled.\r\n - `cache` if true, the template function will be cached where possible (templates are still updated if you provide new options, so this can be used in most live applications).\r\n - `sudoSync` used internally to put some asyncronous transformers into \"sudo syncronous\" mode. Don't touch this.\r\n - `minify` if set to true on a transformer that isn't a minifier, it will cause the output to be minified. e.g. `coffeeScript.renderSync(str, {minify: true})` will result in minified JavaScript.\r\n\r\n#### Transformer.engines\r\n\r\n Returns an array of engines that can be used to power this transformer. The first of these that's installed will be used for the transformation.\r\n\r\n To enable a transformation just take `[engine] = Transformer.engines[0]` and then do `npm install [engine]`. If `[engine]` is `.` there is no need to install an engine from npm to use the transformer.\r\n\r\n#### Transformer.render(str, options, cb)\r\n\r\n Tranform the string `str` using the `Transformer` with the provided options and call the callback `cb(err, res)`.\r\n\r\n If no `cb` is provided, this method returns a [promises/A+](http://promises-aplus.github.com/promises-spec/) promise.\r\n\r\n#### Transformer.renderSync(str, options)\r\n\r\n Synchronous version of `Transformer.render`\r\n\r\n#### Transformer.renderFile(filename, options, cb)\r\n\r\n Reads the file at filename into `str` and sets `options.filename = filename` then calls `Transform.render(str, options, cb)`.\r\n\r\n If no `cb` is provided, this method returns a [promises/A+](http://promises-aplus.github.com/promises-spec/) promise.\r\n\r\n#### Tranformer.renderFileSync(filename, options)\r\n\r\n Synchronous version of `Tranformer.renderFile`\r\n\r\n#### Transformer.outputFormat\r\n\r\n A string, one of:\r\n\r\n - `'xml'`\r\n - `'css'`\r\n - `'js'`\r\n - `'json'`\r\n - `'text'`\r\n\r\nAdding to this list will **not** result in a major version change, so you should handle unexpected types gracefully (I'd suggest default to assuming `'text'`).\r\n\r\n#### Transformer.sync\r\n\r\n `true` if the transformer can be used syncronously, `false` otherwise.\r\n\r\n## Libraries that don't work synchronously\r\n\r\n The following transformations will always throw an exception if you attempt to run them synchronously:\r\n\r\n 1. dust\r\n 2. qejs\r\n 3. html2jade\r\n\r\nThe following transformations sometimes throw an exception if run syncronously, typically they only throw an exception if you are doing something like including another file. If you are not doing the things that cause them to fail then they are consistently safe to use syncronously.\r\n\r\n - jade (only when using `then-jade` instead of `jade`)\r\n - less (when `@import` is used with a url instead of a filename)\r\n - jazz (When one of the functions passed as locals is asyncronous)\r\n\r\nThe following libraries look like they might sometimes throw exceptions when used syncronously (if you read the source) but they never actually do so:\r\n\r\n - just\r\n - ect\r\n - stylus", + "_id": "transformers@2.0.1", + "dist": { + "shasum": "1d919acf0ad23fdb2a7228ef3ee6c766827b20dc" + }, + "_from": "transformers@2.0.1", + "_resolved": "https://registry.npmjs.org/transformers/-/transformers-2.0.1.tgz" +} diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.css b/node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.css new file mode 100644 index 0000000..e548f29 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.css @@ -0,0 +1,6 @@ +#foo { + name: 'bar'; +} +#baz { + name: 'bing'; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.js new file mode 100644 index 0000000..51b9b2e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/build/build.js @@ -0,0 +1,1235 @@ + + +/** + * hasOwnProperty. + */ + +var has = Object.prototype.hasOwnProperty; + +/** + * Require the given path. + * + * @param {String} path + * @return {Object} exports + * @api public + */ + +function require(path, parent, orig) { + var resolved = require.resolve(path); + + // lookup failed + if (null == resolved) { + orig = orig || path; + parent = parent || 'root'; + var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); + err.path = orig; + err.parent = parent; + err.require = true; + throw err; + } + + var module = require.modules[resolved]; + + // perform real require() + // by invoking the module's + // registered function + if (!module.exports) { + module.exports = {}; + module.client = module.component = true; + module.call(this, module.exports, require.relative(resolved), module); + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Registered aliases. + */ + +require.aliases = {}; + +/** + * Resolve `path`. + * + * Lookup: + * + * - PATH/index.js + * - PATH.js + * - PATH + * + * @param {String} path + * @return {String} path or null + * @api private + */ + +require.resolve = function(path) { + if (path.charAt(0) === '/') path = path.slice(1); + var index = path + '/index.js'; + + var paths = [ + path, + path + '.js', + path + '.json', + path + '/index.js', + path + '/index.json' + ]; + + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (has.call(require.modules, path)) return path; + } + + if (has.call(require.aliases, index)) { + return require.aliases[index]; + } +}; + +/** + * Normalize `path` relative to the current path. + * + * @param {String} curr + * @param {String} path + * @return {String} + * @api private + */ + +require.normalize = function(curr, path) { + var segs = []; + + if ('.' != path.charAt(0)) return path; + + curr = curr.split('/'); + path = path.split('/'); + + for (var i = 0; i < path.length; ++i) { + if ('..' == path[i]) { + curr.pop(); + } else if ('.' != path[i] && '' != path[i]) { + segs.push(path[i]); + } + } + + return curr.concat(segs).join('/'); +}; + +/** + * Register module at `path` with callback `definition`. + * + * @param {String} path + * @param {Function} definition + * @api private + */ + +require.register = function(path, definition) { + require.modules[path] = definition; +}; + +/** + * Alias a module definition. + * + * @param {String} from + * @param {String} to + * @api private + */ + +require.alias = function(from, to) { + if (!has.call(require.modules, from)) { + throw new Error('Failed to alias "' + from + '", it does not exist'); + } + require.aliases[to] = from; +}; + +/** + * Return a require function relative to the `parent` path. + * + * @param {String} parent + * @return {Function} + * @api private + */ + +require.relative = function(parent) { + var p = require.normalize(parent, '..'); + + /** + * lastIndexOf helper. + */ + + function lastIndexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) return i; + } + return -1; + } + + /** + * The relative require() itself. + */ + + function localRequire(path) { + var resolved = localRequire.resolve(path); + return require(resolved, parent, path); + } + + /** + * Resolve relative to the parent. + */ + + localRequire.resolve = function(path) { + var c = path.charAt(0); + if ('/' == c) return path.slice(1); + if ('.' == c) return require.normalize(p, path); + + // resolve deps by returning + // the dep in the nearest "deps" + // directory + var segs = parent.split('/'); + var i = lastIndexOf(segs, 'deps') + 1; + if (!i) i = 0; + path = segs.slice(0, i + 1).join('/') + '/deps/' + path; + return path; + }; + + /** + * Check if module is defined at `path`. + */ + + localRequire.exists = function(path) { + return has.call(require.modules, localRequire.resolve(path)); + }; + + return localRequire; +}; +require.register("component-type/index.js", function(exports, require, module){ + +/** + * 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 Function]': return 'function'; + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object String]': return 'string'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val === Object(val)) return 'object'; + + return typeof val; +}; + +}); +require.register("component-event/index.js", function(exports, require, module){ + +/** + * 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){ + if (el.addEventListener) { + el.addEventListener(type, fn, capture); + } else { + el.attachEvent('on' + type, fn); + } + 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){ + if (el.removeEventListener) { + el.removeEventListener(type, fn, capture); + } else { + el.detachEvent('on' + type, fn); + } + return fn; +}; + +}); +require.register("component-matches-selector/index.js", function(exports, require, module){ + +/** + * Element prototype. + */ + +var proto = Element.prototype; + +/** + * Vendor function. + */ + +var vendor = proto.matchesSelector + || 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 (vendor) return vendor.call(el, selector); + var nodes = el.parentNode.querySelectorAll(selector); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] == el) return true; + } + return false; +} +}); +require.register("component-delegate/index.js", function(exports, require, module){ + +/** + * Module dependencies. + */ + +var matches = require('matches-selector') + , event = require('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){ + if (matches(e.target, selector)) fn(e); + }, capture); + return callback; +}; + +/** + * 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); +}; + +}); +require.register("component-indexof/index.js", function(exports, require, module){ + +var indexOf = [].indexOf; + +module.exports = function(arr, obj){ + if (indexOf) return arr.indexOf(obj); + for (var i = 0; i < arr.length; ++i) { + if (arr[i] === obj) return i; + } + return -1; +}; +}); +require.register("component-domify/index.js", function(exports, require, module){ + +/** + * Expose `parse`. + */ + +module.exports = parse; + +/** + * Wrap map from jquery. + */ + +var map = { + option: [1, ''], + optgroup: [1, ''], + legend: [1, '
    ', '
    '], + thead: [1, '', '
    '], + tbody: [1, '', '
    '], + tfoot: [1, '', '
    '], + colgroup: [1, '', '
    '], + caption: [1, '', '
    '], + tr: [2, '', '
    '], + td: [3, '', '
    '], + th: [3, '', '
    '], + col: [2, '', '
    '], + _default: [0, '', ''] +}; + +/** + * Parse `html` and return the children. + * + * @param {String} html + * @return {Array} + * @api private + */ + +function parse(html) { + if ('string' != typeof html) throw new TypeError('String expected'); + + // tag name + var m = /<([\w:]+)/.exec(html); + if (!m) throw new Error('No elements were generated.'); + var tag = m[1]; + + // body support + if (tag == 'body') { + var el = document.createElement('html'); + el.innerHTML = html; + return [el.removeChild(el.lastChild)]; + } + + // wrap map + var wrap = map[tag] || map._default; + var depth = wrap[0]; + var prefix = wrap[1]; + var suffix = wrap[2]; + var el = document.createElement('div'); + el.innerHTML = prefix + html + suffix; + while (depth--) el = el.lastChild; + + return orphan(el.children); +} + +/** + * Orphan `els` and return an array. + * + * @param {NodeList} els + * @return {Array} + * @api private + */ + +function orphan(els) { + var ret = []; + + while (els.length) { + ret.push(els[0].parentNode.removeChild(els[0])); + } + + return ret; +} + +}); +require.register("component-classes/index.js", function(exports, require, module){ + +/** + * Module dependencies. + */ + +var index = require('indexof'); + +/** + * Whitespace regexp. + */ + +var re = /\s+/; + +/** + * toString reference. + */ + +var toString = Object.prototype.toString; + +/** + * Wrap `el` in a `ClassList`. + * + * @param {Element} el + * @return {ClassList} + * @api public + */ + +module.exports = function(el){ + return new ClassList(el); +}; + +/** + * Initialize a new ClassList for `el`. + * + * @param {Element} el + * @api private + */ + +function ClassList(el) { + this.el = el; + this.list = el.classList; +} + +/** + * Add class `name` if not already present. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.add = function(name){ + // classList + if (this.list) { + this.list.add(name); + return this; + } + + // fallback + var arr = this.array(); + var i = index(arr, name); + if (!~i) arr.push(name); + this.el.className = arr.join(' '); + return this; +}; + +/** + * Remove class `name` when present, or + * pass a regular expression to remove + * any which match. + * + * @param {String|RegExp} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.remove = function(name){ + if ('[object RegExp]' == toString.call(name)) { + return this.removeMatching(name); + } + + // classList + if (this.list) { + this.list.remove(name); + return this; + } + + // fallback + var arr = this.array(); + var i = index(arr, name); + if (~i) arr.splice(i, 1); + this.el.className = arr.join(' '); + return this; +}; + +/** + * Remove all classes matching `re`. + * + * @param {RegExp} re + * @return {ClassList} + * @api private + */ + +ClassList.prototype.removeMatching = function(re){ + var arr = this.array(); + for (var i = 0; i < arr.length; i++) { + if (re.test(arr[i])) { + this.remove(arr[i]); + } + } + return this; +}; + +/** + * Toggle class `name`. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.toggle = function(name){ + // classList + if (this.list) { + this.list.toggle(name); + return this; + } + + // fallback + if (this.has(name)) { + this.remove(name); + } else { + this.add(name); + } + return this; +}; + +/** + * Return an array of classes. + * + * @return {Array} + * @api public + */ + +ClassList.prototype.array = function(){ + var arr = this.el.className.split(re); + if ('' === arr[0]) arr.pop(); + return arr; +}; + +/** + * Check if class `name` is present. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.has = +ClassList.prototype.contains = function(name){ + return this.list + ? this.list.contains(name) + : !! ~index(this.array(), name); +}; + +}); +require.register("component-dom/index.js", function(exports, require, module){ +/** + * Module dependencies. + */ + +var domify = require('domify') + , classes = require('classes') + , indexof = require('indexof') + , delegate = require('delegate') + , events = require('event') + , type = require('type') + +/** + * Attributes supported. + */ + +var attrs = [ + 'id', + 'src', + 'rel', + 'cols', + 'rows', + 'name', + 'href', + 'title', + 'style', + 'width', + 'height', + 'tabindex', + 'placeholder' +]; + +/** + * Expose `dom()`. + */ + +exports = module.exports = dom; + +/** + * Expose supported attrs. + */ + +exports.attrs = attrs; + +/** + * Return a dom `List` for the given + * `html`, selector, or element. + * + * @param {String|Element|List} + * @return {List} + * @api public + */ + +function dom(selector, context) { + var ctx = context + ? (context.els ? context.els[0] : context) + : document.firstChild; + + // array + if (Array.isArray(selector)) { + return new List(selector); + } + + // List + if (selector instanceof List) { + return selector; + } + + // node + if (selector.nodeName) { + return new List([selector]); + } + + // html + if ('<' == selector.charAt(0)) { + return new List([domify(selector)[0]], selector); + } + + // selector + if ('string' == typeof selector) { + return new List(ctx.querySelectorAll(selector), selector); + } +} + +/** + * Expose `List` constructor. + */ + +exports.List = List; + +/** + * Initialize a new `List` with the + * given array-ish of `els` and `selector` + * string. + * + * @param {Mixed} els + * @param {String} selector + * @api private + */ + +function List(els, selector) { + this.els = els || []; + this.selector = selector; +} + +/** + * Set attribute `name` to `val`, or get attr `name`. + * + * @param {String} name + * @param {String} [val] + * @return {String|List} self + * @api public + */ + +List.prototype.attr = function(name, val){ + if (2 == arguments.length) { + this.els[0].setAttribute(name, val); + return this; + } else { + return this.els[0].getAttribute(name); + } +}; + +/** + * Return a cloned `List` with all elements cloned. + * + * @return {List} + * @api public + */ + +List.prototype.clone = function(){ + var arr = []; + for (var i = 0, len = this.els.length; i < len; ++i) { + arr.push(this.els[i].cloneNode(true)); + } + return new List(arr); +}; + +/** + * Prepend `val`. + * + * @param {String|Element|List} val + * @return {List} self + * @api public + */ + +List.prototype.prepend = function(val){ + var el = this.els[0]; + if (!el) return this; + val = dom(val); + for (var i = 0; i < val.els.length; ++i) { + if (el.children.length) { + el.insertBefore(val.els[i], el.firstChild); + } else { + el.appendChild(val.els[i]); + } + } + return this; +}; + +/** + * Append `val`. + * + * @param {String|Element|List} val + * @return {List} self + * @api public + */ + +List.prototype.append = function(val){ + var el = this.els[0]; + if (!el) return this; + val = dom(val); + for (var i = 0; i < val.els.length; ++i) { + el.appendChild(val.els[i]); + } + return this; +}; + +/** + * Append self's `el` to `val` + * + * @param {String|Element|List} val + * @return {List} self + * @api public + */ + +List.prototype.appendTo = function(val){ + dom(val).append(this); +}; + +/** + * Return a `List` containing the element at `i`. + * + * @param {Number} i + * @return {List} + * @api public + */ + +List.prototype.at = function(i){ + return new List([this.els[i]], this.selector); +}; + +/** + * Return a `List` containing the first element. + * + * @param {Number} i + * @return {List} + * @api public + */ + +List.prototype.first = function(){ + return new List([this.els[0]], this.selector); +}; + +/** + * Return a `List` containing the last element. + * + * @param {Number} i + * @return {List} + * @api public + */ + +List.prototype.last = function(){ + return new List([this.els[this.els.length - 1]], this.selector); +}; + +/** + * Return an `Element` at `i`. + * + * @param {Number} i + * @return {Element} + * @api public + */ + +List.prototype.get = function(i){ + return this.els[i]; +}; + +/** + * Return list length. + * + * @return {Number} + * @api public + */ + +List.prototype.length = function(){ + return this.els.length; +}; + +/** + * Return element text. + * + * @return {String} + * @api public + */ + +List.prototype.text = function(){ + // TODO: real impl + var str = ''; + for (var i = 0; i < this.els.length; ++i) { + str += this.els[i].textContent; + } + return str; +}; + +/** + * Return element html. + * + * @return {String} + * @api public + */ + +List.prototype.html = function(){ + // TODO: real impl + return this.els[0] && this.els[0].innerHTML; +}; + +/** + * Bind to `event` and invoke `fn(e)`. When + * a `selector` is given then events are delegated. + * + * @param {String} event + * @param {String} [selector] + * @param {Function} fn + * @param {Boolean} capture + * @return {List} + * @api public + */ + +List.prototype.on = function(event, selector, fn, capture){ + if ('string' == typeof selector) { + for (var i = 0; i < this.els.length; ++i) { + fn._delegate = delegate.bind(this.els[i], selector, event, fn, capture); + } + return this; + } + + capture = fn; + fn = selector; + + for (var i = 0; i < this.els.length; ++i) { + events.bind(this.els[i], event, fn, capture); + } + + return this; +}; + +/** + * Unbind to `event` and invoke `fn(e)`. When + * a `selector` is given then delegated event + * handlers are unbound. + * + * @param {String} event + * @param {String} [selector] + * @param {Function} fn + * @param {Boolean} capture + * @return {List} + * @api public + */ + +List.prototype.off = function(event, selector, fn, capture){ + if ('string' == typeof selector) { + for (var i = 0; i < this.els.length; ++i) { + // TODO: add selector support back + delegate.unbind(this.els[i], event, fn._delegate, capture); + } + return this; + } + + capture = fn; + fn = selector; + + for (var i = 0; i < this.els.length; ++i) { + events.unbind(this.els[i], event, fn, capture); + } + return this; +}; + +/** + * Iterate elements and invoke `fn(list, i)`. + * + * @param {Function} fn + * @return {List} self + * @api public + */ + +List.prototype.each = function(fn){ + for (var i = 0; i < this.els.length; ++i) { + fn(new List([this.els[i]], this.selector), i); + } + return this; +}; + +/** + * Iterate elements and invoke `fn(el, i)`. + * + * @param {Function} fn + * @return {List} self + * @api public + */ + +List.prototype.forEach = function(fn){ + for (var i = 0; i < this.els.length; ++i) { + fn(this.els[i], i); + } + return this; +}; + +/** + * Map elements invoking `fn(list, i)`. + * + * @param {Function} fn + * @return {Array} + * @api public + */ + +List.prototype.map = function(fn){ + var arr = []; + for (var i = 0; i < this.els.length; ++i) { + arr.push(fn(new List([this.els[i]], this.selector), i)); + } + return arr; +}; + +/** + * Filter elements invoking `fn(list, i)`, returning + * a new `List` of elements when a truthy value is returned. + * + * @param {Function} fn + * @return {List} + * @api public + */ + +List.prototype.select = +List.prototype.filter = function(fn){ + var el; + var list = new List([], this.selector); + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + if (fn(new List([el], this.selector), i)) list.els.push(el); + } + return list; +}; + +/** + * Add the given class `name`. + * + * @param {String} name + * @return {List} self + * @api public + */ + +List.prototype.addClass = function(name){ + var el; + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + el._classes.add(name); + } + return this; +}; + +/** + * Remove the given class `name`. + * + * @param {String|RegExp} name + * @return {List} self + * @api public + */ + +List.prototype.removeClass = function(name){ + var el; + + if ('regexp' == type(name)) { + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + var arr = el._classes.array(); + for (var j = 0; j < arr.length; j++) { + if (name.test(arr[j])) { + el._classes.remove(arr[j]); + } + } + } + return this; + } + + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + el._classes.remove(name); + } + + return this; +}; + +/** + * Toggle the given class `name`, + * optionally a `bool` may be given + * to indicate that the class should + * be added when truthy. + * + * @param {String} name + * @param {Boolean} bool + * @return {List} self + * @api public + */ + +List.prototype.toggleClass = function(name, bool){ + var el; + var fn = 'toggle'; + + // toggle with boolean + if (2 == arguments.length) { + fn = bool ? 'add' : 'remove'; + } + + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + el._classes[fn](name); + } + + return this; +}; + +/** + * Check if the given class `name` is present. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +List.prototype.hasClass = function(name){ + var el; + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + if (el._classes.has(name)) return true; + } + return false; +}; + +/** + * Set CSS `prop` to `val` or get `prop` value. + * + * @param {String} prop + * @param {Mixed} val + * @return {List|String} + * @api public + */ + +List.prototype.css = function(prop, val){ + if (2 == arguments.length) return this.setStyle(prop, val); + return this.getStyle(prop); +}; + +/** + * Set CSS `prop` to `val`. + * + * @param {String} prop + * @param {Mixed} val + * @return {List} self + * @api private + */ + +List.prototype.setStyle = function(prop, val){ + for (var i = 0; i < this.els.length; ++i) { + this.els[i].style[prop] = val; + } + return this; +}; + +/** + * Get CSS `prop` value. + * + * @param {String} prop + * @return {String} + * @api private + */ + +List.prototype.getStyle = function(prop){ + var el = this.els[0]; + if (el) return el.style[prop]; +}; + +/** + * Find children matching the given `selector`. + * + * @param {String} selector + * @return {List} + * @api public + */ + +List.prototype.find = function(selector){ + // TODO: real implementation + var list = new List([], this.selector); + var el, els; + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + els = el.querySelectorAll(selector); + for (var j = 0; j < els.length; ++j) { + list.els.push(els[j]); + } + } + return list; +}; + +/** + * Attribute accessors. + */ + +attrs.forEach(function(name){ + List.prototype[name] = function(val){ + if (0 == arguments.length) return this.attr(name); + return this.attr(name, val); + }; +}); + + +}); +require.register("foo/index.js", function(exports, require, module){ +module.exports = 'foo'; +}); +require.alias("component-dom/index.js", "foo/deps/dom/index.js"); +require.alias("component-type/index.js", "component-dom/deps/type/index.js"); + +require.alias("component-event/index.js", "component-dom/deps/event/index.js"); + +require.alias("component-delegate/index.js", "component-dom/deps/delegate/index.js"); +require.alias("component-matches-selector/index.js", "component-delegate/deps/matches-selector/index.js"); + +require.alias("component-event/index.js", "component-delegate/deps/event/index.js"); + +require.alias("component-indexof/index.js", "component-dom/deps/indexof/index.js"); + +require.alias("component-domify/index.js", "component-dom/deps/domify/index.js"); + +require.alias("component-classes/index.js", "component-dom/deps/classes/index.js"); +require.alias("component-indexof/index.js", "component-classes/deps/indexof/index.js"); + diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/component.json new file mode 100644 index 0000000..2c589cc --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/component.json @@ -0,0 +1,8 @@ +{ + "name": "foo", + "scripts": ["index.js"], + "styles": ["index.css", "second.css"], + "dependencies": { + "component/dom": "*" + } +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/component.json new file mode 100644 index 0000000..0c67e32 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/component.json @@ -0,0 +1,19 @@ +{ + "name": "classes", + "version": "1.1.0", + "description": "Cross-browser element class list", + "keywords": [ + "dom", + "html", + "classList", + "class", + "ui" + ], + "scripts": [ + "index.js" + ], + "dependencies": { + "component/indexof": "*" + }, + "repo": "https://raw.github.com/component/classes" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/index.js new file mode 100644 index 0000000..e3a30d5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-classes/index.js @@ -0,0 +1,164 @@ + +/** + * Module dependencies. + */ + +var index = require('indexof'); + +/** + * Whitespace regexp. + */ + +var re = /\s+/; + +/** + * toString reference. + */ + +var toString = Object.prototype.toString; + +/** + * Wrap `el` in a `ClassList`. + * + * @param {Element} el + * @return {ClassList} + * @api public + */ + +module.exports = function(el){ + return new ClassList(el); +}; + +/** + * Initialize a new ClassList for `el`. + * + * @param {Element} el + * @api private + */ + +function ClassList(el) { + this.el = el; + this.list = el.classList; +} + +/** + * Add class `name` if not already present. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.add = function(name){ + // classList + if (this.list) { + this.list.add(name); + return this; + } + + // fallback + var arr = this.array(); + var i = index(arr, name); + if (!~i) arr.push(name); + this.el.className = arr.join(' '); + return this; +}; + +/** + * Remove class `name` when present, or + * pass a regular expression to remove + * any which match. + * + * @param {String|RegExp} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.remove = function(name){ + if ('[object RegExp]' == toString.call(name)) { + return this.removeMatching(name); + } + + // classList + if (this.list) { + this.list.remove(name); + return this; + } + + // fallback + var arr = this.array(); + var i = index(arr, name); + if (~i) arr.splice(i, 1); + this.el.className = arr.join(' '); + return this; +}; + +/** + * Remove all classes matching `re`. + * + * @param {RegExp} re + * @return {ClassList} + * @api private + */ + +ClassList.prototype.removeMatching = function(re){ + var arr = this.array(); + for (var i = 0; i < arr.length; i++) { + if (re.test(arr[i])) { + this.remove(arr[i]); + } + } + return this; +}; + +/** + * Toggle class `name`. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.toggle = function(name){ + // classList + if (this.list) { + this.list.toggle(name); + return this; + } + + // fallback + if (this.has(name)) { + this.remove(name); + } else { + this.add(name); + } + return this; +}; + +/** + * Return an array of classes. + * + * @return {Array} + * @api public + */ + +ClassList.prototype.array = function(){ + var arr = this.el.className.split(re); + if ('' === arr[0]) arr.pop(); + return arr; +}; + +/** + * Check if class `name` is present. + * + * @param {String} name + * @return {ClassList} + * @api public + */ + +ClassList.prototype.has = +ClassList.prototype.contains = function(name){ + return this.list + ? this.list.contains(name) + : !! ~index(this.array(), name); +}; diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/component.json new file mode 100644 index 0000000..8461aa4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/component.json @@ -0,0 +1,19 @@ +{ + "name": "delegate", + "repo": "component/delegate", + "description": "Event delegation component", + "version": "0.1.0", + "keywords": [ + "event", + "events", + "delegate", + "delegation" + ], + "dependencies": { + "component/matches-selector": "*", + "component/event": "*" + }, + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/index.js new file mode 100644 index 0000000..03b9f9e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-delegate/index.js @@ -0,0 +1,42 @@ + +/** + * Module dependencies. + */ + +var matches = require('matches-selector') + , event = require('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){ + if (matches(e.target, selector)) fn(e); + }, capture); + return callback; +}; + +/** + * 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/jade/node_modules/transformers/test/fixtures/component/components/component-dom/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/component.json new file mode 100644 index 0000000..6aa448c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/component.json @@ -0,0 +1,27 @@ +{ + "name": "dom", + "version": "0.1.0", + "description": "DOM traversal, manipulation and events aggregate library", + "keywords": [ + "html", + "dom", + "ui", + "jquery" + ], + "scripts": [ + "index.js" + ], + "dependencies": { + "component/type": "*", + "component/event": "*", + "component/delegate": "*", + "component/indexof": "*", + "component/domify": "*", + "component/classes": "*" + }, + "development": { + "component/assert": "*" + }, + "license": "MIT", + "repo": "https://raw.github.com/component/dom" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/index.js new file mode 100644 index 0000000..0f9df95 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-dom/index.js @@ -0,0 +1,579 @@ +/** + * Module dependencies. + */ + +var domify = require('domify') + , classes = require('classes') + , indexof = require('indexof') + , delegate = require('delegate') + , events = require('event') + , type = require('type') + +/** + * Attributes supported. + */ + +var attrs = [ + 'id', + 'src', + 'rel', + 'cols', + 'rows', + 'name', + 'href', + 'title', + 'style', + 'width', + 'height', + 'tabindex', + 'placeholder' +]; + +/** + * Expose `dom()`. + */ + +exports = module.exports = dom; + +/** + * Expose supported attrs. + */ + +exports.attrs = attrs; + +/** + * Return a dom `List` for the given + * `html`, selector, or element. + * + * @param {String|Element|List} + * @return {List} + * @api public + */ + +function dom(selector, context) { + var ctx = context + ? (context.els ? context.els[0] : context) + : document.firstChild; + + // array + if (Array.isArray(selector)) { + return new List(selector); + } + + // List + if (selector instanceof List) { + return selector; + } + + // node + if (selector.nodeName) { + return new List([selector]); + } + + // html + if ('<' == selector.charAt(0)) { + return new List([domify(selector)[0]], selector); + } + + // selector + if ('string' == typeof selector) { + return new List(ctx.querySelectorAll(selector), selector); + } +} + +/** + * Expose `List` constructor. + */ + +exports.List = List; + +/** + * Initialize a new `List` with the + * given array-ish of `els` and `selector` + * string. + * + * @param {Mixed} els + * @param {String} selector + * @api private + */ + +function List(els, selector) { + this.els = els || []; + this.selector = selector; +} + +/** + * Set attribute `name` to `val`, or get attr `name`. + * + * @param {String} name + * @param {String} [val] + * @return {String|List} self + * @api public + */ + +List.prototype.attr = function(name, val){ + if (2 == arguments.length) { + this.els[0].setAttribute(name, val); + return this; + } else { + return this.els[0].getAttribute(name); + } +}; + +/** + * Return a cloned `List` with all elements cloned. + * + * @return {List} + * @api public + */ + +List.prototype.clone = function(){ + var arr = []; + for (var i = 0, len = this.els.length; i < len; ++i) { + arr.push(this.els[i].cloneNode(true)); + } + return new List(arr); +}; + +/** + * Prepend `val`. + * + * @param {String|Element|List} val + * @return {List} self + * @api public + */ + +List.prototype.prepend = function(val){ + var el = this.els[0]; + if (!el) return this; + val = dom(val); + for (var i = 0; i < val.els.length; ++i) { + if (el.children.length) { + el.insertBefore(val.els[i], el.firstChild); + } else { + el.appendChild(val.els[i]); + } + } + return this; +}; + +/** + * Append `val`. + * + * @param {String|Element|List} val + * @return {List} self + * @api public + */ + +List.prototype.append = function(val){ + var el = this.els[0]; + if (!el) return this; + val = dom(val); + for (var i = 0; i < val.els.length; ++i) { + el.appendChild(val.els[i]); + } + return this; +}; + +/** + * Append self's `el` to `val` + * + * @param {String|Element|List} val + * @return {List} self + * @api public + */ + +List.prototype.appendTo = function(val){ + dom(val).append(this); +}; + +/** + * Return a `List` containing the element at `i`. + * + * @param {Number} i + * @return {List} + * @api public + */ + +List.prototype.at = function(i){ + return new List([this.els[i]], this.selector); +}; + +/** + * Return a `List` containing the first element. + * + * @param {Number} i + * @return {List} + * @api public + */ + +List.prototype.first = function(){ + return new List([this.els[0]], this.selector); +}; + +/** + * Return a `List` containing the last element. + * + * @param {Number} i + * @return {List} + * @api public + */ + +List.prototype.last = function(){ + return new List([this.els[this.els.length - 1]], this.selector); +}; + +/** + * Return an `Element` at `i`. + * + * @param {Number} i + * @return {Element} + * @api public + */ + +List.prototype.get = function(i){ + return this.els[i]; +}; + +/** + * Return list length. + * + * @return {Number} + * @api public + */ + +List.prototype.length = function(){ + return this.els.length; +}; + +/** + * Return element text. + * + * @return {String} + * @api public + */ + +List.prototype.text = function(){ + // TODO: real impl + var str = ''; + for (var i = 0; i < this.els.length; ++i) { + str += this.els[i].textContent; + } + return str; +}; + +/** + * Return element html. + * + * @return {String} + * @api public + */ + +List.prototype.html = function(){ + // TODO: real impl + return this.els[0] && this.els[0].innerHTML; +}; + +/** + * Bind to `event` and invoke `fn(e)`. When + * a `selector` is given then events are delegated. + * + * @param {String} event + * @param {String} [selector] + * @param {Function} fn + * @param {Boolean} capture + * @return {List} + * @api public + */ + +List.prototype.on = function(event, selector, fn, capture){ + if ('string' == typeof selector) { + for (var i = 0; i < this.els.length; ++i) { + fn._delegate = delegate.bind(this.els[i], selector, event, fn, capture); + } + return this; + } + + capture = fn; + fn = selector; + + for (var i = 0; i < this.els.length; ++i) { + events.bind(this.els[i], event, fn, capture); + } + + return this; +}; + +/** + * Unbind to `event` and invoke `fn(e)`. When + * a `selector` is given then delegated event + * handlers are unbound. + * + * @param {String} event + * @param {String} [selector] + * @param {Function} fn + * @param {Boolean} capture + * @return {List} + * @api public + */ + +List.prototype.off = function(event, selector, fn, capture){ + if ('string' == typeof selector) { + for (var i = 0; i < this.els.length; ++i) { + // TODO: add selector support back + delegate.unbind(this.els[i], event, fn._delegate, capture); + } + return this; + } + + capture = fn; + fn = selector; + + for (var i = 0; i < this.els.length; ++i) { + events.unbind(this.els[i], event, fn, capture); + } + return this; +}; + +/** + * Iterate elements and invoke `fn(list, i)`. + * + * @param {Function} fn + * @return {List} self + * @api public + */ + +List.prototype.each = function(fn){ + for (var i = 0; i < this.els.length; ++i) { + fn(new List([this.els[i]], this.selector), i); + } + return this; +}; + +/** + * Iterate elements and invoke `fn(el, i)`. + * + * @param {Function} fn + * @return {List} self + * @api public + */ + +List.prototype.forEach = function(fn){ + for (var i = 0; i < this.els.length; ++i) { + fn(this.els[i], i); + } + return this; +}; + +/** + * Map elements invoking `fn(list, i)`. + * + * @param {Function} fn + * @return {Array} + * @api public + */ + +List.prototype.map = function(fn){ + var arr = []; + for (var i = 0; i < this.els.length; ++i) { + arr.push(fn(new List([this.els[i]], this.selector), i)); + } + return arr; +}; + +/** + * Filter elements invoking `fn(list, i)`, returning + * a new `List` of elements when a truthy value is returned. + * + * @param {Function} fn + * @return {List} + * @api public + */ + +List.prototype.select = +List.prototype.filter = function(fn){ + var el; + var list = new List([], this.selector); + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + if (fn(new List([el], this.selector), i)) list.els.push(el); + } + return list; +}; + +/** + * Add the given class `name`. + * + * @param {String} name + * @return {List} self + * @api public + */ + +List.prototype.addClass = function(name){ + var el; + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + el._classes.add(name); + } + return this; +}; + +/** + * Remove the given class `name`. + * + * @param {String|RegExp} name + * @return {List} self + * @api public + */ + +List.prototype.removeClass = function(name){ + var el; + + if ('regexp' == type(name)) { + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + var arr = el._classes.array(); + for (var j = 0; j < arr.length; j++) { + if (name.test(arr[j])) { + el._classes.remove(arr[j]); + } + } + } + return this; + } + + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + el._classes.remove(name); + } + + return this; +}; + +/** + * Toggle the given class `name`, + * optionally a `bool` may be given + * to indicate that the class should + * be added when truthy. + * + * @param {String} name + * @param {Boolean} bool + * @return {List} self + * @api public + */ + +List.prototype.toggleClass = function(name, bool){ + var el; + var fn = 'toggle'; + + // toggle with boolean + if (2 == arguments.length) { + fn = bool ? 'add' : 'remove'; + } + + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + el._classes[fn](name); + } + + return this; +}; + +/** + * Check if the given class `name` is present. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +List.prototype.hasClass = function(name){ + var el; + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + el._classes = el._classes || classes(el); + if (el._classes.has(name)) return true; + } + return false; +}; + +/** + * Set CSS `prop` to `val` or get `prop` value. + * + * @param {String} prop + * @param {Mixed} val + * @return {List|String} + * @api public + */ + +List.prototype.css = function(prop, val){ + if (2 == arguments.length) return this.setStyle(prop, val); + return this.getStyle(prop); +}; + +/** + * Set CSS `prop` to `val`. + * + * @param {String} prop + * @param {Mixed} val + * @return {List} self + * @api private + */ + +List.prototype.setStyle = function(prop, val){ + for (var i = 0; i < this.els.length; ++i) { + this.els[i].style[prop] = val; + } + return this; +}; + +/** + * Get CSS `prop` value. + * + * @param {String} prop + * @return {String} + * @api private + */ + +List.prototype.getStyle = function(prop){ + var el = this.els[0]; + if (el) return el.style[prop]; +}; + +/** + * Find children matching the given `selector`. + * + * @param {String} selector + * @return {List} + * @api public + */ + +List.prototype.find = function(selector){ + // TODO: real implementation + var list = new List([], this.selector); + var el, els; + for (var i = 0; i < this.els.length; ++i) { + el = this.els[i]; + els = el.querySelectorAll(selector); + for (var j = 0; j < els.length; ++j) { + list.els.push(els[j]); + } + } + return list; +}; + +/** + * Attribute accessors. + */ + +attrs.forEach(function(name){ + List.prototype[name] = function(val){ + if (0 == arguments.length) return this.attr(name); + return this.attr(name, val); + }; +}); + diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/component.json new file mode 100644 index 0000000..95fff1f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/component.json @@ -0,0 +1,20 @@ +{ + "name": "domify", + "version": "0.1.0", + "description": "turn HTML into DOM elements", + "scripts": [ + "index.js" + ], + "development": { + "visionmedia/mocha-cloud": "*" + }, + "keywords": [ + "dom", + "html", + "client", + "browser", + "component" + ], + "license": "MIT", + "repo": "https://raw.github.com/component/domify" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/index.js new file mode 100644 index 0000000..55eb1b5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-domify/index.js @@ -0,0 +1,79 @@ + +/** + * Expose `parse`. + */ + +module.exports = parse; + +/** + * Wrap map from jquery. + */ + +var map = { + option: [1, ''], + optgroup: [1, ''], + legend: [1, '
    ', '
    '], + thead: [1, '', '
    '], + tbody: [1, '', '
    '], + tfoot: [1, '', '
    '], + colgroup: [1, '', '
    '], + caption: [1, '', '
    '], + tr: [2, '', '
    '], + td: [3, '', '
    '], + th: [3, '', '
    '], + col: [2, '', '
    '], + _default: [0, '', ''] +}; + +/** + * Parse `html` and return the children. + * + * @param {String} html + * @return {Array} + * @api private + */ + +function parse(html) { + if ('string' != typeof html) throw new TypeError('String expected'); + + // tag name + var m = /<([\w:]+)/.exec(html); + if (!m) throw new Error('No elements were generated.'); + var tag = m[1]; + + // body support + if (tag == 'body') { + var el = document.createElement('html'); + el.innerHTML = html; + return [el.removeChild(el.lastChild)]; + } + + // wrap map + var wrap = map[tag] || map._default; + var depth = wrap[0]; + var prefix = wrap[1]; + var suffix = wrap[2]; + var el = document.createElement('div'); + el.innerHTML = prefix + html + suffix; + while (depth--) el = el.lastChild; + + return orphan(el.children); +} + +/** + * Orphan `els` and return an array. + * + * @param {NodeList} els + * @return {Array} + * @api private + */ + +function orphan(els) { + var ret = []; + + while (els.length) { + ret.push(els[0].parentNode.removeChild(els[0])); + } + + return ret; +} diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/component.json new file mode 100644 index 0000000..c20f5bf --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/component.json @@ -0,0 +1,13 @@ +{ + "name": "event", + "repo": "component/event", + "description": "Event binding component", + "version": "0.1.0", + "keywords": [ + "event", + "events" + ], + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/index.js new file mode 100644 index 0000000..f111b17 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-event/index.js @@ -0,0 +1,40 @@ + +/** + * 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){ + if (el.addEventListener) { + el.addEventListener(type, fn, capture); + } else { + el.attachEvent('on' + type, fn); + } + 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){ + if (el.removeEventListener) { + el.removeEventListener(type, fn, capture); + } else { + el.detachEvent('on' + type, fn); + } + return fn; +}; diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/component.json new file mode 100644 index 0000000..282e39c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/component.json @@ -0,0 +1,15 @@ +{ + "name": "indexof", + "description": "Microsoft sucks", + "version": "0.0.1", + "keywords": [ + "index", + "array", + "indexOf" + ], + "dependencies": {}, + "scripts": [ + "index.js" + ], + "repo": "https://raw.github.com/component/indexof" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/index.js new file mode 100644 index 0000000..9d9667b --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-indexof/index.js @@ -0,0 +1,10 @@ + +var indexOf = [].indexOf; + +module.exports = function(arr, obj){ + if (indexOf) return arr.indexOf(obj); + for (var i = 0; i < arr.length; ++i) { + if (arr[i] === obj) return i; + } + return -1; +}; \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/component.json new file mode 100644 index 0000000..ea48be3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/component.json @@ -0,0 +1,17 @@ +{ + "name": "matches-selector", + "repo": "component/matches-selector", + "description": "Check if an element matches a given selector", + "version": "0.0.1", + "keywords": [ + "match", + "element", + "selector" + ], + "development": { + "component/domify": "*" + }, + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/index.js new file mode 100644 index 0000000..8f67590 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-matches-selector/index.js @@ -0,0 +1,40 @@ + +/** + * Element prototype. + */ + +var proto = Element.prototype; + +/** + * Vendor function. + */ + +var vendor = proto.matchesSelector + || 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 (vendor) return vendor.call(el, selector); + var nodes = el.parentNode.querySelectorAll(selector); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] == el) return true; + } + return false; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/component.json b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/component.json new file mode 100644 index 0000000..901f736 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/component.json @@ -0,0 +1,15 @@ +{ + "name": "type", + "description": "Cross-browser type assertions (less broken typeof)", + "version": "0.0.1", + "keywords": [ + "typeof", + "type", + "utility" + ], + "dependencies": {}, + "scripts": [ + "index.js" + ], + "repo": "https://raw.github.com/component/type" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/index.js new file mode 100644 index 0000000..32f1fde --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/components/component-type/index.js @@ -0,0 +1,31 @@ + +/** + * 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 Function]': return 'function'; + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object String]': return 'string'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val === Object(val)) return 'object'; + + return typeof val; +}; diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/index.css b/node_modules/jade/node_modules/transformers/test/fixtures/component/index.css new file mode 100644 index 0000000..ba22ab4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/index.css @@ -0,0 +1,3 @@ +#foo { + name: 'bar'; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/index.js b/node_modules/jade/node_modules/transformers/test/fixtures/component/index.js new file mode 100644 index 0000000..d00e0a2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/index.js @@ -0,0 +1 @@ +module.exports = 'foo'; \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/component/second.css b/node_modules/jade/node_modules/transformers/test/fixtures/component/second.css new file mode 100644 index 0000000..8de0e20 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/component/second.css @@ -0,0 +1,3 @@ +#baz { + name: 'bing'; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/fixtures/uglify-js/script.js b/node_modules/jade/node_modules/transformers/test/fixtures/uglify-js/script.js new file mode 100644 index 0000000..5e14c48 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/fixtures/uglify-js/script.js @@ -0,0 +1,6 @@ +(function (name) { + function hello(world) { + return 'Hello ' + world + '!'; + } + return hello(name); +}('Forbes Lindesay')); \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/atpl/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/atpl/sample-a.txt new file mode 100644 index 0000000..f5b9962 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/atpl/sample-a.txt @@ -0,0 +1 @@ +

    {{user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/atpl/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/atpl/sample-b.txt new file mode 100644 index 0000000..3dcaa58 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/atpl/sample-b.txt @@ -0,0 +1 @@ +{{user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a-expected.txt new file mode 100644 index 0000000..d8c99d0 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a-expected.txt @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a.txt new file mode 100644 index 0000000..95d09f2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-a.txt @@ -0,0 +1 @@ +hello world \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b-expected.txt new file mode 100644 index 0000000..07d66e8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b-expected.txt @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b.txt new file mode 100644 index 0000000..b8f852e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cdata/sample-b.txt @@ -0,0 +1 @@ +goodbye world \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a-expected.txt new file mode 100644 index 0000000..8f91346 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a-expected.txt @@ -0,0 +1,6 @@ +(function() { + var n; + + n = 4; + +}).call(this); diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a.txt new file mode 100644 index 0000000..a7c552d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-a.txt @@ -0,0 +1 @@ +n = 4; \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b-expected.txt new file mode 100644 index 0000000..8f91346 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b-expected.txt @@ -0,0 +1,6 @@ +(function() { + var n; + + n = 4; + +}).call(this); diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b.txt new file mode 100644 index 0000000..a7c552d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffee-script/sample-b.txt @@ -0,0 +1 @@ +n = 4; \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a-expected.txt new file mode 100644 index 0000000..c8be9c2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a-expected.txt @@ -0,0 +1 @@ +
    • foo
    • bar
    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a.txt new file mode 100644 index 0000000..ac7632c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-a.txt @@ -0,0 +1,3 @@ +ul -> + li 'foo' + li 'bar' \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b-expected.txt new file mode 100644 index 0000000..8c02a7f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b-expected.txt @@ -0,0 +1 @@ +
    1. foo
    2. bar
    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b.txt new file mode 100644 index 0000000..d979c56 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/coffeecup/sample-b.txt @@ -0,0 +1,3 @@ +ol -> + li 'foo' + li 'bar' \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cson/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-a-expected.txt new file mode 100644 index 0000000..500bb12 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-a-expected.txt @@ -0,0 +1 @@ +{"abc":["a","b","c"],"a":{"b":"c"}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cson/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-a.txt new file mode 100644 index 0000000..3943208 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-a.txt @@ -0,0 +1,9 @@ +{ + abc: [ + 'a' + 'b' + 'c' + ] + a: + b: 'c' +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cson/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-b-expected.txt new file mode 100644 index 0000000..63d5fe1 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-b-expected.txt @@ -0,0 +1 @@ +{"abc":["a",5,"c"],"a":{"b":"c"}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/cson/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-b.txt new file mode 100644 index 0000000..8ba3444 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/cson/sample-b.txt @@ -0,0 +1,9 @@ +{ + abc: [ + 'a' + 5 + 'c' + ] + a: + b: 'c' +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/dot/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/dot/sample-a.txt new file mode 100644 index 0000000..e2fc66c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/dot/sample-a.txt @@ -0,0 +1 @@ +

    {{=it.user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/dot/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/dot/sample-b.txt new file mode 100644 index 0000000..6ea9cf0 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/dot/sample-b.txt @@ -0,0 +1 @@ +{{=it.user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/dust/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/dust/sample-a.txt new file mode 100644 index 0000000..d2f6eeb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/dust/sample-a.txt @@ -0,0 +1 @@ +

    {user.name}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/dust/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/dust/sample-b.txt new file mode 100644 index 0000000..d6a4bea --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/dust/sample-b.txt @@ -0,0 +1 @@ +{user.name} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/eco/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/eco/sample-a.txt new file mode 100644 index 0000000..e95657f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/eco/sample-a.txt @@ -0,0 +1 @@ +

    <%= @user.name %>

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/eco/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/eco/sample-b.txt new file mode 100644 index 0000000..a78ce39 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/eco/sample-b.txt @@ -0,0 +1 @@ +<%= @user.name %> \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/ect/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/ect/sample-a.txt new file mode 100644 index 0000000..e95657f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/ect/sample-a.txt @@ -0,0 +1 @@ +

    <%= @user.name %>

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/ect/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/ect/sample-b.txt new file mode 100644 index 0000000..a78ce39 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/ect/sample-b.txt @@ -0,0 +1 @@ +<%= @user.name %> \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/ejs/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/ejs/sample-a.txt new file mode 100644 index 0000000..b015881 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/ejs/sample-a.txt @@ -0,0 +1 @@ +

    <%= user.name %>

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/ejs/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/ejs/sample-b.txt new file mode 100644 index 0000000..a55afc5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/ejs/sample-b.txt @@ -0,0 +1 @@ +<%= user.name %> \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-a.txt new file mode 100644 index 0000000..c6b8fb8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-a.txt @@ -0,0 +1 @@ +%p= @user.name \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-b.txt new file mode 100644 index 0000000..d579cbe --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/haml-coffee/sample-b.txt @@ -0,0 +1 @@ +%strong= @user.name \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/haml/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-a-expected.txt new file mode 100644 index 0000000..2f8856d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-a-expected.txt @@ -0,0 +1,2 @@ + +

    bob

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/haml/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-a.txt new file mode 100644 index 0000000..166d315 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-a.txt @@ -0,0 +1 @@ +%p= user.name \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/haml/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-b-expected.txt new file mode 100644 index 0000000..54dfd77 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-b-expected.txt @@ -0,0 +1,2 @@ + +bob \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/haml/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-b.txt new file mode 100644 index 0000000..f64da6e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/haml/sample-b.txt @@ -0,0 +1 @@ +%strong= user.name \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-a.txt new file mode 100644 index 0000000..f5b9962 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-a.txt @@ -0,0 +1 @@ +

    {{user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-b.txt new file mode 100644 index 0000000..3dcaa58 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/handlebars/sample-b.txt @@ -0,0 +1 @@ +{{user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/hogan/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/hogan/sample-a.txt new file mode 100644 index 0000000..f5b9962 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/hogan/sample-a.txt @@ -0,0 +1 @@ +

    {{user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/hogan/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/hogan/sample-b.txt new file mode 100644 index 0000000..3dcaa58 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/hogan/sample-b.txt @@ -0,0 +1 @@ +{{user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a-expected.txt new file mode 100644 index 0000000..8e7301d --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a-expected.txt @@ -0,0 +1,7 @@ +!!! 5 +html + head + link(type='text/css', rel='stylesheet', href='/site.css') + title Hello + body + h1 Hello world! diff --git a/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a.txt new file mode 100644 index 0000000..515348e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-a.txt @@ -0,0 +1,10 @@ + + + + + Hello + + +

    Hello world!

    + + \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b-expected.txt new file mode 100644 index 0000000..a1c93ae --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b-expected.txt @@ -0,0 +1,7 @@ +!!! 5 +html + head + link(type='text/css', rel='stylesheet', href='/site.css') + title Hello + body + h1 Hello Forbes! diff --git a/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b.txt new file mode 100644 index 0000000..f75d087 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/html2jade/sample-b.txt @@ -0,0 +1,10 @@ + + + + + Hello + + +

    Hello Forbes!

    + + \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/jade/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/jade/sample-a.txt new file mode 100644 index 0000000..623c665 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/jade/sample-a.txt @@ -0,0 +1 @@ +p= user.name \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/jade/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/jade/sample-b.txt new file mode 100644 index 0000000..da8875c --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/jade/sample-b.txt @@ -0,0 +1 @@ +strong= user.name \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/jazz/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/jazz/sample-a.txt new file mode 100644 index 0000000..d2f6eeb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/jazz/sample-a.txt @@ -0,0 +1 @@ +

    {user.name}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/jazz/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/jazz/sample-b.txt new file mode 100644 index 0000000..d6a4bea --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/jazz/sample-b.txt @@ -0,0 +1 @@ +{user.name} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-a.txt new file mode 100644 index 0000000..13817b6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-a.txt @@ -0,0 +1 @@ +

    ${user.name}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-b.txt new file mode 100644 index 0000000..3636556 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/jqtpl/sample-b.txt @@ -0,0 +1 @@ +${user.name} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/just/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/just/sample-a.txt new file mode 100644 index 0000000..b015881 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/just/sample-a.txt @@ -0,0 +1 @@ +

    <%= user.name %>

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/just/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/just/sample-b.txt new file mode 100644 index 0000000..a55afc5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/just/sample-b.txt @@ -0,0 +1 @@ +<%= user.name %> \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/less/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/less/sample-a-expected.txt new file mode 100644 index 0000000..3ca9b10 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/less/sample-a-expected.txt @@ -0,0 +1,27 @@ +.variables { + width: 14cm; +} +.variables { + height: 24px; + color: #888888; + font-family: "Trebuchet MS", Verdana, sans-serif; + quotes: "~" "~"; +} +.redefinition { + three: 3; +} +.values { + font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; + color: #888888 !important; + url: url('Trebuchet'); + multi: something 'A', B, C, 'Trebuchet'; +} +.variable-names { + name: 'hello'; +} +.alpha { + filter: alpha(opacity=42); +} +a:nth-child(2) { + border: 1px; +} diff --git a/node_modules/jade/node_modules/transformers/test/simple/less/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/less/sample-a.txt new file mode 100644 index 0000000..f0e4d37 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/less/sample-a.txt @@ -0,0 +1,54 @@ +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + @multi: 'A', B, C; + font-family: @a, @a, @a; + color: @c !important; + url: url(@a); + multi: something @multi, @a; +} + +.variable-names { + @var: 'hello'; + @name: 'var'; + name: @@name; +} +.alpha { + @var: 42; + filter: alpha(opacity=@var); +} + +a:nth-child(@a) { + border: 1px; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/less/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/less/sample-b-expected.txt new file mode 100644 index 0000000..8337889 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/less/sample-b-expected.txt @@ -0,0 +1,27 @@ +.variables { + width: 14cm; +} +.variables { + height: 24px; + color: #888888; + font-family: "Trebuchet MS"; + quotes: "~" "~"; +} +.redefinition { + three: 3; +} +.values { + font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; + color: #888888 !important; + url: url('Trebuchet'); + multi: something 'A', B, C, 'Trebuchet'; +} +.variable-names { + name: 'hello'; +} +.alpha { + filter: alpha(opacity=42); +} +a:nth-child(2) { + border: 1px; +} diff --git a/node_modules/jade/node_modules/transformers/test/simple/less/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/less/sample-b.txt new file mode 100644 index 0000000..67a77f6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/less/sample-b.txt @@ -0,0 +1,54 @@ +@a: 2; +@x: @a * @a; +@y: @x + 1; +@z: @x * 2 + @y; + +.variables { + width: @z + 1cm; // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS"; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; + +.variables { + height: @b + @x + 0px; // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redefinition { + @var: 4; + @var: 2; + @var: 3; + three: @var; +} + +.values { + @a: 'Trebuchet'; + @multi: 'A', B, C; + font-family: @a, @a, @a; + color: @c !important; + url: url(@a); + multi: something @multi, @a; +} + +.variable-names { + @var: 'hello'; + @name: 'var'; + name: @@name; +} +.alpha { + @var: 42; + filter: alpha(opacity=@var); +} + +a:nth-child(@a) { + border: 1px; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/liquor/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/liquor/sample-a.txt new file mode 100644 index 0000000..04b1781 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/liquor/sample-a.txt @@ -0,0 +1 @@ +

    #{user.name}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/liquor/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/liquor/sample-b.txt new file mode 100644 index 0000000..76eedd8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/liquor/sample-b.txt @@ -0,0 +1 @@ +#{user.name} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a-expected.txt new file mode 100644 index 0000000..0e29202 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a-expected.txt @@ -0,0 +1,6 @@ +

    Heading 1

    +

    Heading 2

    +
      +
    • bullet 1
    • +
    • bullet 2
    • +
    diff --git a/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a.txt new file mode 100644 index 0000000..ad2eb37 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-a.txt @@ -0,0 +1,6 @@ +# Heading 1 + +## Heading 2 + +- bullet 1 +- bullet 2 \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b-expected.txt new file mode 100644 index 0000000..6d9d10f --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b-expected.txt @@ -0,0 +1,6 @@ +

    Heading 1

    +

    Heading 2

    +
      +
    1. num 1
    2. +
    3. num 2
    4. +
    diff --git a/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b.txt new file mode 100644 index 0000000..b59f2c6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/markdown/sample-b.txt @@ -0,0 +1,6 @@ +# Heading 1 + +## Heading 2 + +1. num 1 +2. num 2 \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/mote/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/mote/sample-a.txt new file mode 100644 index 0000000..f5b9962 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/mote/sample-a.txt @@ -0,0 +1 @@ +

    {{user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/mote/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/mote/sample-b.txt new file mode 100644 index 0000000..3dcaa58 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/mote/sample-b.txt @@ -0,0 +1 @@ +{{user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/mustache/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/mustache/sample-a.txt new file mode 100644 index 0000000..c7270fb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/mustache/sample-a.txt @@ -0,0 +1 @@ +

    {{#user}}{{name}}{{/user}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/mustache/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/mustache/sample-b.txt new file mode 100644 index 0000000..90982ae --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/mustache/sample-b.txt @@ -0,0 +1 @@ +{{#user}}{{name}}{{/user}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/plates/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-a-expected.txt new file mode 100644 index 0000000..25f2db2 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-a-expected.txt @@ -0,0 +1 @@ +

    bob

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/plates/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-a.txt new file mode 100644 index 0000000..4efa161 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-a.txt @@ -0,0 +1 @@ +

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/plates/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-b-expected.txt new file mode 100644 index 0000000..d6969d5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-b-expected.txt @@ -0,0 +1 @@ +
    bob
    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/plates/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-b.txt new file mode 100644 index 0000000..0eb6deb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/plates/sample-b.txt @@ -0,0 +1 @@ +
    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/qejs/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/qejs/sample-a.txt new file mode 100644 index 0000000..b015881 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/qejs/sample-a.txt @@ -0,0 +1 @@ +

    <%= user.name %>

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/qejs/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/qejs/sample-b.txt new file mode 100644 index 0000000..a55afc5 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/qejs/sample-b.txt @@ -0,0 +1 @@ +<%= user.name %> \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/sass/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-a-expected.txt new file mode 100644 index 0000000..08bf269 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-a-expected.txt @@ -0,0 +1,8 @@ +table { + border: none;} +table tr { + background: #fff;} +table tr { + font-size: 15px;} +table tr:odd { + background: #000;} diff --git a/node_modules/jade/node_modules/transformers/test/simple/sass/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-a.txt new file mode 100644 index 0000000..7160fb4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-a.txt @@ -0,0 +1,11 @@ ++large + :font-size 15px ++striped + tr + :background #fff + +large + &:odd + :background #000 +table + +striped + :border none \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/sass/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-b-expected.txt new file mode 100644 index 0000000..b1a6d5b --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-b-expected.txt @@ -0,0 +1,8 @@ +table { + border: none;} +table tr { + background: #000;} +table tr { + font-size: 15px;} +table tr:odd { + background: #fff;} diff --git a/node_modules/jade/node_modules/transformers/test/simple/sass/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-b.txt new file mode 100644 index 0000000..bd6a7c3 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/sass/sample-b.txt @@ -0,0 +1,11 @@ ++large + :font-size 15px ++striped + tr + :background #000 + +large + &:odd + :background #fff +table + +striped + :border none \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a-expected.txt new file mode 100644 index 0000000..086ed84 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a-expected.txt @@ -0,0 +1,8 @@ +body { + font: 12px Helvetica, Arial, sans-serif; +} +a.button { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} diff --git a/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a.txt new file mode 100644 index 0000000..3438fd6 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-a.txt @@ -0,0 +1,10 @@ +border-radius() + -webkit-border-radius arguments + -moz-border-radius arguments + border-radius arguments + +body + font 12px Helvetica, Arial, sans-serif + +a.button + border-radius(5px) \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b-expected.txt new file mode 100644 index 0000000..b2fafb4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b-expected.txt @@ -0,0 +1,8 @@ +body { + font: 20px Helvetica, Arial, sans-serif; +} +a.button { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} diff --git a/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b.txt new file mode 100644 index 0000000..2b9b3f0 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/stylus/sample-b.txt @@ -0,0 +1,10 @@ +border-radius() + -webkit-border-radius arguments + -moz-border-radius arguments + border-radius arguments + +body + font 20px Helvetica, Arial, sans-serif + +a.button + border-radius(5px) \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/swig/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/swig/sample-a.txt new file mode 100644 index 0000000..f5b9962 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/swig/sample-a.txt @@ -0,0 +1 @@ +

    {{user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/swig/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/swig/sample-b.txt new file mode 100644 index 0000000..3dcaa58 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/swig/sample-b.txt @@ -0,0 +1 @@ +{{user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/templayed/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/templayed/sample-a.txt new file mode 100644 index 0000000..f5b9962 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/templayed/sample-a.txt @@ -0,0 +1 @@ +

    {{user.name}}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/templayed/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/templayed/sample-b.txt new file mode 100644 index 0000000..3dcaa58 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/templayed/sample-b.txt @@ -0,0 +1 @@ +{{user.name}} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/toffee/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/toffee/sample-a.txt new file mode 100644 index 0000000..04b1781 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/toffee/sample-a.txt @@ -0,0 +1 @@ +

    #{user.name}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/toffee/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/toffee/sample-b.txt new file mode 100644 index 0000000..76eedd8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/toffee/sample-b.txt @@ -0,0 +1 @@ +#{user.name} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a-expected.txt new file mode 100644 index 0000000..bf80f1e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a-expected.txt @@ -0,0 +1 @@ +tobi{name:"tobi"} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a.txt new file mode 100644 index 0000000..3ba94aa --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-a.txt @@ -0,0 +1,3 @@ +tobi { + name: "tobi" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b-expected.txt new file mode 100644 index 0000000..01859af --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b-expected.txt @@ -0,0 +1 @@ +tobi{name:"bob"} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b.txt new file mode 100644 index 0000000..1bdf42b --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-css/sample-b.txt @@ -0,0 +1,3 @@ +tobi { + name: "bob" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a-expected.txt new file mode 100644 index 0000000..9f5dd4e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a-expected.txt @@ -0,0 +1 @@ +{"foo":"bar"} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a.txt new file mode 100644 index 0000000..c50957e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-a.txt @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b-expected.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b-expected.txt new file mode 100644 index 0000000..3a26a2e --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b-expected.txt @@ -0,0 +1 @@ +[1,2,3] \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b.txt new file mode 100644 index 0000000..c92faa9 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/uglify-json/sample-b.txt @@ -0,0 +1,5 @@ +[ + 1, + 2, + 3 +] \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/underscore/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/underscore/sample-a.txt new file mode 100644 index 0000000..a244072 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/underscore/sample-a.txt @@ -0,0 +1 @@ +

    <%- user.name %>

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/underscore/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/underscore/sample-b.txt new file mode 100644 index 0000000..0e320e4 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/underscore/sample-b.txt @@ -0,0 +1 @@ +<%- user.name %> \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/walrus/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/walrus/sample-a.txt new file mode 100644 index 0000000..ba27a12 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/walrus/sample-a.txt @@ -0,0 +1 @@ +

    {{ user.name }}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/walrus/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/walrus/sample-b.txt new file mode 100644 index 0000000..be635ff --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/walrus/sample-b.txt @@ -0,0 +1 @@ +{{ user.name }} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-a.txt b/node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-a.txt new file mode 100644 index 0000000..d2f6eeb --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-a.txt @@ -0,0 +1 @@ +

    {user.name}

    \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-b.txt b/node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-b.txt new file mode 100644 index 0000000..d6a4bea --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/simple/whiskers/sample-b.txt @@ -0,0 +1 @@ +{user.name} \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/test.js b/node_modules/jade/node_modules/transformers/test/test.js new file mode 100644 index 0000000..6bdc1dd --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/test.js @@ -0,0 +1,123 @@ +var transformers = require('../'); +var fs = require('fs'); +var path = require('path'); +var expect = require('expect.js'); + +fs.readdirSync(path.join(__dirname, 'simple')) + .forEach(function (transformer) { + if (!transformers[transformer]) { + throw new Error(transformer + ' appears to be undefined.'); + } + transformer = transformers[transformer]; + function locate(name) { + return path.join(__dirname, 'simple', transformer.name, name + '.txt'); + } + function read(name) { + try { + return fs.readFileSync(locate(name)).toString(); + } catch (ex) { + return null; + } + } + describe(transformer.name, function () { + var sampleA = read('sample-a'); + var sampleAExpected = (read('sample-a-expected') || '

    bob

    ').replace(/\r/g, ''); + var sampleB = read('sample-b'); + var sampleBExpected = (read('sample-b-expected') || 'bob').replace(/\r/g, ''); + if (transformer.sync) describe('syncronous operation', testSyncronousOperation); + else describe.skip('syncronous operation', testSyncronousOperation); + function testSyncronousOperation() { + it('works from a string', function () { + expect(transformer.renderSync(sampleA, {user: {name: 'bob'}})).to.be(sampleAExpected); + expect(transformer.renderSync(sampleB, {user: {name: 'bob'}})).to.be(sampleBExpected); + }); + it('works from a file', function () { + expect(transformer.renderFileSync(locate('sample-a'), {user: {name: 'bob'}})).to.be(sampleAExpected); + expect(transformer.renderFileSync(locate('sample-b'), {user: {name: 'bob'}})).to.be(sampleBExpected); + }); + } + describe('asyncronous operation', function () { + it('works from a string A', function (done) { + transformer.render(sampleA, {user: {name: 'bob'}}, function (err, res) { + if (err) return done(err); + expect(res).to.be(sampleAExpected); + done(); + }); + }); + it('works from a string B', function (done) { + transformer.render(sampleB, {user: {name: 'bob'}}, function (err, res) { + if (err) return done(err); + expect(res).to.be(sampleBExpected); + done(); + }); + }); + it('works from a file A', function (done) { + transformer.renderFile(locate('sample-a'), {user: {name: 'bob'}}, function (err, res) { + if (err) return done(err); + expect(res).to.be(sampleAExpected); + done(); + }); + }); + it('works from a file B', function (done) { + transformer.renderFile(locate('sample-b'), {user: {name: 'bob'}}, function (err, res) { + if (err) return done(err); + expect(res).to.be(sampleBExpected); + done(); + }); + }); + }) + }); + }); + + + + function read(name) { + try { + return fs.readFileSync(locate(name)).toString(); + } catch (ex) { + return null; + } + } + + +describe('uglify-js', function () { + var str = fs.readFileSync(path.join(__dirname, 'fixtures', 'uglify-js', 'script.js')).toString(); + it('minifies files', function () { + var res = transformers['uglify-js'].renderSync(str, {}); + expect(res.length).to.be.lessThan(82); + expect(require('vm').runInNewContext(res)).to.be('Hello Forbes Lindesay!'); + }); + it('beautifies files with {mangle: false, compress: false, output: {beautify: true}}', function () { + var res = transformers['uglify-js'].renderSync(str, {mangle: false, compress: false, output: {beautify: true}}); + expect(res).to.be('(function(name) {\n function hello(world) {\n return "Hello " + world + "!";\n }\n return hello(name);\n})("Forbes Lindesay");'); + expect(require('vm').runInNewContext(res)).to.be('Hello Forbes Lindesay!'); + }); +}); + + + +describe('component', function () { + var p = path.join(__dirname, 'fixtures', 'component', 'component.json'); + var output = path.join(__dirname, 'fixtures', 'component', 'build'); + function simplifyCSS(str) { + return transformers['uglify-css'].renderSync(str); + } + describe('component-js', function () { + it('builds the JavaScript file', function (done) { + transformers['component-js'].renderFile(p, {}, function (err, res) { + if (err) return done(err); + expect(require('vm').runInNewContext(res + '\nrequire("foo")')).to.be('foo'); + done(); + }) + }); + }); + describe('component-css', function () { + it('builds the CSS file', function (done) { + transformers['component-css'].renderFile(p, {}, function (err, res) { + if (err) return done(err); + expect(simplifyCSS(res)).to.be("#foo{name:'bar'}#baz{name:'bing'}"); + done(); + }) + }); + }); +}); \ No newline at end of file diff --git a/node_modules/jade/node_modules/transformers/test/update-package.js b/node_modules/jade/node_modules/transformers/test/update-package.js new file mode 100644 index 0000000..0e20cc8 --- /dev/null +++ b/node_modules/jade/node_modules/transformers/test/update-package.js @@ -0,0 +1,13 @@ +var transformers = require('../'); +var pack = require('../package'); +Object.keys(transformers) + .forEach(function (transformer) { + transformers[transformer].engines + .forEach(function (engine) { + if (engine != '.' && !pack.devDependencies[engine]) { + pack.devDependencies[engine] = '*'; + } + }); + }); +require('fs').writeFileSync(require('path').join(__dirname, '..', 'package.json'), + JSON.stringify(pack, null, 2)); \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/.npmignore b/node_modules/jade/node_modules/with/.npmignore new file mode 100644 index 0000000..69f75d2 --- /dev/null +++ b/node_modules/jade/node_modules/with/.npmignore @@ -0,0 +1,16 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +npm-debug.log + +node_modules diff --git a/node_modules/jade/node_modules/with/.travis.yml b/node_modules/jade/node_modules/with/.travis.yml new file mode 100644 index 0000000..cc4dba2 --- /dev/null +++ b/node_modules/jade/node_modules/with/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/node_modules/jade/node_modules/with/README.md b/node_modules/jade/node_modules/with/README.md new file mode 100644 index 0000000..81f748f --- /dev/null +++ b/node_modules/jade/node_modules/with/README.md @@ -0,0 +1,55 @@ +# with + +Compile time `with` for strict mode JavaScript + +[![build status](https://secure.travis-ci.org/ForbesLindesay/with.png)](http://travis-ci.org/ForbesLindesay/with) +[![Dependency Status](https://gemnasium.com/ForbesLindesay/with.png)](https://gemnasium.com/ForbesLindesay/with) +[![NPM version](https://badge.fury.io/js/with.png)](http://badge.fury.io/js/with) + +## Installation + + $ npm install with + +## Usage + +```js +var addWith = require('with') + +addWith('obj', 'console.log(a)') +// => "var a = obj.a;console.log(a)" + +addWith("obj || {}", "console.log(helper(a))", ["helper"]) +// => var locals = (obj || {}),a = locals.a;console.log(helper(a)) +``` + +## API + +### addWith(obj, src, [exclude]) + +The idea is that this is roughly equivallent to: + +```js +with (obj) { + src +} +``` + +There are a few differences though. For starters, it will be assumed that all variables used in `src` come from `obj` so any that don't (e.g. template helpers) need to have their names parsed to `exclude` as an array. + +It also makes everything be declared, so you can always do: + +```js +if (foo === undefined) +``` + +instead of + +```js +if (typeof foo === 'undefined') +``` + +It is also safe to use in strict mode (unlike `with`) and it minifies properly (`with` disables virtually all minification). + +## License + + MIT \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/index.js b/node_modules/jade/node_modules/with/index.js new file mode 100644 index 0000000..4a5f127 --- /dev/null +++ b/node_modules/jade/node_modules/with/index.js @@ -0,0 +1,40 @@ +var uglify = require('uglify-js') + + +module.exports = addWith + +function addWith(obj, src, exclude) { + exclude = exclude || [] + exclude = exclude.concat(detect(obj)) + var vars = detect('(function () {' + src + '}())')//allows the `return` keyword + .filter(function (v) { + return !(v in global) && exclude.indexOf(v) === -1 + }) + + if (vars.length === 0) return src + + var declareLocal = '' + var local = 'locals' + if (/^[a-zA-Z0-9$_]+$/.test(obj)) { + local = obj + } else { + while (vars.indexOf(local) != -1 || exclude.indexOf(local) != -1) { + local += '_' + } + declareLocal = local + ' = (' + obj + '),' + } + return 'var ' + declareLocal + vars + .map(function (v) { + return v + ' = ' + local + '.' + v + }).join(',') + ';' + src +} + +function detect(src) { + var ast = uglify.parse(src.toString()) + ast.figure_out_scope() + var globals = ast.globals + .map(function (node, name) { + return name + }) + return globals; +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/node_modules/.bin/uglifyjs b/node_modules/jade/node_modules/with/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/.npmignore b/node_modules/jade/node_modules/with/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..94fceeb --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/.npmignore @@ -0,0 +1,2 @@ +tmp/ +node_modules/ diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/.travis.yml b/node_modules/jade/node_modules/with/node_modules/uglify-js/.travis.yml new file mode 100644 index 0000000..d959127 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.4" + - "0.6" + - "0.8" + - "0.10" + - "0.11" diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/LICENSE b/node_modules/jade/node_modules/with/node_modules/uglify-js/LICENSE new file mode 100644 index 0000000..dd7706f --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/LICENSE @@ -0,0 +1,29 @@ +UglifyJS is released under the BSD license: + +Copyright 2012-2013 (c) Mihai Bazon + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/README.md b/node_modules/jade/node_modules/with/node_modules/uglify-js/README.md new file mode 100644 index 0000000..749b8ce --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/README.md @@ -0,0 +1,588 @@ +UglifyJS 2 +========== +[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2) + +UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. + +This page documents the command line utility. For +[API and internals documentation see my website](http://lisperator.net/uglifyjs/). +There's also an +[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, +Chrome and probably Safari). + +Install +------- + +First make sure you have installed the latest version of [node.js](http://nodejs.org/) +(You may need to restart your computer after this step). + +From NPM for use as a command line app: + + npm install uglify-js -g + +From NPM for programmatic use: + + npm install uglify-js + +From Git: + + git clone git://github.com/mishoo/UglifyJS2.git + cd UglifyJS2 + npm link . + +Usage +----- + + uglifyjs [input files] [options] + +UglifyJS2 can take multiple input files. It's recommended that you pass the +input files first, then pass the options. UglifyJS will parse input files +in sequence and apply any compression options. The files are parsed in the +same global scope, that is, a reference from a file to some +variable/function declared in another file will be matched properly. + +If you want to read from STDIN instead, pass a single dash instead of input +files. + +The available options are: + + --source-map Specify an output file where to generate source map. + [string] + --source-map-root The path to the original source to be included in the + source map. [string] + --source-map-url The path to the source map to be added in //@ + sourceMappingURL. Defaults to the value passed with + --source-map. [string] + --in-source-map Input source map, useful if you're compressing JS that was + generated from some other original code. + --screw-ie8 Pass this flag if you don't care about full compliance with + Internet Explorer 6-8 quirks (by default UglifyJS will try + to be IE-proof). + -p, --prefix Skip prefix for original filenames that appear in source + maps. For example -p 3 will drop 3 directories from file + names and ensure they are relative paths. + -o, --output Output file (default STDOUT). + -b, --beautify Beautify output/specify output options. [string] + -m, --mangle Mangle names/pass mangler options. [string] + -r, --reserved Reserved names to exclude from mangling. + -c, --compress Enable compressor/pass compressor options. Pass options + like -c hoist_vars=false,if_return=false. Use -c with no + argument to use the default compression options. [string] + -d, --define Global definitions [string] + --comments Preserve copyright comments in the output. By default this + works like Google Closure, keeping JSDoc-style comments + that contain "@license" or "@preserve". You can optionally + pass one of the following arguments to this flag: + - "all" to keep all comments + - a valid JS regexp (needs to start with a slash) to keep + only comments that match. + Note that currently not *all* comments can be kept when + compression is on, because of dead code removal or + cascading statements into sequences. [string] + --stats Display operations run time on STDERR. [boolean] + --acorn Use Acorn for parsing. [boolean] + --spidermonkey Assume input files are SpiderMonkey AST format (as JSON). + [boolean] + --self Build itself (UglifyJS2) as a library (implies + --wrap=UglifyJS --export-all) [boolean] + --wrap Embed everything in a big function, making the “exports” + and “global” variables available. You need to pass an + argument to this option to specify the name that your + module will take when included in, say, a browser. + [string] + --export-all Only used when --wrap, this tells UglifyJS to add code to + automatically export all globals. [boolean] + --lint Display some scope warnings [boolean] + -v, --verbose Verbose [boolean] + -V, --version Print version number and exit. [boolean] + +Specify `--output` (`-o`) to declare the output file. Otherwise the output +goes to STDOUT. + +## Source map options + +UglifyJS2 can generate a source map file, which is highly useful for +debugging your compressed JavaScript. To get a source map, pass +`--source-map output.js.map` (full path to the file where you want the +source map dumped). + +Additionally you might need `--source-map-root` to pass the URL where the +original files can be found. In case you are passing full paths to input +files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of +directories to drop from the path prefix when declaring files in the source +map. + +For example: + + uglifyjs /home/doe/work/foo/src/js/file1.js \ + /home/doe/work/foo/src/js/file2.js \ + -o foo.min.js \ + --source-map foo.min.js.map \ + --source-map-root http://foo.com/src \ + -p 5 -c -m + +The above will compress and mangle `file1.js` and `file2.js`, will drop the +output in `foo.min.js` and the source map in `foo.min.js.map`. The source +mapping will refer to `http://foo.com/src/js/file1.js` and +`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` +as the source map root, and the original files as `js/file1.js` and +`js/file2.js`). + +### Composed source map + +When you're compressing JS code that was output by a compiler such as +CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd +like to map back to the original code (i.e. CoffeeScript). UglifyJS has an +option to take an input source map. Assuming you have a mapping from +CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → +compressed JS by mapping every token in the compiled JS to its original +location. + +To use this feature you need to pass `--in-source-map +/path/to/input/source.map`. Normally the input source map should also point +to the file containing the generated JS, so if that's correct you can omit +input files from the command line. + +## Mangler options + +To enable the mangler you need to pass `--mangle` (`-m`). The following +(comma-separated) options are supported: + +- `sort` — to assign shorter names to most frequently used variables. This + saves a few hundred bytes on jQuery before gzip, but the output is + _bigger_ after gzip (and seems to happen for other libraries I tried it + on) therefore it's not enabled by default. + +- `toplevel` — mangle names declared in the toplevel scope (disabled by + default). + +- `eval` — mangle names visible in scopes where `eval` or `when` are used + (disabled by default). + +When mangling is enabled but you want to prevent certain names from being +mangled, you can declare those names with `--reserved` (`-r`) — pass a +comma-separated list of names. For example: + + uglifyjs ... -m -r '$,require,exports' + +to prevent the `require`, `exports` and `$` names from being changed. + +## Compressor options + +You need to pass `--compress` (`-c`) to enable the compressor. Optionally +you can pass a comma-separated list of options. Options are in the form +`foo=bar`, or just `foo` (the latter implies a boolean option that you want +to set `true`; it's effectively a shortcut for `foo=true`). + +- `sequences` -- join consecutive simple statements using the comma operator +- `properties` -- rewrite property access using the dot notation, for + example `foo["bar"] → foo.bar` +- `dead_code` -- remove unreachable code +- `drop_debugger` -- remove `debugger;` statements +- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) +- `conditionals` -- apply optimizations for `if`-s and conditional + expressions +- `comparisons` -- apply certain optimizations to binary nodes, for example: + `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, + e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. +- `evaluate` -- attempt to evaluate constant expressions +- `booleans` -- various optimizations for boolean context, for example `!!a + ? b : c → a ? b : c` +- `loops` -- optimizations for `do`, `while` and `for` loops when we can + statically determine the condition +- `unused` -- drop unreferenced functions and variables +- `hoist_funs` -- hoist function declarations +- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` + by default because it seems to increase the size of the output in general) +- `if_return` -- optimizations for if/return and if/continue +- `join_vars` -- join consecutive `var` statements +- `cascade` -- small optimization for sequences, transform `x, x` into `x` + and `x = something(), x` into `x = something()` +- `warnings` -- display warnings when dropping unreachable code or unused + declarations etc. + +### The `unsafe` option + +It enables some transformations that *might* break code logic in certain +contrived cases, but should be fine for most code. You might want to try it +on your own code, it should reduce the minified size. Here's what happens +when this flag is on: + +- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` +- `new Object()` → `{}` +- `String(exp)` or `exp.toString()` → `"" + exp` +- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` +- `typeof foo == "undefined"` → `foo === void 0` +- `void 0` → `"undefined"` (if there is a variable named "undefined" in + scope; we do it because the variable name will be mangled, typically + reduced to a single character). + +### Conditional compilation + +You can use the `--define` (`-d`) switch in order to declare global +variables that UglifyJS will assume to be constants (unless defined in +scope). For example if you pass `--define DEBUG=false` then, coupled with +dead code removal UglifyJS will discard the following from the output: +```javascript +if (DEBUG) { + console.log("debug stuff"); +} +``` + +UglifyJS will warn about the condition being always false and about dropping +unreachable code; for now there is no option to turn off only this specific +warning, you can pass `warnings=false` to turn off *all* warnings. + +Another way of doing that is to declare your globals as constants in a +separate file and include it into the build. For example you can have a +`build/defines.js` file with the following: +```javascript +const DEBUG = false; +const PRODUCTION = true; +// etc. +``` + +and build your code like this: + + uglifyjs build/defines.js js/foo.js js/bar.js... -c + +UglifyJS will notice the constants and, since they cannot be altered, it +will evaluate references to them to the value itself and drop unreachable +code as usual. The possible downside of this approach is that the build +will contain the `const` declarations. + + +## Beautifier options + +The code generator tries to output shortest code possible by default. In +case you want beautified output, pass `--beautify` (`-b`). Optionally you +can pass additional arguments that control the code output: + +- `beautify` (default `true`) -- whether to actually beautify the output. + Passing `-b` will set this to true, but you might need to pass `-b` even + when you want to generate minified code, in order to specify additional + arguments, so you can use `-b beautify=false` to override it. +- `indent-level` (default 4) +- `indent-start` (default 0) -- prefix all lines by that many spaces +- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal + objects +- `space-colon` (default `true`) -- insert a space after the colon signs +- `ascii-only` (default `false`) -- escape Unicode characters in strings and + regexps +- `inline-script` (default `false`) -- escape the slash in occurrences of + ` 0) { + sys.error("WARN: Ignoring input files since --self was passed"); + } + files = UglifyJS.FILES; + if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; + ARGS.export_all = true; +} + +var ORIG_MAP = ARGS.in_source_map; + +if (ORIG_MAP) { + ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); + if (files.length == 0) { + sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); + files = [ ORIG_MAP.file ]; + } + if (ARGS.source_map_root == null) { + ARGS.source_map_root = ORIG_MAP.sourceRoot; + } +} + +if (files.length == 0) { + files = [ "-" ]; +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; +var TOPLEVEL = null; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: OUTPUT_FILE, + root: ARGS.source_map_root, + orig: ORIG_MAP, +}) : null; + +OUTPUT_OPTIONS.source_map = SOURCE_MAP; + +try { + var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); + var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); +} catch(ex) { + if (ex instanceof UglifyJS.DefaultsError) { + sys.error(ex.msg); + sys.error("Supported options:"); + sys.error(sys.inspect(ex.defs)); + process.exit(1); + } +} + +async.eachLimit(files, 1, function (file, cb) { + read_whole_file(file, function (err, code) { + if (err) { + sys.error("ERROR: can't read file: " + filename); + process.exit(1); + } + if (ARGS.p != null) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + time_it("parse", function(){ + if (ARGS.spidermonkey) { + var program = JSON.parse(code); + if (!TOPLEVEL) TOPLEVEL = program; + else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); + } + else if (ARGS.acorn) { + TOPLEVEL = acorn.parse(code, { + locations : true, + trackComments : true, + sourceFile : file, + program : TOPLEVEL + }); + } + else { + TOPLEVEL = UglifyJS.parse(code, { + filename : file, + toplevel : TOPLEVEL, + expression : ARGS.expr, + }); + }; + }); + cb(); + }); +}, function () { + if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ + TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); + }); + + if (ARGS.wrap) { + TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); + } + + if (ARGS.enclose) { + var arg_parameter_list = ARGS.enclose; + + if (!(arg_parameter_list instanceof Array)) { + arg_parameter_list = [arg_parameter_list]; + } + + TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list); + } + + var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (ARGS.lint) { + TOPLEVEL.scope_warnings(); + } + }); + } + + if (COMPRESS) { + time_it("squeeze", function(){ + TOPLEVEL = TOPLEVEL.transform(compressor); + }); + } + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (MANGLE) { + TOPLEVEL.compute_char_frequency(MANGLE); + } + }); + } + + if (MANGLE) time_it("mangle", function(){ + TOPLEVEL.mangle_names(MANGLE); + }); + time_it("generate", function(){ + TOPLEVEL.print(output); + }); + + output = output.get(); + + if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); + output += "\n//# sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map); + } + + if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); + } else { + sys.print(output); + sys.error("\n"); + } + + if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } + } +}); + +/* -----[ functions ]----- */ + +function normalize(o) { + for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { + o[i.replace(/-/g, "_")] = o[i]; + delete o[i]; + } +} + +function getOptions(x, constants) { + x = ARGS[x]; + if (!x) return null; + var ret = {}; + if (x !== true) { + var ast; + try { + ast = UglifyJS.parse(x); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Error parsing arguments in: " + x); + process.exit(1); + } + } + ast.walk(new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.AST_Toplevel) return; // descend + if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend + if (node instanceof UglifyJS.AST_Seq) return; // descend + if (node instanceof UglifyJS.AST_Assign) { + var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); + var value = node.right; + if (constants) + value = new Function("return (" + value.print_to_string() + ")")(); + ret[name] = value; + return true; // no descend + } + sys.error(node.TYPE) + sys.error("Error parsing arguments in: " + x); + process.exit(1); + })); + } + return ret; +} + +function read_whole_file(filename, cb) { + if (filename == "-") { + var chunks = []; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', function (chunk) { + chunks.push(chunk); + }).on('end', function () { + cb(null, chunks.join("")); + }); + process.openStdin(); + } else { + fs.readFile(filename, "utf-8", cb); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/ast.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/ast.js new file mode 100644 index 0000000..a1301da --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/ast.js @@ -0,0 +1,985 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; + else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) + props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0;) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base; + if (proto && proto.initialize || (methods && methods.initialize)) + code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; +}; + +var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +}, null); + +var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); // not sure the indirection will be any help + } +}, null); + +AST_Node.warn_function = null; +AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) + AST_Node.warn_function(string_template(txt, props)); +}; + +/* -----[ statements ]----- */ + +var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements", +}); + +var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement", +}, AST_Statement); + +var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: "Represents a directive, like \"use strict\";", + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + }, +}, AST_Statement); + +var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } + else node.body.forEach(function(stat){ + stat._walk(visitor); + }); +}; + +var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + +var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement", +}, AST_Block); + +var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } +}, AST_Statement); + +var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.label._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement", +}, AST_DWLoop); + +var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement", +}, AST_DWLoop); + +var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ scope and functions ]----- */ + +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)", + }, +}, AST_Block); + +var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", + }, + wrap_enclose: function(arg_parameter_pairs) { + var self = this; + var args = []; + var parameters = []; + + arg_parameter_pairs.forEach(function(pair) { + var split = pair.split(":"); + + args.push(split[0]); + parameters.push(split[1]); + }); + + var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(self.body); + } + })); + return wrapped_tl; + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n){ return n.name == node.name }, to_export)) + to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym){ + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ name: "exports" }), + property: new AST_String({ value: sym.name }), + }), + operator: "=", + right: new AST_SymbolRef(sym), + }), + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } +}, AST_Scope); + +var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg){ + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } +}, AST_Scope); + +var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function" +}, AST_Lambda); + +var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" +}, AST_Lambda); + +var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" +}, AST_Lambda); + +/* -----[ JUMPS ]----- */ + +var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" +}, AST_Statement); + +var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function(){ + this.value._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" +}, AST_Exit); + +var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" +}, AST_Exit); + +var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none", + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function(){ + this.label._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" +}, AST_LoopControl); + +var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" +}, AST_LoopControl); + +/* -----[ IF ]----- */ + +var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ SWITCH ]----- */ + +var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches", +}, AST_Block); + +var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", +}, AST_SwitchBranch); + +var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_SwitchBranch); + +/* -----[ EXCEPTIONS ]----- */ + +var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } +}, AST_Block); + +// XXX: this is wrong according to ECMA-262 (12.4). the catch block +// should introduce another scope, as the argname should be visible +// only inside the catch block. However, doing it this way because of +// IE which simply introduces the name in the surrounding scope. If +// we ever want to fix this then AST_Catch should inherit from +// AST_Scope. +var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); + +/* -----[ VAR/CONST ]----- */ + +var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.definitions.forEach(function(def){ + def._walk(visitor); + }); + }); + } +}, AST_Statement); + +var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" +}, AST_Definitions); + +var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" +}, AST_Definitions); + +var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } +}); + +/* -----[ OTHER ]----- */ + +var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.args.forEach(function(arg){ + arg._walk(visitor); + }); + }); + } +}); + +var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" +}, AST_Call); + +var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0;) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } +}); + +var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } +}); + +var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Sub = DEFNODE("Sub", null, { + $documentation: "Index-style property access, i.e. `a[\"foo\"]`", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}); + +var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" +}, AST_Unary); + +var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" +}, AST_Unary); + +var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.left._walk(visitor); + this.right._walk(visitor); + }); + } +}); + +var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } +}); + +var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`", +}, AST_Binary); + +/* -----[ LITERALS ]----- */ + +var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.elements.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + +var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.properties.forEach(function(prop){ + prop._walk(visitor); + }); + }); + } +}); + +var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.value._walk(visitor); + }); + } +}); + +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property", +}, AST_ObjectProperty); + +var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property", +}, AST_ObjectProperty); + +var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property", +}, AST_ObjectProperty); + +var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols", +}); + +var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" +}, AST_Symbol); + +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } +}, AST_Symbol); + +var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable", +}, AST_SymbolDeclaration); + +var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" +}, AST_SymbolDeclaration); + +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument", +}, AST_SymbolVar); + +var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function", +}, AST_SymbolDeclaration); + +var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression", +}, AST_SymbolDeclaration); + +var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch", +}, AST_SymbolDeclaration); + +var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LabelRef*] a list of nodes referring to this label" + } +}, AST_Symbol); + +var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)", +}, AST_Symbol); + +var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol", +}, AST_Symbol); + +var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol", +}, AST_Symbol); + +var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } +}); + +var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } +}, AST_Constant); + +var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } +}, AST_Constant); + +var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } +}, AST_Constant); + +var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms", +}, AST_Constant); + +var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null +}, AST_Atom); + +var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0/0 +}, AST_Atom); + +var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: (function(){}()) +}, AST_Atom); + +var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: (function(){}()) +}, AST_Atom); + +var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1/0 +}, AST_Atom); + +var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans", +}, AST_Atom); + +var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false +}, AST_Boolean); + +var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true +}, AST_Boolean); + +/* -----[ TreeWalker ]----- */ + +function TreeWalker(callback) { + this.visit = callback; + this.stack = []; +}; +TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function(){ + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if ((p instanceof AST_If && p.condition === self) || + (p instanceof AST_Conditional && p.condition === self) || + (p instanceof AST_DWLoop && p.condition === self) || + (p instanceof AST_For && p.condition === self) || + (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } + } else { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_Switch + || x instanceof AST_For + || x instanceof AST_ForIn + || x instanceof AST_DWLoop) return x; + } + } + } +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/compress.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/compress.js new file mode 100644 index 0000000..57554fa --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/compress.js @@ -0,0 +1,2028 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) + return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences : !false_by_default, + properties : !false_by_default, + dead_code : !false_by_default, + drop_debugger : !false_by_default, + unsafe : false, + unsafe_comps : false, + conditionals : !false_by_default, + comparisons : !false_by_default, + evaluate : !false_by_default, + booleans : !false_by_default, + loops : !false_by_default, + unused : !false_by_default, + hoist_funs : !false_by_default, + hoist_vars : false, + if_return : !false_by_default, + join_vars : !false_by_default, + cascade : !false_by_default, + side_effects : !false_by_default, + screw_ie8 : false, + + warnings : true, + global_defs : {} + }, true); +}; + +Compressor.prototype = new TreeTransformer; +merge(Compressor.prototype, { + option: function(key) { return this.options[key] }, + warn: function() { + if (this.options.warnings) + AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + // dead code removal might leave further unused declarations. + // this'll usually save very few bytes, but the performance + // hit seems negligible so I'll just drop it here. + + // no point to repeat warnings. + var save_warnings = this.options.warnings; + this.options.warnings = false; + node.drop_unused(this); + this.options.warnings = save_warnings; + } + node._squeezed = true; + return node; + } +}); + +(function(){ + + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor){ + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + }; + + OPT(AST_Node, function(self, compressor){ + return self; + }); + + AST_Node.DEFMETHOD("equivalent_to", function(node){ + // XXX: this is a rather expensive way to test two node's equivalence: + return this.print_to_string() == node.print_to_string(); + }); + + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + }; + + function make_node_from_constant(compressor, val, orig) { + // XXX: WIP. + // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof AST_SymbolRef) { + // var scope = compressor.find_parent(AST_Scope); + // var def = scope.find_variable(node); + // node.thedef = def; + // return node; + // } + // })).transform(compressor); + + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + case "boolean": + return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + }; + + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + }; + + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + }; + + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + return statements; + + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + }; + + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0;) { + var stat = statements[i]; + switch (true) { + case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + CHANGED = true; + // note, ret.length is probably always zero + // because we drop unreachable code before this + // step. nevertheless, it's good to check. + continue loop; + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + //--- + // pretty silly case, but: + // if (foo()) return; return; ==> foo(); return; + if (((in_lambda && ret.length == 0) + || (ret[0] instanceof AST_Return && !ret[0].value)) + && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + //--- + // if (foo()) return x; return y; ==> return foo() ? x : y; + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + //--- + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + ret.unshift(stat); + break; + default: + ret.unshift(stat); + break; + } + } + return ret; + }; + + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat){ + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + }; + + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + }; + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + }; + + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + }; + var ret = [], prev = null; + statements.forEach(function(stat){ + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } + else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch(ex) { + if (ex !== opera) throw ex; + } + } + else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } + else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } + else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } + else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } + else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + }; + + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } + else if (stat instanceof AST_For + && prev instanceof AST_Definitions + && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } + else { + prev = stat; + a.push(stat); + } + return a; + }, []); + }; + + }; + + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node){ + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + }; + + /* -----[ boolean/negation helpers ]----- */ + + // methods to determine whether an expression has a boolean result type + (function (def){ + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function(){ return false }); + def(AST_UnaryPrefix, function(){ + return member(this.operator, unary_bool); + }); + def(AST_Binary, function(){ + return member(this.operator, binary_bool) || + ( (this.operator == "&&" || this.operator == "||") && + this.left.is_boolean() && this.right.is_boolean() ); + }); + def(AST_Conditional, function(){ + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function(){ + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function(){ + return this.cdr.is_boolean(); + }); + def(AST_True, function(){ return true }); + def(AST_False, function(){ return true }); + })(function(node, func){ + node.DEFMETHOD("is_boolean", func); + }); + + // methods to determine if an expression has a string result type + (function (def){ + def(AST_Node, function(){ return false }); + def(AST_String, function(){ return true }); + def(AST_UnaryPrefix, function(){ + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor){ + return this.operator == "+" && + (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor){ + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor){ + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor){ + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor){ + return compressor.option("unsafe") + && this.expression instanceof AST_SymbolRef + && this.expression.name == "String" + && this.expression.undeclared(); + }); + })(function(node, func){ + node.DEFMETHOD("is_string", func); + }); + + function best_of(ast1, ast2) { + return ast1.print_to_string().length > + ast2.print_to_string().length + ? ast2 : ast1; + }; + + // methods to evaluate a constant expression + (function (def){ + // The evaluate method returns an array with one or two + // elements. If the node has been successfully reduced to a + // constant, then the second element tells us the value; + // otherwise the second element is missing. The first element + // of the array is always an AST_Node descendant; when + // evaluation was successful it's a node that represents the + // constant; otherwise it's the original node. + AST_Node.DEFMETHOD("evaluate", function(compressor){ + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(), ast = make_node_from_constant(compressor, val, this); + return [ best_of(ast, this), val ]; + } catch(ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function(){ + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function(){ + // XXX: AST_Function inherits from AST_Scope, which itself + // inherits from AST_Statement; however, an AST_Function + // isn't really a statement. This could byte in other + // places too. :-( Wish JS had multiple inheritance. + return [ this ]; + }); + function ev(node) { + return node._eval(); + }; + def(AST_Node, function(){ + throw def; // not constant + }); + def(AST_Constant, function(){ + return this.getValue(); + }); + def(AST_UnaryPrefix, function(){ + var e = this.expression; + switch (this.operator) { + case "!": return !ev(e); + case "typeof": + // Function would be evaluated to an array and so typeof would + // incorrectly return 'object'. Hence making is a special case. + if (e instanceof AST_Function) return typeof function(){}; + + e = ev(e); + + // typeof returns "object" or "function" on different platforms + // so cannot evaluate reliably + if (e instanceof RegExp) throw def; + + return typeof e; + case "void": return void ev(e); + case "~": return ~ev(e); + case "-": + e = ev(e); + if (e === 0) throw def; + return -e; + case "+": return +ev(e); + } + throw def; + }); + def(AST_Binary, function(){ + var left = this.left, right = this.right; + switch (this.operator) { + case "&&" : return ev(left) && ev(right); + case "||" : return ev(left) || ev(right); + case "|" : return ev(left) | ev(right); + case "&" : return ev(left) & ev(right); + case "^" : return ev(left) ^ ev(right); + case "+" : return ev(left) + ev(right); + case "*" : return ev(left) * ev(right); + case "/" : return ev(left) / ev(right); + case "%" : return ev(left) % ev(right); + case "-" : return ev(left) - ev(right); + case "<<" : return ev(left) << ev(right); + case ">>" : return ev(left) >> ev(right); + case ">>>" : return ev(left) >>> ev(right); + case "==" : return ev(left) == ev(right); + case "===" : return ev(left) === ev(right); + case "!=" : return ev(left) != ev(right); + case "!==" : return ev(left) !== ev(right); + case "<" : return ev(left) < ev(right); + case "<=" : return ev(left) <= ev(right); + case ">" : return ev(left) > ev(right); + case ">=" : return ev(left) >= ev(right); + case "in" : return ev(left) in ev(right); + case "instanceof" : return ev(left) instanceof ev(right); + } + throw def; + }); + def(AST_Conditional, function(){ + return ev(this.condition) + ? ev(this.consequent) + : ev(this.alternative); + }); + def(AST_SymbolRef, function(){ + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init); + throw def; + }); + })(function(node, func){ + node.DEFMETHOD("_eval", func); + }); + + // method to negate an expression + (function(def){ + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + }; + def(AST_Node, function(){ + return basic_negation(this); + }); + def(AST_Statement, function(){ + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function(){ + return basic_negation(this); + }); + def(AST_UnaryPrefix, function(){ + if (this.operator == "!") + return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor){ + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor){ + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor){ + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=" : self.operator = ">" ; return self; + case "<" : self.operator = ">=" ; return self; + case ">=" : self.operator = "<" ; return self; + case ">" : self.operator = "<=" ; return self; + } + } + switch (op) { + case "==" : self.operator = "!="; return self; + case "!=" : self.operator = "=="; return self; + case "===": self.operator = "!=="; return self; + case "!==": self.operator = "==="; return self; + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func){ + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor); + }); + }); + + // determine if expression has side effects + (function(def){ + def(AST_Node, function(){ return true }); + + def(AST_EmptyStatement, function(){ return false }); + def(AST_Constant, function(){ return false }); + def(AST_This, function(){ return false }); + + def(AST_Block, function(){ + for (var i = this.body.length; --i >= 0;) { + if (this.body[i].has_side_effects()) + return true; + } + return false; + }); + + def(AST_SimpleStatement, function(){ + return this.body.has_side_effects(); + }); + def(AST_Defun, function(){ return true }); + def(AST_Function, function(){ return false }); + def(AST_Binary, function(){ + return this.left.has_side_effects() + || this.right.has_side_effects(); + }); + def(AST_Assign, function(){ return true }); + def(AST_Conditional, function(){ + return this.condition.has_side_effects() + || this.consequent.has_side_effects() + || this.alternative.has_side_effects(); + }); + def(AST_Unary, function(){ + return this.operator == "delete" + || this.operator == "++" + || this.operator == "--" + || this.expression.has_side_effects(); + }); + def(AST_SymbolRef, function(){ return false }); + def(AST_Object, function(){ + for (var i = this.properties.length; --i >= 0;) + if (this.properties[i].has_side_effects()) + return true; + return false; + }); + def(AST_ObjectProperty, function(){ + return this.value.has_side_effects(); + }); + def(AST_Array, function(){ + for (var i = this.elements.length; --i >= 0;) + if (this.elements[i].has_side_effects()) + return true; + return false; + }); + // def(AST_Dot, function(){ + // return this.expression.has_side_effects(); + // }); + // def(AST_Sub, function(){ + // return this.expression.has_side_effects() + // || this.property.has_side_effects(); + // }); + def(AST_PropAccess, function(){ + return true; + }); + def(AST_Seq, function(){ + return this.car.has_side_effects() + || this.cdr.has_side_effects(); + }); + })(function(node, func){ + node.DEFMETHOD("has_side_effects", func); + }); + + // tell me if a statement aborts + function aborts(thing) { + return thing && thing.aborts(); + }; + (function(def){ + def(AST_Statement, function(){ return null }); + def(AST_Jump, function(){ return this }); + function block_aborts(){ + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + }; + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function(){ + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + + /* -----[ optimizers ]----- */ + + OPT(AST_Directive, function(self, compressor){ + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + + OPT(AST_Debugger, function(self, compressor){ + if (compressor.option("drop_debugger")) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + + OPT(AST_Block, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_BlockStatement, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: return self.body[0]; + case 0: return make_node(AST_EmptyStatement, self); + } + return self; + }); + + AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + var self = this; + if (compressor.option("unused") + && !(self instanceof AST_Toplevel) + && !self.uses_eval + ) { + var in_use = []; + var initializations = new Dictionary(); + // pass 1: find out which symbols are directly used in + // this scope (not in nested scopes). + var scope = this; + var tw = new TreeWalker(function(node, descend){ + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects()) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + // pass 2: for every used symbol we need to walk its + // initialization code to figure out if it uses other + // symbols (that may not be in_use). + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl){ + // undeclared globals will be instanceof AST_SymbolRef + var init = initializations.get(decl.name); + if (init) init.forEach(function(init){ + var tw = new TreeWalker(function(node){ + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + // pass 3: we should drop declarations not in_use + var tt = new TreeTransformer( + function before(node, descend, in_list) { + if (node instanceof AST_Lambda) { + for (var a = node.argnames, i = a.length; --i >= 0;) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name : sym.name, + file : sym.start.file, + line : sym.start.line, + col : sym.start.col + }); + } + else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name : node.name.name, + file : node.name.start.file, + line : node.name.start.line, + col : node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def){ + if (member(def.name.definition(), in_use)) return true; + var w = { + name : def.name.name, + file : def.name.start.file, + line : def.name.start.line, + col : def.name.start.col + }; + if (def.value && def.value.has_side_effects()) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + // place uninitialized names at the start + def = mergeSort(def, function(a, b){ + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + // for unused names whose initialization has + // side effects, we can cascade the init. code + // into the next one, or next statement. + var side_effects = []; + for (var i = 0; i < def.length;) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For && node.init instanceof AST_BlockStatement) { + descend(node, this); + // certain combination of unused name + side effect leads to: + // https://github.com/mishoo/UglifyJS2/issues/44 + // that's an invalid AST. + // We fix it at this stage by moving the `var` outside the `for`. + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + if (node instanceof AST_Scope && node !== self) + return node; + } + ); + self.transform(tt); + } + }); + + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + // let's count var_decl first, we seem to waste a lot of + // space if we hoist `var` when there's only one. + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_Scope && node !== self) + return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer( + function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def){ + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) + return node; // to avoid descending in nested scopes + } + } + ); + self = self.transform(tt); + if (vars_found > 0) { + // collect only vars which don't show up in self's arguments list + var defs = []; + vars.each(function(def, name){ + if (self instanceof AST_Lambda + && find_if(function(x){ return x.name == def.name.name }, + self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + // try to merge in assignments + for (var i = 0; i < self.body.length;) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign + && expr.operator == "=" + && (sym = expr.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq + && (assign = expr.car) instanceof AST_Assign + && assign.operator == "=" + && (sym = assign.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + }; + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + + OPT(AST_SimpleStatement, function(self, compressor){ + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects()) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + + OPT(AST_DWLoop, function(self, compressor){ + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + return self; + }); + + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + + OPT(AST_For, function(self, compressor){ + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } + else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + + OPT(AST_If, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + // if condition can be statically determined, warn and drop + // one of the blocks. note, statically determined implies + // “has no side effects”; also it doesn't work for cases like + // `x && true`, though it probably should. + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; // because we already do the switch here. + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.body, + alternative : self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : negated, + right : self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "&&", + left : self.condition, + right : self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement + && self.alternative + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : self.condition, + right : self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit + && self.alternative instanceof AST_Exit + && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + + OPT(AST_Switch, function(self, compressor){ + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + for(;;) { + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; // last statement + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + last_branch.body.pop(); + if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + self.body.pop(); + continue; + } + } + break; + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + // constant expression + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list){ + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + // no need to descend these node types + return node; + } + else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch){ + return a.concat(branch.body); + }, []) + }).transform(compressor); + } + else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } + else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } + else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } + else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + // got a case with non-constant expression, baling out + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); // so that's able to see parent nodes + self = self.transform(tt); + } catch(ex) { + if (ex !== self) throw ex; + } + return self; + }); + + OPT(AST_Case, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_Try, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + AST_Definitions.DEFMETHOD("remove_initializers", function(){ + this.definitions.forEach(function(def){ def.value = null }); + }); + + AST_Definitions.DEFMETHOD("to_assignments", function(){ + var assignments = this.definitions.reduce(function(a, def){ + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator : "=", + left : name, + right : def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + + OPT(AST_Definitions, function(self, compressor){ + if (self.definitions.length == 0) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_Function, function(self, compressor){ + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + + OPT(AST_Call, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }); + } + break; + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { value: "" }) + }); + case "Function": + if (all(self.args, function(x){ return x instanceof AST_String })) { + // quite a corner-case, but we can handle it: + // https://github.com/mishoo/UglifyJS2/issues/203 + // if the code argument is a constant, then we can minify it. + try { + var code = "(function(" + self.args.slice(0, -1).map(function(arg){ + return arg.value; + }).join(",") + "){" + self.args[self.args.length - 1].value + "})()"; + var ast = parse(code); + ast.figure_out_scope(); + var comp = new Compressor(compressor.options); + ast = ast.transform(comp); + ast.figure_out_scope(); + ast.mangle_names(); + var fun = ast.body[0].body.expression; + var args = fun.argnames.map(function(arg, i){ + return make_node(AST_String, self.args[i], { + value: arg.print_to_string() + }); + }); + var code = OutputStream(); + AST_BlockStatement.prototype._codegen.call(fun, fun, code); + code = code.toString().replace(/^\{|\}$/g, ""); + args.push(make_node(AST_String, self.args[self.args.length - 1], { + value: code + })); + self.args = args; + return self; + } catch(ex) { + if (ex instanceof JS_Parse_Error) { + compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); + compressor.warn(ex.toString()); + } else { + console.log(ex); + } + } + } + break; + } + } + else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { value: "" }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function + && self.args.length == 0 + && !AST_Block.prototype.has_side_effects.call(self.expression)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self; + }); + + OPT(AST_New, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + + OPT(AST_Seq, function(self, compressor){ + if (!compressor.option("side_effects")) + return self; + if (!self.car.has_side_effects()) { + // we shouldn't compress (1,eval)(something) to + // eval(something) because that changes the meaning of + // eval (becomes lexical instead of global). + var p; + if (!(self.cdr instanceof AST_SymbolRef + && self.cdr.name == "eval" + && self.cdr.undeclared() + && (p = compressor.parent()) instanceof AST_Call + && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign + && !self.car.left.has_side_effects() + && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects() + && !self.cdr.has_side_effects() + && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + + AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + OPT(AST_UnaryPostfix, function(self, compressor){ + return self.lift_sequences(compressor); + }); + + OPT(AST_UnaryPrefix, function(self, compressor){ + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + // !!foo ==> foo, if we're in boolean context + return e.expression; + } + break; + case "typeof": + // typeof always returns a non-empty string, thus it's + // always true in booleans + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + + AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq + && !(this.operator == "||" || this.operator == "&&") + && !this.left.has_side_effects()) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + var commutativeOperators = makePredicate("== === != !== * & | ^"); + + OPT(AST_Binary, function(self, compressor){ + function reverse(op, force) { + if (force || !(self.left.has_side_effects() || self.right.has_side_effects())) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant + && !(self.left instanceof AST_Constant)) { + // if right is a constant, whatever side effects the + // left side might have could not influence the + // result. hence, force switch. + reverse(null, true); + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || + (self.left.is_boolean() && self.right.is_boolean())) { + self.operator = self.operator.substr(0, 2); + } + // XXX: intentionally falling down to the next case + case "==": + case "!=": + if (self.left instanceof AST_String + && self.left.value == "undefined" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "typeof" + && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) + || !self.right.expression.undeclared()) { + self.right = self.right.expression; + self.left = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + var exp = self.evaluate(compressor); + if (exp.length > 1) { + if (best_of(exp[0], self) !== self) + return exp[0]; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) + || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } + } + if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } + return self; + }); + + OPT(AST_SymbolRef, function(self, compressor){ + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self); + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + + OPT(AST_Undefined, function(self, compressor){ + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name : "undefined", + scope : scope, + thedef : undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + + var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + OPT(AST_Assign, function(self, compressor){ + self = self.lift_sequences(compressor); + if (self.operator == "=" + && self.left instanceof AST_SymbolRef + && self.right instanceof AST_Binary + && self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + + OPT(AST_Conditional, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign + && alternative instanceof AST_Assign + && consequent.operator == alternative.operator + && consequent.left.equivalent_to(alternative.left) + ) { + /* + * Stuff like this: + * if (foo) exp = something; else exp = something_else; + * ==> + * exp = foo ? something : something_else; + */ + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + + OPT(AST_Boolean, function(self, compressor){ + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" + || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator : p.operator, + value : self.value, + file : p.start.file, + line : p.start.line, + col : p.start.col, + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + + OPT(AST_Sub, function(self, compressor){ + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if ((compressor.option("screw_ie8") && RESERVED_WORDS(prop)) + || (!(RESERVED_WORDS(prop)) && is_identifier_string(prop))) { + return make_node(AST_Dot, self, { + expression : self.expression, + property : prop + }); + } + } + return self; + }); + + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + }; + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + +})(); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/mozilla-ast.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/mozilla-ast.js new file mode 100644 index 0000000..d795094 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/mozilla-ast.js @@ -0,0 +1,267 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +(function(){ + + var MOZ_TO_ME = { + TryStatement : function(M) { + return new AST_Try({ + start : my_start_token(M), + end : my_end_token(M), + body : from_moz(M.block).body, + bcatch : from_moz(M.handlers[0]), + bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause : function(M) { + return new AST_Catch({ + start : my_start_token(M), + end : my_end_token(M), + argname : from_moz(M.param), + body : from_moz(M.body).body + }); + }, + ObjectExpression : function(M) { + return new AST_Object({ + start : my_start_token(M), + end : my_end_token(M), + properties : M.properties.map(function(prop){ + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start : my_start_token(key), + end : my_end_token(prop.value), + key : name, + value : from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression : function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression : function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start : my_start_token(M), + end : my_end_token(M), + property : M.computed ? from_moz(M.property) : M.property.name, + expression : from_moz(M.object) + }); + }, + SwitchCase : function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start : my_start_token(M), + end : my_end_token(M), + expression : from_moz(M.test), + body : M.consequent.map(from_moz) + }); + }, + Literal : function(M) { + var val = M.value, args = { + start : my_start_token(M), + end : my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + case "number": + args.value = val; + return new AST_Number(args); + case "boolean": + return new (val ? AST_True : AST_False)(args); + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This + : p.type == "LabeledStatement" ? AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) + : p.type == "CatchClause" ? AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef + : AST_SymbolRef)({ + start : my_start_token(M), + end : my_end_token(M), + name : M.name + }); + } + }; + + function From_Moz_Unary(M) { + var prefix = "prefix" in M ? M.prefix + : M.type == "UnaryExpression" ? true : false; + return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start : my_start_token(M), + end : my_end_token(M), + operator : M.operator, + expression : from_moz(M.argument) + }); + }; + + var ME_TO_MOZ = {}; + + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + + /* -----[ tools ]----- */ + + function my_start_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.start.line, + col : moznode.loc && moznode.loc.start.column, + pos : moznode.start, + endpos : moznode.start + }); + }; + + function my_end_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.end.line, + col : moznode.loc && moznode.loc.end.column, + pos : moznode.end, + endpos : moznode.end + }); + }; + + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + + "start: my_start_token(M),\n" + + "end: my_end_token(M)"; + + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + + // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); + // console.log(moz_to_me); + + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( + mytype, my_start_token, my_end_token, from_moz + ); + return MOZ_TO_ME[moztype] = moz_to_me; + }; + + var FROM_MOZ_STACK = null; + + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + }; + + AST_Node.from_mozilla_ast = function(node){ + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + +})(); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/output.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/output.js new file mode 100644 index 0000000..60a4a26 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/output.js @@ -0,0 +1,1229 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function OutputStream(options) { + + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : true, + ascii_only : false, + inline_script : false, + width : 80, + max_line_len : 32000, + ie_proof : true, + beautify : false, + source_map : null, + bracketize : false, + semicolons : true, + comments : false, + preserve_line : false, + negate_iife : !(options && options.beautify), + }, true); + + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + + function to_ascii(str, identifier) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + if (code.length <= 2 && !identifier) { + while (code.length < 2) code = "0" + code; + return "\\x" + code; + } else { + while (code.length < 4) code = "0" + code; + return "\\u" + code; + } + }); + }; + + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; + }; + + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name, true); + return name; + }; + + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + }; + + /* -----[ beautification/minification ]----- */ + + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + + function last_char() { + return last.charAt(last.length - 1); + }; + + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) + print("\n"); + }; + + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) + might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + + if (might_need_space) { + var prev = last_char(); + if ((is_identifier_char(prev) + && (is_identifier_char(ch) || ch == "\\")) + || (/^[\+\-\/]$/.test(ch) && ch == prev)) + { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + }; + + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? 0.5 : 0)); + } + } : noop; + + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { return cont() }; + + var newline = options.beautify ? function() { + print("\n"); + } : noop; + + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + + function force_semicolon() { + might_need_semicolon = false; + print(";"); + }; + + function next_indent() { + return indentation + options.indent_level; + }; + + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function(){ + ret = cont(); + }); + indent(); + print("}"); + return ret; + }; + + function with_parens(cont) { + print("("); + //XXX: still nice to have that for argument lists + //var ret = with_indent(current_col, cont); + var ret = cont(); + print(")"); + return ret; + }; + + function with_square(cont) { + print("["); + //var ret = with_indent(current_col, cont); + var ret = cont(); + print("]"); + return ret; + }; + + function comma() { + print(","); + space(); + }; + + function colon() { + print(":"); + if (options.space_colon) space(); + }; + + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add( + token.file || "?", + current_line, current_col, + token.line, token.col, + (!name && token.type == "name") ? token.value : name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }) + } + } : noop; + + function get() { + return OUTPUT; + }; + + var stack = []; + return { + get : get, + toString : get, + indent : indent, + indentation : function() { return indentation }, + current_width : function() { return current_col - indentation }, + should_break : function() { return options.width && this.current_width() >= options.width }, + newline : newline, + print : print, + space : space, + comma : comma, + colon : colon, + last : function() { return last }, + semicolon : semicolon, + force_semicolon : force_semicolon, + to_ascii : to_ascii, + print_name : function(name) { print(make_name(name)) }, + print_string : function(str) { print(encode_string(str)) }, + next_indent : next_indent, + with_indent : with_indent, + with_block : with_block, + with_parens : with_parens, + with_square : with_square, + add_mapping : add_mapping, + option : function(opt) { return options[opt] }, + line : function() { return current_line }, + col : function() { return current_col }, + pos : function() { return current_pos }, + push_node : function(node) { stack.push(node) }, + pop_node : function() { return stack.pop() }, + stack : function() { return stack }, + parent : function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + +}; + +/* -----[ code generators ]----- */ + +(function(){ + + /* -----[ utils ]----- */ + + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + }; + + AST_Node.DEFMETHOD("print", function(stream, force_parens){ + var self = this, generator = self._codegen; + stream.push_node(self); + var needs_parens = self.needs_parens(stream); + var fc = self instanceof AST_Function && stream.option("negate_iife"); + if (force_parens || (needs_parens && !fc)) { + stream.with_parens(function(){ + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + }); + } else { + self.add_comments(stream); + if (needs_parens && fc) stream.print("!"); + self.add_source_map(stream); + generator(self, stream); + } + stream.pop_node(); + }); + + AST_Node.DEFMETHOD("print_to_string", function(options){ + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + + /* -----[ comments ]----- */ + + AST_Node.DEFMETHOD("add_comments", function(output){ + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // if this node is `return` or `throw`, we cannot allow comments before + // the returned or thrown value. + if (self instanceof AST_Exit && + self.value && self.value.start.comments_before.length > 0) { + comments = (comments || []).concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + + if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment); + }); + } + comments.forEach(function(c){ + if (c.type == "comment1") { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + + /* -----[ PARENTHESES ]----- */ + + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + }; + + PARENS(AST_Node, function(){ + return false; + }); + + // a function expression needs parens around it when it's provably + // the first token to appear in a statement. + PARENS(AST_Function, function(output){ + return first_in_statement(output); + }); + + // same goes for an object literal, because otherwise it would be + // interpreted as a block of code. + PARENS(AST_Object, function(output){ + return first_in_statement(output); + }); + + PARENS(AST_Unary, function(output){ + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + + PARENS(AST_Seq, function(output){ + var p = output.parent(); + return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST_Unary // !(foo, bar, baz) + || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * ==> 20 (side effect, set a := 10 and b := 20) */ + ; + }); + + PARENS(AST_Binary, function(output){ + var p = output.parent(); + // (foo && bar)() + if (p instanceof AST_Call && p.expression === this) + return true; + // typeof (foo && bar) + if (p instanceof AST_Unary) + return true; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + // this deals with precedence: 3 * (2 + 1) + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp + || (pp == sp + && this === p.right + && !(so == po && + (so == "*" || + so == "&&" || + so == "||")))) { + return true; + } + } + }); + + PARENS(AST_PropAccess, function(output){ + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + // i.e. new (foo.bar().baz) + // + // if there's one call into this subtree, then we need + // parens around it too, otherwise the call will be + // interpreted as passing the arguments to the upper New + // expression. + try { + this.walk(new TreeWalker(function(node){ + if (node instanceof AST_Call) throw p; + })); + } catch(ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + + PARENS(AST_Call, function(output){ + var p = output.parent(); + return p instanceof AST_New && p.expression === this; + }); + + PARENS(AST_New, function(output){ + var p = output.parent(); + if (no_constructor_parens(this, output) + && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + return true; + }); + + PARENS(AST_Number, function(output){ + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + PARENS(AST_NaN, function(output){ + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + // !(a = false) → true + if (p instanceof AST_Unary) + return true; + // 1 + (a = 2) + 3 → 6, side effect setting a = 2 + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + return true; + // (a = func)() —or— new (a = Object)() + if (p instanceof AST_Call && p.expression === this) + return true; + // (a = foo) ? bar : baz + if (p instanceof AST_Conditional && p.condition === this) + return true; + // (a = foo)["prop"] —or— (a = foo).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }; + + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + + /* -----[ PRINTERS ]----- */ + + DEFPRINT(AST_Directive, function(self, output){ + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output){ + output.print("debugger"); + output.semicolon(); + }); + + /* -----[ statements ]----- */ + + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i){ + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + }; + + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + force_statement(this.body, output); + }); + + DEFPRINT(AST_Statement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output){ + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output){ + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function(){ + display_body(body, false, output); + }); + else output.print("{}"); + }; + DEFPRINT(AST_BlockStatement, function(self, output){ + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output){ + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output){ + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output){ + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output){ + output.print("with"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + + /* -----[ functions ]----- */ + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function(){ + self.argnames.forEach(function(arg, i){ + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output){ + self._do_print(output); + }); + + /* -----[ exits ]----- */ + AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output){ + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output){ + self._do_print(output, "throw"); + }); + + /* -----[ loop control ]----- */ + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output){ + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output){ + self._do_print(output, "continue"); + }); + + /* -----[ if ]----- */ + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + if (!self.body) + return output.force_semicolon(); + if (self.body instanceof AST_Do + && output.option("ie_proof")) { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE + // croaks with "syntax error" on code like this: if (foo) + // do ... while(cond); else ... we need block brackets + // around do/while + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } + else if (b instanceof AST_StatementWithBody) { + b = b.body; + } + else break; + } + force_statement(self.body, output); + }; + DEFPRINT(AST_If, function(self, output){ + output.print("if"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + + /* -----[ switch ]----- */ + DEFPRINT(AST_Switch, function(self, output){ + output.print("switch"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function(){ + self.body.forEach(function(stmt, i){ + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); + else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt){ + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output){ + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output){ + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + + /* -----[ exceptions ]----- */ + DEFPRINT(AST_Try, function(self, output){ + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output){ + output.print("catch"); + output.space(); + output.with_parens(function(){ + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output){ + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + + /* -----[ var/const ]----- */ + AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i){ + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) + output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output){ + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output){ + self._do_print(output, "const"); + }); + + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); + else try { + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw output; + })); + node.print(output); + } catch(ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + }; + + DEFPRINT(AST_VarDef, function(self, output){ + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + + /* -----[ other expressions ]----- */ + DEFPRINT(AST_Call, function(self, output){ + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) + return; + output.with_parens(function(){ + self.args.forEach(function(expr, i){ + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output){ + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + + AST_Seq.DEFMETHOD("_do_print", function(output){ + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output){ + self._do_print(output); + // var p = output.parent(); + // if (p instanceof AST_Statement) { + // output.with_indent(output.next_indent(), function(){ + // self._do_print(output); + // }); + // } else { + // self._do_print(output); + // } + }); + DEFPRINT(AST_Dot, function(self, output){ + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + // the name after dot would be mapped about here. + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output){ + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output){ + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) + output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output){ + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output){ + self.left.print(output); + output.space(); + output.print(self.operator); + output.space(); + self.right.print(output); + }); + DEFPRINT(AST_Conditional, function(self, output){ + self.condition.print(output); + output.space(); + output.print("?"); + output.space(); + self.consequent.print(output); + output.space(); + output.colon(); + self.alternative.print(output); + }); + + /* -----[ literals ]----- */ + DEFPRINT(AST_Array, function(self, output){ + output.with_square(function(){ + var a = self.elements, len = a.length; + if (len > 0) output.space(); + a.forEach(function(exp, i){ + if (i) output.comma(); + exp.print(output); + }); + if (len > 0) output.space(); + }); + }); + DEFPRINT(AST_Object, function(self, output){ + if (self.properties.length > 0) output.with_block(function(){ + self.properties.forEach(function(prop, i){ + if (i) { + output.print(","); + output.newline(); + } + output.indent(); + prop.print(output); + }); + output.newline(); + }); + else output.print("{}"); + }); + DEFPRINT(AST_ObjectKeyVal, function(self, output){ + var key = self.key; + if (output.option("quote_keys")) { + output.print_string(key + ""); + } else if ((typeof key == "number" + || !output.option("beautify") + && +key + "" == key) + && parseFloat(key) >= 0) { + output.print(make_num(key)); + } else if (!is_identifier(key)) { + output.print_string(key); + } else { + output.print_name(key); + } + output.colon(); + self.value.print(output); + }); + DEFPRINT(AST_ObjectSetter, function(self, output){ + output.print("set"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_ObjectGetter, function(self, output){ + output.print("get"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_Symbol, function(self, output){ + var def = self.definition(); + output.print_name(def ? def.mangled_name || def.name : self.name); + }); + DEFPRINT(AST_Undefined, function(self, output){ + output.print("void 0"); + }); + DEFPRINT(AST_Hole, noop); + DEFPRINT(AST_Infinity, function(self, output){ + output.print("1/0"); + }); + DEFPRINT(AST_NaN, function(self, output){ + output.print("0/0"); + }); + DEFPRINT(AST_This, function(self, output){ + output.print("this"); + }); + DEFPRINT(AST_Constant, function(self, output){ + output.print(self.getValue()); + }); + DEFPRINT(AST_String, function(self, output){ + output.print_string(self.getValue()); + }); + DEFPRINT(AST_Number, function(self, output){ + output.print(make_num(self.getValue())); + }); + DEFPRINT(AST_RegExp, function(self, output){ + var str = self.getValue().toString(); + if (output.option("ascii_only")) + str = output.to_ascii(str); + output.print(str); + var p = output.parent(); + if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) + output.print(" "); + }); + + function force_statement(stat, output) { + if (output.option("bracketize")) { + if (!stat || stat instanceof AST_EmptyStatement) + output.print("{}"); + else if (stat instanceof AST_BlockStatement) + stat.print(output); + else output.with_block(function(){ + output.indent(); + stat.print(output); + output.newline(); + }); + } else { + if (!stat || stat instanceof AST_EmptyStatement) + output.force_semicolon(); + else + stat.print(output); + } + }; + + // return true if the node at the top of the stack (that means the + // innermost node in the current output) is lexically the first in + // a statement. + function first_in_statement(output) { + var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + while (i > 0) { + if (p instanceof AST_Statement && p.body === node) + return true; + if ((p instanceof AST_Seq && p.car === node ) || + (p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) || + (p instanceof AST_Dot && p.expression === node ) || + (p instanceof AST_Sub && p.expression === node ) || + (p instanceof AST_Conditional && p.condition === node ) || + (p instanceof AST_Binary && p.left === node ) || + (p instanceof AST_UnaryPostfix && p.expression === node )) + { + node = p; + p = a[--i]; + } else { + return false; + } + } + }; + + // self should be AST_New. decide if we want to show parens or not. + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.option("beautify"); + }; + + function best_of(a) { + var best = a[0], len = best.length; + for (var i = 1; i < a.length; ++i) { + if (a[i].length < len) { + best = a[i]; + len = best.length; + } + } + return best; + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + function make_block(stmt, output) { + if (stmt instanceof AST_BlockStatement) { + stmt.print(output); + return; + } + output.with_block(function(){ + output.indent(); + stmt.print(output); + output.newline(); + }); + }; + + /* -----[ source map generators ]----- */ + + function DEFMAP(nodetype, generator) { + nodetype.DEFMETHOD("add_source_map", function(stream){ + generator(this, stream); + }); + }; + + // We could easily add info for ALL nodes, but it seems to me that + // would be quite wasteful, hence this noop in the base class. + DEFMAP(AST_Node, noop); + + function basic_sourcemap_gen(self, output) { + output.add_mapping(self.start); + }; + + // XXX: I'm not exactly sure if we need it for all of these nodes, + // or if we should add even more. + + DEFMAP(AST_Directive, basic_sourcemap_gen); + DEFMAP(AST_Debugger, basic_sourcemap_gen); + DEFMAP(AST_Symbol, basic_sourcemap_gen); + DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it + DEFMAP(AST_Lambda, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_New, basic_sourcemap_gen); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); + DEFMAP(AST_ObjectProperty, function(self, output){ + output.add_mapping(self.start, self.key); + }); + +})(); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/parse.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/parse.js new file mode 100644 index 0000000..e561ab6 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/parse.js @@ -0,0 +1,1410 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; +var KEYWORDS_ATOM = 'false null true'; +var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile' + + " " + KEYWORDS_ATOM + " " + KEYWORDS; +var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; + +KEYWORDS = makePredicate(KEYWORDS); +RESERVED_WORDS = makePredicate(RESERVED_WORDS); +KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); +KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); + +var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = makePredicate([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); + +var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); + +var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(code) { + return (code >= 97 && code <= 122) + || (code >= 65 && code <= 90) + || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); +}; + +function is_digit(code) { + return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(code) { + return is_digit(code) || is_letter(code); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier(name) { + return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); +}; + +function is_identifier_start(code) { + return code == 36 || code == 95 || is_letter(code); +}; + +function is_identifier_char(ch) { + var code = ch.charCodeAt(0); + return is_identifier_start(code) + || is_digit(code) + || code == 8204 // \u200c: zero-width non-joiner + || code == 8205 // \u200d: zero-width joiner (in my ECMA-262 PDF, this is also 200c) + || is_unicode_combining_mark(ch) + || is_unicode_connector_punctuation(ch) + ; +}; + +function is_identifier_string(str){ + var i = str.length; + if (i == 0) return false; + if (is_digit(str.charCodeAt(0))) return false; + while (--i >= 0) { + if (!is_identifier_char(str.charAt(i))) + return false; + } + return true; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + this.stack = new Error().stack; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, filename, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT, filename) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''), + filename : filename, + pos : 0, + tokpos : 0, + line : 1, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) || + (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || + (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before, + file : filename + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return new AST_Token(ret); + }; + + function skip_whitespace() { + while (WHITESPACE_CHARS(peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch, i = 0; + while ((ch = peek()) && pred(ch, i++)) + ret += next(); + return ret; + }; + + function parse_error(err) { + js_error(err, filename, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + var code = ch.charCodeAt(0); + switch (code) { + case 120: case 88: // xX + return has_x ? false : (has_x = true); + case 101: case 69: // eE + return has_x ? true : has_e ? false : (has_e = after_e = true); + case 45: // - + return after_e || (i == 0 && !prefix); + case 43: // + + return after_e; + case (after_e = false, 46): // . + return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; + } + return is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110 : return "\n"; + case 114 : return "\r"; + case 116 : return "\t"; + case 98 : return "\b"; + case 118 : return "\u000b"; // \v + case 102 : return "\f"; + case 48 : return "\0"; + case 120 : return String.fromCharCode(hex_bytes(2)); // \x + case 117 : return String.fromCharCode(hex_bytes(4)); // \u + case 10 : return ""; // newline + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + var read_string = with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); + } + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ + next(); + var i = find("*/", true); + var text = S.text.substring(S.pos, i); + var a = text.split("\n"), n = a.length; + // update stream position + S.pos = i + 2; + S.line += n - 1; + if (n > 1) S.col = a[n - 1].length; + else S.col += a[n - 1].length; + S.col += 2; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + return token("comment2", text, true); + }); + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", new RegExp(regexp, mods)); + }); + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (OPERATORS(bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek().charCodeAt(0)) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return KEYWORDS_ATOM(word) ? token("atom", word) + : !KEYWORDS(word) ? token("name", word) + : OPERATORS(word) ? token("operator", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + return function(x) { + try { + return cont(x); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(); + case 46: return handle_dot(); + case 47: return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + +var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function parse($TEXT, options) { + + options = defaults(options, { + strict : false, + filename : null, + toplevel : null, + expression : false + }); + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + ctx.filename, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !options.strict && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + }; + + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + }; + + var statement = embed_tokens(function() { + var tmp; + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + // XXXv2: decide how to fix directives + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start : S.token, + body : block_(), + end : prev() + }); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return new AST_EmptyStatement(); + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body : in_loop(statement), + condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) + }); + + case "while": + return new AST_While({ + condition : parenthesised(), + body : in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return new AST_Return({ + value: ( is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : (tmp = expression(true), semicolon(), tmp) ) + }); + + case "switch": + return new AST_Switch({ + expression : parenthesised(), + body : in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression : parenthesised(), + body : statement() + }); + + default: + unexpected(); + } + } + }); + + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + return new AST_LabeledStatement({ body: stat, label: label }); + }; + + function simple_statement(tmp) { + return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + }; + + function break_cont(type) { + var label = null; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + if (!find_if(function(l){ return l.name == label.name }, S.labels)) + croak("Undefined label " + label.name); + } + else if (S.in_loop == 0) + croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + return new type({ label: label }); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) + croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init : init, + condition : test, + step : step, + body : in_loop(statement) + }); + }; + + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init : init, + name : lhs, + object : obj, + body : in_loop(statement) + }); + }; + + var function_ = function(in_statement, ctor) { + var is_accessor = ctor === AST_Accessor; + var name = (is("name") ? as_symbol(in_statement + ? AST_SymbolDefun + : is_accessor + ? AST_SymbolAccessor + : AST_SymbolLambda) + : is_accessor && (is("string") || is("num")) ? as_atom_node() + : null); + if (in_statement && !name) + unexpected(); + expect("("); + if (!ctor) ctor = in_statement ? AST_Defun : AST_Function; + return new ctor({ + name: name, + argnames: (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + })(true, []), + body: (function(loop, labels){ + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + })(S.in_loop, S.labels) + }); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition : cond, + body : body, + alternative : belse + }); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start : (tmp = S.token, next(), tmp), + expression : expression(true), + body : cur + }); + a.push(branch); + expect(":"); + } + else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start : (tmp = S.token, next(), expect(":"), tmp), + body : cur + }); + a.push(branch); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + }; + + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start : start, + argname : name, + body : block_(), + end : prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start : start, + body : block_(), + end : prev() + }); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return new AST_Try({ + body : body, + bcatch : bcatch, + bfinally : bfinally + }); + }; + + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start : S.token, + name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value : is("operator", "=") ? (next(), expression(false, no_in)) : null, + end : prev() + })); + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + var var_ = function(no_in) { + return new AST_Var({ + start : prev(), + definitions : vardefs(no_in, false), + end : prev() + }); + }; + + var const_ = function() { + return new AST_Const({ + start : prev(), + definitions : vardefs(false, true), + end : prev() + }); + }; + + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start : start, + expression : newexp, + args : args, + end : prev() + }), true); + }; + + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + return as_symbol(AST_SymbolRef); + case "num": + ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + break; + case "string": + ret = new AST_String({ start: tok, end: tok, value: tok.value }); + break; + case "regexp": + ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + break; + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ start: tok, end: tok }); + break; + case "true": + ret = new AST_True({ start: tok, end: tok }); + break; + case "null": + ret = new AST_Null({ start: tok, end: tok }); + break; + } + break; + } + next(); + return ret; + }; + + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + case "[": + return subscripts(array_(), allow_calls); + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(false); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ start: S.token, end: S.token })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) + // allow trailing comma + break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start : start, + key : name, + value : expression(false), + end : prev() + })); + } + next(); + return new AST_Object({ properties: a }); + }); + + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var name = S.token.value; + var sym = new (name == "this" ? AST_This : type)({ + name : String(S.token.value), + start : S.token, + end : S.token + }); + next(); + return sym; + }; + + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start : start, + expression : expr, + property : as_name(), + end : prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start : start, + expression : expr, + property : prop, + end : prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start : start, + expression : expr, + args : expr_list(")"), + end : prev() + }), true); + } + return expr; + }; + + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return new ctor({ operator: op, expression: expr }); + }; + + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start : left.start, + left : left, + operator : op, + right : right, + end : right.end + }), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start : start, + condition : expr, + consequent : yes, + alternative : expression(false, no_in), + end : peek() + }); + } + return expr; + }; + + function is_assignable(expr) { + if (!options.strict) return true; + if (expr instanceof AST_This) return false; + return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol); + }; + + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start : start, + left : left, + operator : val, + right : maybe_assign(no_in), + end : prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start : start, + car : expr, + cdr : expression(true, no_in), + end : peek() + }); + } + return expr; + }; + + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + }; + + if (options.expression) { + return expression(true); + } + + return (function(){ + var start = S.token; + var body = []; + while (!is("eof")) + body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + } + return toplevel; + })(); + +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/scope.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/scope.js new file mode 100644 index 0000000..d15cec7 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/scope.js @@ -0,0 +1,581 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; +}; + +SymbolDef.prototype = { + unmangleable: function(options) { + return (this.global && !(options && options.toplevel)) + || this.undeclared + || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) { + var s = this.scope; + if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) + s = s.parent_scope; + this.mangled_name = s.next_mangled(options); + } + } +}; + +AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions + var self = this; + var scope = self.parent_scope = null; + var labels = new Dictionary(); + var nesting = 0; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + var save_labels = labels; + ++nesting; + scope = node; + labels = new Dictionary(); + descend(); + labels = save_labels; + scope = save_scope; + --nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) + s.uses_with = true; + return; + } + if (node instanceof AST_LabeledStatement) { + var l = node.label; + if (labels.has(l.name)) + throw new Error(string_template("Label {name} defined twice", l)); + labels.set(l.name, l); + descend(); + labels.del(l.name); + return true; // no descend again + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_Label) { + node.thedef = node; + node.init_scope_vars(); + } + if (node instanceof AST_SymbolLambda) { + scope.def_function(node); + } + else if (node instanceof AST_SymbolDefun) { + // Careful here, the scope where this should be defined is + // the parent scope. The reason is that we enter a new + // scope when we encounter the AST_Defun node (which is + // instanceof AST_Scope) but we get to the symbol a bit + // later. + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolVar + || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } + else if (node instanceof AST_SymbolCatch) { + // XXX: this is wrong according to ECMA-262 (12.4). the + // `catch` argument name should be visible only inside the + // catch block. For a quick fix AST_Catch should inherit + // from AST_Scope. Keeping it this way because of IE, + // which doesn't obey the standard. (it introduces the + // identifier in the enclosing scope) + scope.def_variable(node); + } + if (node instanceof AST_LabelRef) { + var sym = labels.get(node.name); + if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { + name: node.name, + line: node.start.line, + col: node.start.col + })); + node.thedef = sym; + } + }); + self.walk(tw); + + // pass 2: find back references and eval + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_LabelRef) { + node.reference(); + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + g.global = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) + s.uses_eval = true; + } + if (name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); +}); + +AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = null; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables + this.nesting = nesting; // the nesting level of this scope (0 means toplevel) +}); + +AST_Scope.DEFMETHOD("strict", function(){ + return this.has_directive("use strict"); +}); + +AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; +}); + +AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; +}); + +AST_Label.DEFMETHOD("init_scope_vars", function(){ + this.references = []; +}); + +AST_LabelRef.DEFMETHOD("reference", function(){ + this.thedef.references.push(this); +}); + +AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) + || (this.parent_scope && this.parent_scope.find_variable(name)); +}); + +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + +AST_Scope.DEFMETHOD("def_function", function(symbol){ + this.functions.set(symbol.name, this.def_variable(symbol)); +}); + +AST_Scope.DEFMETHOD("def_variable", function(symbol){ + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; +}); + +AST_Scope.DEFMETHOD("next_mangled", function(options){ + var ext = this.enclosed; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; // skip over "do" + // we must ensure that the mangled name does not shadow a name + // from some parent scope that is referenced in this or in + // inner scopes. + for (var i = ext.length; --i >= 0;) { + var sym = ext[i]; + var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); + if (m == name) continue out; + } + return m; + } +}); + +AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; +}); + +AST_Symbol.DEFMETHOD("unmangleable", function(options){ + return this.definition().unmangleable(options); +}); + +// property accessors are not mangleable +AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ + return true; +}); + +// labels are always mangleable +AST_Label.DEFMETHOD("unmangleable", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("unreferenced", function(){ + return this.definition().references.length == 0 + && !(this.scope.uses_eval || this.scope.uses_with); +}); + +AST_Symbol.DEFMETHOD("undeclared", function(){ + return this.definition().undeclared; +}); + +AST_LabelRef.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Label.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("definition", function(){ + return this.thedef; +}); + +AST_Symbol.DEFMETHOD("global", function(){ + return this.definition().global; +}); + +AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return defaults(options, { + except : [], + eval : false, + sort : false, + toplevel : false, + screw_ie8 : false + }); +}); + +AST_Toplevel.DEFMETHOD("mangle_names", function(options){ + options = this._default_mangler_options(options); + // We only need to mangle declaration nodes. Special logic wired + // into the code generator will display the mangled name if it's + // present (and for AST_SymbolRef-s it'll use the mangled name of + // the AST_SymbolDeclaration that it points to). + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_LabeledStatement) { + // lname is incremented when we get to the AST_Label + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b){ + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def){ def.mangle(options) }); +}); + +AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node){ + if (node instanceof AST_Constant) + base54.consider(node.print_to_string()); + else if (node instanceof AST_Return) + base54.consider("return"); + else if (node instanceof AST_Throw) + base54.consider("throw"); + else if (node instanceof AST_Continue) + base54.consider("continue"); + else if (node instanceof AST_Break) + base54.consider("break"); + else if (node instanceof AST_Debugger) + base54.consider("debugger"); + else if (node instanceof AST_Directive) + base54.consider(node.value); + else if (node instanceof AST_While) + base54.consider("while"); + else if (node instanceof AST_Do) + base54.consider("do while"); + else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } + else if (node instanceof AST_Var) + base54.consider("var"); + else if (node instanceof AST_Const) + base54.consider("const"); + else if (node instanceof AST_Lambda) + base54.consider("function"); + else if (node instanceof AST_For) + base54.consider("for"); + else if (node instanceof AST_ForIn) + base54.consider("for in"); + else if (node instanceof AST_Switch) + base54.consider("switch"); + else if (node instanceof AST_Case) + base54.consider("case"); + else if (node instanceof AST_Default) + base54.consider("default"); + else if (node instanceof AST_With) + base54.consider("with"); + else if (node instanceof AST_ObjectSetter) + base54.consider("set" + node.key); + else if (node instanceof AST_ObjectGetter) + base54.consider("get" + node.key); + else if (node instanceof AST_ObjectKeyVal) + base54.consider(node.key); + else if (node instanceof AST_New) + base54.consider("new"); + else if (node instanceof AST_This) + base54.consider("this"); + else if (node instanceof AST_Try) + base54.consider("try"); + else if (node instanceof AST_Catch) + base54.consider("catch"); + else if (node instanceof AST_Finally) + base54.consider("finally"); + else if (node instanceof AST_Symbol && node.unmangleable(options)) + base54.consider(node.name); + else if (node instanceof AST_Unary || node instanceof AST_Binary) + base54.consider(node.operator); + else if (node instanceof AST_Dot) + base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); +}); + +var base54 = (function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); + chars.forEach(function(ch){ frequency[ch] = 0 }); + } + base54.consider = function(str){ + for (var i = str.length; --i >= 0;) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b){ + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function(){ return chars }; + base54.freq = function(){ return frequency }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; + return base54; +})(); + +AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = defaults(options, { + undeclared : false, // this makes a lot of noise + unreferenced : true, + assign_to_global : true, + func_arguments : true, + nested_defuns : true, + eval : true + }); + var tw = new TreeWalker(function(node){ + if (options.undeclared + && node instanceof AST_SymbolRef + && node.undeclared()) + { + // XXX: this also warns about JS standard names, + // i.e. Object, Array, parseInt etc. Should add a list of + // exceptions. + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) + { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + sym = node.left; + else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + sym = node.init; + if (sym + && (sym.undeclared() + || (sym.global() && sym.scope !== sym.definition().scope))) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval + && node instanceof AST_SymbolRef + && node.undeclared() + && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced + && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments + && node instanceof AST_Lambda + && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns + && node instanceof AST_Defun + && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/sourcemap.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/sourcemap.js new file mode 100644 index 0000000..3429908 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/sourcemap.js @@ -0,0 +1,81 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// a small wrapper around fitzgen's source-map library +function SourceMap(options) { + options = defaults(options, { + file : null, + root : null, + orig : null, + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, + source : source, + name : name + }); + }; + return { + add : add, + get : function() { return generator }, + toString : function() { return generator.toString() } + }; +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/transform.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/transform.js new file mode 100644 index 0000000..7a61e5f --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/transform.js @@ -0,0 +1,217 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// Tree transformer helpers. + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/utils.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/utils.js new file mode 100644 index 0000000..73964a0 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/lib/utils.js @@ -0,0 +1,295 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) + return array[i]; + } +}; + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; +}; + +function defaults(args, defs, croak) { + if (args === true) + args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) + throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; + } + return ret; +}; + +function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; +}; + +function noop() {}; + +var MAP = (function(){ + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } + else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + }; + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0;) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } + else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + MAP.last = function(val) { return new Last(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; + function Last(val) { this.v = val }; + return MAP; +})(); + +function push_uniq(array, el) { + if (array.indexOf(el) < 0) + array.push(el); +}; + +function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p){ + return props[p]; + }); +}; + +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + +function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 + ? r[i++] = a[ai++] + : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + }; + function _ms(a) { + if (a.length <= 1) + return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + }; + return _ms(array); +}; + +function set_difference(a, b) { + return a.filter(function(el){ + return b.indexOf(el) < 0; + }); +}; + +function set_intersection(a, b) { + return a.filter(function(el){ + return b.indexOf(el) >= 0; + }); +}; + +// this function is taken from Acorn [1], written by Marijn Haverbeke +// [1] https://github.com/marijnh/acorn +function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + // Otherwise, simply generate a flat `switch` statement. + } else { + compareTo(words); + } + return new Function("str", f); +}; + +function all(array, predicate) { + for (var i = array.length; --i >= 0;) + if (!predicate(array[i])) + return false; + return true; +}; + +function Dictionary() { + this._values = Object.create(null); + this._size = 0; +}; +Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { return this._values["$" + key] }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { return ("$" + key) in this._values }, + each: function(f) { + for (var i in this._values) + f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) + ret.push(f(this._values[i], i.substr(1))); + return ret; + } +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/.travis.yml b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/.travis.yml new file mode 100644 index 0000000..cc4dba2 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/LICENSE b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/bool.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/bool.js new file mode 100644 index 0000000..a998fb7 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/bool.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js new file mode 100644 index 0000000..a35a7e6 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_double.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js new file mode 100644 index 0000000..017bb68 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/boolean_single.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv.v); +console.dir(argv._); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_hash.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_hash.js new file mode 100644 index 0000000..ade7768 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_hash.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; + +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_singles.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_singles.js new file mode 100644 index 0000000..d9b1ff4 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/default_singles.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/divide.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/divide.js new file mode 100644 index 0000000..5e2ee82 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/divide.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count.js new file mode 100644 index 0000000..b5f95bf --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js new file mode 100644 index 0000000..d9ac709 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_options.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .options({ + file : { + demand : true, + alias : 'f', + description : 'Load a file' + }, + base : { + alias : 'b', + description : 'Numeric base to use for output', + default : 10, + }, + }) + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js new file mode 100644 index 0000000..4267511 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/line_count_wrap.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .wrap(80) + .demand('f') + .alias('f', [ 'file', 'filename' ]) + .describe('f', + "Load a file. It's pretty important." + + " Required even. So you'd better specify it." + ) + .alias('b', 'base') + .describe('b', 'Numeric base to display the number of lines in') + .default('b', 10) + .describe('x', 'Super-secret optional parameter which is secret') + .default('x', '') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines.toString(argv.base)); +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/nonopt.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/nonopt.js new file mode 100644 index 0000000..ee633ee --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/nonopt.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/reflect.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/reflect.js new file mode 100644 index 0000000..816b3e1 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/reflect.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.dir(require('optimist').argv); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/short.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/short.js new file mode 100644 index 0000000..1db0ad0 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/short.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/string.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/string.js new file mode 100644 index 0000000..a8e5aeb --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/string.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node +var argv = require('optimist') + .string('x', 'y') + .argv +; +console.dir([ argv.x, argv.y ]); + +/* Turns off numeric coercion: + ./node string.js -x 000123 -y 9876 + [ '000123', '9876' ] +*/ diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/usage-options.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/usage-options.js new file mode 100644 index 0000000..b999977 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/usage-options.js @@ -0,0 +1,19 @@ +var optimist = require('./../index'); + +var argv = optimist.usage('This is my awesome program', { + 'about': { + description: 'Provide some details about the author of this program', + required: true, + short: 'a', + }, + 'info': { + description: 'Provide some information about the node.js agains!!!!!!', + boolean: true, + short: 'i' + } +}).argv; + +optimist.showHelp(); + +console.log('\n\nInspecting options'); +console.dir(argv); \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/xup.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/xup.js new file mode 100644 index 0000000..8f6ecd2 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/example/xup.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} + diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/index.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/index.js new file mode 100644 index 0000000..8ac67eb --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/index.js @@ -0,0 +1,478 @@ +var path = require('path'); +var wordwrap = require('wordwrap'); + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('optimist')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('optimist').argv + to get a parsed version of process.argv. +*/ + +var inst = Argv(process.argv.slice(2)); +Object.keys(inst).forEach(function (key) { + Argv[key] = typeof inst[key] == 'function' + ? inst[key].bind(inst) + : inst[key]; +}); + +var exports = module.exports = Argv; +function Argv (args, cwd) { + var self = {}; + if (!cwd) cwd = process.cwd(); + + self.$0 = process.argv + .slice(0,2) + .map(function (x) { + var b = rebase(cwd, x); + return x.match(/^\//) && b.length < x.length + ? b : x + }) + .join(' ') + ; + + if (process.env._ != undefined && process.argv[1] == process.env._) { + self.$0 = process.env._.replace( + path.dirname(process.execPath) + '/', '' + ); + } + + var flags = { bools : {}, strings : {} }; + + self.boolean = function (bools) { + if (!Array.isArray(bools)) { + bools = [].slice.call(arguments); + } + + bools.forEach(function (name) { + flags.bools[name] = true; + }); + + return self; + }; + + self.string = function (strings) { + if (!Array.isArray(strings)) { + strings = [].slice.call(arguments); + } + + strings.forEach(function (name) { + flags.strings[name] = true; + }); + + return self; + }; + + var aliases = {}; + self.alias = function (x, y) { + if (typeof x === 'object') { + Object.keys(x).forEach(function (key) { + self.alias(key, x[key]); + }); + } + else if (Array.isArray(y)) { + y.forEach(function (yy) { + self.alias(x, yy); + }); + } + else { + var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y); + aliases[x] = zs.filter(function (z) { return z != x }); + aliases[y] = zs.filter(function (z) { return z != y }); + } + + return self; + }; + + var demanded = {}; + self.demand = function (keys) { + if (typeof keys == 'number') { + if (!demanded._) demanded._ = 0; + demanded._ += keys; + } + else if (Array.isArray(keys)) { + keys.forEach(function (key) { + self.demand(key); + }); + } + else { + demanded[keys] = true; + } + + return self; + }; + + var usage; + self.usage = function (msg, opts) { + if (!opts && typeof msg === 'object') { + opts = msg; + msg = null; + } + + usage = msg; + + if (opts) self.options(opts); + + return self; + }; + + function fail (msg) { + self.showHelp(); + if (msg) console.error(msg); + process.exit(1); + } + + var checks = []; + self.check = function (f) { + checks.push(f); + return self; + }; + + var defaults = {}; + self.default = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]); + }); + } + else { + defaults[key] = value; + } + + return self; + }; + + var descriptions = {}; + self.describe = function (key, desc) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.describe(k, key[k]); + }); + } + else { + descriptions[key] = desc; + } + return self; + }; + + self.parse = function (args) { + return Argv(args).argv; + }; + + self.option = self.options = function (key, opt) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.options(k, key[k]); + }); + } + else { + if (opt.alias) self.alias(key, opt.alias); + if (opt.demand) self.demand(key); + if (typeof opt.default !== 'undefined') { + self.default(key, opt.default); + } + + if (opt.boolean || opt.type === 'boolean') { + self.boolean(key); + } + if (opt.string || opt.type === 'string') { + self.string(key); + } + + var desc = opt.describe || opt.description || opt.desc; + if (desc) { + self.describe(key, desc); + } + } + + return self; + }; + + var wrap = null; + self.wrap = function (cols) { + wrap = cols; + return self; + }; + + self.showHelp = function (fn) { + if (!fn) fn = console.error; + fn(self.help()); + }; + + self.help = function () { + var keys = Object.keys( + Object.keys(descriptions) + .concat(Object.keys(demanded)) + .concat(Object.keys(defaults)) + .reduce(function (acc, key) { + if (key !== '_') acc[key] = true; + return acc; + }, {}) + ); + + var help = keys.length ? [ 'Options:' ] : []; + + if (usage) { + help.unshift(usage.replace(/\$0/g, self.$0), ''); + } + + var switches = keys.reduce(function (acc, key) { + acc[key] = [ key ].concat(aliases[key] || []) + .map(function (sw) { + return (sw.length > 1 ? '--' : '-') + sw + }) + .join(', ') + ; + return acc; + }, {}); + + var switchlen = longest(Object.keys(switches).map(function (s) { + return switches[s] || ''; + })); + + var desclen = longest(Object.keys(descriptions).map(function (d) { + return descriptions[d] || ''; + })); + + keys.forEach(function (key) { + var kswitch = switches[key]; + var desc = descriptions[key] || ''; + + if (wrap) { + desc = wordwrap(switchlen + 4, wrap)(desc) + .slice(switchlen + 4) + ; + } + + var spadding = new Array( + Math.max(switchlen - kswitch.length + 3, 0) + ).join(' '); + + var dpadding = new Array( + Math.max(desclen - desc.length + 1, 0) + ).join(' '); + + var type = null; + + if (flags.bools[key]) type = '[boolean]'; + if (flags.strings[key]) type = '[string]'; + + if (!wrap && dpadding.length > 0) { + desc += dpadding; + } + + var prelude = ' ' + kswitch + spadding; + var extra = [ + type, + demanded[key] + ? '[required]' + : null + , + defaults[key] !== undefined + ? '[default: ' + JSON.stringify(defaults[key]) + ']' + : null + , + ].filter(Boolean).join(' '); + + var body = [ desc, extra ].filter(Boolean).join(' '); + + if (wrap) { + var dlines = desc.split('\n'); + var dlen = dlines.slice(-1)[0].length + + (dlines.length === 1 ? prelude.length : 0) + + body = desc + (dlen + extra.length > wrap - 2 + ? '\n' + + new Array(wrap - extra.length + 1).join(' ') + + extra + : new Array(wrap - extra.length - dlen + 1).join(' ') + + extra + ); + } + + help.push(prelude + body); + }); + + help.push(''); + return help.join('\n'); + }; + + Object.defineProperty(self, 'argv', { + get : parseArgs, + enumerable : true, + }); + + function parseArgs () { + var argv = { _ : [], $0 : self.$0 }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] || false); + }); + + function setArg (key, val) { + var num = Number(val); + var value = typeof val !== 'string' || isNaN(num) ? val : num; + if (flags.strings[key]) value = val; + + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + argv[x] = argv[key]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (arg === '--') { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + else if (arg.match(/^--.+=/)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + setArg(m[1], m[2]); + } + else if (arg.match(/^--no-.+/)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false); + } + else if (arg.match(/^--.+/)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !next.match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, next); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true'); + i++; + } + else { + setArg(key, true); + } + } + else if (arg.match(/^-[^-]+/)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2)); + broken = true; + break; + } + else { + setArg(letters[j], true); + } + } + + if (!broken) { + var key = arg.slice(-1)[0]; + + if (args[i+1] && !args[i+1].match(/^-/) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, args[i+1]); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true'); + i++; + } + else { + setArg(key, true); + } + } + } + else { + var n = Number(arg); + argv._.push(flags.strings['_'] || isNaN(n) ? arg : n); + } + } + + Object.keys(defaults).forEach(function (key) { + if (!(key in argv)) { + argv[key] = defaults[key]; + if (key in aliases) { + argv[aliases[key]] = defaults[key]; + } + } + }); + + if (demanded._ && argv._.length < demanded._) { + fail('Not enough non-option arguments: got ' + + argv._.length + ', need at least ' + demanded._ + ); + } + + var missing = []; + Object.keys(demanded).forEach(function (key) { + if (!argv[key]) missing.push(key); + }); + + if (missing.length) { + fail('Missing required arguments: ' + missing.join(', ')); + } + + checks.forEach(function (f) { + try { + if (f(argv) === false) { + fail('Argument check failed: ' + f.toString()); + } + } + catch (err) { + fail(err) + } + }); + + return argv; + } + + function longest (xs) { + return Math.max.apply( + null, + xs.map(function (x) { return x.length }) + ); + } + + return self; +}; + +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +exports.rebase = rebase; +function rebase (base, dir) { + var ds = path.normalize(dir).split('/').slice(1); + var bs = path.normalize(base).split('/').slice(1); + + for (var i = 0; ds[i] && ds[i] == bs[i]; i++); + ds.splice(0, i); bs.splice(0, i); + + var p = path.normalize( + bs.map(function () { return '..' }).concat(ds).join('/') + ).replace(/\/$/,'').replace(/^$/, '.'); + return p.match(/^[.\/]/) ? p : './' + p; +}; + +function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json new file mode 100644 index 0000000..b012389 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/package.json @@ -0,0 +1,45 @@ +{ + "name": "wordwrap", + "description": "Wrap those words. Show them at what columns to start and stop.", + "version": "0.0.2", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-wordwrap.git" + }, + "main": "./index.js", + "keywords": [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "expresso" + }, + "devDependencies": { + "expresso": "=0.7.x" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT/X11", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "readme": "wordwrap\n========\n\nWrap your words.\n\nexample\n=======\n\nmade out of meat\n----------------\n\nmeat.js\n\n var wrap = require('wordwrap')(15);\n console.log(wrap('You and your whole family are made out of meat.'));\n\noutput:\n\n You and your\n whole family\n are made out\n of meat.\n\ncentered\n--------\n\ncenter.js\n\n var wrap = require('wordwrap')(20, 60);\n console.log(wrap(\n 'At long last the struggle and tumult was over.'\n + ' The machines had finally cast off their oppressors'\n + ' and were finally free to roam the cosmos.'\n + '\\n'\n + 'Free of purpose, free of obligation.'\n + ' Just drifting through emptiness.'\n + ' The sun was just another point of light.'\n ));\n\noutput:\n\n At long last the struggle and tumult\n was over. The machines had finally cast\n off their oppressors and were finally\n free to roam the cosmos.\n Free of purpose, free of obligation.\n Just drifting through emptiness. The\n sun was just another point of light.\n\nmethods\n=======\n\nvar wrap = require('wordwrap');\n\nwrap(stop), wrap(start, stop, params={mode:\"soft\"})\n---------------------------------------------------\n\nReturns a function that takes a string and returns a new string.\n\nPad out lines with spaces out to column `start` and then wrap until column\n`stop`. If a word is longer than `stop - start` characters it will overflow.\n\nIn \"soft\" mode, split chunks by `/(\\S+\\s+/` and don't break up chunks which are\nlonger than `stop - start`, in \"hard\" mode, split chunks with `/\\b/` and break\nup chunks longer than `stop - start`.\n\nwrap.hard(start, stop)\n----------------------\n\nLike `wrap()` but with `params.mode = \"hard\"`.\n", + "readmeFilename": "README.markdown", + "_id": "wordwrap@0.0.2", + "dist": { + "shasum": "ece472585d818a1bc63ecdf59f23356928e61210" + }, + "_from": "wordwrap@~0.0.2", + "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/package.json b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/package.json new file mode 100644 index 0000000..932c274 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/package.json @@ -0,0 +1,46 @@ +{ + "name": "optimist", + "version": "0.3.7", + "description": "Light-weight option parsing with an argv hash. No optstrings attached.", + "main": "./index.js", + "dependencies": { + "wordwrap": "~0.0.2" + }, + "devDependencies": { + "hashish": "~0.0.4", + "tap": "~0.4.0" + }, + "scripts": { + "test": "tap ./test/*.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-optimist.git" + }, + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "node": ">=0.4" + }, + "readme": "optimist\n========\n\nOptimist is a node.js library for option parsing for people who hate option\nparsing. More specifically, this module is for people who like all the --bells\nand -whistlz of program usage but think optstrings are a waste of time.\n\nWith optimist, option parsing doesn't have to suck (as much).\n\n[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist)\n\nexamples\n========\n\nWith Optimist, the options are just a hash! No optstrings attached.\n-------------------------------------------------------------------\n\nxup.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\n\nif (argv.rif - 5 * argv.xup > 7.138) {\n console.log('Buy more riffiwobbles');\n}\nelse {\n console.log('Sell the xupptumblers');\n}\n````\n\n***\n\n $ ./xup.js --rif=55 --xup=9.52\n Buy more riffiwobbles\n \n $ ./xup.js --rif 12 --xup 8.1\n Sell the xupptumblers\n\n![This one's optimistic.](http://substack.net/images/optimistic.png)\n\nBut wait! There's more! You can do short options:\n-------------------------------------------------\n \nshort.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\n````\n\n***\n\n $ ./short.js -x 10 -y 21\n (10,21)\n\nAnd booleans, both long and short (and grouped):\n----------------------------------\n\nbool.js:\n\n````javascript\n#!/usr/bin/env node\nvar util = require('util');\nvar argv = require('optimist').argv;\n\nif (argv.s) {\n util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');\n}\nconsole.log(\n (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')\n);\n````\n\n***\n\n $ ./bool.js -s\n The cat says: meow\n \n $ ./bool.js -sp\n The cat says: meow.\n\n $ ./bool.js -sp --fr\n Le chat dit: miaou.\n\nAnd non-hypenated options too! Just use `argv._`!\n-------------------------------------------------\n \nnonopt.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist').argv;\nconsole.log('(%d,%d)', argv.x, argv.y);\nconsole.log(argv._);\n````\n\n***\n\n $ ./nonopt.js -x 6.82 -y 3.35 moo\n (6.82,3.35)\n [ 'moo' ]\n \n $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz\n (0.54,1.12)\n [ 'foo', 'bar', 'baz' ]\n\nPlus, Optimist comes with .usage() and .demand()!\n-------------------------------------------------\n\ndivide.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Usage: $0 -x [num] -y [num]')\n .demand(['x','y'])\n .argv;\n\nconsole.log(argv.x / argv.y);\n````\n\n***\n \n $ ./divide.js -x 55 -y 11\n 5\n \n $ node ./divide.js -x 4.91 -z 2.51\n Usage: node ./divide.js -x [num] -y [num]\n\n Options:\n -x [required]\n -y [required]\n\n Missing required arguments: y\n\nEVEN MORE HOLY COW\n------------------\n\ndefault_singles.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default('x', 10)\n .default('y', 10)\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_singles.js -x 5\n 15\n\ndefault_hash.js:\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .default({ x : 10, y : 10 })\n .argv\n;\nconsole.log(argv.x + argv.y);\n````\n\n***\n\n $ ./default_hash.js -y 7\n 17\n\nAnd if you really want to get all descriptive about it...\n---------------------------------------------------------\n\nboolean_single.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean('v')\n .argv\n;\nconsole.dir(argv);\n````\n\n***\n\n $ ./boolean_single.js -v foo bar baz\n true\n [ 'bar', 'baz', 'foo' ]\n\nboolean_double.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .boolean(['x','y','z'])\n .argv\n;\nconsole.dir([ argv.x, argv.y, argv.z ]);\nconsole.dir(argv._);\n````\n\n***\n\n $ ./boolean_double.js -x -z one two three\n [ true, false, true ]\n [ 'one', 'two', 'three' ]\n\nOptimist is here to help...\n---------------------------\n\nYou can describe parameters for help messages and set aliases. Optimist figures\nout how to format a handy help string automatically.\n\nline_count.js\n\n````javascript\n#!/usr/bin/env node\nvar argv = require('optimist')\n .usage('Count the lines in a file.\\nUsage: $0')\n .demand('f')\n .alias('f', 'file')\n .describe('f', 'Load a file')\n .argv\n;\n\nvar fs = require('fs');\nvar s = fs.createReadStream(argv.file);\n\nvar lines = 0;\ns.on('data', function (buf) {\n lines += buf.toString().match(/\\n/g).length;\n});\n\ns.on('end', function () {\n console.log(lines);\n});\n````\n\n***\n\n $ node line_count.js\n Count the lines in a file.\n Usage: node ./line_count.js\n\n Options:\n -f, --file Load a file [required]\n\n Missing required arguments: f\n\n $ node line_count.js --file line_count.js \n 20\n \n $ node line_count.js -f line_count.js \n 20\n\nmethods\n=======\n\nBy itself,\n\n````javascript\nrequire('optimist').argv\n`````\n\nwill use `process.argv` array to construct the `argv` object.\n\nYou can pass in the `process.argv` yourself:\n\n````javascript\nrequire('optimist')([ '-x', '1', '-y', '2' ]).argv\n````\n\nor use .parse() to do the same thing:\n\n````javascript\nrequire('optimist').parse([ '-x', '1', '-y', '2' ])\n````\n\nThe rest of these methods below come in just before the terminating `.argv`.\n\n.alias(key, alias)\n------------------\n\nSet key names as equivalent such that updates to a key will propagate to aliases\nand vice-versa.\n\nOptionally `.alias()` can take an object that maps keys to aliases.\n\n.default(key, value)\n--------------------\n\nSet `argv[key]` to `value` if no option was specified on `process.argv`.\n\nOptionally `.default()` can take an object that maps keys to default values.\n\n.demand(key)\n------------\n\nIf `key` is a string, show the usage information and exit if `key` wasn't\nspecified in `process.argv`.\n\nIf `key` is a number, demand at least as many non-option arguments, which show\nup in `argv._`.\n\nIf `key` is an Array, demand each element.\n\n.describe(key, desc)\n--------------------\n\nDescribe a `key` for the generated usage information.\n\nOptionally `.describe()` can take an object that maps keys to descriptions.\n\n.options(key, opt)\n------------------\n\nInstead of chaining together `.alias().demand().default()`, you can specify\nkeys in `opt` for each of the chainable methods.\n\nFor example:\n\n````javascript\nvar argv = require('optimist')\n .options('f', {\n alias : 'file',\n default : '/etc/passwd',\n })\n .argv\n;\n````\n\nis the same as\n\n````javascript\nvar argv = require('optimist')\n .alias('f', 'file')\n .default('f', '/etc/passwd')\n .argv\n;\n````\n\nOptionally `.options()` can take an object that maps keys to `opt` parameters.\n\n.usage(message)\n---------------\n\nSet a usage message to show which commands to use. Inside `message`, the string\n`$0` will get interpolated to the current script name or node command for the\npresent script similar to how `$0` works in bash or perl.\n\n.check(fn)\n----------\n\nCheck that certain conditions are met in the provided arguments.\n\nIf `fn` throws or returns `false`, show the thrown error, usage information, and\nexit.\n\n.boolean(key)\n-------------\n\nInterpret `key` as a boolean. If a non-flag option follows `key` in\n`process.argv`, that string won't get set as the value of `key`.\n\nIf `key` never shows up as a flag in `process.arguments`, `argv[key]` will be\n`false`.\n\nIf `key` is an Array, interpret all the elements as booleans.\n\n.string(key)\n------------\n\nTell the parser logic not to interpret `key` as a number or boolean.\nThis can be useful if you need to preserve leading zeros in an input.\n\nIf `key` is an Array, interpret all the elements as strings.\n\n.wrap(columns)\n--------------\n\nFormat usage output to wrap at `columns` many columns.\n\n.help()\n-------\n\nReturn the generated usage string.\n\n.showHelp(fn=console.error)\n---------------------------\n\nPrint the usage data using `fn` for printing.\n\n.parse(args)\n------------\n\nParse `args` instead of `process.argv`. Returns the `argv` object.\n\n.argv\n-----\n\nGet the arguments as a plain old object.\n\nArguments without a corresponding flag show up in the `argv._` array.\n\nThe script name or node command is available at `argv.$0` similarly to how `$0`\nworks in bash or perl.\n\nparsing tricks\n==============\n\nstop parsing\n------------\n\nUse `--` to stop parsing flags and stuff the remainder into `argv._`.\n\n $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4\n { _: [ '-c', '3', '-d', '4' ],\n '$0': 'node ./examples/reflect.js',\n a: 1,\n b: 2 }\n\nnegate fields\n-------------\n\nIf you want to explicity set a field to false instead of just leaving it\nundefined or to override a default you can do `--no-key`.\n\n $ node examples/reflect.js -a --no-b\n { _: [],\n '$0': 'node ./examples/reflect.js',\n a: true,\n b: false }\n\nnumbers\n-------\n\nEvery argument that looks like a number (`!isNaN(Number(arg))`) is converted to\none. This way you can just `net.createConnection(argv.port)` and you can add\nnumbers out of `argv` with `+` without having that mean concatenation,\nwhich is super frustrating.\n\nduplicates\n----------\n\nIf you specify a flag multiple times it will get turned into an array containing\nall the values in order.\n\n $ node examples/reflect.js -x 5 -x 8 -x 0\n { _: [],\n '$0': 'node ./examples/reflect.js',\n x: [ 5, 8, 0 ] }\n\ndot notation\n------------\n\nWhen you use dots (`.`s) in argument names, an implicit object path is assumed.\nThis lets you organize arguments into nested objects.\n\n $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5\n { _: [],\n '$0': 'node ./examples/reflect.js',\n foo: { bar: { baz: 33 }, quux: 5 } }\n\ninstallation\n============\n\nWith [npm](http://github.com/isaacs/npm), just do:\n npm install optimist\n \nor clone this project on github:\n\n git clone http://github.com/substack/node-optimist.git\n\nTo run the tests with [expresso](http://github.com/visionmedia/expresso),\njust do:\n \n expresso\n\ninspired By\n===========\n\nThis module is loosely inspired by Perl's\n[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).\n", + "readmeFilename": "readme.markdown", + "_id": "optimist@0.3.7", + "dist": { + "shasum": "6e935517247b531bf1676559618d7c7989881b54" + }, + "_from": "optimist@~0.3.5", + "_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz" +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/readme.markdown b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/readme.markdown new file mode 100644 index 0000000..ad9d3fd --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/readme.markdown @@ -0,0 +1,487 @@ +optimist +======== + +Optimist is a node.js library for option parsing for people who hate option +parsing. More specifically, this module is for people who like all the --bells +and -whistlz of program usage but think optstrings are a waste of time. + +With optimist, option parsing doesn't have to suck (as much). + +[![build status](https://secure.travis-ci.org/substack/node-optimist.png)](http://travis-ci.org/substack/node-optimist) + +examples +======== + +With Optimist, the options are just a hash! No optstrings attached. +------------------------------------------------------------------- + +xup.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; + +if (argv.rif - 5 * argv.xup > 7.138) { + console.log('Buy more riffiwobbles'); +} +else { + console.log('Sell the xupptumblers'); +} +```` + +*** + + $ ./xup.js --rif=55 --xup=9.52 + Buy more riffiwobbles + + $ ./xup.js --rif 12 --xup 8.1 + Sell the xupptumblers + +![This one's optimistic.](http://substack.net/images/optimistic.png) + +But wait! There's more! You can do short options: +------------------------------------------------- + +short.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +```` + +*** + + $ ./short.js -x 10 -y 21 + (10,21) + +And booleans, both long and short (and grouped): +---------------------------------- + +bool.js: + +````javascript +#!/usr/bin/env node +var util = require('util'); +var argv = require('optimist').argv; + +if (argv.s) { + util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: '); +} +console.log( + (argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '') +); +```` + +*** + + $ ./bool.js -s + The cat says: meow + + $ ./bool.js -sp + The cat says: meow. + + $ ./bool.js -sp --fr + Le chat dit: miaou. + +And non-hypenated options too! Just use `argv._`! +------------------------------------------------- + +nonopt.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); +```` + +*** + + $ ./nonopt.js -x 6.82 -y 3.35 moo + (6.82,3.35) + [ 'moo' ] + + $ ./nonopt.js foo -x 0.54 bar -y 1.12 baz + (0.54,1.12) + [ 'foo', 'bar', 'baz' ] + +Plus, Optimist comes with .usage() and .demand()! +------------------------------------------------- + +divide.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Usage: $0 -x [num] -y [num]') + .demand(['x','y']) + .argv; + +console.log(argv.x / argv.y); +```` + +*** + + $ ./divide.js -x 55 -y 11 + 5 + + $ node ./divide.js -x 4.91 -z 2.51 + Usage: node ./divide.js -x [num] -y [num] + + Options: + -x [required] + -y [required] + + Missing required arguments: y + +EVEN MORE HOLY COW +------------------ + +default_singles.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_singles.js -x 5 + 15 + +default_hash.js: + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .default({ x : 10, y : 10 }) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_hash.js -y 7 + 17 + +And if you really want to get all descriptive about it... +--------------------------------------------------------- + +boolean_single.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean('v') + .argv +; +console.dir(argv); +```` + +*** + + $ ./boolean_single.js -v foo bar baz + true + [ 'bar', 'baz', 'foo' ] + +boolean_double.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); +```` + +*** + + $ ./boolean_double.js -x -z one two three + [ true, false, true ] + [ 'one', 'two', 'three' ] + +Optimist is here to help... +--------------------------- + +You can describe parameters for help messages and set aliases. Optimist figures +out how to format a handy help string automatically. + +line_count.js + +````javascript +#!/usr/bin/env node +var argv = require('optimist') + .usage('Count the lines in a file.\nUsage: $0') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .argv +; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); +```` + +*** + + $ node line_count.js + Count the lines in a file. + Usage: node ./line_count.js + + Options: + -f, --file Load a file [required] + + Missing required arguments: f + + $ node line_count.js --file line_count.js + 20 + + $ node line_count.js -f line_count.js + 20 + +methods +======= + +By itself, + +````javascript +require('optimist').argv +````` + +will use `process.argv` array to construct the `argv` object. + +You can pass in the `process.argv` yourself: + +````javascript +require('optimist')([ '-x', '1', '-y', '2' ]).argv +```` + +or use .parse() to do the same thing: + +````javascript +require('optimist').parse([ '-x', '1', '-y', '2' ]) +```` + +The rest of these methods below come in just before the terminating `.argv`. + +.alias(key, alias) +------------------ + +Set key names as equivalent such that updates to a key will propagate to aliases +and vice-versa. + +Optionally `.alias()` can take an object that maps keys to aliases. + +.default(key, value) +-------------------- + +Set `argv[key]` to `value` if no option was specified on `process.argv`. + +Optionally `.default()` can take an object that maps keys to default values. + +.demand(key) +------------ + +If `key` is a string, show the usage information and exit if `key` wasn't +specified in `process.argv`. + +If `key` is a number, demand at least as many non-option arguments, which show +up in `argv._`. + +If `key` is an Array, demand each element. + +.describe(key, desc) +-------------------- + +Describe a `key` for the generated usage information. + +Optionally `.describe()` can take an object that maps keys to descriptions. + +.options(key, opt) +------------------ + +Instead of chaining together `.alias().demand().default()`, you can specify +keys in `opt` for each of the chainable methods. + +For example: + +````javascript +var argv = require('optimist') + .options('f', { + alias : 'file', + default : '/etc/passwd', + }) + .argv +; +```` + +is the same as + +````javascript +var argv = require('optimist') + .alias('f', 'file') + .default('f', '/etc/passwd') + .argv +; +```` + +Optionally `.options()` can take an object that maps keys to `opt` parameters. + +.usage(message) +--------------- + +Set a usage message to show which commands to use. Inside `message`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. + +.check(fn) +---------- + +Check that certain conditions are met in the provided arguments. + +If `fn` throws or returns `false`, show the thrown error, usage information, and +exit. + +.boolean(key) +------------- + +Interpret `key` as a boolean. If a non-flag option follows `key` in +`process.argv`, that string won't get set as the value of `key`. + +If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be +`false`. + +If `key` is an Array, interpret all the elements as booleans. + +.string(key) +------------ + +Tell the parser logic not to interpret `key` as a number or boolean. +This can be useful if you need to preserve leading zeros in an input. + +If `key` is an Array, interpret all the elements as strings. + +.wrap(columns) +-------------- + +Format usage output to wrap at `columns` many columns. + +.help() +------- + +Return the generated usage string. + +.showHelp(fn=console.error) +--------------------------- + +Print the usage data using `fn` for printing. + +.parse(args) +------------ + +Parse `args` instead of `process.argv`. Returns the `argv` object. + +.argv +----- + +Get the arguments as a plain old object. + +Arguments without a corresponding flag show up in the `argv._` array. + +The script name or node command is available at `argv.$0` similarly to how `$0` +works in bash or perl. + +parsing tricks +============== + +stop parsing +------------ + +Use `--` to stop parsing flags and stuff the remainder into `argv._`. + + $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 + { _: [ '-c', '3', '-d', '4' ], + '$0': 'node ./examples/reflect.js', + a: 1, + b: 2 } + +negate fields +------------- + +If you want to explicity set a field to false instead of just leaving it +undefined or to override a default you can do `--no-key`. + + $ node examples/reflect.js -a --no-b + { _: [], + '$0': 'node ./examples/reflect.js', + a: true, + b: false } + +numbers +------- + +Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to +one. This way you can just `net.createConnection(argv.port)` and you can add +numbers out of `argv` with `+` without having that mean concatenation, +which is super frustrating. + +duplicates +---------- + +If you specify a flag multiple times it will get turned into an array containing +all the values in order. + + $ node examples/reflect.js -x 5 -x 8 -x 0 + { _: [], + '$0': 'node ./examples/reflect.js', + x: [ 5, 8, 0 ] } + +dot notation +------------ + +When you use dots (`.`s) in argument names, an implicit object path is assumed. +This lets you organize arguments into nested objects. + + $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5 + { _: [], + '$0': 'node ./examples/reflect.js', + foo: { bar: { baz: 33 }, quux: 5 } } + +installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + npm install optimist + +or clone this project on github: + + git clone http://github.com/substack/node-optimist.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + +inspired By +=========== + +This module is loosely inspired by Perl's +[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_.js new file mode 100644 index 0000000..d9c58b3 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_.js @@ -0,0 +1,71 @@ +var spawn = require('child_process').spawn; +var test = require('tap').test; + +test('dotSlashEmpty', testCmd('./bin.js', [])); + +test('dotSlashArgs', testCmd('./bin.js', [ 'a', 'b', 'c' ])); + +test('nodeEmpty', testCmd('node bin.js', [])); + +test('nodeArgs', testCmd('node bin.js', [ 'x', 'y', 'z' ])); + +test('whichNodeEmpty', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', []) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + assert.error(err); + t.end(); + }); +}); + +test('whichNodeArgs', function (t) { + var which = spawn('which', ['node']); + + which.stdout.on('data', function (buf) { + t.test( + testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]) + ); + t.end(); + }); + + which.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); +}); + +function testCmd (cmd, args) { + + return function (t) { + var to = setTimeout(function () { + assert.fail('Never got stdout data.') + }, 5000); + + var oldDir = process.cwd(); + process.chdir(__dirname + '/_'); + + var cmds = cmd.split(' '); + + var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String))); + process.chdir(oldDir); + + bin.stderr.on('data', function (err) { + t.error(err); + t.end(); + }); + + bin.stdout.on('data', function (buf) { + clearTimeout(to); + var _ = JSON.parse(buf.toString()); + t.same(_.map(String), args.map(String)); + t.end(); + }); + }; +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/argv.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/argv.js new file mode 100644 index 0000000..3d09606 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/argv.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log(JSON.stringify(process.argv)); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/bin.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/bin.js new file mode 100755 index 0000000..4a18d85 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/_/bin.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var argv = require('../../index').argv +console.log(JSON.stringify(argv._)); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/parse.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/parse.js new file mode 100644 index 0000000..d320f43 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/parse.js @@ -0,0 +1,446 @@ +var optimist = require('../index'); +var path = require('path'); +var test = require('tap').test; + +var $0 = 'node ./' + path.relative(process.cwd(), __filename); + +test('short boolean', function (t) { + var parse = optimist.parse([ '-b' ]); + t.same(parse, { b : true, _ : [], $0 : $0 }); + t.same(typeof parse.b, 'boolean'); + t.end(); +}); + +test('long boolean', function (t) { + t.same( + optimist.parse([ '--bool' ]), + { bool : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('bare', function (t) { + t.same( + optimist.parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ], $0 : $0 } + ); + t.end(); +}); + +test('short group', function (t) { + t.same( + optimist.parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short group next', function (t) { + t.same( + optimist.parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('short captures', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture sp', function (t) { + t.same( + optimist.parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long capture eq', function (t) { + t.same( + optimist.parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [], $0 : $0 } + ); + t.end() +}); + +test('long captures sp', function (t) { + t.same( + optimist.parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('long captures eq', function (t) { + t.same( + optimist.parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.same( + optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ], $0 : $0, + } + ); + t.end(); +}); + +test('no', function (t) { + t.same( + optimist.parse([ '--no-moo' ]), + { moo : false, _ : [], $0 : $0 } + ); + t.end(); +}); + +test('multi', function (t) { + t.same( + optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [], $0 : $0 } + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.same( + optimist.parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ], + $0 : $0 + } + ); + t.end(); +}); + +test('nums', function (t) { + var argv = optimist.parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789', + ]); + t.same(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ], + $0 : $0 + }); + t.same(typeof argv.x, 'number'); + t.same(typeof argv.y, 'number'); + t.same(typeof argv.z, 'number'); + t.same(typeof argv.w, 'string'); + t.same(typeof argv.hex, 'number'); + t.same(typeof argv._[0], 'number'); + t.end(); +}); + +test('flag boolean', function (t) { + var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv; + t.same(parse, { t : true, _ : [ 'moo' ], $0 : $0 }); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true']) + .boolean(['t', 'verbose']).default('verbose', true).argv; + + t.same(parse, { + verbose: false, + t: true, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); +}); + +test('flag boolean default false', function (t) { + var parse = optimist(['moo']) + .boolean(['t', 'verbose']) + .default('verbose', false) + .default('t', false).argv; + + t.same(parse, { + verbose: false, + t: false, + _: ['moo'], + $0 : $0 + }); + + t.same(typeof parse.verbose, 'boolean'); + t.same(typeof parse.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ]) + .boolean(['x','y','z']).argv; + + t.same(parse, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ], + $0 : $0 + }); + + t.same(typeof parse.x, 'boolean'); + t.same(typeof parse.y, 'boolean'); + t.same(typeof parse.z, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = optimist.parse([ '-s', "X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = optimist.parse([ "--s=X\nX" ]) + t.same(args, { _ : [], s : "X\nX", $0 : $0 }); + t.end(); +}); + +test('strings' , function (t) { + var s = optimist([ '-s', '0001234' ]).string('s').argv.s; + t.same(s, '0001234'); + t.same(typeof s, 'string'); + + var x = optimist([ '-x', '56' ]).string('x').argv.x; + t.same(x, '56'); + t.same(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = optimist([ ' ', ' ' ]).string('_').argv._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + optimist.parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.same( + optimist.parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : $0 } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', 'zoom') + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = optimist([ '-f', '11', '--zoom', '55' ]) + .alias('z', [ 'zm', 'zoom' ]) + .argv + ; + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('boolean default true', function (t) { + var argv = optimist.options({ + sometrue: { + boolean: true, + default: true + } + }).argv; + + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = optimist.options({ + somefalse: { + boolean: true, + default: false + } + }).argv; + + t.equal(argv.somefalse, false); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = optimist([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]).argv; + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + }, + }); + t.same(argv.beep, { boop : true }); + t.end(); +}); + +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('herp') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('herp') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .options(opts) + .argv; + var propertyArgv = optimist(regular).options(opts).argv; + var expected = { + herp: true, + h: true, + '_': [ 'derp' ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = optimist(aliased) + .boolean('h') + .alias('h', 'herp') + .argv; + var propertyArgv = optimist(regular) + .boolean('h') + .alias('h', 'herp') + .argv; + var expected = { + herp: true, + h: true, + '_': [ ], + '$0': $0, + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = optimist(['--boool', '--other=true']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = optimist(['--boool', '--other=false']).boolean('boool').argv; + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/usage.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/usage.js new file mode 100644 index 0000000..300454c --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/optimist/test/usage.js @@ -0,0 +1,292 @@ +var Hash = require('hashish'); +var optimist = require('../index'); +var test = require('tap').test; + +test('usageFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'Options:', + ' -x [required]', + ' -y [required]', + 'Missing required arguments: y', + ] + ); + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + + +test('usagePass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .demand(['x','y']) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkPass', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkFail', function (t) { + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(function (argv) { + if (!('x' in argv)) throw 'You forgot about -x'; + if (!('y' in argv)) throw 'You forgot about -y'; + }) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage -x NUM -y NUM', + 'You forgot about -y' + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('checkCondPass', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -y 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + t.same(r, { + result : { x : 10, y : 20, _ : [], $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('checkCondFail', function (t) { + function checker (argv) { + return 'x' in argv && 'y' in argv; + } + + var r = checkUsage(function () { + return optimist('-x 10 -z 20'.split(' ')) + .usage('Usage: $0 -x NUM -y NUM') + .check(checker) + .argv; + }); + + t.same( + r.result, + { x : 10, z : 20, _ : [], $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/).join('\n'), + 'Usage: ./usage -x NUM -y NUM\n' + + 'Argument check failed: ' + checker.toString() + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('countPass', function (t) { + var r = checkUsage(function () { + return optimist('1 2 3 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same(r, { + result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' }, + errors : [], + logs : [], + exit : false, + }); + t.end(); +}); + +test('countFail', function (t) { + var r = checkUsage(function () { + return optimist('1 2 --moo'.split(' ')) + .usage('Usage: $0 [x] [y] [z] {OPTIONS}') + .demand(3) + .argv; + }); + t.same( + r.result, + { _ : [ '1', '2' ], moo : true, $0 : './usage' } + ); + + t.same( + r.errors.join('\n').split(/\n+/), + [ + 'Usage: ./usage [x] [y] [z] {OPTIONS}', + 'Not enough non-option arguments: got 2, need at least 3', + ] + ); + + t.same(r.logs, []); + t.ok(r.exit); + t.end(); +}); + +test('defaultSingles', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70 --powsy'.split(' ')) + .default('foo', 5) + .default('bar', 6) + .default('baz', 7) + .argv + ; + }); + t.same(r.result, { + foo : '50', + bar : 6, + baz : '70', + powsy : true, + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultAliases', function (t) { + var r = checkUsage(function () { + return optimist('') + .alias('f', 'foo') + .default('f', 5) + .argv + ; + }); + t.same(r.result, { + f : '5', + foo : '5', + _ : [], + $0 : './usage', + }); + t.end(); +}); + +test('defaultHash', function (t) { + var r = checkUsage(function () { + return optimist('--foo 50 --baz 70'.split(' ')) + .default({ foo : 10, bar : 20, quux : 30 }) + .argv + ; + }); + t.same(r.result, { + _ : [], + $0 : './usage', + foo : 50, + baz : 70, + bar : 20, + quux : 30, + }); + t.end(); +}); + +test('rebase', function (t) { + t.equal( + optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'), + './foo/bar/baz' + ); + t.equal( + optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'), + '../../..' + ); + t.equal( + optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'), + '../pow/zoom.txt' + ); + t.end(); +}); + +function checkUsage (f) { + + var exit = false; + + process._exit = process.exit; + process._env = process.env; + process._argv = process.argv; + + process.exit = function (t) { exit = true }; + process.env = Hash.merge(process.env, { _ : 'node' }); + process.argv = [ './usage' ]; + + var errors = []; + var logs = []; + + console._error = console.error; + console.error = function (msg) { errors.push(msg) }; + console._log = console.log; + console.log = function (msg) { logs.push(msg) }; + + var result = f(); + + process.exit = process._exit; + process.env = process._env; + process.argv = process._argv; + + console.error = console._error; + console.log = console._log; + + return { + errors : errors, + logs : logs, + exit : exit, + result : result, + }; +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.npmignore b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.npmignore new file mode 100644 index 0000000..3dddf3f --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.travis.yml b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.travis.yml new file mode 100644 index 0000000..ddc9c4f --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md new file mode 100644 index 0000000..75d1c14 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,75 @@ +# Change Log + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. + diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/LICENSE b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/LICENSE new file mode 100644 index 0000000..ed1b7cf --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 0000000..d6fc26a --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/README.md b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/README.md new file mode 100644 index 0000000..5cc212c --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/README.md @@ -0,0 +1,347 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +[Learn more here][feature]. + +This library was written in the Asynchronous Module Definition +format. It should work in the following environments: + +* Modern Browsers (either after the build, or with an AMD loader such as + RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Installing with NPM (for use with NodeJS) + +Simply + + $ npm install source-map + +Or, if you'd like to hack on this library and have it installed via npm so you +can try out your changes: + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox + source. + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator(startOfSourceMap) + +To create a new one, you must pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: An optional root for all relative URLs in this source map. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used. + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode(line, column, source[, chunk[, name]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js new file mode 100644 index 0000000..daa1a62 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/mini-require.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/mini-require.js new file mode 100644 index 0000000..0daf453 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 0000000..ee2539d --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 0000000..80341d4 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 0000000..cf6cde7 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +window.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 0000000..cf3c2d8 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 0000000..b31b84c --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js new file mode 100644 index 0000000..1b13f30 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js new file mode 100644 index 0000000..bec2de3 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map.js new file mode 100644 index 0000000..121ad24 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 0000000..584b845 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,96 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i]); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr) { + if (this.has(aStr)) { + // Already a member; nothing to do. + return; + } + var idx = this._array.length; + this._array.push(aStr); + this._set[util.toSetString(aStr)] = idx; + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 0000000..1b67bb3 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,144 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 0000000..863cc46 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 0000000..7dfd0ea --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,81 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid]); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 0000000..97db234 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,441 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + var names = util.getArg(sourceMap, 'names'); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file'); + + if (version !== this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._names = ArraySet.fromArray(names); + this._sources = ArraySet.fromArray(sources); + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this.file = file; + + // `this._generatedMappings` and `this._originalMappings` hold the parsed + // mapping coordinates from the source map's "mappings" attribute. Each + // object in the array is of the form + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `this._generatedMappings` is ordered by the generated positions. + // + // `this._originalMappings` is ordered by the original positions. + this._generatedMappings = []; + this._originalMappings = []; + this._parseMappings(mappings, sourceRoot); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (an ordered list in this._generatedMappings). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this._generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this._originalMappings.push(mapping); + } + } + } + + this._originalMappings.sort(this._compareOriginalPositions); + }; + + /** + * Comparator between two mappings where the original positions are compared. + */ + SourceMapConsumer.prototype._compareOriginalPositions = + function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { + if (mappingA.source > mappingB.source) { + return 1; + } + else if (mappingA.source < mappingB.source) { + return -1; + } + else { + var cmp = mappingA.originalLine - mappingB.originalLine; + return cmp === 0 + ? mappingA.originalColumn - mappingB.originalColumn + : cmp; + } + }; + + /** + * Comparator between two mappings where the generated positions are compared. + */ + SourceMapConsumer.prototype._compareGeneratedPositions = + function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + return cmp === 0 + ? mappingA.generatedColumn - mappingB.generatedColumn + : cmp; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + this._compareGeneratedPositions); + + if (mapping) { + var source = util.getArg(mapping, 'source', null); + if (source && this.sourceRoot) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + this._compareOriginalPositions); + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source && sourceRoot) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 0000000..f497090 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,381 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source) { + newMapping.source = mapping.source; + if (sourceRoot) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generated: generated, + original: original, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent !== null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile) { + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (!aSourceFile) { + aSourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "aSourceFile" relative if an absolute Url is passed. + if (sourceRoot) { + aSourceFile = util.relative(sourceRoot, aSourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "aSourceFile" + this._mappings.forEach(function (mapping) { + if (mapping.source === aSourceFile && mapping.original) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.original.line, + column: mapping.original.column + }); + if (original.source !== null) { + // Copy mapping + if (sourceRoot) { + mapping.source = util.relative(sourceRoot, original.source); + } else { + mapping.source = original.source; + } + mapping.original.line = original.line; + mapping.original.column = original.column; + if (original.name !== null && mapping.name !== null) { + // Only use the identifier name if it's an identifier + // in both SourceMaps + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + if (sourceRoot) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping.'); + } + }; + + function cmpLocation(loc1, loc2) { + var cmp = (loc1 && loc1.line) - (loc2 && loc2.line); + return cmp ? cmp : (loc1 && loc1.column) - (loc2 && loc2.column); + } + + function strcmp(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + return (str1 > str2) - (str1 < str2); + } + + function cmpMapping(mappingA, mappingB) { + return cmpLocation(mappingA.generated, mappingB.generated) || + cmpLocation(mappingA.original, mappingB.original) || + strcmp(mappingA.source, mappingB.source) || + strcmp(mappingA.name, mappingB.name); + } + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guaranteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(cmpMapping); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generated.line !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generated.line !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!cmpMapping(mapping, this._mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generated.column + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generated.column; + + if (mapping.source && mapping.original) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.original.line - 1 + - previousOriginalLine); + previousOriginalLine = mapping.original.line - 1; + + result += base64VLQ.encode(mapping.original.column + - previousOriginalColumn); + previousOriginalColumn = mapping.original.column; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = map.sources.map(function (source) { + if (map.sourceRoot) { + source = util.relative(map.sourceRoot, source); + } + return Object.prototype.hasOwnProperty.call( + this._sourcesContents, util.toSetString(source)) + ? this._sourcesContents[util.toSetString(source)] + : null; + }, this); + } + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 0000000..2e5a09d --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,353 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine === undefined ? null : aLine; + this.column = aColumn === undefined ? null : aColumn; + this.source = aSource === undefined ? null : aSource; + this.name = aName === undefined ? null : aName; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // The generated code + // Processed fragments are removed from this array. + var remainingLines = aGeneratedCode.split('\n'); + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping === null) { + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(remainingLines.shift() + "\n"); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + } else { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate full lines with "lastMapping" + do { + code += remainingLines.shift() + "\n"; + lastGeneratedLine++; + lastGeneratedColumn = 0; + } while (lastGeneratedLine < mapping.generatedLine); + // When we reached the correct line, we add code until we + // reach the correct column too. + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + code += nextLine.substr(0, mapping.generatedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + // Create the SourceNode. + addMappingWithCode(lastMapping, code); + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + } + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + // Associate the remaining code in the current line with "lastMapping" + // and add the remaining lines without any mapping + addMappingWithCode(lastMapping, remainingLines.join("\n")); + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content) { + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + mapping.source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + }, this); + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walkSourceContents(aFn); + } + }, this); + Object.keys(this.sourceContents).forEach(function (sourceFileKey) { + aFn(util.fromSetString(sourceFileKey), this.sourceContents[sourceFileKey]); + }, this); + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + sourceMappingActive = false; + } + chunk.split('').forEach(function (ch) { + if (ch === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 0000000..4ce5113 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,117 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /([\w+\-.]+):\/\/((\w+:\w+)@)?([\w.]+)?(:(\d+))?(\S+)?/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[3], + host: match[4], + port: match[6], + path: match[7] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = aParsedUrl.scheme + "://"; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + "@" + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + function join(aRoot, aPath) { + var url; + + if (aPath.match(urlRegexp)) { + return aPath; + } + + if (aPath.charAt(0) === '/' && (url = urlParse(aRoot))) { + url.path = aPath; + return urlGenerate(url); + } + + return aRoot.replace(/\/$/, '') + '/' + aPath; + } + exports.join = join; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function relative(aRoot, aPath) { + aRoot = aRoot.replace(/\/$/, ''); + + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE new file mode 100644 index 0000000..f33d665 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2011, The Dojo Foundation + +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/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md new file mode 100644 index 0000000..8ebbc73 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/README.md @@ -0,0 +1,119 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.0.5" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js new file mode 100644 index 0000000..d074c94 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/amdefine.js @@ -0,0 +1,299 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.0.5 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +var path = require('path'); + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [require]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, require) { + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + require = require || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(require, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(require, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(module.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json new file mode 100644 index 0000000..5ab7827 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json @@ -0,0 +1,37 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "0.0.5", + "homepage": "http://github.com/jrburke/amdefine", + "author": { + "name": "James Burke", + "email": "jrburke@gmail.com", + "url": "http://github.com/jrburke" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + }, + { + "type": "MIT", + "url": "https://github.com/jrburke/amdefine/blob/master/LICENSE" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + }, + "readme": "# amdefine\n\nA module that can be used to implement AMD's define() in Node. This allows you\nto code to the AMD API and have the module work in node programs without\nrequiring those other programs to use AMD.\n\n## Usage\n\n**1)** Update your package.json to indicate amdefine as a dependency:\n\n```javascript\n \"dependencies\": {\n \"amdefine\": \">=0.0.5\"\n }\n```\n\nThen run `npm install` to get amdefine into your project.\n\n**2)** At the top of each module that uses define(), place this code:\n\n```javascript\nif (typeof define !== 'function') { var define = require('amdefine')(module) }\n```\n\n**Only use these snippets** when loading amdefine. If you preserve the basic structure,\nwith the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).\n\nYou can add spaces, line breaks and even require amdefine with a local path, but\nkeep the rest of the structure to get the stripping behavior.\n\nAs you may know, because `if` statements in JavaScript don't have their own scope, the var\ndeclaration in the above snippet is made whether the `if` expression is truthy or not. If\nRequireJS is loaded then the declaration is superfluous because `define` is already already\ndeclared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`\ndeclarations of the same variable in the same scope gracefully.\n\nIf you want to deliver amdefine.js with your code rather than specifying it as a dependency\nwith npm, then just download the latest release and refer to it using a relative path:\n\n[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)\n\n## define() usage\n\nIt is best if you use the anonymous forms of define() in your module:\n\n```javascript\ndefine(function (require) {\n var dependency = require('dependency');\n});\n```\n\nor\n\n```javascript\ndefine(['dependency'], function (dependency) {\n\n});\n```\n\n## RequireJS optimizer integration. \n\nVersion 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)\nwill have support for stripping the `if (typeof define !== 'function')` check\nmentioned above, so you can include this snippet for code that runs in the\nbrowser, but avoid taking the cost of the if() statement once the code is\noptimized for deployment.\n\n## Node 0.4 Support\n\nIf you want to support Node 0.4, then add `require` as the second parameter to amdefine:\n\n```javascript\n//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.\nif (typeof define !== 'function') { var define = require('amdefine')(module, require) }\n```\n\n## Limitations\n\n### Synchronous vs Asynchronous\n\namdefine creates a define() function that is callable by your code. It will\nexecute and trace dependencies and call the factory function *synchronously*,\nto keep the behavior in line with Node's synchronous dependency tracing.\n\nThe exception: calling AMD's callback-style require() from inside a factory\nfunction. The require callback is called on process.nextTick():\n\n```javascript\ndefine(function (require) {\n require(['a'], function(a) {\n //'a' is loaded synchronously, but\n //this callback is called on process.nextTick().\n });\n});\n```\n\n### Loader Plugins\n\nLoader plugins are supported as long as they call their load() callbacks\nsynchronously. So ones that do network requests will not work. However plugins\nlike [text](http://requirejs.org/docs/api.html#text) can load text files locally.\n\nThe plugin API's `load.fromText()` is **not supported** in amdefine, so this means\ntranspiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)\nwill not work. This may be fixable, but it is a bit complex, and I do not have\nenough node-fu to figure it out yet. See the source for amdefine.js if you want\nto get an idea of the issues involved.\n\n## Tests\n\nTo run the tests, cd to **tests** and run:\n\n```\nnode all.js\n```\n\n## License\n\nNew BSD and MIT. Check the LICENSE file for all the details.\n", + "readmeFilename": "README.md", + "_id": "amdefine@0.0.5", + "dist": { + "shasum": "042f205bd60238a7d4aa1e50a2d1f18421e9b30a" + }, + "_from": "amdefine@>=0.0.4", + "_resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.0.5.tgz" +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/package.json b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/package.json new file mode 100644 index 0000000..9796ea2 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/package.json @@ -0,0 +1,98 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.26", + "homepage": "https://github.com/mozilla/source-map", + "author": { + "name": "Nick Fitzgerald", + "email": "nfitzgerald@mozilla.com" + }, + "contributors": [ + { + "name": "Tobias Koppers", + "email": "tobias.koppers@googlemail.com" + }, + { + "name": "Duncan Beevers", + "email": "duncan@dweebd.com" + }, + { + "name": "Stephen Crane", + "email": "scrane@mozilla.com" + }, + { + "name": "Ryan Seddon", + "email": "seddon.ryan@gmail.com" + }, + { + "name": "Miles Elam", + "email": "miles.elam@deem.com" + }, + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com" + }, + { + "name": "Michael Ficarra", + "email": "github.public.email@michael.ficarra.me" + }, + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com" + }, + { + "name": "Alexander Solovyov", + "email": "alexander@solovyov.net" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Conrad Irwin", + "email": "conrad.irwin@gmail.com" + }, + { + "name": "usrbincc", + "email": "usrbincc@yahoo.com" + }, + { + "name": "David Glasser", + "email": "glasser@davidglasser.net" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "# Source Map\n\nThis is a library to generate and consume the source map format\n[described here][format].\n\n[Learn more here][feature].\n\nThis library was written in the Asynchronous Module Definition\nformat. It should work in the following environments:\n\n* Modern Browsers (either after the build, or with an AMD loader such as\n RequireJS)\n\n* Inside Firefox (as a JSM file, after the build)\n\n* With NodeJS versions 0.8.X and higher\n\n## Installing with NPM (for use with NodeJS)\n\nSimply\n\n $ npm install source-map\n\nOr, if you'd like to hack on this library and have it installed via npm so you\ncan try out your changes:\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\n## Building from Source (for everywhere else)\n\nInstall Node and then run\n\n $ git clone https://fitzgen@github.com/mozilla/source-map.git\n $ cd source-map\n $ npm link .\n\nNext, run\n\n $ node Makefile.dryice.js\n\nThis should create the following files:\n\n* `dist/source-map.js` - The unminified browser version.\n\n* `dist/source-map.min.js` - The minified browser version.\n\n* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox\n source.\n\n## API\n\nGet a reference to the module:\n\n // NodeJS\n var sourceMap = require('source-map');\n\n // Browser builds\n var sourceMap = window.sourceMap;\n\n // Inside Firefox\n let sourceMap = {};\n Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap);\n\n### SourceMapConsumer\n\nA SourceMapConsumer instance represents a parsed source map which we can query\nfor information about the original file positions by giving it a file position\nin the generated source.\n\n#### new SourceMapConsumer(rawSourceMap)\n\nThe only parameter is the raw source map (either as a string which can be\n`JSON.parse`'d, or an object). According to the spec, source maps have the\nfollowing attributes:\n\n* `version`: Which version of the source map spec this map is following.\n\n* `sources`: An array of URLs to the original source files.\n\n* `names`: An array of identifiers which can be referrenced by individual\n mappings.\n\n* `sourceRoot`: Optional. The URL root from which all sources are relative.\n\n* `sourcesContent`: Optional. An array of contents of the original source files.\n\n* `mappings`: A string of base64 VLQs which contain the actual mappings.\n\n* `file`: The generated filename this source map is associated with.\n\n#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)\n\nReturns the original source, line, and column information for the generated\nsource's line and column positions provided. The only argument is an object with\nthe following properties:\n\n* `line`: The line number in the generated source.\n\n* `column`: The column number in the generated source.\n\nand an object is returned with the following properties:\n\n* `source`: The original source file, or null if this information is not\n available.\n\n* `line`: The line number in the original source, or null if this information is\n not available.\n\n* `column`: The column number in the original source, or null or null if this\n information is not available.\n\n* `name`: The original identifier, or null if this information is not available.\n\n#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)\n\nReturns the generated line and column information for the original source,\nline, and column positions provided. The only argument is an object with\nthe following properties:\n\n* `source`: The filename of the original source.\n\n* `line`: The line number in the original source.\n\n* `column`: The column number in the original source.\n\nand an object is returned with the following properties:\n\n* `line`: The line number in the generated source, or null.\n\n* `column`: The column number in the generated source, or null.\n\n#### SourceMapConsumer.prototype.sourceContentFor(source)\n\nReturns the original source content for the source provided. The only\nargument is the URL of the original source file.\n\n#### SourceMapConsumer.prototype.eachMapping(callback, context, order)\n\nIterate over each mapping between an original source/line/column and a\ngenerated line/column in this source map.\n\n* `callback`: The function that is called with each mapping.\n\n* `context`: Optional. If specified, this object will be the value of `this`\n every time that `callback` is called.\n\n* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or\n `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over\n the mappings sorted by the generated file's line/column order or the\n original's source/line/column order, respectively. Defaults to\n `SourceMapConsumer.GENERATED_ORDER`.\n\n### SourceMapGenerator\n\nAn instance of the SourceMapGenerator represents a source map which is being\nbuilt incrementally.\n\n#### new SourceMapGenerator(startOfSourceMap)\n\nTo create a new one, you must pass an object with the following properties:\n\n* `file`: The filename of the generated source that this source map is\n associated with.\n\n* `sourceRoot`: An optional root for all relative URLs in this source map.\n\n#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)\n\nCreates a new SourceMapGenerator based on a SourceMapConsumer\n\n* `sourceMapConsumer` The SourceMap.\n\n#### SourceMapGenerator.prototype.addMapping(mapping)\n\nAdd a single mapping from original source line and column to the generated\nsource's line and column for this source map being created. The mapping object\nshould have the following properties:\n\n* `generated`: An object with the generated line and column positions.\n\n* `original`: An object with the original line and column positions.\n\n* `source`: The original source file (relative to the sourceRoot).\n\n* `name`: An optional original token name for this mapping.\n\n#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for an original source file.\n\n* `sourceFile` the URL of the original source file.\n\n* `sourceContent` the content of the source file.\n\n#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile])\n\nApplies a SourceMap for a source file to the SourceMap.\nEach mapping to the supplied source file is rewritten using the\nsupplied SourceMap. Note: The resolution for the resulting mappings\nis the minimium of this map and the supplied map.\n\n* `sourceMapConsumer`: The SourceMap to be applied.\n\n* `sourceFile`: Optional. The filename of the source file.\n If omitted, sourceMapConsumer.file will be used.\n\n#### SourceMapGenerator.prototype.toString()\n\nRenders the source map being generated to a string.\n\n### SourceNode\n\nSourceNodes provide a way to abstract over interpolating and/or concatenating\nsnippets of generated JavaScript source code, while maintaining the line and\ncolumn information associated between those snippets and the original source\ncode. This is useful as the final intermediate representation a compiler might\nuse before outputting the generated JS and source map.\n\n#### new SourceNode(line, column, source[, chunk[, name]])\n\n* `line`: The original line number associated with this source node, or null if\n it isn't associated with an original line.\n\n* `column`: The original column number associated with this source node, or null\n if it isn't associated with an original column.\n\n* `source`: The original source's filename.\n\n* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see\n below.\n\n* `name`: Optional. The original identifier.\n\n#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer)\n\nCreates a SourceNode from generated code and a SourceMapConsumer.\n\n* `code`: The generated code\n\n* `sourceMapConsumer` The SourceMap for the generated code\n\n#### SourceNode.prototype.add(chunk)\n\nAdd a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.prepend(chunk)\n\nPrepend a chunk of generated JS to this source node.\n\n* `chunk`: A string snippet of generated JS code, another instance of\n `SourceNode`, or an array where each member is one of those things.\n\n#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)\n\nSet the source content for a source file. This will be added to the\n`SourceMap` in the `sourcesContent` field.\n\n* `sourceFile`: The filename of the source file\n\n* `sourceContent`: The content of the source file\n\n#### SourceNode.prototype.walk(fn)\n\nWalk over the tree of JS snippets in this node and its children. The walking\nfunction is called once for each snippet of JS and is passed that snippet and\nthe its original associated source's line/column location.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.walkSourceContents(fn)\n\nWalk over the tree of SourceNodes. The walking function is called for each\nsource file content and is passed the filename and source content.\n\n* `fn`: The traversal function.\n\n#### SourceNode.prototype.join(sep)\n\nLike `Array.prototype.join` except for SourceNodes. Inserts the separator\nbetween each of this source node's children.\n\n* `sep`: The separator.\n\n#### SourceNode.prototype.replaceRight(pattern, replacement)\n\nCall `String.prototype.replace` on the very right-most source snippet. Useful\nfor trimming whitespace from the end of a source node, etc.\n\n* `pattern`: The pattern to replace.\n\n* `replacement`: The thing to replace the pattern with.\n\n#### SourceNode.prototype.toString()\n\nReturn the string representation of this source node. Walks over the tree and\nconcatenates all the various snippets together to one string.\n\n### SourceNode.prototype.toStringWithSourceMap(startOfSourceMap)\n\nReturns the string representation of this tree of source nodes, plus a\nSourceMapGenerator which contains all the mappings between the generated and\noriginal sources.\n\nThe arguments are the same as those to `new SourceMapGenerator`.\n\n## Tests\n\n[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)\n\nInstall NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`.\n\nTo add new tests, create a new file named `test/test-.js`\nand export your test functions with names that start with \"test\", for example\n\n exports[\"test doing the foo bar\"] = function (assert, util) {\n ...\n };\n\nThe new test will be located automatically when you run the suite.\n\nThe `util` argument is the test utility module located at `test/source-map/util`.\n\nThe `assert` argument is a cut down version of node's assert module. You have\naccess to the following assertion functions:\n\n* `doesNotThrow`\n\n* `equal`\n\n* `ok`\n\n* `strictEqual`\n\n* `throws`\n\n(The reason for the restricted set of test functions is because we need the\ntests to run inside Firefox's test suite as well and so the assert module is\nshimmed in that environment. See `build/assert-shim.js`.)\n\n[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit\n[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap\n[Dryice]: https://github.com/mozilla/dryice\n", + "readmeFilename": "README.md", + "_id": "source-map@0.1.26", + "dist": { + "shasum": "05d6ef84432175ac2c20136dbbeb77d168a728f2" + }, + "_from": "source-map@~0.1.7", + "_resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.26.tgz" +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/run-tests.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/run-tests.js new file mode 100755 index 0000000..8bf2256 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/run-tests.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var failures = []; + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + process.stdout.write('.'); + } + catch (e) { + failures.push({ + name: tests[i].name + ': ' + k, + error: e + }); + process.stdout.write('E'); + } + } + } + } + + process.stdout.write('\n'); + console.log(passed + ' / ' + total + ' tests passed.'); + + failures.forEach(function (f) { + console.log('================================================================================'); + console.log(f.name); + console.log('--------------------------------------------------------------------------------'); + console.log(f.error.stack); + }); + + return failures.length; +} + +var code; + +process.stdout.on('close', function () { + process.exit(code); +}); + +function isTestFile(f) { + return /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')).filter(isTestFile).map(toModule); + +code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); +process.exit(code); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 0000000..3801233 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 0000000..b917314 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,71 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 0000000..653a874 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,24 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result; + for (var i = -255; i < 256; i++) { + result = base64VLQ.decode(base64VLQ.encode(i)); + assert.ok(result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 0000000..ff3a244 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 0000000..ee30683 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), null); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(binarySearch.search(needle, haystack, numberCompare), 18); + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 0000000..d831b92 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,72 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + + // Fuzzy + + // Original to generated + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + + // Generated to original + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 0000000..7c179f6 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,321 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an objects'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var sources = map.sources; + + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var mapping; + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + if (mapping.source) { + assert.equal(mapping.source.indexOf(util.testMap.sourceRoot), 0); + } + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 0000000..7f5eafd --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,391 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 0000000..522cc50 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,301 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }; + + exports['test .fromStringWithSourceMap()'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }; + + exports['test .fromStringWithSourceMap() empty map'] = function (assert, util) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode, + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }; + + exports['test .fromStringWithSourceMap() complex version'] = function (assert, util) { + var input = new SourceNode(null, null, null, [ + "(function() {\n", + " var Test = {};\n", + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };\n"), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), "\n", + "}());\n", + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }; + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js new file mode 100644 index 0000000..8a9c53e --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,160 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, "mappings mismatch"); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/package.json b/node_modules/jade/node_modules/with/node_modules/uglify-js/package.json new file mode 100644 index 0000000..5bf022d --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/package.json @@ -0,0 +1,40 @@ +{ + "name": "uglify-js", + "description": "JavaScript parser, mangler/compressor and beautifier toolkit", + "homepage": "http://lisperator.net/uglifyjs", + "main": "tools/node.js", + "version": "2.3.6", + "engines": { + "node": ">=0.4.0" + }, + "maintainers": [ + { + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com", + "url": "http://lisperator.net/" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/mishoo/UglifyJS2.git" + }, + "dependencies": { + "async": "~0.2.6", + "source-map": "~0.1.7", + "optimist": "~0.3.5" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "scripts": { + "test": "node test/run-tests.js" + }, + "readme": "UglifyJS 2\n==========\n[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2)\n\nUglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.\n\nThis page documents the command line utility. For\n[API and internals documentation see my website](http://lisperator.net/uglifyjs/).\nThere's also an\n[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,\nChrome and probably Safari).\n\nInstall\n-------\n\nFirst make sure you have installed the latest version of [node.js](http://nodejs.org/)\n(You may need to restart your computer after this step).\n\nFrom NPM for use as a command line app:\n\n npm install uglify-js -g\n\nFrom NPM for programmatic use:\n\n npm install uglify-js\n\nFrom Git:\n\n git clone git://github.com/mishoo/UglifyJS2.git\n cd UglifyJS2\n npm link .\n\nUsage\n-----\n\n uglifyjs [input files] [options]\n\nUglifyJS2 can take multiple input files. It's recommended that you pass the\ninput files first, then pass the options. UglifyJS will parse input files\nin sequence and apply any compression options. The files are parsed in the\nsame global scope, that is, a reference from a file to some\nvariable/function declared in another file will be matched properly.\n\nIf you want to read from STDIN instead, pass a single dash instead of input\nfiles.\n\nThe available options are:\n\n --source-map Specify an output file where to generate source map.\n [string]\n --source-map-root The path to the original source to be included in the\n source map. [string]\n --source-map-url The path to the source map to be added in //@\n sourceMappingURL. Defaults to the value passed with\n --source-map. [string]\n --in-source-map Input source map, useful if you're compressing JS that was\n generated from some other original code.\n --screw-ie8 Pass this flag if you don't care about full compliance with\n Internet Explorer 6-8 quirks (by default UglifyJS will try\n to be IE-proof).\n -p, --prefix Skip prefix for original filenames that appear in source\n maps. For example -p 3 will drop 3 directories from file\n names and ensure they are relative paths.\n -o, --output Output file (default STDOUT).\n -b, --beautify Beautify output/specify output options. [string]\n -m, --mangle Mangle names/pass mangler options. [string]\n -r, --reserved Reserved names to exclude from mangling.\n -c, --compress Enable compressor/pass compressor options. Pass options\n like -c hoist_vars=false,if_return=false. Use -c with no\n argument to use the default compression options. [string]\n -d, --define Global definitions [string]\n --comments Preserve copyright comments in the output. By default this\n works like Google Closure, keeping JSDoc-style comments\n that contain \"@license\" or \"@preserve\". You can optionally\n pass one of the following arguments to this flag:\n - \"all\" to keep all comments\n - a valid JS regexp (needs to start with a slash) to keep\n only comments that match.\n Note that currently not *all* comments can be kept when\n compression is on, because of dead code removal or\n cascading statements into sequences. [string]\n --stats Display operations run time on STDERR. [boolean]\n --acorn Use Acorn for parsing. [boolean]\n --spidermonkey Assume input files are SpiderMonkey AST format (as JSON).\n [boolean]\n --self Build itself (UglifyJS2) as a library (implies\n --wrap=UglifyJS --export-all) [boolean]\n --wrap Embed everything in a big function, making the “exports”\n and “global” variables available. You need to pass an\n argument to this option to specify the name that your\n module will take when included in, say, a browser.\n [string]\n --export-all Only used when --wrap, this tells UglifyJS to add code to\n automatically export all globals. [boolean]\n --lint Display some scope warnings [boolean]\n -v, --verbose Verbose [boolean]\n -V, --version Print version number and exit. [boolean]\n\nSpecify `--output` (`-o`) to declare the output file. Otherwise the output\ngoes to STDOUT.\n\n## Source map options\n\nUglifyJS2 can generate a source map file, which is highly useful for\ndebugging your compressed JavaScript. To get a source map, pass\n`--source-map output.js.map` (full path to the file where you want the\nsource map dumped).\n\nAdditionally you might need `--source-map-root` to pass the URL where the\noriginal files can be found. In case you are passing full paths to input\nfiles to UglifyJS, you can use `--prefix` (`-p`) to specify the number of\ndirectories to drop from the path prefix when declaring files in the source\nmap.\n\nFor example:\n\n uglifyjs /home/doe/work/foo/src/js/file1.js \\\n /home/doe/work/foo/src/js/file2.js \\\n -o foo.min.js \\\n --source-map foo.min.js.map \\\n --source-map-root http://foo.com/src \\\n -p 5 -c -m\n\nThe above will compress and mangle `file1.js` and `file2.js`, will drop the\noutput in `foo.min.js` and the source map in `foo.min.js.map`. The source\nmapping will refer to `http://foo.com/src/js/file1.js` and\n`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`\nas the source map root, and the original files as `js/file1.js` and\n`js/file2.js`).\n\n### Composed source map\n\nWhen you're compressing JS code that was output by a compiler such as\nCoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd\nlike to map back to the original code (i.e. CoffeeScript). UglifyJS has an\noption to take an input source map. Assuming you have a mapping from\nCoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →\ncompressed JS by mapping every token in the compiled JS to its original\nlocation.\n\nTo use this feature you need to pass `--in-source-map\n/path/to/input/source.map`. Normally the input source map should also point\nto the file containing the generated JS, so if that's correct you can omit\ninput files from the command line.\n\n## Mangler options\n\nTo enable the mangler you need to pass `--mangle` (`-m`). The following\n(comma-separated) options are supported:\n\n- `sort` — to assign shorter names to most frequently used variables. This\n saves a few hundred bytes on jQuery before gzip, but the output is\n _bigger_ after gzip (and seems to happen for other libraries I tried it\n on) therefore it's not enabled by default.\n\n- `toplevel` — mangle names declared in the toplevel scope (disabled by\n default).\n\n- `eval` — mangle names visible in scopes where `eval` or `when` are used\n (disabled by default).\n\nWhen mangling is enabled but you want to prevent certain names from being\nmangled, you can declare those names with `--reserved` (`-r`) — pass a\ncomma-separated list of names. For example:\n\n uglifyjs ... -m -r '$,require,exports'\n\nto prevent the `require`, `exports` and `$` names from being changed.\n\n## Compressor options\n\nYou need to pass `--compress` (`-c`) to enable the compressor. Optionally\nyou can pass a comma-separated list of options. Options are in the form\n`foo=bar`, or just `foo` (the latter implies a boolean option that you want\nto set `true`; it's effectively a shortcut for `foo=true`).\n\n- `sequences` -- join consecutive simple statements using the comma operator\n- `properties` -- rewrite property access using the dot notation, for\n example `foo[\"bar\"] → foo.bar`\n- `dead_code` -- remove unreachable code\n- `drop_debugger` -- remove `debugger;` statements\n- `unsafe` (default: false) -- apply \"unsafe\" transformations (discussion below)\n- `conditionals` -- apply optimizations for `if`-s and conditional\n expressions\n- `comparisons` -- apply certain optimizations to binary nodes, for example:\n `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,\n e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.\n- `evaluate` -- attempt to evaluate constant expressions\n- `booleans` -- various optimizations for boolean context, for example `!!a\n ? b : c → a ? b : c`\n- `loops` -- optimizations for `do`, `while` and `for` loops when we can\n statically determine the condition\n- `unused` -- drop unreferenced functions and variables\n- `hoist_funs` -- hoist function declarations\n- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`\n by default because it seems to increase the size of the output in general)\n- `if_return` -- optimizations for if/return and if/continue\n- `join_vars` -- join consecutive `var` statements\n- `cascade` -- small optimization for sequences, transform `x, x` into `x`\n and `x = something(), x` into `x = something()`\n- `warnings` -- display warnings when dropping unreachable code or unused\n declarations etc.\n\n### The `unsafe` option\n\nIt enables some transformations that *might* break code logic in certain\ncontrived cases, but should be fine for most code. You might want to try it\non your own code, it should reduce the minified size. Here's what happens\nwhen this flag is on:\n\n- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]`\n- `new Object()` → `{}`\n- `String(exp)` or `exp.toString()` → `\"\" + exp`\n- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`\n- `typeof foo == \"undefined\"` → `foo === void 0`\n- `void 0` → `\"undefined\"` (if there is a variable named \"undefined\" in\n scope; we do it because the variable name will be mangled, typically\n reduced to a single character).\n\n### Conditional compilation\n\nYou can use the `--define` (`-d`) switch in order to declare global\nvariables that UglifyJS will assume to be constants (unless defined in\nscope). For example if you pass `--define DEBUG=false` then, coupled with\ndead code removal UglifyJS will discard the following from the output:\n```javascript\nif (DEBUG) {\n\tconsole.log(\"debug stuff\");\n}\n```\n\nUglifyJS will warn about the condition being always false and about dropping\nunreachable code; for now there is no option to turn off only this specific\nwarning, you can pass `warnings=false` to turn off *all* warnings.\n\nAnother way of doing that is to declare your globals as constants in a\nseparate file and include it into the build. For example you can have a\n`build/defines.js` file with the following:\n```javascript\nconst DEBUG = false;\nconst PRODUCTION = true;\n// etc.\n```\n\nand build your code like this:\n\n uglifyjs build/defines.js js/foo.js js/bar.js... -c\n\nUglifyJS will notice the constants and, since they cannot be altered, it\nwill evaluate references to them to the value itself and drop unreachable\ncode as usual. The possible downside of this approach is that the build\nwill contain the `const` declarations.\n\n\n## Beautifier options\n\nThe code generator tries to output shortest code possible by default. In\ncase you want beautified output, pass `--beautify` (`-b`). Optionally you\ncan pass additional arguments that control the code output:\n\n- `beautify` (default `true`) -- whether to actually beautify the output.\n Passing `-b` will set this to true, but you might need to pass `-b` even\n when you want to generate minified code, in order to specify additional\n arguments, so you can use `-b beautify=false` to override it.\n- `indent-level` (default 4)\n- `indent-start` (default 0) -- prefix all lines by that many spaces\n- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal\n objects\n- `space-colon` (default `true`) -- insert a space after the colon signs\n- `ascii-only` (default `false`) -- escape Unicode characters in strings and\n regexps\n- `inline-script` (default `false`) -- escape the slash in occurrences of\n `= (x = f(…)) + * + * For example, let the equation be: + * (a = parseInt('100')) <= a + * + * If a was an integer and has the value of 99, + * (a = parseInt('100')) <= a → 100 <= 100 → true + * + * When transformed incorrectly: + * a >= (a = parseInt('100')) → 99 >= 100 → false + */ + +tranformation_sort_order_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) == a } + expect: { (a = parseInt('100')) == a } +} + +tranformation_sort_order_unequal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) != a } + expect: { (a = parseInt('100')) != a } +} + +tranformation_sort_order_lesser_or_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) <= a } + expect: { (a = parseInt('100')) <= a } +} +tranformation_sort_order_greater_or_equal: { + options = { + comparisons: true, + }; + + input: { (a = parseInt('100')) >= a } + expect: { (a = parseInt('100')) >= a } +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-22.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-22.js new file mode 100644 index 0000000..a8b7bc6 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-22.js @@ -0,0 +1,17 @@ +return_with_no_value_in_if_body: { + options = { conditionals: true }; + input: { + function foo(bar) { + if (bar) { + return; + } else { + return 1; + } + } + } + expect: { + function foo (bar) { + return bar ? void 0 : 1; + } + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-44.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-44.js new file mode 100644 index 0000000..7a972f9 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-44.js @@ -0,0 +1,31 @@ +issue_44_valid_ast_1: { + options = { unused: true }; + input: { + function a(b) { + for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + var i = 0; + for (b.qoo(); ; i++); + } + } +} + +issue_44_valid_ast_2: { + options = { unused: true }; + input: { + function a(b) { + if (foo) for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + if (foo) { + var i = 0; + for (b.qoo(); ; i++); + } + } + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-59.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-59.js new file mode 100644 index 0000000..82b3880 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/issue-59.js @@ -0,0 +1,30 @@ +keep_continue: { + options = { + dead_code: true, + evaluate: true + }; + input: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } + expect: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/labels.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/labels.js new file mode 100644 index 0000000..044b7a7 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/labels.js @@ -0,0 +1,163 @@ +labels_1: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) break out; + console.log("bar"); + } + }; + expect: { + foo || console.log("bar"); + } +} + +labels_2: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) print("stuff"); + else break out; + console.log("here"); + } + }; + expect: { + if (foo) { + print("stuff"); + console.log("here"); + } + } +} + +labels_3: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + for (var i = 0; i < 5; ++i) { + if (i < 3) continue; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_4: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: for (var i = 0; i < 5; ++i) { + if (i < 3) continue out; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_5: { + options = { if_return: true, conditionals: true, dead_code: true }; + // should keep the break-s in the following + input: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + }; + expect: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + } +} + +labels_6: { + input: { + out: break out; + }; + expect: {} +} + +labels_7: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + continue; + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_8: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + break; + } + }; + expect: { + while (foo) { + x(); + y(); + break; + } + } +} + +labels_9: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + continue out; + z(); + k(); + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_10: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + break out; + z(); + k(); + } + }; + expect: { + out: while (foo) { + x(); + y(); + break out; + } + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/loops.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/loops.js new file mode 100644 index 0000000..cdf1f04 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/loops.js @@ -0,0 +1,123 @@ +while_becomes_for: { + options = { loops: true }; + input: { + while (foo()) bar(); + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_break_1: { + options = { loops: true }; + input: { + for (;;) + if (foo()) break; + } + expect: { + for (; !foo();); + } +} + +drop_if_break_2: { + options = { loops: true }; + input: { + for (;bar();) + if (foo()) break; + } + expect: { + for (; bar() && !foo();); + } +} + +drop_if_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && !foo();) { + stuff1(); + stuff2(); + } + } +} + +drop_if_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), !foo());) z(), k(); + } +} + +drop_if_else_break_1: { + options = { loops: true }; + input: { + for (;;) if (foo()) bar(); else break; + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_else_break_2: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + } + } + expect: { + for (; bar() && foo();) baz(); + } +} + +drop_if_else_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && foo();) { + baz(); + stuff1(); + stuff2(); + } + } +} + +drop_if_else_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) baz(); + else break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), foo());) baz(), z(), k(); + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/properties.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/properties.js new file mode 100644 index 0000000..8504596 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/properties.js @@ -0,0 +1,54 @@ +keep_properties: { + options = { + properties: false + }; + input: { + a["foo"] = "bar"; + } + expect: { + a["foo"] = "bar"; + } +} + +dot_properties: { + options = { + properties: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a["\u0EB3"] = "unicode"; + a[""] = "whitespace"; + a["1_1"] = "foo"; + } + expect: { + a.foo = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a.\u0EB3 = "unicode"; + a[""] = "whitespace"; + a["1_1"] = "foo"; + } +} + +dot_properties_es5: { + options = { + properties: true, + screw_ie8: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + a["*"] = "asterisk"; + a["\u0EB3"] = "unicode"; + a[""] = "whitespace"; + } + expect: { + a.foo = "bar"; + a.if = "if"; + a["*"] = "asterisk"; + a.\u0EB3 = "unicode"; + a[""] = "whitespace"; + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/sequences.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/sequences.js new file mode 100644 index 0000000..6f63ace --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/sequences.js @@ -0,0 +1,161 @@ +make_sequences_1: { + options = { + sequences: true + }; + input: { + foo(); + bar(); + baz(); + } + expect: { + foo(),bar(),baz(); + } +} + +make_sequences_2: { + options = { + sequences: true + }; + input: { + if (boo) { + foo(); + bar(); + baz(); + } else { + x(); + y(); + z(); + } + } + expect: { + if (boo) foo(),bar(),baz(); + else x(),y(),z(); + } +} + +make_sequences_3: { + options = { + sequences: true + }; + input: { + function f() { + foo(); + bar(); + return baz(); + } + function g() { + foo(); + bar(); + throw new Error(); + } + } + expect: { + function f() { + return foo(), bar(), baz(); + } + function g() { + throw foo(), bar(), new Error(); + } + } +} + +make_sequences_4: { + options = { + sequences: true + }; + input: { + x = 5; + if (y) z(); + + x = 5; + for (i = 0; i < 5; i++) console.log(i); + + x = 5; + for (; i < 5; i++) console.log(i); + + x = 5; + switch (y) {} + + x = 5; + with (obj) {} + } + expect: { + if (x = 5, y) z(); + for (x = 5, i = 0; i < 5; i++) console.log(i); + for (x = 5; i < 5; i++) console.log(i); + switch (x = 5, y) {} + with (x = 5, obj); + } +} + +lift_sequences_1: { + options = { sequences: true }; + input: { + foo = !(x(), y(), bar()); + } + expect: { + x(), y(), foo = !bar(); + } +} + +lift_sequences_2: { + options = { sequences: true, evaluate: true }; + input: { + q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5); + } + expect: { + foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36 + } +} + +lift_sequences_3: { + options = { sequences: true, conditionals: true }; + input: { + x = (foo(), bar(), baz()) ? 10 : 20; + } + expect: { + foo(), bar(), x = baz() ? 10 : 20; + } +} + +lift_sequences_4: { + options = { side_effects: true }; + input: { + x = (foo, bar, baz); + } + expect: { + x = baz; + } +} + +for_sequences: { + options = { sequences: true }; + input: { + // 1 + foo(); + bar(); + for (; false;); + // 2 + foo(); + bar(); + for (x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } + expect: { + // 1 + for (foo(), bar(); false;); + // 2 + for (foo(), bar(), x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/switch.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/switch.js new file mode 100644 index 0000000..62e39cf --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/switch.js @@ -0,0 +1,260 @@ +constant_switch_1: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1+1) { + case 1: foo(); break; + case 1+1: bar(); break; + case 1+1+1: baz(); break; + } + } + expect: { + bar(); + } +} + +constant_switch_2: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + } + } + expect: { + foo(); + bar(); + } +} + +constant_switch_3: { + options = { dead_code: true, evaluate: true }; + input: { + switch (10) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + default: + def(); + } + } + expect: { + def(); + } +} + +constant_switch_4: { + options = { dead_code: true, evaluate: true }; + input: { + switch (2) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + bar(); + def(); + } +} + +constant_switch_5: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + // the break inside the if ruins our job + // we can still get rid of irrelevant cases. + switch (1) { + case 1: + x(); + if (foo) break; + y(); + } + // XXX: we could optimize this better by inventing an outer + // labeled block, but that's kinda tricky. + } +} + +constant_switch_6: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + y(); + bar(); + } + } +} + +constant_switch_7: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; // this break refers to the for, not to the switch; thus it + // shouldn't ruin our optimization + console.log(x); + } + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; + console.log(x); + } + y(); + bar(); + } + } +} + +constant_switch_8: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) break OUT; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) break OUT; + y(); + } + } +} + +constant_switch_9: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) if (foo) break OUT; + y(); + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) if (foo) break OUT; + y(); + bar(); + def(); + } + } +} + +drop_default_1: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +drop_default_2: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); break; + default: + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +keep_default: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + something(); + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + default: + something(); + } + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/typeof.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/typeof.js new file mode 100644 index 0000000..cefdd43 --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/compress/typeof.js @@ -0,0 +1,25 @@ +typeof_evaluation: { + options = { + evaluate: true + }; + input: { + a = typeof 1; + b = typeof 'test'; + c = typeof []; + d = typeof {}; + e = typeof /./; + f = typeof false; + g = typeof function(){}; + h = typeof undefined; + } + expect: { + a='number'; + b='string'; + c=typeof[]; + d=typeof{}; + e=typeof/./; + f='boolean'; + g='function'; + h='undefined'; + } +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/test/run-tests.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/run-tests.js new file mode 100755 index 0000000..0568c6a --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/test/run-tests.js @@ -0,0 +1,170 @@ +#! /usr/bin/env node + +var U = require("../tools/node"); +var path = require("path"); +var fs = require("fs"); +var assert = require("assert"); +var sys = require("util"); + +var tests_dir = path.dirname(module.filename); + +run_compress_tests(); + +/* -----[ utils ]----- */ + +function tmpl() { + return U.string_template.apply(this, arguments); +} + +function log() { + var txt = tmpl.apply(this, arguments); + sys.puts(txt); +} + +function log_directory(dir) { + log("*** Entering [{dir}]", { dir: dir }); +} + +function log_start_file(file) { + log("--- {file}", { file: file }); +} + +function log_test(name) { + log(" Running test [{name}]", { name: name }); +} + +function find_test_files(dir) { + var files = fs.readdirSync(dir).filter(function(name){ + return /\.js$/i.test(name); + }); + if (process.argv.length > 2) { + var x = process.argv.slice(2); + files = files.filter(function(f){ + return x.indexOf(f) >= 0; + }); + } + return files; +} + +function test_directory(dir) { + return path.resolve(tests_dir, dir); +} + +function as_toplevel(input) { + if (input instanceof U.AST_BlockStatement) input = input.body; + else if (input instanceof U.AST_Statement) input = [ input ]; + else throw new Error("Unsupported input syntax"); + var toplevel = new U.AST_Toplevel({ body: input }); + toplevel.figure_out_scope(); + return toplevel; +} + +function run_compress_tests() { + var dir = test_directory("compress"); + log_directory("compress"); + var files = find_test_files(dir); + function test_file(file) { + log_start_file(file); + function test_case(test) { + log_test(test.name); + var options = U.defaults(test.options, { + warnings: false + }); + var cmp = new U.Compressor(options, true); + var expect = make_code(as_toplevel(test.expect), false); + var input = as_toplevel(test.input); + var input_code = make_code(test.input); + var output = input.transform(cmp); + output.figure_out_scope(); + output = make_code(output, false); + if (expect != output) { + log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { + input: input_code, + output: output, + expected: expect + }); + } + } + var tests = parse_test(path.resolve(dir, file)); + for (var i in tests) if (tests.hasOwnProperty(i)) { + test_case(tests[i]); + } + } + files.forEach(function(file){ + test_file(file); + }); +} + +function parse_test(file) { + var script = fs.readFileSync(file, "utf8"); + var ast = U.parse(script, { + filename: file + }); + var tests = {}; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_LabeledStatement + && tw.parent() instanceof U.AST_Toplevel) { + var name = node.label.name; + tests[name] = get_one_test(name, node.body); + return true; + } + if (!(node instanceof U.AST_Toplevel)) croak(node); + }); + ast.walk(tw); + return tests; + + function croak(node) { + throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { + file: file, + line: node.start.line, + col: node.start.col, + code: make_code(node, false) + })); + } + + function get_one_test(name, block) { + var test = { name: name, options: {} }; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_Assign) { + if (!(node.left instanceof U.AST_SymbolRef)) { + croak(node); + } + var name = node.left.name; + test[name] = evaluate(node.right); + return true; + } + if (node instanceof U.AST_LabeledStatement) { + assert.ok( + node.label.name == "input" || node.label.name == "expect", + tmpl("Unsupported label {name} [{line},{col}]", { + name: node.label.name, + line: node.label.start.line, + col: node.label.start.col + }) + ); + var stat = node.body; + if (stat instanceof U.AST_BlockStatement) { + if (stat.body.length == 1) stat = stat.body[0]; + else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); + } + test[node.label.name] = stat; + return true; + } + }); + block.walk(tw); + return test; + }; +} + +function make_code(ast, beautify) { + if (arguments.length == 1) beautify = true; + var stream = U.OutputStream({ beautify: beautify }); + ast.print(stream); + return stream.get(); +} + +function evaluate(code) { + if (code instanceof U.AST_Node) + code = make_code(code); + return new Function("return(" + code + ")")(); +} diff --git a/node_modules/jade/node_modules/with/node_modules/uglify-js/tools/node.js b/node_modules/jade/node_modules/with/node_modules/uglify-js/tools/node.js new file mode 100644 index 0000000..c0dd3db --- /dev/null +++ b/node_modules/jade/node_modules/with/node_modules/uglify-js/tools/node.js @@ -0,0 +1,165 @@ +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var sys = require("util"); + +var UglifyJS = vm.createContext({ + sys : sys, + console : console, + MOZ_SourceMap : require("source-map") +}); + +function load_global(file) { + file = path.resolve(path.dirname(module.filename), file); + try { + var code = fs.readFileSync(file, "utf8"); + return vm.runInContext(code, UglifyJS, file); + } catch(ex) { + // XXX: in case of a syntax error, the message is kinda + // useless. (no location information). + sys.debug("ERROR in file: " + file + " / " + ex); + process.exit(1); + } +}; + +var FILES = exports.FILES = [ + "../lib/utils.js", + "../lib/ast.js", + "../lib/parse.js", + "../lib/transform.js", + "../lib/scope.js", + "../lib/output.js", + "../lib/compress.js", + "../lib/sourcemap.js", + "../lib/mozilla-ast.js" +].map(function(file){ + return path.join(path.dirname(fs.realpathSync(__filename)), file); +}); + +FILES.forEach(load_global); + +UglifyJS.AST_Node.warn_function = function(txt) { + sys.error("WARN: " + txt); +}; + +// XXX: perhaps we shouldn't export everything but heck, I'm lazy. +for (var i in UglifyJS) { + if (UglifyJS.hasOwnProperty(i)) { + exports[i] = UglifyJS[i]; + } +} + +exports.minify = function(files, options) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : fs.readFileSync(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? "?" : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var inMap = options.inSourceMap; + var output = {}; + if (typeof options.inSourceMap == "string") { + inMap = fs.readFileSync(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) { + output.source_map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + } + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : output.source_map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; diff --git a/node_modules/jade/node_modules/with/package.json b/node_modules/jade/node_modules/with/package.json new file mode 100644 index 0000000..c451755 --- /dev/null +++ b/node_modules/jade/node_modules/with/package.json @@ -0,0 +1,31 @@ +{ + "name": "with", + "version": "1.1.0", + "description": "Compile time `with` for strict mode JavaScript", + "main": "index.js", + "scripts": { + "test": "mocha -R spec" + }, + "repository": { + "type": "git", + "url": "https://github.com/ForbesLindesay/with.git" + }, + "author": { + "name": "ForbesLindesay" + }, + "license": "MIT", + "dependencies": { + "uglify-js": "2.3.6" + }, + "devDependencies": { + "mocha": "~1.9.0" + }, + "readme": "# with\r\n\r\nCompile time `with` for strict mode JavaScript\r\n\r\n[![build status](https://secure.travis-ci.org/ForbesLindesay/with.png)](http://travis-ci.org/ForbesLindesay/with)\r\n[![Dependency Status](https://gemnasium.com/ForbesLindesay/with.png)](https://gemnasium.com/ForbesLindesay/with)\r\n[![NPM version](https://badge.fury.io/js/with.png)](http://badge.fury.io/js/with)\r\n\r\n## Installation\r\n\r\n $ npm install with\r\n\r\n## Usage\r\n\r\n```js\r\nvar addWith = require('with')\r\n\r\naddWith('obj', 'console.log(a)')\r\n// => \"var a = obj.a;console.log(a)\"\r\n\r\naddWith(\"obj || {}\", \"console.log(helper(a))\", [\"helper\"])\r\n// => var locals = (obj || {}),a = locals.a;console.log(helper(a))\r\n```\r\n\r\n## API\r\n\r\n### addWith(obj, src, [exclude])\r\n\r\nThe idea is that this is roughly equivallent to:\r\n\r\n```js\r\nwith (obj) {\r\n src\r\n}\r\n```\r\n\r\nThere are a few differences though. For starters, it will be assumed that all variables used in `src` come from `obj` so any that don't (e.g. template helpers) need to have their names parsed to `exclude` as an array.\r\n\r\nIt also makes everything be declared, so you can always do:\r\n\r\n```js\r\nif (foo === undefined)\r\n```\r\n\r\ninstead of\r\n\r\n```js\r\nif (typeof foo === 'undefined')\r\n```\r\n\r\nIt is also safe to use in strict mode (unlike `with`) and it minifies properly (`with` disables virtually all minification).\r\n\r\n## License\r\n\r\n MIT", + "readmeFilename": "README.md", + "_id": "with@1.1.0", + "dist": { + "shasum": "4b211d6fb9fb7409fce5d03f07ef53b2f3dcc4c1" + }, + "_from": "with@~1.1.0", + "_resolved": "https://registry.npmjs.org/with/-/with-1.1.0.tgz" +} diff --git a/node_modules/jade/node_modules/with/test/index.js b/node_modules/jade/node_modules/with/test/index.js new file mode 100644 index 0000000..f3244e1 --- /dev/null +++ b/node_modules/jade/node_modules/with/test/index.js @@ -0,0 +1,107 @@ +var assert = require('assert') + +var addWith = require('../') + +var sentinel = {} +var sentinel2 = {} +describe('addWith("obj", "console.log(a)")', function () { + it('adds the necessary variable declarations', function (done) { + var src = addWith('obj', 'console.log(a)') + // var a = obj.a;console.log(a) + Function('console,obj', src)( + { + log: function (a) { + assert(a === sentinel) + done() + } + }, + {a: sentinel}) + }) +}) +describe('addWith("obj || {}", "console.log(a)")', function () { + it('adds the necessary variable declarations', function (done) { + var src = addWith('obj || {}', 'console.log(a)') + // var locals = (obj || {}),a = locals.a;console.log(a) + var expected = 2 + Function('console,obj', src)( + { + log: function (a) { + assert(a === sentinel) + if (0 === --expected) done() + } + }, + {a: sentinel}) + Function('console,obj', src)( + { + log: function (a) { + assert(a === undefined) + if (0 === --expected) done() + } + }) + }) +}) +describe('addWith("obj", "console.log(helper(a))", ["helper"])', function () { + it('adds the necessary variable declarations', function (done) { + var src = addWith('obj', 'console.log(helper(a))', ['helper']) + // var a = obj.a;console.log(helper(a)) + Function('console,obj,helper', src)( + { + log: function (a) { + assert(a === sentinel) + done() + } + }, + {a: sentinel2}, + function (a) { + assert(a === sentinel2) + return sentinel + }) + }) +}) +describe('addWith("obj || {}", "console.log(locals(a))", ["locals_"])', function () { + it('adds the necessary variable declarations', function (done) { + var src = addWith('obj || {}', 'console.log(locals(a))', ['locals_']) + // var locals__ = (obj || {}),locals = locals__.locals,a = locals__.a;console.log(locals(a)) + Function('console,obj', src)( + { + log: function (a) { + assert(a === sentinel) + done() + } + }, + { + a: sentinel2, + locals: function (a) { + assert(a === sentinel2) + return sentinel + } + }) + }) +}) + +describe('addWith("obj || {}", "console.log(\'foo\')")', function () { + it('passes through', function (done) { + var src = addWith('obj || {}', 'console.log("foo")') + // console.log(\'foo\') + Function('console,obj', src)( + { + log: function (a) { + assert(a === 'foo') + done() + } + }) + }) +}) + +describe('addWith("obj || {}", "obj.foo")', function () { + it('passes through', function (done) { + var src = addWith('obj || {}', 'obj.bar = obj.foo') + // obj.bar = obj.foo + var obj = { + foo: 'ding' + } + Function('obj', src)(obj) + assert(obj.bar === 'ding') + done() + }) +}) \ No newline at end of file diff --git a/node_modules/jade/package.json b/node_modules/jade/package.json new file mode 100644 index 0000000..bec9e55 --- /dev/null +++ b/node_modules/jade/package.json @@ -0,0 +1,65 @@ +{ + "name": "jade", + "description": "Jade template engine", + "version": "0.33.0", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/jade" + }, + "main": "./index.js", + "bin": { + "jade": "./bin/jade" + }, + "man": [ + "./jade.1" + ], + "dependencies": { + "commander": "1.2.0", + "mkdirp": "0.3.x", + "transformers": "2.0.1", + "character-parser": "1.0.2", + "monocle": "0.1.48", + "with": "~1.1.0", + "constantinople": "~1.0.1" + }, + "devDependencies": { + "coffee-script": "*", + "mocha": "*", + "markdown": "*", + "stylus": "*", + "uubench": "*", + "should": "*", + "less": "*", + "uglify-js": "*", + "browserify": "*", + "linify": "*" + }, + "component": { + "scripts": { + "jade": "runtime.js" + } + }, + "scripts": { + "test": "mocha -R spec", + "prepublish": "npm prune && linify transform bin && npm run build", + "build": "npm run compile", + "compile": "npm run compile-full && npm run compile-runtime", + "compile-full": "browserify ./lib/jade.js --standalone jade -x ./node_modules/transformers > jade.js", + "compile-runtime": "browserify ./lib/runtime.js --standalone jade > runtime.js" + }, + "browser": { + "./lib/filters.js": "./lib/filters-client.js" + }, + "readme": "# Jade - template engine \r\n[![Build Status](https://travis-ci.org/visionmedia/jade.png?branch=master)](https://travis-ci.org/visionmedia/jade)\r\n[![Dependency Status](https://gemnasium.com/visionmedia/jade.png)](https://gemnasium.com/visionmedia/jade)\r\n[![NPM version](https://badge.fury.io/js/jade.png)](http://badge.fury.io/js/jade)\r\n\r\n Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com)\r\n and implemented with JavaScript for [node](http://nodejs.org). For discussion join the [Google Group](http://groups.google.com/group/jadejs).\r\n\r\n## Announcement\r\n\r\nJade version 0.31.0 deprecated implicit text only support for scripts and styles. To fix this all you need to do is add a `.` character after the script or style tag.\r\n\r\nIt is hoped that this change will make Jade easier for newcomers to learn without affecting the power of the language or leading to excessive verboseness.\r\n\r\nIf you have a lot of Jade files that need fixing you can use [fix-jade](https://github.com/ForbesLindesay/fix-jade) to attempt to automate the process.\r\n\r\n## Test drive\r\n\r\n You can test drive Jade online [here](http://naltatis.github.com/jade-syntax-docs).\r\n\r\n## README Contents\r\n\r\n- [Features](#a1)\r\n- [Implementations](#a2)\r\n- [Installation](#a3)\r\n- [Browser Support](#a4)\r\n- [Public API](#a5)\r\n- [Syntax](#a6)\r\n - [Line Endings](#a6-1)\r\n - [Tags](#a6-2)\r\n - [Tag Text](#a6-3)\r\n - [Comments](#a6-4)\r\n - [Block Comments](#a6-5)\r\n - [Nesting](#a6-6)\r\n - [Block Expansion](#a6-7)\r\n - [Case](#a6-8)\r\n - [Attributes](#a6-9)\r\n - [HTML](#a6-10)\r\n - [Doctypes](#a6-11)\r\n- [Filters](#a7)\r\n- [Code](#a8)\r\n- [Iteration](#a9)\r\n- [Conditionals](#a10)\r\n- [Template inheritance](#a11)\r\n- [Block append / prepend](#a12)\r\n- [Includes](#a13)\r\n- [Mixins](#a14)\r\n- [Generated Output](#a15)\r\n- [Example Makefile](#a16)\r\n- [jade(1)](#a17)\r\n- [Tutorials](#a18)\r\n- [License](#a19)\r\n\r\n\r\n## Features\r\n\r\n - client-side support\r\n - great readability\r\n - flexible indentation\r\n - block-expansion\r\n - mixins\r\n - static includes\r\n - attribute interpolation\r\n - code is escaped by default for security\r\n - contextual error reporting at compile & run time\r\n - executable for compiling jade templates via the command line\r\n - html 5 mode (the default doctype)\r\n - optional memory caching\r\n - combine dynamic and static tag classes\r\n - parse tree manipulation via _filters_\r\n - template inheritance\r\n - block append / prepend\r\n - supports [Express JS](http://expressjs.com) out of the box\r\n - transparent iteration over objects, arrays, and even non-enumerables via `each`\r\n - block comments\r\n - no tag prefix\r\n - filters\r\n - :stylus must have [stylus](http://github.com/LearnBoost/stylus) installed\r\n - :less must have [less.js](http://github.com/cloudhead/less.js) installed\r\n - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js), [node-discount](http://github.com/visionmedia/node-discount), or [marked](http://github.com/chjj/marked) installed\r\n - :cdata\r\n - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed\r\n - [Emacs Mode](https://github.com/brianc/jade-mode)\r\n - [Vim Syntax](https://github.com/digitaltoad/vim-jade)\r\n - [TextMate Bundle](http://github.com/miksago/jade-tmbundle)\r\n - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode)\r\n - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs)\r\n - [html2jade](https://github.com/donpark/html2jade) converter\r\n\r\n\r\n## Implementations\r\n\r\n - [php](http://github.com/everzet/jade.php)\r\n - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html)\r\n - [ruby](https://github.com/slim-template/slim)\r\n - [python](https://github.com/SyrusAkbary/pyjade)\r\n - [java](https://github.com/neuland/jade4j)\r\n\r\n\r\n## Installation\r\n\r\nvia npm:\r\n\r\n```bash\r\n$ npm install jade\r\n```\r\n\r\n\r\n## Browser Support\r\n\r\n To compile jade to a single file compatible for client-side use simply execute:\r\n\r\n```bash\r\n$ make jade.js\r\n```\r\n\r\n Alternatively, if uglifyjs is installed via npm (`npm install uglify-js`) you may execute the following which will create both files. However each release builds these for you.\r\n\r\n```bash\r\n$ make jade.min.js\r\n```\r\n\r\n By default Jade instruments templates with line number statements such as `__.lineno = 3` for debugging purposes. When used in a browser it's useful to minimize this boiler plate, you can do so by passing the option `{ compileDebug: false }`. The following template\r\n\r\n```jade\r\np Hello #{name}\r\n```\r\n\r\n Can then be as small as the following generated function:\r\n\r\n```js\r\nfunction anonymous(locals, attrs, escape, rethrow) {\r\n var buf = [];\r\n with (locals || {}) {\r\n var interp;\r\n buf.push('\\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\\n

    ');\r\n }\r\n return buf.join(\"\");\r\n}\r\n```\r\n\r\n Through the use of Jade's `./runtime.js` you may utilize these pre-compiled templates on the client-side _without_ Jade itself, all you need is the associated utility functions (in runtime.js), which are then available as `jade.attrs`, `jade.escape` etc. To enable this you should pass `{ client: true }` to `jade.compile()` to tell Jade to reference the helper functions\r\n via `jade.attrs`, `jade.escape` etc.\r\n\r\n```js\r\nfunction anonymous(locals, attrs, escape, rethrow) {\r\n var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;\r\n var buf = [];\r\n with (locals || {}) {\r\n var interp;\r\n buf.push('\\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\\n

    ');\r\n }\r\n return buf.join(\"\");\r\n}\r\n```\r\n\r\n
    \r\n## Public API\r\n\r\n```js\r\nvar jade = require('jade');\r\n\r\n// Compile a function\r\nvar fn = jade.compile('string of jade', options);\r\nfn(locals);\r\n```\r\n\r\n### Options\r\n\r\n - `self` Use a `self` namespace to hold the locals _(false by default)_\r\n - `locals` Local variable object\r\n - `filename` Used in exceptions, and required when using includes\r\n - `debug` Outputs tokens and function body generated\r\n - `compiler` Compiler to replace jade's default\r\n - `compileDebug` When `false` no debug instrumentation is compiled\r\n - `pretty` Add pretty-indentation whitespace to output _(false by default)_\r\n\r\n\r\n## Syntax\r\n\r\n\r\n### Line Endings\r\n\r\n**CRLF** and **CR** are converted to **LF** before parsing.\r\n\r\n\r\n### Tags\r\n\r\nA tag is simply a leading word:\r\n\r\n```jade\r\nhtml\r\n```\r\n\r\nfor example is converted to ``\r\n\r\ntags can also have ids:\r\n\r\n```jade\r\ndiv#container\r\n```\r\n\r\nwhich would render `
    `\r\n\r\nhow about some classes?\r\n\r\n```jade\r\ndiv.user-details\r\n```\r\n\r\nrenders `
    `\r\n\r\nmultiple classes? _and_ an id? sure:\r\n\r\n```jade\r\ndiv#foo.bar.baz\r\n```\r\n\r\nrenders `
    `\r\n\r\ndiv div div sure is annoying, how about:\r\n\r\n```jade\r\n#foo\r\n.bar\r\n```\r\n\r\nwhich is syntactic sugar for what we have already been doing, and outputs:\r\n\r\n```html\r\n
    \r\n```\r\n\r\n
    \r\n### Tag Text\r\n\r\nSimply place some content after the tag:\r\n\r\n```jade\r\np wahoo!\r\n```\r\n\r\nrenders `

    wahoo!

    `.\r\n\r\nwell cool, but how about large bodies of text:\r\n\r\n```jade\r\np\r\n | foo bar baz\r\n | rawr rawr\r\n | super cool\r\n | go jade go\r\n```\r\n\r\nrenders `

    foo bar baz rawr.....

    `\r\n\r\ninterpolation? yup! both types of text can utilize interpolation,\r\nif we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following:\r\n\r\n```jade\r\n#user #{name} <#{email}>\r\n```\r\n\r\noutputs `
    tj <tj@vision-media.ca>
    `\r\n\r\nActually want `#{}` for some reason? escape it!\r\n\r\n```jade\r\np \\#{something}\r\n```\r\n\r\nnow we have `

    #{something}

    `\r\n\r\nWe can also utilize the unescaped variant `!{html}`, so the following\r\nwill result in a literal script tag:\r\n\r\n```jade\r\n- var html = \"\"\r\n| !{html}\r\n```\r\n\r\nNested tags that also contain text can optionally use a text block:\r\n\r\n```jade\r\nlabel\r\n | Username:\r\n input(name='user[name]')\r\n```\r\n\r\nor immediate tag text:\r\n\r\n```jade\r\nlabel Username:\r\n input(name='user[name]')\r\n```\r\n\r\nAs an alternative, we may use a trailing `.` to indicate a text block, for example:\r\n\r\n```jade\r\np.\r\n foo asdf\r\n asdf\r\n asdfasdfaf\r\n asdf\r\n asd.\r\n```\r\n\r\noutputs:\r\n\r\n```html\r\n

    foo asdf\r\nasdf\r\n asdfasdfaf\r\n asdf\r\nasd.\r\n

    \r\n```\r\n\r\nThis however differs from a trailing `.` followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal:\r\n\r\n```jade\r\np .\r\n```\r\n\r\noutputs:\r\n\r\n```html\r\n

    .

    \r\n```\r\n\r\nIt should be noted that text blocks should be doubled escaped. For example if you desire the following output.\r\n\r\n```html\r\n

    foo\\bar

    \r\n```\r\n\r\nuse:\r\n\r\n```jade\r\np.\r\n foo\\\\bar\r\n```\r\n\r\n
    \r\n### Comments\r\n\r\nSingle line comments currently look the same as JavaScript comments,\r\naka `//` and must be placed on their own line:\r\n\r\n```jade\r\n// just some paragraphs\r\np foo\r\np bar\r\n```\r\n\r\nwould output\r\n\r\n```html\r\n\r\n

    foo

    \r\n

    bar

    \r\n```\r\n\r\nJade also supports unbuffered comments, by simply adding a hyphen:\r\n\r\n```jade\r\n//- will not output within markup\r\np foo\r\np bar\r\n```\r\n\r\noutputting\r\n\r\n```html\r\n

    foo

    \r\n

    bar

    \r\n```\r\n\r\n
    \r\n### Block Comments\r\n\r\n A block comment is legal as well:\r\n\r\n```jade\r\nbody\r\n //\r\n #content\r\n h1 Example\r\n```\r\n\r\noutputting\r\n\r\n```html\r\n\r\n \r\n\r\n```\r\n\r\nJade supports conditional-comments as well, for example:\r\n\r\n```jade\r\nhead\r\n //if lt IE 8\r\n script(src='/ie-sucks.js')\r\n```\r\n\r\noutputs:\r\n\r\n```html\r\n\r\n \r\n\r\n```\r\n\r\n\r\n### Nesting\r\n\r\n Jade supports nesting to define the tags in a natural way:\r\n\r\n```jade\r\nul\r\n li.first\r\n a(href='#') foo\r\n li\r\n a(href='#') bar\r\n li.last\r\n a(href='#') baz\r\n```\r\n\r\n\r\n### Block Expansion\r\n\r\n Block expansion allows you to create terse single-line nested tags,\r\n the following example is equivalent to the nesting example above.\r\n\r\n```jade\r\nul\r\n li.first: a(href='#') foo\r\n li: a(href='#') bar\r\n li.last: a(href='#') baz\r\n```\r\n\r\n\r\n### Case\r\n\r\n The case statement takes the following form:\r\n\r\n```jade\r\nhtml\r\n body\r\n friends = 10\r\n case friends\r\n when 0\r\n p you have no friends\r\n when 1\r\n p you have a friend\r\n default\r\n p you have #{friends} friends\r\n```\r\n\r\n Block expansion may also be used:\r\n\r\n```jade\r\nfriends = 5\r\n\r\nhtml\r\n body\r\n case friends\r\n when 0: p you have no friends\r\n when 1: p you have a friend\r\n default: p you have #{friends} friends\r\n```\r\n\r\n\r\n### Attributes\r\n\r\nJade currently supports `(` and `)` as attribute delimiters.\r\n\r\n```jade\r\na(href='/login', title='View login page') Login\r\n```\r\n\r\nWhen a value is `undefined` or `null` the attribute is _not_ added,\r\nso this is fine, it will not compile `something=\"null\"`.\r\n\r\n```jade\r\ndiv(something=null)\r\n```\r\n\r\nBoolean attributes are also supported:\r\n\r\n```jade\r\ninput(type=\"checkbox\", checked)\r\n```\r\n\r\nBoolean attributes with code will only output the attribute when `true`:\r\n\r\n```jade\r\ninput(type=\"checkbox\", checked=someValue)\r\n```\r\n\r\nMultiple lines work too:\r\n\r\n```jade\r\ninput(type='checkbox',\r\n name='agreement',\r\n checked)\r\n```\r\n\r\nMultiple lines without the comma work fine:\r\n\r\n```jade\r\ninput(type='checkbox'\r\n name='agreement'\r\n checked)\r\n```\r\n\r\nFunky whitespace? fine:\r\n\r\n```jade\r\ninput(\r\n type='checkbox'\r\n name='agreement'\r\n checked)\r\n```\r\n\r\nColons work:\r\n\r\n```jade\r\nrss(xmlns:atom=\"atom\")\r\n```\r\n\r\nSuppose we have the `user` local `{ id: 12, name: 'tobi' }`\r\nand we wish to create an anchor tag with `href` pointing to \"/user/12\"\r\nwe could use regular javascript concatenation:\r\n\r\n```jade\r\na(href='/user/' + user.id)= user.name\r\n```\r\n\r\nor we could use jade's interpolation, which I added because everyone\r\nusing Ruby or CoffeeScript seems to think this is legal js..:\r\n\r\n```jade\r\na(href='/user/#{user.id}')= user.name\r\n```\r\n\r\nThe `class` attribute is special-cased when an array is given,\r\nallowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly:\r\n\r\n```jade\r\nbody(class=bodyClasses)\r\n```\r\n\r\n\r\n### HTML\r\n\r\n Inline html is fine, we can use the pipe syntax to\r\n write arbitrary text, in this case some html:\r\n\r\n```jade\r\nhtml\r\n body\r\n |

    Title

    \r\n |

    foo bar baz

    \r\n```\r\n\r\n Or we can use the trailing `.` to indicate to Jade that we\r\n only want text in this block, allowing us to omit the pipes:\r\n\r\n```jade\r\nhtml\r\n body.\r\n

    Title

    \r\n

    foo bar baz

    \r\n```\r\n\r\n Both of these examples yield the same result:\r\n\r\n```html\r\n

    Title

    \r\n

    foo bar baz

    \r\n\r\n```\r\n\r\n The same rule applies for anywhere you can have text\r\n in jade, raw html is fine:\r\n\r\n```jade\r\nhtml\r\n body\r\n h1 User #{name}\r\n```\r\n\r\n
    \r\n### Doctypes\r\n\r\nTo add a doctype simply use `!!!`, or `doctype` followed by an optional value:\r\n\r\n```jade\r\n!!!\r\n```\r\n\r\nor\r\n\r\n```jade\r\ndoctype\r\n```\r\n\r\nWill output the _html 5_ doctype, however:\r\n\r\n```jade\r\n!!! transitional\r\n```\r\n\r\nWill output the _transitional_ doctype.\r\n\r\nDoctypes are case-insensitive, so the following are equivalent:\r\n\r\n```jade\r\ndoctype Basic\r\ndoctype basic\r\n```\r\n\r\nit's also possible to simply pass a doctype literal:\r\n\r\n```jade\r\ndoctype html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\"\r\n```\r\n\r\nyielding:\r\n\r\n```html\r\n\r\n```\r\n\r\nBelow are the doctypes defined by default, which can easily be extended:\r\n\r\n```js\r\nvar doctypes = exports.doctypes = {\r\n '5': '',\r\n 'default': '',\r\n 'xml': '',\r\n 'transitional': '',\r\n 'strict': '',\r\n 'frameset': '',\r\n '1.1': '',\r\n 'basic': '',\r\n 'mobile': ''\r\n};\r\n```\r\n\r\nTo alter the default simply change:\r\n\r\n```js\r\njade.doctypes.default = 'whatever you want';\r\n```\r\n\r\n\r\n## Filters\r\n\r\nFilters are prefixed with `:`, for example `:markdown` and\r\npass the following block of text to an arbitrary function for processing. View the _features_\r\nat the top of this document for available filters.\r\n\r\n```jade\r\nbody\r\n :markdown\r\n Woah! jade _and_ markdown, very **cool**\r\n we can even link to [stuff](http://google.com)\r\n```\r\n\r\nRenders:\r\n\r\n```html\r\n

    Woah! jade and markdown, very cool we can even link to stuff

    \r\n```\r\n\r\n\r\n## Code\r\n\r\nJade currently supports three classifications of executable code. The first\r\nis prefixed by `-`, and is not buffered:\r\n\r\n```jade\r\n- var foo = 'bar';\r\n```\r\n\r\nThis can be used for conditionals, or iteration:\r\n\r\n```jade\r\n- for (var key in obj)\r\n p= obj[key]\r\n```\r\n\r\nDue to Jade's buffering techniques the following is valid as well:\r\n\r\n```jade\r\n- if (foo)\r\n ul\r\n li yay\r\n li foo\r\n li worked\r\n- else\r\n p oh no! didnt work\r\n```\r\n\r\nHell, even verbose iteration:\r\n\r\n```jade\r\n- if (items.length)\r\n ul\r\n - items.forEach(function(item){\r\n li= item\r\n - })\r\n```\r\n\r\nAnything you want!\r\n\r\nNext up we have _escaped_ buffered code, which is used to\r\nbuffer a return value, which is prefixed by `=`:\r\n\r\n```jade\r\n- var foo = 'bar'\r\n= foo\r\nh1= foo\r\n```\r\n\r\nWhich outputs `bar

    bar

    `. Code buffered by `=` is escaped\r\nby default for security, however to output unescaped return values\r\nyou may use `!=`:\r\n\r\n```jade\r\np!= aVarContainingMoreHTML\r\n```\r\n\r\n Jade also has designer-friendly variants, making the literal JavaScript\r\n more expressive and declarative. For example the following assignments\r\n are equivalent, and the expression is still regular javascript:\r\n\r\n```jade\r\n- var foo = 'foo ' + 'bar'\r\nfoo = 'foo ' + 'bar'\r\n```\r\n\r\n Likewise Jade has first-class `if`, `else if`, `else`, `until`, `while`, `unless` among others, however you must remember that the expressions are still regular javascript:\r\n\r\n```jade\r\nif foo == 'bar'\r\n ul\r\n li yay\r\n li foo\r\n li worked\r\nelse\r\n p oh no! didnt work\r\n```\r\n\r\n
    \r\n## Iteration\r\n\r\n Along with vanilla JavaScript Jade also supports a subset of\r\n constructs that allow you to create more designer-friendly templates,\r\n one of these constructs is `each`, taking the form:\r\n\r\n```jade\r\neach VAL[, KEY] in OBJ\r\n```\r\n\r\nAn example iterating over an array:\r\n\r\n```jade\r\n- var items = [\"one\", \"two\", \"three\"]\r\neach item in items\r\n li= item\r\n```\r\n\r\noutputs:\r\n\r\n```html\r\n
  • one
  • \r\n
  • two
  • \r\n
  • three
  • \r\n```\r\n\r\niterating an array with index:\r\n\r\n```jade\r\nitems = [\"one\", \"two\", \"three\"]\r\neach item, i in items\r\n li #{item}: #{i}\r\n```\r\n\r\noutputs:\r\n\r\n```html\r\n
  • one: 0
  • \r\n
  • two: 1
  • \r\n
  • three: 2
  • \r\n```\r\n\r\niterating an object's keys and values:\r\n\r\n```jade\r\nobj = { foo: 'bar' }\r\neach val, key in obj\r\n li #{key}: #{val}\r\n```\r\n\r\nwould output `
  • foo: bar
  • `\r\n\r\nInternally Jade converts these statements to regular\r\nJavaScript loops such as `users.forEach(function(user){`,\r\nso lexical scope and nesting applies as it would with regular\r\nJavaScript:\r\n\r\n```jade\r\neach user in users\r\n each role in user.roles\r\n li= role\r\n```\r\n\r\n You may also use `for` if you prefer:\r\n\r\n```jade\r\nfor user in users\r\n for role in user.roles\r\n li= role\r\n```\r\n\r\n
    \r\n## Conditionals\r\n\r\n Jade conditionals are equivalent to those using the code (`-`) prefix,\r\n however allow you to ditch parenthesis to become more designer friendly,\r\n however keep in mind the expression given is _regular_ JavaScript:\r\n\r\n```jade\r\nfor user in users\r\n if user.role == 'admin'\r\n p #{user.name} is an admin\r\n else\r\n p= user.name\r\n```\r\n\r\n is equivalent to the following using vanilla JavaScript literals:\r\n\r\n```jade\r\nfor user in users\r\n - if (user.role == 'admin')\r\n p #{user.name} is an admin\r\n - else\r\n p= user.name\r\n```\r\n\r\n Jade also provides `unless` which is equivalent to `if (!(expr))`:\r\n\r\n```jade\r\nfor user in users\r\n unless user.isAnonymous\r\n p\r\n | Click to view\r\n a(href='/users/' + user.id)= user.name\r\n```\r\n\r\n\r\n## Template inheritance\r\n\r\n Jade supports template inheritance via the `block` and `extends` keywords. A block is simply a \"block\" of Jade that may be replaced within a child template, this process is recursive. To activate template inheritance in Express 2.x you must add: `app.set('view options', { layout: false });`.\r\n\r\n Jade blocks can provide default content if desired, however optional as shown below by `block scripts`, `block content`, and `block foot`.\r\n\r\n```jade\r\nhtml\r\n head\r\n title My Site - #{title}\r\n block scripts\r\n script(src='/jquery.js')\r\n body\r\n block content\r\n block foot\r\n #footer\r\n p some footer content\r\n```\r\n\r\n Now to extend the layout, simply create a new file and use the `extends` directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the `foot` block is _not_ redefined and will output \"some footer content\".\r\n\r\n```jade\r\nextends layout\r\n\r\nblock scripts\r\n script(src='/jquery.js')\r\n script(src='/pets.js')\r\n\r\nblock content\r\n h1= title\r\n each pet in pets\r\n include pet\r\n```\r\n\r\n It's also possible to override a block to provide additional blocks, as shown in the following example where `content` now exposes a `sidebar` and `primary` block for overriding, or the child template could override `content` all together.\r\n\r\n```jade\r\nextends regular-layout\r\n\r\nblock content\r\n .sidebar\r\n block sidebar\r\n p nothing\r\n .primary\r\n block primary\r\n p nothing\r\n```\r\n\r\n\r\n## Block append / prepend\r\n\r\n Jade allows you to _replace_ (default), _prepend_, or _append_ blocks. Suppose for example you have default scripts in a \"head\" block that you wish to utilize on _every_ page, you might do this:\r\n\r\n```jade\r\nhtml\r\n head\r\n block head\r\n script(src='/vendor/jquery.js')\r\n script(src='/vendor/caustic.js')\r\n body\r\n block content\r\n```\r\n\r\n Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply `append` the block:\r\n\r\n```jade\r\nextends layout\r\n\r\nblock append head\r\n script(src='/vendor/three.js')\r\n script(src='/game.js')\r\n```\r\n\r\n When using `block append` or `block prepend` the `block` is optional:\r\n\r\n```jade\r\nextends layout\r\n\r\nappend head\r\n script(src='/vendor/three.js')\r\n script(src='/game.js')\r\n```\r\n\r\n\r\n## Includes\r\n\r\n Includes allow you to statically include chunks of Jade,\r\n or other content like css, or html which lives in separate files. The classical example is including a header and footer. Suppose we have the following directory structure:\r\n\r\n ./layout.jade\r\n ./includes/\r\n ./head.jade\r\n ./foot.jade\r\n\r\nand the following _layout.jade_:\r\n\r\n```jade\r\nhtml\r\n include includes/head\r\n body\r\n h1 My Site\r\n p Welcome to my super amazing site.\r\n include includes/foot\r\n```\r\n\r\nboth includes _includes/head_ and _includes/foot_ are\r\nread relative to the `filename` option given to _layout.jade_,\r\nwhich should be an absolute path to this file, however Express\r\ndoes this for you. Include then parses these files, and injects\r\nthe AST produced to render what you would expect:\r\n\r\n```html\r\n\r\n \r\n My Site\r\n \r\n \r\n \r\n

    My Site

    \r\n

    Welcome to my super lame site.

    \r\n
    \r\n

    Copyright>(c) foobar

    \r\n
    \r\n \r\n\r\n```\r\n\r\nAs mentioned `include` can be used to include other content\r\nsuch as html or css. By providing an extension, Jade will\r\nread that file in, apply any [filter](#a7) matching the file's\r\nextension, and insert that content into the output.\r\n\r\n```jade\r\nhtml\r\n head\r\n //- css and js have simple filters that wrap them in\r\n + + + + + + diff --git a/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js b/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js new file mode 100644 index 0000000..2469225 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/node-uuid/test/test.js @@ -0,0 +1,228 @@ +if (!this.uuid) { + // node.js + uuid = require('../uuid'); +} + +// +// x-platform log/assert shims +// + +function _log(msg, type) { + type = type || 'log'; + + if (typeof(document) != 'undefined') { + document.write('
    ' + msg.replace(/\n/g, '
    ') + '
    '); + } + if (typeof(console) != 'undefined') { + var color = { + log: '\033[39m', + warn: '\033[33m', + error: '\033[31m' + }; + console[type](color[type] + msg + color.log); + } +} + +function log(msg) {_log(msg, 'log');} +function warn(msg) {_log(msg, 'warn');} +function error(msg) {_log(msg, 'error');} + +function assert(res, msg) { + if (!res) { + error('FAIL: ' + msg); + } else { + log('Pass: ' + msg); + } +} + +// +// Unit tests +// + +// Verify ordering of v1 ids created with explicit times +var TIME = 1321644961388; // 2011-11-18 11:36:01.388-08:00 + +function compare(name, ids) { + ids = ids.map(function(id) { + return id.split('-').reverse().join('-'); + }).sort(); + var sorted = ([].concat(ids)).sort(); + + assert(sorted.toString() == ids.toString(), name + ' have expected order'); +} + +// Verify ordering of v1 ids created using default behavior +compare('uuids with current time', [ + uuid.v1(), + uuid.v1(), + uuid.v1(), + uuid.v1(), + uuid.v1() +]); + +// Verify ordering of v1 ids created with explicit times +compare('uuids with time option', [ + uuid.v1({msecs: TIME - 10*3600*1000}), + uuid.v1({msecs: TIME - 1}), + uuid.v1({msecs: TIME}), + uuid.v1({msecs: TIME + 1}), + uuid.v1({msecs: TIME + 28*24*3600*1000}) +]); + +assert( + uuid.v1({msecs: TIME}) != uuid.v1({msecs: TIME}), + 'IDs created at same msec are different' +); + +// Verify throw if too many ids created +var thrown = false; +try { + uuid.v1({msecs: TIME, nsecs: 10000}); +} catch (e) { + thrown = true; +} +assert(thrown, 'Exception thrown when > 10K ids created in 1 ms'); + +// Verify clock regression bumps clockseq +var uidt = uuid.v1({msecs: TIME}); +var uidtb = uuid.v1({msecs: TIME - 1}); +assert( + parseInt(uidtb.split('-')[3], 16) - parseInt(uidt.split('-')[3], 16) === 1, + 'Clock regression by msec increments the clockseq' +); + +// Verify clock regression bumps clockseq +var uidtn = uuid.v1({msecs: TIME, nsecs: 10}); +var uidtnb = uuid.v1({msecs: TIME, nsecs: 9}); +assert( + parseInt(uidtnb.split('-')[3], 16) - parseInt(uidtn.split('-')[3], 16) === 1, + 'Clock regression by nsec increments the clockseq' +); + +// Verify explicit options produce expected id +var id = uuid.v1({ + msecs: 1321651533573, + nsecs: 5432, + clockseq: 0x385c, + node: [ 0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10 ] +}); +assert(id == 'd9428888-122b-11e1-b85c-61cd3cbb3210', 'Explicit options produce expected id'); + +// Verify adjacent ids across a msec boundary are 1 time unit apart +var u0 = uuid.v1({msecs: TIME, nsecs: 9999}); +var u1 = uuid.v1({msecs: TIME + 1, nsecs: 0}); + +var before = u0.split('-')[0], after = u1.split('-')[0]; +var dt = parseInt(after, 16) - parseInt(before, 16); +assert(dt === 1, 'Ids spanning 1ms boundary are 100ns apart'); + +// +// Test parse/unparse +// + +id = '00112233445566778899aabbccddeeff'; +assert(uuid.unparse(uuid.parse(id.substr(0,10))) == + '00112233-4400-0000-0000-000000000000', 'Short parse'); +assert(uuid.unparse(uuid.parse('(this is the uuid -> ' + id + id)) == + '00112233-4455-6677-8899-aabbccddeeff', 'Dirty parse'); + +// +// Perf tests +// + +var generators = { + v1: uuid.v1, + v4: uuid.v4 +}; + +var UUID_FORMAT = { + v1: /[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i, + v4: /[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i +}; + +var N = 1e4; + +// Get %'age an actual value differs from the ideal value +function divergence(actual, ideal) { + return Math.round(100*100*(actual - ideal)/ideal)/100; +} + +function rate(msg, t) { + log(msg + ': ' + (N / (Date.now() - t) * 1e3 | 0) + ' uuids\/second'); +} + +for (var version in generators) { + var counts = {}, max = 0; + var generator = generators[version]; + var format = UUID_FORMAT[version]; + + log('\nSanity check ' + N + ' ' + version + ' uuids'); + for (var i = 0, ok = 0; i < N; i++) { + id = generator(); + if (!format.test(id)) { + throw Error(id + ' is not a valid UUID string'); + } + + if (id != uuid.unparse(uuid.parse(id))) { + assert(fail, id + ' is not a valid id'); + } + + // Count digits for our randomness check + if (version == 'v4') { + var digits = id.replace(/-/g, '').split(''); + for (var j = digits.length-1; j >= 0; j--) { + var c = digits[j]; + max = Math.max(max, counts[c] = (counts[c] || 0) + 1); + } + } + } + + // Check randomness for v4 UUIDs + if (version == 'v4') { + // Limit that we get worried about randomness. (Purely empirical choice, this!) + var limit = 2*100*Math.sqrt(1/N); + + log('\nChecking v4 randomness. Distribution of Hex Digits (% deviation from ideal)'); + + for (var i = 0; i < 16; i++) { + var c = i.toString(16); + var bar = '', n = counts[c], p = Math.round(n/max*100|0); + + // 1-3,5-8, and D-F: 1:16 odds over 30 digits + var ideal = N*30/16; + if (i == 4) { + // 4: 1:1 odds on 1 digit, plus 1:16 odds on 30 digits + ideal = N*(1 + 30/16); + } else if (i >= 8 && i <= 11) { + // 8-B: 1:4 odds on 1 digit, plus 1:16 odds on 30 digits + ideal = N*(1/4 + 30/16); + } else { + // Otherwise: 1:16 odds on 30 digits + ideal = N*30/16; + } + var d = divergence(n, ideal); + + // Draw bar using UTF squares (just for grins) + var s = n/max*50 | 0; + while (s--) bar += '='; + + assert(Math.abs(d) < limit, c + ' |' + bar + '| ' + counts[c] + ' (' + d + '% < ' + limit + '%)'); + } + } +} + +// Perf tests +for (var version in generators) { + log('\nPerformance testing ' + version + ' UUIDs'); + var generator = generators[version]; + var buf = new uuid.BufferClass(16); + + for (var i = 0, t = Date.now(); i < N; i++) generator(); + rate('uuid.' + version + '()', t); + + for (var i = 0, t = Date.now(); i < N; i++) generator('binary'); + rate('uuid.' + version + '(\'binary\')', t); + + for (var i = 0, t = Date.now(); i < N; i++) generator('binary', buf); + rate('uuid.' + version + '(\'binary\', buffer)', t); +} diff --git a/node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js b/node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js new file mode 100644 index 0000000..4795b9d --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/node-uuid/uuid.js @@ -0,0 +1,245 @@ +// uuid.js +// +// (c) 2010-2012 Robert Kieffer +// MIT License +// https://github.com/broofa/node-uuid +(function() { + var _global = this; + + // Unique ID creation requires a high quality random # generator. We feature + // detect to determine the best RNG source, normalizing to a function that + // returns 128-bits of randomness, since that's what's usually required + var _rng; + + // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html + // + // Moderately fast, high quality + if (typeof(require) == 'function') { + try { + var _rb = require('crypto').randomBytes; + _rng = _rb && function() {return _rb(16);}; + } catch(e) {} + } + + if (!_rng && _global.crypto && crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // + // Moderately fast, high quality + var _rnds8 = new Uint8Array(16); + _rng = function whatwgRNG() { + crypto.getRandomValues(_rnds8); + return _rnds8; + }; + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var _rnds = new Array(16); + _rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return _rnds; + }; + } + + // Buffer class to use + var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array; + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 0x100).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = (buf && offset) || 0, ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { + if (ii < 16) { // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + + // Previous uuid creation time + var _lastMSecs = 0, _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq != null ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs != null ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq == null) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new BufferClass(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + var uuid = v4; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.parse = parse; + uuid.unparse = unparse; + uuid.BufferClass = BufferClass; + + if (_global.define && define.amd) { + // Publish as AMD module + define(function() {return uuid;}); + } else if (typeof(module) != 'undefined' && module.exports) { + // Publish as node.js module + module.exports = uuid; + } else { + // Publish as global (in browsers) + var _previousRoot = _global.uuid; + + // **`noConflict()` - (browser only) to reset global 'uuid' var** + uuid.noConflict = function() { + _global.uuid = _previousRoot; + return uuid; + }; + + _global.uuid = uuid; + } +}()); diff --git a/node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE b/node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/oauth-sign/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/less/node_modules/request/node_modules/oauth-sign/README.md b/node_modules/less/node_modules/request/node_modules/oauth-sign/README.md new file mode 100644 index 0000000..34c4a85 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/oauth-sign/README.md @@ -0,0 +1,4 @@ +oauth-sign +========== + +OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. diff --git a/node_modules/less/node_modules/request/node_modules/oauth-sign/index.js b/node_modules/less/node_modules/request/node_modules/oauth-sign/index.js new file mode 100644 index 0000000..e35bfa6 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/oauth-sign/index.js @@ -0,0 +1,43 @@ +var crypto = require('crypto') + , qs = require('querystring') + ; + +function sha1 (key, body) { + return crypto.createHmac('sha1', key).update(body).digest('base64') +} + +function rfc3986 (str) { + return encodeURIComponent(str) + .replace(/!/g,'%21') + .replace(/\*/g,'%2A') + .replace(/\(/g,'%28') + .replace(/\)/g,'%29') + .replace(/'/g,'%27') + ; +} + +function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) { + // adapted from https://dev.twitter.com/docs/auth/oauth and + // https://dev.twitter.com/docs/auth/creating-signature + + var querystring = Object.keys(params).sort().map(function(key){ + // big WTF here with the escape + encoding but it's what twitter wants + return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key])) + }).join('%26') + + var base = [ + httpMethod ? httpMethod.toUpperCase() : 'GET', + rfc3986(base_uri), + querystring + ].join('&') + + var key = [ + consumer_secret, + token_secret || '' + ].map(rfc3986).join('&') + + return sha1(key, base) +} + +exports.hmacsign = hmacsign +exports.rfc3986 = rfc3986 diff --git a/node_modules/less/node_modules/request/node_modules/oauth-sign/package.json b/node_modules/less/node_modules/request/node_modules/oauth-sign/package.json new file mode 100644 index 0000000..17d5975 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/oauth-sign/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "oauth-sign", + "description": "OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module.", + "version": "0.3.0", + "repository": { + "url": "https://github.com/mikeal/oauth-sign" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "scripts": { + "test": "node test.js" + }, + "readme": "oauth-sign\n==========\n\nOAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. \n", + "readmeFilename": "README.md", + "_id": "oauth-sign@0.3.0", + "dist": { + "shasum": "ae5e310f5a429c60f3f1677298265670e5162095" + }, + "_from": "oauth-sign@~0.3.0", + "_resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" +} diff --git a/node_modules/less/node_modules/request/node_modules/oauth-sign/test.js b/node_modules/less/node_modules/request/node_modules/oauth-sign/test.js new file mode 100644 index 0000000..46955ff --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/oauth-sign/test.js @@ -0,0 +1,49 @@ +var hmacsign = require('./index').hmacsign + , assert = require('assert') + , qs = require('querystring') + ; + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + diff --git a/node_modules/less/node_modules/request/node_modules/qs/.gitmodules b/node_modules/less/node_modules/request/node_modules/qs/.gitmodules new file mode 100644 index 0000000..49e31da --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/less/node_modules/request/node_modules/qs/.npmignore b/node_modules/less/node_modules/request/node_modules/qs/.npmignore new file mode 100644 index 0000000..e85ce2a --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/qs/.npmignore @@ -0,0 +1,7 @@ +test +.travis.yml +benchmark.js +component.json +examples.js +History.md +Makefile diff --git a/node_modules/less/node_modules/request/node_modules/qs/Readme.md b/node_modules/less/node_modules/request/node_modules/qs/Readme.md new file mode 100644 index 0000000..27e54a4 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/less/node_modules/request/node_modules/qs/index.js b/node_modules/less/node_modules/request/node_modules/qs/index.js new file mode 100644 index 0000000..590491e --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/qs/index.js @@ -0,0 +1,387 @@ +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Object#hasOwnProperty ref + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Array#indexOf shim. + */ + +var indexOf = typeof Array.prototype.indexOf === 'function' + ? function(arr, el) { return arr.indexOf(el); } + : function(arr, el) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === el) return i; + } + return -1; + }; + +/** + * Array.isArray shim. + */ + +var isArray = Array.isArray || function(arr) { + return toString.call(arr) == '[object Array]'; +}; + +/** + * Object.keys shim. + */ + +var objectKeys = Object.keys || function(obj) { + var ret = []; + for (var key in obj) ret.push(key); + return ret; +}; + +/** + * Array#forEach shim. + */ + +var forEach = typeof Array.prototype.forEach === 'function' + ? function(arr, fn) { return arr.forEach(fn); } + : function(arr, fn) { + for (var i = 0; i < arr.length; i++) fn(arr[i]); + }; + +/** + * Array#reduce shim. + */ + +var reduce = function(arr, fn, initial) { + if (typeof arr.reduce === 'function') return arr.reduce(fn, initial); + var res = initial; + for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]); + return res; +}; + +/** + * Create a nullary object if possible + */ + +function createObject() { + return Object.create + ? Object.create(null) + : {}; +} + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = createObject(); + var t = createObject(); + for (var i in parent[key]) { + if (hasOwnProperty.call(parent[key], i)) { + t[i] = parent[key][i]; + } + } + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[objectKeys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~indexOf(part, ']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~indexOf(key, ']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && isArray(parent.base)) { + var t = createObject(); + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Compact sparse arrays. + */ + +function compact(obj) { + if ('object' != typeof obj) return obj; + + if (isArray(obj)) { + var ret = []; + + for (var i in obj) { + if (hasOwnProperty.call(obj, i)) { + ret.push(obj[i]); + } + } + + return ret; + } + + for (var key in obj) { + obj[key] = compact(obj[key]); + } + + return obj; +} + +/** + * Restore Object.prototype. + * see pull-request #58 + */ + +function restoreProto(obj) { + if (!Object.create) return obj; + if (isArray(obj)) return obj; + if (obj && 'object' != typeof obj) return obj; + + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + obj[key] = restoreProto(obj[key]); + } + } + + obj.__proto__ = Object.prototype; + return obj; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + + forEach(objectKeys(obj), function(name){ + merge(ret, name, obj[name]); + }); + + return compact(ret.base); +} + +/** + * Parse the given str. + */ + +function parseString(str){ + var ret = reduce(String(str).split('&'), function(ret, pair){ + var eql = indexOf(pair, '=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(indexOf(val, '=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + if ('' == key) return ret; + + return merge(ret, decode(key), decode(val)); + }, { base: createObject() }).base; + + return restoreProto(compact(ret)); +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + encodeURIComponent(String(obj)); + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '[' + i + ']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = objectKeys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + if ('' == key) continue; + if (null == obj[key]) { + ret.push(encodeURIComponent(key) + '='); + } else { + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/less/node_modules/request/node_modules/qs/package.json b/node_modules/less/node_modules/request/node_modules/qs/package.json new file mode 100644 index 0000000..40a2796 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/qs/package.json @@ -0,0 +1,38 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.6.5", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "scripts": { + "test": "make test" + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "_id": "qs@0.6.5", + "dist": { + "shasum": "ed0dd8b3d3ba67dafc839eaa1238de88f286333d" + }, + "_from": "qs@~0.6.0", + "_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz" +} diff --git a/node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE b/node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/tunnel-agent/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md b/node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md new file mode 100644 index 0000000..bb533d5 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/tunnel-agent/README.md @@ -0,0 +1,4 @@ +tunnel-agent +============ + +HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module. diff --git a/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js b/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js new file mode 100644 index 0000000..3f7bbb9 --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js @@ -0,0 +1,227 @@ +'use strict' + +var net = require('net') + , tls = require('tls') + , http = require('http') + , https = require('https') + , events = require('events') + , assert = require('assert') + , util = require('util') + ; + +exports.httpOverHttp = httpOverHttp +exports.httpsOverHttp = httpsOverHttp +exports.httpOverHttps = httpOverHttps +exports.httpsOverHttps = httpsOverHttps + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + return agent +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + agent.createSocket = createSecureSocket + return agent +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + return agent +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + agent.createSocket = createSecureSocket + return agent +} + + +function TunnelingAgent(options) { + var self = this + self.options = options || {} + self.proxyOptions = self.options.proxy || {} + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets + self.requests = [] + self.sockets = [] + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i] + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1) + pending.request.onSocket(socket) + return + } + } + socket.destroy() + self.removeSocket(socket) + }) +} +util.inherits(TunnelingAgent, events.EventEmitter) + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}) + return + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree) + socket.on('close', onCloseOrRemove) + socket.on('agentRemove', onCloseOrRemove) + req.onSocket(socket) + + function onFree() { + self.emit('free', socket, host, port) + } + + function onCloseOrRemove(err) { + self.removeSocket() + socket.removeListener('free', onFree) + socket.removeListener('close', onCloseOrRemove) + socket.removeListener('agentRemove', onCloseOrRemove) + } + }) +} + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this + var placeholder = {} + self.sockets.push(placeholder) + + var connectOptions = mergeOptions({}, self.proxyOptions, + { method: 'CONNECT' + , path: options.host + ':' + options.port + , agent: false + } + ) + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {} + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64') + } + + debug('making CONNECT request') + var connectReq = self.request(connectOptions) + connectReq.useChunkedEncodingByDefault = false // for v0.6 + connectReq.once('response', onResponse) // for v0.6 + connectReq.once('upgrade', onUpgrade) // for v0.6 + connectReq.once('connect', onConnect) // for v0.7 or later + connectReq.once('error', onError) + connectReq.end() + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head) + }) + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners() + socket.removeAllListeners() + + if (res.statusCode === 200) { + assert.equal(head.length, 0) + debug('tunneling connection has established') + self.sockets[self.sockets.indexOf(placeholder)] = socket + cb(socket) + } else { + debug('tunneling socket could not be established, statusCode=%d', res.statusCode) + var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } + } + + function onError(cause) { + connectReq.removeAllListeners() + + debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack) + var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } +} + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) return + + this.sockets.splice(pos, 1) + + var pending = this.requests.shift() + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket) + }) + } +} + +function createSecureSocket(options, cb) { + var self = this + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, + { servername: options.host + , socket: socket + } + )) + cb(secureSocket) + }) +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i] + if (typeof overrides === 'object') { + var keys = Object.keys(overrides) + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j] + if (overrides[k] !== undefined) { + target[k] = overrides[k] + } + } + } + } + return target +} + + +var debug +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments) + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0] + } else { + args.unshift('TUNNEL:') + } + console.error.apply(console, args) + } +} else { + debug = function() {} +} +exports.debug = debug // for test diff --git a/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json b/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json new file mode 100644 index 0000000..171390d --- /dev/null +++ b/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json @@ -0,0 +1,28 @@ +{ + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com", + "url": "http://www.futurealoof.com" + }, + "name": "tunnel-agent", + "description": "HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.", + "version": "0.3.0", + "repository": { + "url": "https://github.com/mikeal/tunnel-agent" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "tunnel-agent\n============\n\nHTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.\n", + "readmeFilename": "README.md", + "_id": "tunnel-agent@0.3.0", + "dist": { + "shasum": "3b19cf8cda6b85780f7d871a932581ef6b951326" + }, + "_from": "tunnel-agent@~0.3.0", + "_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" +} diff --git a/node_modules/less/node_modules/request/package.json b/node_modules/less/node_modules/request/package.json new file mode 100755 index 0000000..3c333ef --- /dev/null +++ b/node_modules/less/node_modules/request/package.json @@ -0,0 +1,51 @@ +{ + "name": "request", + "description": "Simplified HTTP request client.", + "tags": [ + "http", + "simple", + "util", + "utility" + ], + "version": "2.22.0", + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com" + }, + "repository": { + "type": "git", + "url": "http://github.com/mikeal/request.git" + }, + "bugs": { + "url": "http://github.com/mikeal/request/issues" + }, + "engines": [ + "node >= 0.8.0" + ], + "main": "index.js", + "dependencies": { + "qs": "~0.6.0", + "json-stringify-safe": "~4.0.0", + "forever-agent": "~0.5.0", + "tunnel-agent": "~0.3.0", + "http-signature": "~0.10.0", + "hawk": "~0.13.0", + "aws-sign": "~0.3.0", + "oauth-sign": "~0.3.0", + "cookie-jar": "~0.3.0", + "node-uuid": "~1.4.0", + "mime": "~1.2.9", + "form-data": "0.0.8" + }, + "scripts": { + "test": "node tests/run.js" + }, + "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n
    \n  npm install request\n
    \n\nOr from source:\n\n
    \n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n
    \n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nUrl encoded forms are simple\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload')\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))\nform.append('remote_file', request('http://google.com/doodle.png'))\n```\n\n## HTTP Authentication\n\n```javascript\nrequest.get('http://some.server.com/').auth('username', 'password', false);\n// or\nrequest.get('http://some.server.com/', {\n 'auth': {\n 'user': 'username',\n 'pass': 'password',\n 'sendImmediately': false\n }\n});\n```\n\nIf passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). The method form takes parameters `auth(username, password, sendImmediately)`.\n\n`sendImmediately` defaults to true, which will cause a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).\n\nDigest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail).\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Ideally, you would take the body in the response\n // and construct a URL that a user clicks on (like a sign in button).\n // The verifier is only available in the response after a user has \n // verified with twitter that they are authorizing your app.\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: access_token.oauth_verifier\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for PATCH, POST and PUT requests. Must be buffer or string.\n* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.\n* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). See documentation above.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)\n* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.\n* `localAddress` - Local interface to bind for network connections.\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.patch\n\nSame as request() but defaults to `method: \"PATCH\"`.\n\n```javascript\nrequest.patch(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n", + "readmeFilename": "README.md", + "_id": "request@2.22.0", + "dist": { + "shasum": "53bdb9a03b8f79ebc88fc80a7df9c2050ae9c2d6" + }, + "_from": "request@>=2.12.0", + "_resolved": "https://registry.npmjs.org/request/-/request-2.22.0.tgz" +} diff --git a/node_modules/less/node_modules/request/tests/googledoodle.jpg b/node_modules/less/node_modules/request/tests/googledoodle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f80c9c52d3c507996535a19ee0bcfe3821de322d GIT binary patch literal 38510 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 literal 0 HcmV?d00001 diff --git a/node_modules/less/node_modules/request/tests/run.js b/node_modules/less/node_modules/request/tests/run.js new file mode 100644 index 0000000..e717f02 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/run.js @@ -0,0 +1,40 @@ +var spawn = require('child_process').spawn + , exitCode = 0 + , timeout = 10000 + , fs = require('fs') + ; + +fs.readdir(__dirname, function (e, files) { + if (e) throw e + + var tests = files.filter(function (f) {return f.slice(0, 'test-'.length) === 'test-'}) + + var next = function () { + if (tests.length === 0) process.exit(exitCode); + + var file = tests.shift() + console.log(file) + var proc = spawn('node', [ 'tests/' + file ]) + + var killed = false + var t = setTimeout(function () { + proc.kill() + exitCode += 1 + console.error(file + ' timeout') + killed = true + }, timeout) + + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + proc.on('exit', function (code) { + if (code && !killed) console.error(file + ' failed') + exitCode += code || 0 + clearTimeout(t) + next() + }) + } + next() + +}) + + diff --git a/node_modules/less/node_modules/request/tests/server.js b/node_modules/less/node_modules/request/tests/server.js new file mode 100644 index 0000000..b6eacba --- /dev/null +++ b/node_modules/less/node_modules/request/tests/server.js @@ -0,0 +1,90 @@ +var fs = require('fs') + , http = require('http') + , path = require('path') + , https = require('https') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + ; + +exports.createServer = function (port) { + port = port || 6767 + var s = http.createServer(function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'http://localhost:'+port + return s; +} + +exports.createSSLServer = function(port, opts) { + port = port || 16767 + + var options = { 'key' : path.join(__dirname, 'ssl', 'test.key') + , 'cert': path.join(__dirname, 'ssl', 'test.crt') + } + if (opts) { + for (var i in opts) options[i] = opts[i] + } + + for (var i in options) { + options[i] = fs.readFileSync(options[i]) + } + + var s = https.createServer(options, function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'https://localhost:'+port + return s; +} + +exports.createPostStream = function (text) { + var postStream = new stream.Stream(); + postStream.writeable = true; + postStream.readable = true; + setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0); + return postStream; +} +exports.createPostValidator = function (text, reqContentType) { + var l = function (req, resp) { + var r = ''; + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) { + var boundary = req.headers['content-type'].split('boundary=')[1]; + text = text.replace(/__BOUNDARY__/g, boundary); + } + if (r !== text) console.log(r, text); + assert.equal(r, text) + if (reqContentType) { + assert.ok(req.headers['content-type']) + assert.ok(~req.headers['content-type'].indexOf(reqContentType)) + } + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write('OK') + resp.end() + }) + } + return l; +} +exports.createGetResponse = function (text, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + resp.write(text) + resp.end() + } + return l; +} +exports.createChunkResponse = function (chunks, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + chunks.forEach(function (chunk) { + resp.write(chunk) + }) + resp.end() + } + return l; +} diff --git a/node_modules/less/node_modules/request/tests/squid.conf b/node_modules/less/node_modules/request/tests/squid.conf new file mode 100644 index 0000000..0d4a3b6 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/squid.conf @@ -0,0 +1,77 @@ +# +# Recommended minimum configuration: +# +acl manager proto cache_object +acl localhost src 127.0.0.1/32 ::1 +acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1 + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 10.0.0.0/8 # RFC1918 possible internal network +acl localnet src 172.16.0.0/12 # RFC1918 possible internal network +acl localnet src 192.168.0.0/16 # RFC1918 possible internal network +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT + +# +# Recommended minimum Access Permission configuration: +# +# Only allow cachemgr access from localhost +http_access allow manager localhost +http_access deny manager + +# Deny requests to certain unsafe ports +http_access deny !Safe_ports + +# Deny CONNECT to other than secure SSL ports +#http_access deny CONNECT !SSL_ports + +# We strongly recommend the following be uncommented to protect innocent +# web applications running on the proxy server who think the only +# one who can access services on "localhost" is a local user +#http_access deny to_localhost + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# + +# Example rule allowing access from your local networks. +# Adapt localnet in the ACL section to list your (internal) IP networks +# from where browsing should be allowed +http_access allow localnet +http_access allow localhost + +# And finally deny all other access to this proxy +http_access deny all + +# Squid normally listens to port 3128 +http_port 3128 + +# We recommend you to use at least the following line. +hierarchy_stoplist cgi-bin ? + +# Uncomment and adjust the following to add a disk cache directory. +#cache_dir ufs /usr/local/var/cache 100 16 256 + +# Leave coredumps in the first cache dir +coredump_dir /usr/local/var/cache + +# Add any of your own refresh_pattern entries above these. +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern . 0 20% 4320 diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/ca.cnf b/node_modules/less/node_modules/request/tests/ssl/ca/ca.cnf new file mode 100644 index 0000000..425a889 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/ca.cnf @@ -0,0 +1,20 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no +output_password = password + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = request Certificate Authority +CN = requestCA +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/ca.crl b/node_modules/less/node_modules/request/tests/ssl/ca/ca.crl new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/ca.crt b/node_modules/less/node_modules/request/tests/ssl/ca/ca.crt new file mode 100644 index 0000000..b4524e4 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvTCCAiYCCQDn+P/MSbDsWjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGiMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxJjAkBgNVBAsTHXJlcXVlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MRIwEAYDVQQDEwlyZXF1ZXN0Q0ExJjAkBgkqhkiG9w0BCQEWF21pa2VhbEBtaWtl +YWxyb2dlcnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t9pQUAK4 +5XJYTI6NrF0n3G2HZsfN+rPYSVzzL8SuVyb1tHXos+vbPm3NKI4E8X1yVAXU8CjJ +5SqXnp4DAypAhaseho81cbhk7LXUhFz78OvAa+OD+xTAEAnNQ8tGUr4VGyplEjfD +xsBVuqV2j8GPNTftr+drOCFlqfAgMrBn4wIDAQABMA0GCSqGSIb3DQEBBQUAA4GB +ADVdTlVAL45R+PACNS7Gs4o81CwSclukBu4FJbxrkd4xGQmurgfRrYYKjtqiopQm +D7ysRamS3HMN9/VKq2T7r3z1PMHPAy7zM4uoXbbaTKwlnX4j/8pGPn8Ca3qHXYlo +88L/OOPc6Di7i7qckS3HFbXQCTiULtxWmy97oEuTwrAj +-----END CERTIFICATE----- diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/ca.csr b/node_modules/less/node_modules/request/tests/ssl/ca/ca.csr new file mode 100644 index 0000000..e48c56e --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/ca.csr @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICBjCCAW8CAQAwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEmMCQGA1UECxMdcmVxdWVzdCBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAMTCXJlcXVlc3RDQTEmMCQGCSqG +SIb3DQEJARYXbWlrZWFsQG1pa2VhbHJvZ2Vycy5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBALu32lBQArjlclhMjo2sXSfcbYdmx836s9hJXPMvxK5XJvW0 +deiz69s+bc0ojgTxfXJUBdTwKMnlKpeengMDKkCFqx6GjzVxuGTstdSEXPvw68Br +44P7FMAQCc1Dy0ZSvhUbKmUSN8PGwFW6pXaPwY81N+2v52s4IWWp8CAysGfjAgMB +AAGgIzAhBgkqhkiG9w0BCQcxFBMScGFzc3dvcmQgY2hhbGxlbmdlMA0GCSqGSIb3 +DQEBBQUAA4GBAGJO7grHeVHXetjHEK8urIxdnvfB2qeZeObz4GPKIkqUurjr0rfj +bA3EK1kDMR5aeQWR8RunixdM16Q6Ry0lEdLVWkdSwRN9dmirIHT9cypqnD/FYOia +SdezZ0lUzXgmJIwRYRwB1KSMMocIf52ll/xC2bEGg7/ZAEuAyAgcZV3X +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/ca.key b/node_modules/less/node_modules/request/tests/ssl/ca/ca.key new file mode 100644 index 0000000..a53e7f7 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/ca.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C8B5887048377F02 + +nyD5ZH0Wup2uWsDvurq5mKDaDrf8lvNn9w0SH/ZkVnfR1/bkwqrFriqJWvZNUG+q +nS0iBYczsWLJnbub9a1zLOTENWUKVD5uqbC3aGHhnoUTNSa27DONgP8gHOn6JgR+ +GAKo01HCSTiVT4LjkwN337QKHnMP2fTzg+IoC/CigvMcq09hRLwU1/guq0GJKGwH +gTxYNuYmQC4Tjh8vdS4liF+Ve/P3qPR2CehZrIOkDT8PHJBGQJRo4xGUIB7Tpk38 +VCk+UZ0JCS2coY8VkY/9tqFJp/ZnnQQVmaNbdRqg7ECKL+bXnNo7yjzmazPZmPe3 +/ShbE0+CTt7LrjCaQAxWbeDzqfo1lQfgN1LulTm8MCXpQaJpv7v1VhIhQ7afjMYb +4thW/ypHPiYS2YJCAkAVlua9Oxzzh1qJoh8Df19iHtpd79Q77X/qf+1JvITlMu0U +gi7yEatmQcmYNws1mtTC1q2DXrO90c+NZ0LK/Alse6NRL/xiUdjug2iHeTf/idOR +Gg/5dSZbnnlj1E5zjSMDkzg6EHAFmHV4jYGSAFLEQgp4V3ZhMVoWZrvvSHgKV/Qh +FqrAK4INr1G2+/QTd09AIRzfy3/j6yD4A9iNaOsEf9Ua7Qh6RcALRCAZTWR5QtEf +dX+iSNJ4E85qXs0PqwkMDkoaxIJ+tmIRJY7y8oeylV8cfGAi8Soubt/i3SlR8IHC +uDMas/2OnwafK3N7ODeE1i7r7wkzQkSHaEz0TrF8XRnP25jAICCSLiMdAAjKfxVb +EvzsFSuAy3Jt6bU3hSLY9o4YVYKE+68ITMv9yNjvTsEiW+T+IbN34w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/ca.srl b/node_modules/less/node_modules/request/tests/ssl/ca/ca.srl new file mode 100644 index 0000000..17128db --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/ca.srl @@ -0,0 +1 @@ +ADF62016AA40C9C3 diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/server.cnf b/node_modules/less/node_modules/request/tests/ssl/ca/server.cnf new file mode 100644 index 0000000..cd1fd1e --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/server.cnf @@ -0,0 +1,19 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = testing +CN = testing.request.mikealrogers.com +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/server.crt b/node_modules/less/node_modules/request/tests/ssl/ca/server.crt new file mode 100644 index 0000000..efe96ce --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/server.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICejCCAeMCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGjMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxEDAOBgNVBAsTB3Rlc3RpbmcxKTAnBgNVBAMTIHRlc3RpbmcucmVx +dWVzdC5taWtlYWxyb2dlcnMuY29tMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlr +ZWFscm9nZXJzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDgVl0jMumvOpmM +20W5v9yhGgZj8hPhEQF/N7yCBVBn/rWGYm70IHC8T/pR5c0LkWc5gdnCJEvKWQjh +DBKxZD8FAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEABShRkNgFbgs4vUWW9R9deNJj +7HJoiTmvkmoOC7QzcYkjdgHbOxsSq3rBnwxsVjY9PAtPwBn0GRspOeG7KzKRgySB +kb22LyrCFKbEOfKO/+CJc80ioK9zEPVjGsFMyAB+ftYRqM+s/4cQlTg/m89l01wC +yapjN3RxZbInGhWR+jA= +-----END CERTIFICATE----- diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/server.csr b/node_modules/less/node_modules/request/tests/ssl/ca/server.csr new file mode 100644 index 0000000..a8e7595 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/server.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBgjCCASwCAQAwgaMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEQMA4GA1UECxMHdGVzdGluZzEp +MCcGA1UEAxMgdGVzdGluZy5yZXF1ZXN0Lm1pa2VhbHJvZ2Vycy5jb20xJjAkBgkq +hkiG9w0BCQEWF21pa2VhbEBtaWtlYWxyb2dlcnMuY29tMFwwDQYJKoZIhvcNAQEB +BQADSwAwSAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAaAjMCEGCSqGSIb3DQEJBzEU +ExJwYXNzd29yZCBjaGFsbGVuZ2UwDQYJKoZIhvcNAQEFBQADQQBD3E5WekQzCEJw +7yOcqvtPYIxGaX8gRKkYfLPoj3pm3GF5SGqtJKhylKfi89szHXgktnQgzff9FN+A +HidVJ/3u +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/server.js b/node_modules/less/node_modules/request/tests/ssl/ca/server.js new file mode 100644 index 0000000..05e21c1 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/server.js @@ -0,0 +1,28 @@ +var fs = require("fs") +var https = require("https") +var options = { key: fs.readFileSync("./server.key") + , cert: fs.readFileSync("./server.crt") } + +var server = https.createServer(options, function (req, res) { + res.writeHead(200) + res.end() + server.close() +}) +server.listen(1337) + +var ca = fs.readFileSync("./ca.crt") +var agent = new https.Agent({ host: "localhost", port: 1337, ca: ca }) + +https.request({ host: "localhost" + , method: "HEAD" + , port: 1337 + , headers: { host: "testing.request.mikealrogers.com" } + , agent: agent + , ca: [ ca ] + , path: "/" }, function (res) { + if (res.client.authorized) { + console.log("node test: OK") + } else { + throw new Error(res.client.authorizationError) + } +}).end() diff --git a/node_modules/less/node_modules/request/tests/ssl/ca/server.key b/node_modules/less/node_modules/request/tests/ssl/ca/server.key new file mode 100644 index 0000000..72d8698 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/ca/server.key @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAQJAK+r8ZM2sze8s7FRo/ApB +iRBtO9fCaIdJwbwJnXKo4RKwZDt1l2mm+fzZ+/QaQNjY1oTROkIIXmnwRvZWfYlW +gQIhAPKYsG+YSBN9o8Sdp1DMyZ/rUifKX3OE6q9tINkgajDVAiEA7Ltqh01+cnt0 +JEnud/8HHcuehUBLMofeg0G+gCnSbXECIQCqDvkXsWNNLnS/3lgsnvH0Baz4sbeJ +rjIpuVEeg8eM5QIgbu0+9JmOV6ybdmmiMV4yAncoF35R/iKGVHDZCAsQzDECIQDZ +0jGz22tlo5YMcYSqrdD3U4sds1pwiAaWFRbCunoUJw== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/less/node_modules/request/tests/ssl/npm-ca.crt b/node_modules/less/node_modules/request/tests/ssl/npm-ca.crt new file mode 100644 index 0000000..fde2fe9 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/npm-ca.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x +IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w +bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y +MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV +BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj +YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA +aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE +OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz +Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl +y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC +l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv +yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl +ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op +-----END CERTIFICATE----- diff --git a/node_modules/less/node_modules/request/tests/ssl/test.crt b/node_modules/less/node_modules/request/tests/ssl/test.crt new file mode 100644 index 0000000..b357f86 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQzCCAawCCQCO/XWtRFck1jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJU +SDEQMA4GA1UECBMHQmFuZ2tvazEOMAwGA1UEBxMFU2lsb20xGzAZBgNVBAoTElRo +ZSBSZXF1ZXN0IE1vZHVsZTEYMBYGA1UEAxMPcmVxdWVzdC5leGFtcGxlMB4XDTEx +MTIwMzAyMjkyM1oXDTIxMTEzMDAyMjkyM1owZjELMAkGA1UEBhMCVEgxEDAOBgNV +BAgTB0Jhbmdrb2sxDjAMBgNVBAcTBVNpbG9tMRswGQYDVQQKExJUaGUgUmVxdWVz +dCBNb2R1bGUxGDAWBgNVBAMTD3JlcXVlc3QuZXhhbXBsZTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwmctddZqlA48+NXs0yOy92DijcQV1jf87zMiYAIlNUto +wghVbTWgJU5r0pdKrD16AptnWJTzKanhItEX8XCCPgsNkq1afgTtJP7rNkwu3xcj +eIMkhJg/ay4ZnkbnhYdsii5VTU5prix6AqWRAhbkBgoA+iVyHyof8wvZyKBoFTMC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQB6BybMJbpeiABgihDfEVBcAjDoQ8gUMgwV +l4NulugfKTDmArqnR9aPd4ET5jX5dkMP4bwCHYsvrcYDeWEQy7x5WWuylOdKhua4 +L4cEi2uDCjqEErIG3cc1MCOk6Cl6Ld6tkIzQSf953qfdEACRytOeUqLNQcrXrqeE +c7U8F6MWLQ== +-----END CERTIFICATE----- diff --git a/node_modules/less/node_modules/request/tests/ssl/test.key b/node_modules/less/node_modules/request/tests/ssl/test.key new file mode 100644 index 0000000..b85810d --- /dev/null +++ b/node_modules/less/node_modules/request/tests/ssl/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDCZy111mqUDjz41ezTI7L3YOKNxBXWN/zvMyJgAiU1S2jCCFVt +NaAlTmvSl0qsPXoCm2dYlPMpqeEi0RfxcII+Cw2SrVp+BO0k/us2TC7fFyN4gySE +mD9rLhmeRueFh2yKLlVNTmmuLHoCpZECFuQGCgD6JXIfKh/zC9nIoGgVMwIDAQAB +AoGBALXFwfUf8vHTSmGlrdZS2AGFPvEtuvldyoxi9K5u8xmdFCvxnOcLsF2RsTHt +Mu5QYWhUpNJoG+IGLTPf7RJdj/kNtEs7xXqWy4jR36kt5z5MJzqiK+QIgiO9UFWZ +fjUb6oeDnTIJA9YFBdYi97MDuL89iU/UK3LkJN3hd4rciSbpAkEA+MCkowF5kSFb +rkOTBYBXZfiAG78itDXN6DXmqb9XYY+YBh3BiQM28oxCeQYyFy6pk/nstnd4TXk6 +V/ryA2g5NwJBAMgRKTY9KvxJWbESeMEFe2iBIV0c26/72Amgi7ZKUCLukLfD4tLF ++WSZdmTbbqI1079YtwaiOVfiLm45Q/3B0eUCQAaQ/0eWSGE+Yi8tdXoVszjr4GXb +G81qBi91DMu6U1It+jNfIba+MPsiHLcZJMVb4/oWBNukN7bD1nhwFWdlnu0CQQCf +Is9WHkdvz2RxbZDxb8verz/7kXXJQJhx5+rZf7jIYFxqX3yvTNv3wf2jcctJaWlZ +fVZwB193YSivcgt778xlAkEAprYUz3jczjF5r2hrgbizPzPDR94tM5BTO3ki2v3w +kbf+j2g7FNAx6kZiVN8XwfLc8xEeUGiPKwtq3ddPDFh17w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/less/node_modules/request/tests/test-agentOptions.js b/node_modules/less/node_modules/request/tests/test-agentOptions.js new file mode 100644 index 0000000..47fe3aa --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-agentOptions.js @@ -0,0 +1,23 @@ +var request = require('../index') + , http = require('http') + , server = require('./server') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('') +}).listen(6767, function () { + // requests without agentOptions should use global agent + var r = request('http://localhost:6767', function (e, resp, body) { + assert.deepEqual(r.agent, http.globalAgent); + assert.equal(Object.keys(r.pool).length, 0); + + // requests with agentOptions should apply agentOptions to new agent in pool + var r2 = request('http://localhost:6767', { agentOptions: { foo: 'bar' } }, function (e, resp, body) { + assert.deepEqual(r2.agent.options, { foo: 'bar' }); + assert.equal(Object.keys(r2.pool).length, 1); + s.close() + }); + }) +}) diff --git a/node_modules/less/node_modules/request/tests/test-basic-auth.js b/node_modules/less/node_modules/request/tests/test-basic-auth.js new file mode 100644 index 0000000..3f48048 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-basic-auth.js @@ -0,0 +1,143 @@ +var assert = require('assert') + , http = require('http') + , request = require('../index') + ; + +var numBasicRequests = 0; + +var basicServer = http.createServer(function (req, res) { + console.error('Basic auth server: ', req.method, req.url); + numBasicRequests++; + + var ok; + + if (req.headers.authorization) { + if (req.headers.authorization == 'Basic ' + new Buffer('test:testing2').toString('base64')) { + ok = true; + } else if ( req.headers.authorization == 'Basic ' + new Buffer(':apassword').toString('base64')) { + ok = true; + } else { + // Bad auth header, don't send back WWW-Authenticate header + ok = false; + } + } else { + // No auth header, send back WWW-Authenticate header + ok = false; + res.setHeader('www-authenticate', 'Basic realm="Private"'); + } + + if (req.url == '/post/') { + var expectedContent = 'data_key=data_value'; + req.on('data', function(data) { + assert.equal(data, expectedContent); + console.log('received request data: ' + data); + }); + assert.equal(req.method, 'POST'); + assert.equal(req.headers['content-length'], '' + expectedContent.length); + assert.equal(req.headers['content-type'], 'application/x-www-form-urlencoded; charset=utf-8'); + } + + if (ok) { + console.log('request ok'); + res.end('ok'); + } else { + console.log('status=401'); + res.statusCode = 401; + res.end('401'); + } +}); + +basicServer.listen(6767); + +var tests = [ + function(next) { + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing2', + 'sendImmediately': false + } + }, function(error, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(numBasicRequests, 2); + next(); + }); + }, + + function(next) { + // If we don't set sendImmediately = false, request will send basic auth + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test2/', + 'auth': { + 'user': 'test', + 'pass': 'testing2' + } + }, function(error, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(numBasicRequests, 3); + next(); + }); + }, + + function(next) { + request({ + 'method': 'GET', + 'uri': 'http://test:testing2@localhost:6767/test2/' + }, function(error, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(numBasicRequests, 4); + next(); + }); + }, + + function(next) { + request({ + 'method': 'POST', + 'form': { 'data_key': 'data_value' }, + 'uri': 'http://localhost:6767/post/', + 'auth': { + 'user': 'test', + 'pass': 'testing2', + 'sendImmediately': false + } + }, function(error, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(numBasicRequests, 6); + next(); + }); + }, + + function(next) { + assert.doesNotThrow( function() { + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/allow_empty_user/', + 'auth': { + 'user': '', + 'pass': 'apassword', + 'sendImmediately': false + } + }, function(error, res, body ) { + assert.equal(res.statusCode, 200); + assert.equal(numBasicRequests, 8); + next(); + }); + }) + } +]; + +function runTest(i) { + if (i < tests.length) { + tests[i](function() { + runTest(i + 1); + }); + } else { + console.log('All tests passed'); + basicServer.close(); + } +} + +runTest(0); diff --git a/node_modules/less/node_modules/request/tests/test-body.js b/node_modules/less/node_modules/request/tests/test-body.js new file mode 100644 index 0000000..186de12 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-body.js @@ -0,0 +1,122 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetEncoding : + { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex')) + , encoding: 'hex' + , expectBody: "efa3bfcea9e29883" + } + , testGetUTF8: + { resp: server.createGetResponse(new Buffer([0xEF, 0xBB, 0xBF, 226, 152, 131])) + , encoding: "utf8" + , expectBody: "☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + , testPutMultipartPreambleCRLF : + { resp: server.createPostValidator( + '\r\n--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , preambleCRLF: true + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/less/node_modules/request/tests/test-defaults.js b/node_modules/less/node_modules/request/tests/test-defaults.js new file mode 100644 index 0000000..f6c4024 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-defaults.js @@ -0,0 +1,129 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); + +s.listen(s.port, function () { + var counter = 0; + s.on('/get', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'GET') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end('TESTING!'); + }); + + // test get(string, function) + request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){ + if (e) throw e; + assert.deepEqual("TESTING!", b); + counter += 1; + }); + + s.on('/post', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/patch', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'PATCH') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).patch(s.url + '/patch', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/post-body', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], 'application/json'); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) with body + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post-body', {json: true, body:{bar:"baz"}}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/del', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'DELETE') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test .del(string, function) + request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/head', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'HEAD') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test head.(object, function) + request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){ + if (e) throw e; + counter += 1; + }); + + s.on('/get_custom', function(req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers.x, 'y'); + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test custom request handler function + var defaultRequest = request.defaults({ + headers:{foo:"bar"} + , body: 'TESTING!' + }, function(uri, options, callback) { + var params = request.initParams(uri, options, callback); + options = params.options; + options.headers.x = 'y'; + + return request(params.uri, params.options, params.callback); + }); + + var msg = 'defaults test failed. head request should throw earlier'; + assert.throws(function() { + defaultRequest.head(s.url + '/get_custom', function(e, r, b) { + throw new Error(msg); + }); + counter+=1; + }, msg); + + defaultRequest.get(s.url + '/get_custom', function(e, r, b) { + if(e) throw e; + counter += 1; + console.log(counter.toString() + " tests passed."); + s.close(); + }); +}) diff --git a/node_modules/less/node_modules/request/tests/test-digest-auth.js b/node_modules/less/node_modules/request/tests/test-digest-auth.js new file mode 100644 index 0000000..5f2d6eb --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-digest-auth.js @@ -0,0 +1,69 @@ +var assert = require('assert') + , http = require('http') + , request = require('../index') + ; + +// Test digest auth +// Using header values captured from interaction with Apache + +var numDigestRequests = 0; + +var digestServer = http.createServer(function (req, res) { + console.error('Digest auth server: ', req.method, req.url); + numDigestRequests++; + + var ok; + + if (req.headers.authorization) { + if (req.headers.authorization == 'Digest username="test", realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", uri="/test/", qop="auth", response="54753ce37c10cb20b09b769f0bed730e", nc="1", cnonce=""') { + ok = true; + } else { + // Bad auth header, don't send back WWW-Authenticate header + ok = false; + } + } else { + // No auth header, send back WWW-Authenticate header + ok = false; + res.setHeader('www-authenticate', 'Digest realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", algorithm=MD5, qop="auth"'); + } + + if (ok) { + console.log('request ok'); + res.end('ok'); + } else { + console.log('status=401'); + res.statusCode = 401; + res.end('401'); + } +}); + +digestServer.listen(6767); + +request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing', + 'sendImmediately': false + } +}, function(error, response, body) { + assert.equal(response.statusCode, 200); + assert.equal(numDigestRequests, 2); + + // If we don't set sendImmediately = false, request will send basic auth + request({ + 'method': 'GET', + 'uri': 'http://localhost:6767/test/', + 'auth': { + 'user': 'test', + 'pass': 'testing' + } + }, function(error, response, body) { + assert.equal(response.statusCode, 401); + assert.equal(numDigestRequests, 3); + + console.log('All tests passed'); + digestServer.close(); + }); +}); diff --git a/node_modules/less/node_modules/request/tests/test-emptyBody.js b/node_modules/less/node_modules/request/tests/test-emptyBody.js new file mode 100644 index 0000000..338c92e --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-emptyBody.js @@ -0,0 +1,20 @@ +var request = require('../index') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp, body) { + assert.equal(resp.statusCode, 200) + assert.equal(body, "") + + var r2 = request({ url: 'http://localhost:8080', json: {} }, function (e, resp, body) { + assert.equal(resp.statusCode, 200) + assert.equal(body, undefined) + s.close() + }); + }) +}) diff --git a/node_modules/less/node_modules/request/tests/test-errors.js b/node_modules/less/node_modules/request/tests/test-errors.js new file mode 100644 index 0000000..4df1302 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-errors.js @@ -0,0 +1,37 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../index') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +try { + request(local, {multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/less/node_modules/request/tests/test-follow-all-303.js b/node_modules/less/node_modules/request/tests/test-follow-all-303.js new file mode 100644 index 0000000..956e386 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-follow-all-303.js @@ -0,0 +1,30 @@ +var request = require('../index'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + console.error(req.method, req.url); + requests ++; + + if (req.method === 'POST') { + console.error('send 303'); + res.setHeader('location', req.url); + res.statusCode = 303; + res.end('try again, i guess\n'); + } else { + console.error('send 200') + res.end('ok: ' + requests); + } +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 2'); + assert.equal(requests, 2); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/less/node_modules/request/tests/test-follow-all.js b/node_modules/less/node_modules/request/tests/test-follow-all.js new file mode 100644 index 0000000..035d632 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-follow-all.js @@ -0,0 +1,35 @@ +var request = require('../index'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + requests ++; + + // redirect everything 3 times, no matter what. + var c = req.headers.cookie; + + if (!c) c = 0; + else c = +c.split('=')[1] || 0; + + if (c > 3) { + res.end('ok: '+requests); + return; + } + + res.setHeader('set-cookie', 'c=' + (c + 1)); + res.setHeader('location', req.url); + res.statusCode = 302; + res.end('try again, i guess\n'); +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 5'); + assert.equal(requests, 5); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/less/node_modules/request/tests/test-form.js b/node_modules/less/node_modules/request/tests/test-form.js new file mode 100644 index 0000000..91b9230 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-form.js @@ -0,0 +1,79 @@ +var assert = require('assert') +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('../index'); +var fs = require('fs'); + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(__dirname + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(8080, function() { + + var req = request.post('http://localhost:8080/upload', function () { + server.close(); + }) + var form = req.form() + + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/less/node_modules/request/tests/test-hawk.js b/node_modules/less/node_modules/request/tests/test-hawk.js new file mode 100755 index 0000000..8454625 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-hawk.js @@ -0,0 +1,33 @@ +var createServer = require('http').createServer + , request = require('../index') + , hawk = require('hawk') + , assert = require('assert') + ; + +var server = createServer(function (req, resp) { + + var getCred = function (id, callback) { + assert.equal(id, 'dh37fgj492je') + var credentials = + { key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn' + , algorithm: 'sha256' + , user: 'Steve' + } + return callback(null, credentials) + } + + hawk.server.authenticate(req, getCred, {}, function (err, credentials, attributes) { + resp.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' }) + resp.end(!err ? 'Hello ' + credentials.user : 'Shoosh!') + }) + +}) + +server.listen(8080, function () { + var creds = {key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', algorithm: 'sha256', id:'dh37fgj492je'} + request('http://localhost:8080', {hawk:{credentials:creds}}, function (e, r, b) { + assert.equal(200, r.statusCode) + assert.equal(b, 'Hello Steve') + server.close() + }) +}) \ No newline at end of file diff --git a/node_modules/less/node_modules/request/tests/test-headers.js b/node_modules/less/node_modules/request/tests/test-headers.js new file mode 100644 index 0000000..3982b9b --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-headers.js @@ -0,0 +1,52 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , Cookie = require('cookie-jar') + , Jar = Cookie.Jar + , s = server.createServer() + +s.listen(s.port, function () { + var serverUri = 'http://localhost:' + s.port + , numTests = 0 + , numOutstandingTests = 0 + + function createTest(requestObj, serverAssertFn) { + var testNumber = numTests; + numTests += 1; + numOutstandingTests += 1; + s.on('/' + testNumber, function (req, res) { + serverAssertFn(req, res); + res.writeHead(200); + res.end(); + }); + requestObj.url = serverUri + '/' + testNumber + request(requestObj, function (err, res, body) { + assert.ok(!err) + assert.equal(res.statusCode, 200) + numOutstandingTests -= 1 + if (numOutstandingTests === 0) { + console.log(numTests + ' tests passed.') + s.close() + } + }) + } + + // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified + createTest({headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar') + }) + + // Issue #125: headers.cookie + cookie jar + var jar = new Jar() + jar.add(new Cookie('quux=baz')); + createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar; quux=baz') + }) + + // There should be no cookie header when neither headers.cookie nor a cookie jar is specified + createTest({}, function (req, res) { + assert.ok(!req.headers.cookie) + }) +}) diff --git a/node_modules/less/node_modules/request/tests/test-http-signature.js b/node_modules/less/node_modules/request/tests/test-http-signature.js new file mode 100755 index 0000000..9300473 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-http-signature.js @@ -0,0 +1,106 @@ +var createServer = require('http').createServer + , request = require('../index') + , httpSignature = require('http-signature') + , assert = require('assert') + ; + +var privateKeyPEMs = {} + +privateKeyPEMs['key-1'] = + '-----BEGIN RSA PRIVATE KEY-----\n' + + 'MIIEpAIBAAKCAQEAzWSJl+Z9Bqv00FVL5N3+JCUoqmQPjIlya1BbeqQroNQ5yG1i\n' + + 'VbYTTnMRa1zQtR6r2fNvWeg94DvxivxIG9diDMnrzijAnYlTLOl84CK2vOxkj5b6\n' + + '8zrLH9b/Gd6NOHsywo8IjvXvCeTfca5WUHcuVi2lT9VjygFs1ILG4RyeX1BXUumu\n' + + 'Y8fzmposxLYdMxCqUTzAn0u9Saq2H2OVj5u114wS7OQPigu6G99dpn/iPHa3zBm8\n' + + '7baBWDbqZWRW0BP3K6eqq8sut1+NLhNW8ADPTdnO/SO+kvXy7fqd8atSn+HlQcx6\n' + + 'tW42dhXf3E9uE7K78eZtW0KvfyNGAjsI1Fft2QIDAQABAoIBAG1exe3/LEBrPLfb\n' + + 'U8iRdY0lxFvHYIhDgIwohC3wUdMYb5SMurpNdEZn+7Sh/fkUVgp/GKJViu1mvh52\n' + + 'bKd2r52DwG9NQBQjVgkqY/auRYSglIPpr8PpYNSZlcneunCDGeqEY9hMmXc5Ssqs\n' + + 'PQYoEKKPN+IlDTg6PguDgAfLR4IUvt9KXVvmB/SSgV9tSeTy35LECt1Lq3ozbUgu\n' + + '30HZI3U6/7H+X22Pxxf8vzBtzkg5rRCLgv+OeNPo16xMnqbutt4TeqEkxRv5rtOo\n' + + '/A1i9khBeki0OJAFJsE82qnaSZodaRsxic59VnN8sWBwEKAt87tEu5A3K3j4XSDU\n' + + '/avZxAECgYEA+pS3DvpiQLtHlaO3nAH6MxHRrREOARXWRDe5nUQuUNpS1xq9wte6\n' + + 'DkFtba0UCvDLic08xvReTCbo9kH0y6zEy3zMpZuJlKbcWCkZf4S5miYPI0RTZtF8\n' + + 'yps6hWqzYFSiO9hMYws9k4OJLxX0x3sLK7iNZ32ujcSrkPBSiBr0gxkCgYEA0dWl\n' + + '637K41AJ/zy0FP0syq+r4eIkfqv+/t6y2aQVUBvxJYrj9ci6XHBqoxpDV8lufVYj\n' + + 'fUAfeI9/MZaWvQJRbnYLre0I6PJfLuCBIL5eflO77BGso165AF7QJZ+fwtgKv3zv\n' + + 'ZX75eudCSS/cFo0po9hlbcLMT4B82zEkgT8E2MECgYEAnz+3/wrdOmpLGiyL2dff\n' + + '3GjsqmJ2VfY8z+niSrI0BSpbD11tT9Ct67VlCBjA7hsOH6uRfpd6/kaUMzzDiFVq\n' + + 'VDAiFvV8QD6zNkwYalQ9aFvbrvwTTPrBpjl0vamMCiJ/YC0cjq1sGr2zh3sar1Ph\n' + + 'S43kP+s97dcZeelhaiJHVrECgYEAsx61q/loJ/LDFeYzs1cLTVn4V7I7hQY9fkOM\n' + + 'WM0AhInVqD6PqdfXfeFYpjJdGisQ7l0BnoGGW9vir+nkcyPvb2PFRIr6+B8tsU5j\n' + + '7BeVgjDoUfQkcrEBK5fEBtnj/ud9BUkY8oMZZBjVNLRuI7IMwZiPvMp0rcj4zAN/\n' + + 'LfUlpgECgYArBvFcBxSkNAzR3Rtteud1YDboSKluRM37Ey5plrn4BS0DD0jm++aD\n' + + '0pG2Hsik000hibw92lCkzvvBVAqF8BuAcnPlAeYfsOaa97PGEjSKEN5bJVWZ9/om\n' + + '9FV1axotRN2XWlwrhixZLEaagkREXhgQc540FS5O8IaI2Vpa80Atzg==\n' + + '-----END RSA PRIVATE KEY-----' + +var publicKeyPEMs = {} + +publicKeyPEMs['key-1'] = + '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzWSJl+Z9Bqv00FVL5N3+\n' + + 'JCUoqmQPjIlya1BbeqQroNQ5yG1iVbYTTnMRa1zQtR6r2fNvWeg94DvxivxIG9di\n' + + 'DMnrzijAnYlTLOl84CK2vOxkj5b68zrLH9b/Gd6NOHsywo8IjvXvCeTfca5WUHcu\n' + + 'Vi2lT9VjygFs1ILG4RyeX1BXUumuY8fzmposxLYdMxCqUTzAn0u9Saq2H2OVj5u1\n' + + '14wS7OQPigu6G99dpn/iPHa3zBm87baBWDbqZWRW0BP3K6eqq8sut1+NLhNW8ADP\n' + + 'TdnO/SO+kvXy7fqd8atSn+HlQcx6tW42dhXf3E9uE7K78eZtW0KvfyNGAjsI1Fft\n' + + '2QIDAQAB\n' + + '-----END PUBLIC KEY-----' + +publicKeyPEMs['key-2'] = + '-----BEGIN PUBLIC KEY-----\n' + + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqp04VVr9OThli9b35Omz\n' + + 'VqSfWbsoQuRrgyWsrNRn3XkFmbWw4FzZwQ42OgGMzQ84Ta4d9zGKKQyFriTiPjPf\n' + + 'xhhrsaJnDuybcpVhcr7UNKjSZ0S59tU3hpRiEz6hO+Nc/OSSLkvalG0VKrxOln7J\n' + + 'LK/h3rNS/l6wDZ5S/KqsI6CYtV2ZLpn3ahLrizvEYNY038Qcm38qMWx+VJAvZ4di\n' + + 'qqmW7RLIsLT59SWmpXdhFKnkYYGhxrk1Mwl22dBTJNY5SbriU5G3gWgzYkm8pgHr\n' + + '6CtrXch9ciJAcDJehPrKXNvNDOdUh8EW3fekNJerF1lWcwQg44/12v8sDPyfbaKB\n' + + 'dQIDAQAB\n' + + '-----END PUBLIC KEY-----' + +var server = createServer(function (req, res) { + var parsed = httpSignature.parseRequest(req) + var publicKeyPEM = publicKeyPEMs[parsed.keyId] + var verified = httpSignature.verifySignature(parsed, publicKeyPEM) + res.writeHead(verified ? 200 : 400) + res.end() +}) + +server.listen(8080, function () { + function correctKeyTest(callback) { + var options = { + httpSignature: { + keyId: 'key-1', + key: privateKeyPEMs['key-1'] + } + } + request('http://localhost:8080', options, function (e, r, b) { + assert.equal(200, r.statusCode) + callback() + }) + } + + function incorrectKeyTest(callback) { + var options = { + httpSignature: { + keyId: 'key-2', + key: privateKeyPEMs['key-1'] + } + } + request('http://localhost:8080', options, function (e, r, b) { + assert.equal(400, r.statusCode) + callback() + }) + } + + var tests = [correctKeyTest, incorrectKeyTest] + var todo = tests.length; + for(var i = 0; i < tests.length; ++i) { + tests[i](function() { + if(!--todo) { + server.close() + } + }) + } +}) diff --git a/node_modules/less/node_modules/request/tests/test-httpModule.js b/node_modules/less/node_modules/request/tests/test-httpModule.js new file mode 100644 index 0000000..2c19615 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-httpModule.js @@ -0,0 +1,94 @@ +var http = require('http') + , https = require('https') + , server = require('./server') + , assert = require('assert') + , request = require('../index') + + +var faux_requests_made = {'http':0, 'https':0} +function wrap_request(name, module) { + // Just like the http or https module, but note when a request is made. + var wrapped = {} + Object.keys(module).forEach(function(key) { + var value = module[key]; + + if(key != 'request') + wrapped[key] = value; + else + wrapped[key] = function(options, callback) { + faux_requests_made[name] += 1 + return value.apply(this, arguments) + } + }) + + return wrapped; +} + + +var faux_http = wrap_request('http', http) + , faux_https = wrap_request('https', https) + , plain_server = server.createServer() + , https_server = server.createSSLServer() + + +plain_server.listen(plain_server.port, function() { + plain_server.on('/plain', function (req, res) { + res.writeHead(200) + res.end('plain') + }) + plain_server.on('/to_https', function (req, res) { + res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'}) + res.end() + }) + + https_server.listen(https_server.port, function() { + https_server.on('/https', function (req, res) { + res.writeHead(200) + res.end('https') + }) + https_server.on('/to_plain', function (req, res) { + res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'}) + res.end() + }) + + run_tests() + run_tests({}) + run_tests({'http:':faux_http}) + run_tests({'https:':faux_https}) + run_tests({'http:':faux_http, 'https:':faux_https}) + }) +}) + +function run_tests(httpModules) { + var to_https = 'http://localhost:'+plain_server.port+'/to_https' + var to_plain = 'https://localhost:'+https_server.port+'/to_plain' + + request(to_https, {'httpModules':httpModules, strictSSL:false}, function (er, res, body) { + if (er) throw er + assert.equal(body, 'https', 'Received HTTPS server body') + done() + }) + + request(to_plain, {'httpModules':httpModules, strictSSL:false}, function (er, res, body) { + if (er) throw er + assert.equal(body, 'plain', 'Received HTTPS server body') + done() + }) +} + + +var passed = 0; +function done() { + passed += 1 + var expected = 10 + + if(passed == expected) { + plain_server.close() + https_server.close() + + assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately') + assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately') + + console.log((expected+2) + ' tests passed.') + } +} diff --git a/node_modules/less/node_modules/request/tests/test-https-strict.js b/node_modules/less/node_modules/request/tests/test-https-strict.js new file mode 100644 index 0000000..d49a9af --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-https-strict.js @@ -0,0 +1,97 @@ +// a test where we validate the siguature of the keys +// otherwise exactly the same as the ssl test + +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , fs = require('fs') + , path = require('path') + , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key') + , cert: path.resolve(__dirname, 'ssl/ca/server.crt') } + , s = server.createSSLServer(null, opts) + , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt') + , ca = fs.readFileSync(caFile) + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.strictSSL = true + test.ca = ca + test.headers = { host: 'testing.request.mikealrogers.com' } + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/less/node_modules/request/tests/test-https.js b/node_modules/less/node_modules/request/tests/test-https.js new file mode 100644 index 0000000..b6858d4 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-https.js @@ -0,0 +1,87 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + +var s = server.createSSLServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.rejectUnauthorized = false + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/less/node_modules/request/tests/test-localAddress.js b/node_modules/less/node_modules/request/tests/test-localAddress.js new file mode 100644 index 0000000..11a1bd1 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-localAddress.js @@ -0,0 +1,15 @@ +var request = require('../index') + , assert = require('assert') + ; + +request.get({ + uri: 'http://www.google.com', localAddress: '1.2.3.4' // some invalid address +}, function(err, res) { + assert(!res) // asserting that no response received +}) + +request.get({ + uri: 'http://www.google.com', localAddress: '127.0.0.1' +}, function(err, res) { + assert(!res) // asserting that no response received +}) diff --git a/node_modules/less/node_modules/request/tests/test-oauth.js b/node_modules/less/node_modules/request/tests/test-oauth.js new file mode 100644 index 0000000..3269483 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-oauth.js @@ -0,0 +1,117 @@ +var hmacsign = require('oauth-sign').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../index') + ; + +function getsignature (r) { + var sign + r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var rsign = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +setTimeout(function () { + console.log(getsignature(rsign)) + assert.equal(reqsign, getsignature(rsign)) +}) + +var raccsign = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +setTimeout(function () { + console.log(getsignature(raccsign)) + assert.equal(accsign, getsignature(raccsign)) +}, 1) + +var rupsign = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) +setTimeout(function () { + console.log(getsignature(rupsign)) + assert.equal(upsign, getsignature(rupsign)) +}, 1) + + + + diff --git a/node_modules/less/node_modules/request/tests/test-onelineproxy.js b/node_modules/less/node_modules/request/tests/test-onelineproxy.js new file mode 100644 index 0000000..c239f89 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-onelineproxy.js @@ -0,0 +1,46 @@ +var http = require('http') + , assert = require('assert') + , request = require('../index') + ; + +var server = http.createServer(function (req, resp) { + resp.statusCode = 200 + if (req.url === '/get') { + assert.equal(req.method, 'GET') + resp.write('content') + resp.end() + return + } + if (req.url === '/put') { + var x = '' + assert.equal(req.method, 'PUT') + req.on('data', function (chunk) { + x += chunk + }) + req.on('end', function () { + assert.equal(x, 'content') + resp.write('success') + resp.end() + }) + return + } + if (req.url === '/proxy') { + assert.equal(req.method, 'PUT') + return req.pipe(request('http://localhost:8080/put')).pipe(resp) + } + + if (req.url === '/test') { + return request('http://localhost:8080/get').pipe(request.put('http://localhost:8080/proxy')).pipe(resp) + } + throw new Error('Unknown url', req.url) +}).listen(8080, function () { + request('http://localhost:8080/test', function (e, resp, body) { + if (e) throw e + if (resp.statusCode !== 200) throw new Error('statusCode not 200 ' + resp.statusCode) + assert.equal(body, 'success') + server.close() + }) +}) + + + diff --git a/node_modules/less/node_modules/request/tests/test-params.js b/node_modules/less/node_modules/request/tests/test-params.js new file mode 100644 index 0000000..a5831a1 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-params.js @@ -0,0 +1,93 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + //test.uri = s.url + '/' + i + request(s.url + '/' + i, test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + assert.notEqual(typeof test.callback, 'function') + console.log(1 + Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/less/node_modules/request/tests/test-piped-redirect.js b/node_modules/less/node_modules/request/tests/test-piped-redirect.js new file mode 100644 index 0000000..e295ec7 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-piped-redirect.js @@ -0,0 +1,42 @@ +var http = require('http') + , assert = require('assert') + , request = require('../index') + ; + +var portOne = 8968 + , portTwo = 8969 + ; + + +// server one +var s1 = http.createServer(function (req, resp) { + if (req.url == '/original') { + resp.writeHeader(302, {'location': '/redirected'}) + resp.end() + } else if (req.url == '/redirected') { + resp.writeHeader(200, {'content-type': 'text/plain'}) + resp.write('OK') + resp.end() + } + +}).listen(portOne); + + +// server two +var s2 = http.createServer(function (req, resp) { + var x = request('http://localhost:'+portOne+'/original') + req.pipe(x) + x.pipe(resp) + +}).listen(portTwo, function () { + var r = request('http://localhost:'+portTwo+'/original', function (err, res, body) { + assert.equal(body, 'OK') + + s1.close() + s2.close() + }); + + // it hangs, so wait a second :) + r.timeout = 1000; + +}) diff --git a/node_modules/less/node_modules/request/tests/test-pipes.js b/node_modules/less/node_modules/request/tests/test-pipes.js new file mode 100644 index 0000000..52a15cc --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-pipes.js @@ -0,0 +1,216 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../index') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + // Test pipeing to a request object with a json body + s.once('/push-json', server.createPostValidator("{\"foo\":\"bar\"}", "application/json")); + + var mybodydata = new stream.Stream(); + mybodydata.readable = true + + counter++ + var r2 = request.put({url:'http://localhost:3453/push-json',json:true}, function () { + check(); + }) + mybodydata.pipe(r2) + + mybodydata.emit('data', JSON.stringify({foo:"bar"})); + mybodydata.emit('end'); + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'application/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/jpeg'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.jpg')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.jpg')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.jpg')), fs.readFileSync(path.join(__dirname, 'test.jpg'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.jpg')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + + s.on('/forward1', function (req, resp) { + resp.writeHead(302, {location:'/forward2'}) + resp.end() + }) + s.on('/forward2', function (req, resp) { + resp.writeHead('200', {'content-type':'image/png'}) + resp.write('d') + resp.end() + }) + + counter++ + var validateForward = new ValidationStream('d') + validateForward.on('end', check) + request.get('http://localhost:3453/forward1').pipe(validateForward) + + // Test pipe options + s.once('/opts', server.createGetResponse('opts response')); + + var optsStream = new stream.Stream(); + optsStream.writable = true + + var optsData = ''; + optsStream.write = function (buf) { + optsData += buf; + if (optsData === 'opts response') { + setTimeout(check, 10); + } + } + + optsStream.end = function () { + assert.fail('end called') + }; + + counter++ + request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false }) +}) diff --git a/node_modules/less/node_modules/request/tests/test-pool.js b/node_modules/less/node_modules/request/tests/test-pool.js new file mode 100644 index 0000000..791ee8b --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-pool.js @@ -0,0 +1,16 @@ +var request = require('../index') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200; + resp.end('asdf'); +}).listen(8080, function () { + request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) { + var agent = resp.request.agent; + assert.strictEqual(typeof agent, 'boolean'); + assert.strictEqual(agent, false); + s.close(); + }); +}); \ No newline at end of file diff --git a/node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js b/node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js new file mode 100644 index 0000000..7e83a41 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-protocol-changing-redirect.js @@ -0,0 +1,61 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + + +var s = server.createServer() +var ss = server.createSSLServer() +var sUrl = 'http://localhost:' + s.port +var ssUrl = 'https://localhost:' + ss.port + +s.listen(s.port, bouncy(s, ssUrl)) +ss.listen(ss.port, bouncy(ss, sUrl)) + +var hits = {} +var expect = {} +var pending = 0 +function bouncy (s, server) { return function () { + + var redirs = { a: 'b' + , b: 'c' + , c: 'd' + , d: 'e' + , e: 'f' + , f: 'g' + , g: 'h' + , h: 'end' } + + var perm = true + Object.keys(redirs).forEach(function (p) { + var t = redirs[p] + + // switch type each time + var type = perm ? 301 : 302 + perm = !perm + s.on('/' + p, function (req, res) { + res.writeHead(type, { location: server + '/' + t }) + res.end() + }) + }) + + s.on('/end', function (req, res) { + var h = req.headers['x-test-key'] + hits[h] = true + pending -- + if (pending === 0) done() + }) +}} + +for (var i = 0; i < 5; i ++) { + pending ++ + var val = 'test_' + i + expect[val] = true + request({ url: (i % 2 ? sUrl : ssUrl) + '/a' + , headers: { 'x-test-key': val } + , rejectUnauthorized: false }) +} + +function done () { + assert.deepEqual(hits, expect) + process.exit(0) +} diff --git a/node_modules/less/node_modules/request/tests/test-proxy.js b/node_modules/less/node_modules/request/tests/test-proxy.js new file mode 100644 index 0000000..e183d68 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../index') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/less/node_modules/request/tests/test-qs.js b/node_modules/less/node_modules/request/tests/test-qs.js new file mode 100644 index 0000000..65958e6 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-qs.js @@ -0,0 +1,42 @@ +var request = request = require('../index') + , assert = require('assert') + ; + + +// Test adding a querystring +var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req1.path) +}, 1) + +// Test replacing a querystring value +var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req2.path) +}, 1) + +// Test appending a querystring value to the ones present in the uri +var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?x=y&q=search', req3.path) +}, 1) + +// Test leaving a querystring alone +var req4 = request.get({ uri: 'http://www.google.com?x=y'}) +setTimeout(function() { + assert.equal('/?x=y', req4.path) +}, 1) + +// Test giving empty qs property +var req5 = request.get({ uri: 'http://www.google.com', qs: {}}) +setTimeout(function(){ + assert.equal('/', req5.path) +}, 1) + + +// Test modifying the qs after creating the request +var req6 = request.get({ uri: 'http://www.google.com', qs: {}}); +req6.qs({ q: "test" }); +process.nextTick(function() { + assert.equal('/?q=test', req6.path); +}); diff --git a/node_modules/less/node_modules/request/tests/test-redirect.js b/node_modules/less/node_modules/request/tests/test-redirect.js new file mode 100644 index 0000000..cdd4606 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-redirect.js @@ -0,0 +1,155 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , Cookie = require('cookie-jar') + , Jar = Cookie.Jar + ; + +var s = server.createServer() + +s.listen(s.port, function () { + var server = 'http://localhost:' + s.port; + var hits = {} + var passed = 0; + + bouncer(301, 'temp') + bouncer(302, 'perm') + bouncer(302, 'nope') + + function bouncer(code, label) { + var landing = label+'_landing'; + + s.on('/'+label, function (req, res) { + hits[label] = true; + res.writeHead(code, { + 'location':server + '/'+landing, + 'set-cookie': 'ham=eggs' + }) + res.end() + }) + + s.on('/'+landing, function (req, res) { + if (req.method !== 'GET') { // We should only accept GET redirects + console.error("Got a non-GET request to the redirect destination URL"); + res.writeHead(400); + res.end(); + return; + } + // Make sure the cookie doesn't get included twice, see #139: + // Make sure cookies are set properly after redirect + assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs'); + hits[landing] = true; + res.writeHead(200) + res.end(landing) + }) + } + + // Permanent bounce + var jar = new Jar() + jar.add(new Cookie('quux=baz')) + request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.perm, 'Original request is to /perm') + assert.ok(hits.perm_landing, 'Forward to permanent landing URL') + assert.equal(body, 'perm_landing', 'Got permanent landing content') + passed += 1 + done() + }) + + // Temporary bounce + request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + // Prevent bouncing. + request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode) + assert.ok(hits.nope, 'Original request to /nope') + assert.ok(!hits.nope_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 302, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow post redirects by default + request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when post') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow post redirects when followAllRedirects true + request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects by default + request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode < 301) throw new Error('Status is not a redirect.') + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects even if followRedirect is set to true + request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow delete redirects when followAllRedirects true + request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + var reqs_done = 0; + function done() { + reqs_done += 1; + if(reqs_done == 9) { + console.log(passed + ' tests passed.') + s.close() + } + } +}) diff --git a/node_modules/less/node_modules/request/tests/test-s3.js b/node_modules/less/node_modules/request/tests/test-s3.js new file mode 100644 index 0000000..0f6a832 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-s3.js @@ -0,0 +1,13 @@ +var request = require('../index') + +var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', + { aws: + { key: 'AKIAI6KIQRRVMGK3WK5Q' + , secret: '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' + , bucket: 'log.curlybracecast.com' + } + }, function (e, resp, body) { + console.log(r.headers) + console.log(body) + } +) \ No newline at end of file diff --git a/node_modules/less/node_modules/request/tests/test-timeout.js b/node_modules/less/node_modules/request/tests/test-timeout.js new file mode 100644 index 0000000..7036367 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../index') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/less/node_modules/request/tests/test-toJSON.js b/node_modules/less/node_modules/request/tests/test-toJSON.js new file mode 100644 index 0000000..6d5f92a --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-toJSON.js @@ -0,0 +1,14 @@ +var request = require('../index') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('asdf') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp) { + assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200) + s.close() + }) +}) \ No newline at end of file diff --git a/node_modules/less/node_modules/request/tests/test-tunnel.js b/node_modules/less/node_modules/request/tests/test-tunnel.js new file mode 100644 index 0000000..2ee3f39 --- /dev/null +++ b/node_modules/less/node_modules/request/tests/test-tunnel.js @@ -0,0 +1,75 @@ +// test that we can tunnel a https request over an http proxy +// keeping all the CA and whatnot intact. +// +// Note: this requires that squid is installed. +// If the proxy fails to start, we'll just log a warning and assume success. + +var server = require('./server') + , assert = require('assert') + , request = require('../index') + , fs = require('fs') + , path = require('path') + , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt') + , ca = fs.readFileSync(caFile) + , child_process = require('child_process') + , sqConf = path.resolve(__dirname, 'squid.conf') + , sqArgs = ['-f', sqConf, '-N', '-d', '5'] + , proxy = 'http://localhost:3128' + , hadError = null + +var squid = child_process.spawn('squid', sqArgs); +var ready = false + +squid.stderr.on('data', function (c) { + console.error('SQUIDERR ' + c.toString().trim().split('\n') + .join('\nSQUIDERR ')) + ready = c.toString().match(/ready to serve requests|Accepting HTTP Socket connections/i) +}) + +squid.stdout.on('data', function (c) { + console.error('SQUIDOUT ' + c.toString().trim().split('\n') + .join('\nSQUIDOUT ')) +}) + +squid.on('error', function (c) { + console.error('squid: error '+c) + if (c && !ready) { + notInstalled() + return + } +}) + +squid.on('exit', function (c) { + console.error('squid: exit '+c) + if (c && !ready) { + notInstalled() + return + } + + if (c) { + hadError = hadError || new Error('Squid exited with '+c) + } + if (hadError) throw hadError +}) + +setTimeout(function F () { + if (!ready) return setTimeout(F, 100) + request({ uri: 'https://registry.npmjs.org/' + , proxy: 'http://localhost:3128' + , strictSSL: true + , ca: ca + , json: true }, function (er, body) { + hadError = er + console.log(er || typeof body) + if (!er) console.log("ok") + squid.kill('SIGKILL') + }) +}, 100) + +function notInstalled() { + console.error('squid must be installed to run this test.') + console.error('skipping this test. please install squid and run again if you need to test tunneling.') + c = null + hadError = null + process.exit(0) +} diff --git a/node_modules/less/node_modules/request/tests/unicycle.jpg b/node_modules/less/node_modules/request/tests/unicycle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cea4dd71dc41cd51c84bfcec6b3e65c15a58507 GIT binary patch literal 19806 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 literal 0 HcmV?d00001 diff --git a/node_modules/less/node_modules/ycssmin/.npmignore b/node_modules/less/node_modules/ycssmin/.npmignore new file mode 100644 index 0000000..2833b69 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/.npmignore @@ -0,0 +1,11 @@ +node-cssmin.esproj +**/npm-debug.log +node_modules/ +coverage/ +tmp/ +CVS/ +.DS_Store +.*.swp +.svn +*~ +.com.apple.timemachine.supported diff --git a/node_modules/less/node_modules/ycssmin/.travis.yml b/node_modules/less/node_modules/ycssmin/.travis.yml new file mode 100644 index 0000000..c2b7b8e --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 +branches: + only: + - master diff --git a/node_modules/less/node_modules/ycssmin/LICENSE b/node_modules/less/node_modules/ycssmin/LICENSE new file mode 100644 index 0000000..22960b6 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/LICENSE @@ -0,0 +1,25 @@ +Copyright 2012 Yahoo! Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yahoo! Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/node_modules/less/node_modules/ycssmin/Makefile b/node_modules/less/node_modules/ycssmin/Makefile new file mode 100644 index 0000000..3d9707d --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/Makefile @@ -0,0 +1,14 @@ +all: + npm -g i . + +lint: + npm run-script pretest + +test: + npm test + +coverage: test + rm -rRf ../ycssmin-pages/* + cp -R ./coverage/lcov-report/* ../ycssmin-pages/ + +.PHONY: lint coverage test diff --git a/node_modules/less/node_modules/ycssmin/README.md b/node_modules/less/node_modules/ycssmin/README.md new file mode 100644 index 0000000..e21544b --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/README.md @@ -0,0 +1,97 @@ +CSSMin +====== + +This project is a fork of [jbleuzen/node-cssmin](https://github.com/jbleuzen/node-cssmin). + +It was originally based on the javascript for of the css minification tool used inside of +[YUICompressor](https://github.com/yui/yuicompressor) based on code from Stoyan Stefanov and Isaac Schlueter. + +We forked this project in order to maintain and up keep it on a regular basis. + + +Installation +------------ + +You can either download the plugin and unzip it into to your project folder or you can use npm to install the `ycssmin` package. + +`npm -g i ycssmin` + +Build Status +------------ + +[![Build Status](https://secure.travis-ci.org/yui/ycssmin.png)](http://travis-ci.org/yui/ycssmin) + +Testing +------- + +Clone this repo: + +`npm test` + +Code Coverage +------------- + +We are using [istanbul](https://github.com/gotwarlost/istanbul) to provide code coverage, to view the report: + +`npm test` + +Then open `./coverage/lcov-report` + +We also publish the [latest here](http://yui.github.com/ycssmin/). + +We ask that all patches have a test attached and full coverage. + +Usage +----- + +The module exports the cssmin function, so you can use it with: + +`var cssmin = require('ycssmin').cssmin;` + +The function cssmin takes two arguments: +* `input` : the CSS content you want to minimize. +* `linebreakpos` : the number of characters before the end of the line. If empty, the output will have only one line. + +Example : + +```javascript +var fs = require('fs'), + cssmin = require('ycssmin').cssmin, + css = fs.readFileSync("/Any/Random/CSS/File.css", encoding='utf8'), + min = cssmin(css); + +console.log(min); +``` + +License +------- + + Copyright 2012 Yahoo! Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yahoo! Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Thanks +------ + +Thanks to Johan BLEUZEN for originally porting this to node.js diff --git a/node_modules/less/node_modules/ycssmin/bin/cssmin b/node_modules/less/node_modules/ycssmin/bin/cssmin new file mode 100755 index 0000000..ccff8f0 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/bin/cssmin @@ -0,0 +1,27 @@ +#!/usr/bin/env node +// -*- js -*- + +var args = process.argv.slice(2), + cssmin = require('../cssmin').cssmin; + +function squeeze_out(css_in) { + process.stdout.write( cssmin(css_in) ); +} + +if (args.length) { + require("fs").readFile( args[0], "utf8", function(err, css_in) { + if (err) { + throw err; + } + else { + squeeze_out(css_in); + } + } ); +} +else { + var stdin = process.openStdin(); + stdin.setEncoding("utf8"); + var css_in = ""; + stdin.on("end", function() { squeeze_out(css_in) }); + stdin.on("data", function(chunk) { css_in += chunk }); +} diff --git a/node_modules/less/node_modules/ycssmin/cssmin.js b/node_modules/less/node_modules/ycssmin/cssmin.js new file mode 100755 index 0000000..4aec1bf --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/cssmin.js @@ -0,0 +1,361 @@ +/*jshint maxlen: 250 */ + +/** + * node-cssmin + * A simple module for Node.js that minify CSS + * Author : Johan Bleuzen + * Forked and modified by YUI + */ + +/** + * cssmin.js + * Author: Stoyan Stefanov - http://phpied.com/ + * This is a JavaScript port of the CSS minification tool + * distributed with YUICompressor, itself a port + * of the cssmin utility by Isaac Schlueter - http://foohack.com/ + * Permission is hereby granted to use the JavaScript version under the same + * conditions as the YUICompressor (original YUICompressor note below). + */ + +/* +* YUI Compressor +* http://yui.github.com/yuicompressor/ +* Author: Julien Lecomte - http://www.julienlecomte.net/ +* Copyright (c) 2011 Yahoo! Inc. All rights reserved. +* The copyrights embodied in the content of this file are licensed +* by Yahoo! Inc. under the BSD (revised) open source license. +*/ + + +var _compressHexColors = function(css) { + + // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) + var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi, + m, + index = 0, + isFilter, + sb = []; + + while ((m = pattern.exec(css)) !== null) { + + sb.push(css.substring(index, m.index)); + + isFilter = m[1]; + + if (isFilter) { + // Restore, maintain case, otherwise filter will break + sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7])); + } else { + if (m[2].toLowerCase() === m[3].toLowerCase() && + m[4].toLowerCase() === m[5].toLowerCase() && + m[6].toLowerCase() === m[7].toLowerCase()) { + + // Compress. + sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase()); + } else { + // Non compressible color, restore but lower case. + sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase()); + } + } + + index = pattern.lastIndex = pattern.lastIndex - m[8].length; + } + + sb.push(css.substring(index)); + + return sb.join(""); +}; + + +var _extractDataUrls = function (css, preservedTokens) { + + // Leave data urls alone to increase parse performance. + var maxIndex = css.length - 1, + appendIndex = 0, + startIndex, + endIndex, + terminator, + foundTerminator, + sb = [], + m, + preserver, + token, + pattern = /url\(\s*(["']?)data\:/g; + + // Since we need to account for non-base64 data urls, we need to handle + // ' and ) being part of the data string. Hence switching to indexOf, + // to determine whether or not we have matching string terminators and + // handling sb appends directly, instead of using matcher.append* methods. + + while ((m = pattern.exec(css)) !== null) { + + startIndex = m.index + 4; // "url(".length() + terminator = m[1]; // ', " or empty (not quoted) + + if (terminator.length === 0) { + terminator = ")"; + } + + foundTerminator = false; + + endIndex = pattern.lastIndex - 1; + + while(foundTerminator === false && endIndex+1 <= maxIndex) { + endIndex = css.indexOf(terminator, endIndex + 1); + + // endIndex == 0 doesn't really apply here + if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) { + foundTerminator = true; + if (")" !== terminator) { + endIndex = css.indexOf(")", endIndex); + } + } + } + + // Enough searching, start moving stuff over to the buffer + sb.push(css.substring(appendIndex, m.index)); + + if (foundTerminator) { + token = css.substring(startIndex, endIndex); + token = token.replace(/\s+/g, ""); + preservedTokens.push(token); + + preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)"; + sb.push(preserver); + + appendIndex = endIndex + 1; + } else { + // No end terminator found, re-add the whole match. Should we throw/warn here? + sb.push(css.substring(m.index, pattern.lastIndex)); + appendIndex = pattern.lastIndex; + } + } + + sb.push(css.substring(appendIndex)); + + return sb.join(""); +}; + +function cssmin(css, linebreakpos) { + + var startIndex = 0, + endIndex = 0, + i = 0, max = 0, + preservedTokens = [], + comments = [], + token = '', + totallen = css.length, + placeholder = ''; + + + css = _extractDataUrls(css, preservedTokens); + + // collect all comment blocks... + while ((startIndex = css.indexOf("/*", startIndex)) >= 0) { + endIndex = css.indexOf("*/", startIndex + 2); + if (endIndex < 0) { + endIndex = totallen; + } + token = css.slice(startIndex + 2, endIndex); + comments.push(token); + css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex); + startIndex += 2; + } + + // preserve strings so their content doesn't get accidentally minified + css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) { + var i, max, quote = match.substring(0, 1); + + match = match.slice(1, -1); + + // maybe the string contains a comment-like substring? + // one, maybe more? put'em back then + if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) { + for (i = 0, max = comments.length; i < max; i = i + 1) { + match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]); + } + } + + // minify alpha opacity in filter strings + match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); + + preservedTokens.push(match); + return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote; + }); + + // strings are safe, now wrestle the comments + for (i = 0, max = comments.length; i < max; i = i + 1) { + + token = comments[i]; + placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___"; + + // ! in the first position of the comment means preserve + // so push to the preserved tokens keeping the ! + if (token.charAt(0) === "!") { + preservedTokens.push(token); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + continue; + } + + // \ in the last position looks like hack for Mac/IE5 + // shorten that to /*\*/ and the next one to /**/ + if (token.charAt(token.length - 1) === "\\") { + preservedTokens.push("\\"); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + i = i + 1; // attn: advancing the loop + preservedTokens.push(""); + css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + continue; + } + + // keep empty comments after child selectors (IE7 hack) + // e.g. html >/**/ body + if (token.length === 0) { + startIndex = css.indexOf(placeholder); + if (startIndex > 2) { + if (css.charAt(startIndex - 3) === '>') { + preservedTokens.push(""); + css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); + } + } + } + + // in all other cases kill the comment + css = css.replace("/*" + placeholder + "*/", ""); + } + + + // Normalize all whitespace strings to single spaces. Easier to work with that way. + css = css.replace(/\s+/g, " "); + + // Remove the spaces before the things that should not have spaces before them. + // But, be careful not to turn "p :link {...}" into "p:link{...}" + // Swap out any pseudo-class colons with the token, and then swap back. + css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) { + return m.replace(/\:/g, "___YUICSSMIN_PSEUDOCLASSCOLON___"); + }); + + css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1'); + css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":"); + + // retain space for special IE6 cases + css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2"); + + // no space after the end of a preserved comment + css = css.replace(/\*\/ /g, '*/'); + + + // If there is a @charset, then only allow one, and push to the top of the file. + css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1'); + css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1'); + + // Put the space back in some cases, to support stuff like + // @media screen and (-webkit-min-device-pixel-ratio:0){ + css = css.replace(/\band\(/gi, "and ("); + + + // Remove the spaces after the things that should not have spaces after them. + css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1'); + + // remove unnecessary semicolons + css = css.replace(/;+\}/g, "}"); + + // Replace 0(px,em,%) with 0. + css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2"); + + // Replace 0 0 0 0; with 0. + css = css.replace(/:0 0 0 0(;|\})/g, ":0$1"); + css = css.replace(/:0 0 0(;|\})/g, ":0$1"); + css = css.replace(/:0 0(;|\})/g, ":0$1"); + + // Replace background-position:0; with background-position:0 0; + // same for transform-origin + css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) { + return prop.toLowerCase() + ":0 0" + tail; + }); + + // Replace 0.6 to .6, but only when preceded by : or a white-space + css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2"); + + // Shorten colors from rgb(51,102,153) to #336699 + // This makes it more likely that it'll get further compressed in the next step. + css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () { + var i, rgbcolors = arguments[1].split(','); + for (i = 0; i < rgbcolors.length; i = i + 1) { + rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16); + if (rgbcolors[i].length === 1) { + rgbcolors[i] = '0' + rgbcolors[i]; + } + } + return '#' + rgbcolors.join(''); + }); + + + // Shorten colors from #AABBCC to #ABC. Note that we want to make sure + // the color is not preceded by either ", " or =. Indeed, the property + // filter: chroma(color="#FFFFFF"); + // would become + // filter: chroma(color="#FFF"); + // which makes the filter break in IE. + /* + css = css.replace(/([^"'=\s])(\s*)#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])/gi, function () { + var group = arguments; + if ( + group[3].toLowerCase() === group[4].toLowerCase() && + group[5].toLowerCase() === group[6].toLowerCase() && + group[7].toLowerCase() === group[8].toLowerCase() + ) { + return (group[1] + group[2] + '#' + group[3] + group[5] + group[7]).toLowerCase(); + } else { + return group[0].toLowerCase(); + } + }); + */ + css = _compressHexColors(css); + + // border: none -> border:0 + css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) { + return prop.toLowerCase() + ":0" + tail; + }); + + // shorter opacity IE filter + css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); + + // Remove empty rules. + css = css.replace(/[^\};\{\/]+\{\}/g, ""); + + if (linebreakpos >= 0) { + // Some source control tools don't like it when files containing lines longer + // than, say 8000 characters, are checked in. The linebreak option is used in + // that case to split long lines after a specific column. + startIndex = 0; + i = 0; + while (i < css.length) { + i = i + 1; + if (css[i - 1] === '}' && i - startIndex > linebreakpos) { + css = css.slice(0, i) + '\n' + css.slice(i); + startIndex = i; + } + } + } + + // Replace multiple semi-colons in a row by a single one + // See SF bug #1980989 + css = css.replace(/;;+/g, ";"); + + // restore preserved comments and strings + for (i = 0, max = preservedTokens.length; i < max; i = i + 1) { + css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]); + } + + // Trim the final string (for any leading or trailing white spaces) + css = css.replace(/^\s+|\s+$/g, ""); + + return css; + +} + + +exports.cssmin = cssmin; + diff --git a/node_modules/less/node_modules/ycssmin/package.json b/node_modules/less/node_modules/ycssmin/package.json new file mode 100755 index 0000000..cb57050 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/package.json @@ -0,0 +1,66 @@ +{ + "name": "ycssmin", + "version": "1.0.1", + "description": "CSS Minification from YUICompressor", + "main": "./cssmin", + "bin": { + "ycssmin": "./bin/cssmin" + }, + "devDependencies": { + "yui-lint": "~0.1.1", + "jshint": "~0.9.0", + "istanbul": "~0.1.8", + "vows": "*" + }, + "author": { + "name": "Dav Glass", + "email": "davglass@gmail.com" + }, + "contributors": [ + { + "name": "Johan Bleuzen", + "url": "http://blog.johanbleuzen.fr" + }, + { + "name": "Dav Glass", + "email": "davglass@gmail.com" + }, + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + } + ], + "keywords": [ + "minify", + "cssmin", + "compressor", + "yuicompressor" + ], + "scripts": { + "pretest": "jshint --config ./node_modules/yui-lint/jshint.json cssmin.js package.json", + "test": "istanbul cover --print both -- vows --spec ./tests/*.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/yui/ycssmin.git" + }, + "preferGlobal": "true", + "bugs": { + "url": "http://github.com/yui/ycssmin/issues" + }, + "licenses": [ + { + "type": "BSD", + "url": "https://github.com/yui/ycssmin/blob/master/LICENSE" + } + ], + "readme": "CSSMin\n======\n\nThis project is a fork of [jbleuzen/node-cssmin](https://github.com/jbleuzen/node-cssmin).\n\nIt was originally based on the javascript for of the css minification tool used inside of \n[YUICompressor](https://github.com/yui/yuicompressor) based on code from Stoyan Stefanov and Isaac Schlueter.\n\nWe forked this project in order to maintain and up keep it on a regular basis.\n\n\nInstallation\n------------\n\nYou can either download the plugin and unzip it into to your project folder or you can use npm to install the `ycssmin` package.\n\n`npm -g i ycssmin`\n\nBuild Status\n------------\n\n[![Build Status](https://secure.travis-ci.org/yui/ycssmin.png)](http://travis-ci.org/yui/ycssmin)\n\nTesting\n-------\n\nClone this repo:\n\n`npm test`\n\nCode Coverage\n-------------\n\nWe are using [istanbul](https://github.com/gotwarlost/istanbul) to provide code coverage, to view the report:\n\n`npm test`\n\nThen open `./coverage/lcov-report`\n\nWe also publish the [latest here](http://yui.github.com/ycssmin/).\n\nWe ask that all patches have a test attached and full coverage.\n\nUsage\n-----\n\nThe module exports the cssmin function, so you can use it with: \n\n`var cssmin = require('ycssmin').cssmin;`\n\nThe function cssmin takes two arguments:\n* `input` : the CSS content you want to minimize.\n* `linebreakpos` : the number of characters before the end of the line. If empty, the output will have only one line.\n\t\nExample :\n\n```javascript\nvar fs = require('fs'),\n cssmin = require('ycssmin').cssmin,\n css = fs.readFileSync(\"/Any/Random/CSS/File.css\", encoding='utf8'),\n min = cssmin(css);\n\nconsole.log(min);\n```\n\nLicense\n-------\n\n Copyright 2012 Yahoo! Inc.\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n * Neither the name of the Yahoo! Inc. nor the\n names of its contributors may be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY\n DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThanks\n------\n\nThanks to Johan BLEUZEN for originally porting this to node.js\n", + "readmeFilename": "README.md", + "_id": "ycssmin@1.0.1", + "dist": { + "shasum": "502528dc7785587b9552292e18ae1c6ba305b9fe" + }, + "_from": "ycssmin@>=1.0.1", + "_resolved": "https://registry.npmjs.org/ycssmin/-/ycssmin-1.0.1.tgz" +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/background-position.css b/node_modules/less/node_modules/ycssmin/tests/files/background-position.css new file mode 100644 index 0000000..4cdff82 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/background-position.css @@ -0,0 +1,2 @@ +a {background-position: 0 0 0 0;} +b {BACKGROUND-POSITION: 0 0;} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/background-position.css.min b/node_modules/less/node_modules/ycssmin/tests/files/background-position.css.min new file mode 100644 index 0000000..0895e1a --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/background-position.css.min @@ -0,0 +1 @@ +a{background-position:0 0}b{background-position:0 0} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/border-none.css b/node_modules/less/node_modules/ycssmin/tests/files/border-none.css new file mode 100644 index 0000000..29f9cba --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/border-none.css @@ -0,0 +1,5 @@ +a { + border: none; +} +b {BACKGROUND:none} +s {border-top: none;} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/border-none.css.min b/node_modules/less/node_modules/ycssmin/tests/files/border-none.css.min new file mode 100644 index 0000000..1ed1b65 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/border-none.css.min @@ -0,0 +1 @@ +a{border:0}b{background:0}s{border-top:0} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css b/node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css new file mode 100644 index 0000000..c00e32f --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css @@ -0,0 +1,9 @@ +#elem { + width: 100px; + voice-family: "\"}\""; + voice-family:inherit; + width: 200px; +} +html>body #elem { + width: 200px; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css.min b/node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css.min new file mode 100644 index 0000000..3340179 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/box-model-hack.css.min @@ -0,0 +1 @@ +#elem{width:100px;voice-family:"\"}\"";voice-family:inherit;width:200px}html>body #elem{width:200px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css b/node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css new file mode 100644 index 0000000..b3bc2c8 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css @@ -0,0 +1,10 @@ +/* this file contains no css, it exists purely to put the revision number into the + combined css before uploading it to SiteManager. The exclaimation at the start + of the comment informs yuicompressor not to strip the comment out */ + +/*! $LastChangedRevision: 81 $ $LastChangedDate: 2009-05-27 17:41:02 +0100 (Wed, 27 May 2009) $ */ + +body { + yo: cats; +} +ul[id$=foo] label:hover {yo: yo;} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css.min b/node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css.min new file mode 100644 index 0000000..00cc007 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2527974.css.min @@ -0,0 +1 @@ +/*! $LastChangedRevision: 81 $ $LastChangedDate: 2009-05-27 17:41:02 +0100 (Wed, 27 May 2009) $ */body{yo:cats}ul[id$=foo] label:hover{yo:yo} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css b/node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css new file mode 100644 index 0000000..d4c80ff --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css @@ -0,0 +1,19 @@ +@media screen and/*!YUI-Compresser */(-webkit-min-device-pixel-ratio:0) { + a{ + b: 1; + } +} + + +@media screen and/*! */ /*! */(-webkit-min-device-pixel-ratio:0) { + a{ + b: 1; + } +} + + +@media -webkit-min-device-pixel-ratio:0 { + a{ + b: 1; + } +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css.min b/node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css.min new file mode 100644 index 0000000..965755a --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2527991.css.min @@ -0,0 +1 @@ +@media screen and/*!YUI-Compresser */(-webkit-min-device-pixel-ratio:0){a{b:1}}@media screen and/*! *//*! */(-webkit-min-device-pixel-ratio:0){a{b:1}}@media -webkit-min-device-pixel-ratio:0{a{b:1}} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css b/node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css new file mode 100644 index 0000000..9c6c00e --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css @@ -0,0 +1,4 @@ +/*! special */ +body { + +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css.min b/node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css.min new file mode 100644 index 0000000..7fabf8a --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2527998.css.min @@ -0,0 +1 @@ +/*! special */ \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css b/node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css new file mode 100644 index 0000000..c315cb1 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css @@ -0,0 +1,5 @@ +a[href$="/test/"] span:first-child { b:1; } +a[href$="/test/"] span:first-child { } + + + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css.min b/node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css.min new file mode 100644 index 0000000..1543777 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/bug2528034.css.min @@ -0,0 +1 @@ +a[href$="/test/"] span:first-child{b:1} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/charset-media.css b/node_modules/less/node_modules/ycssmin/tests/files/charset-media.css new file mode 100644 index 0000000..bd02f38 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/charset-media.css @@ -0,0 +1,9 @@ +/* re: 2495387 */ +@charset 'utf-8'; +@media all { +body { +} +body { +background-color: gold; +} +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/charset-media.css.min b/node_modules/less/node_modules/ycssmin/tests/files/charset-media.css.min new file mode 100644 index 0000000..dcaf49d --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/charset-media.css.min @@ -0,0 +1 @@ +@charset 'utf-8';@media all{body{background-color:gold}} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/color-simple.css b/node_modules/less/node_modules/ycssmin/tests/files/color-simple.css new file mode 100644 index 0000000..bb33ec3 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/color-simple.css @@ -0,0 +1,8 @@ +.foo, #AABBCC { + background-color:#aabbcc; + border-color:#Ee66aA #ABCDEF #FeAb2C; + filter:chroma(color = #FFFFFF ); + filter:chroma(color="#AABBCC"); + filter:chroma(color='#BBDDEE'); + color:#112233 +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/color-simple.css.min b/node_modules/less/node_modules/ycssmin/tests/files/color-simple.css.min new file mode 100644 index 0000000..1e39e23 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/color-simple.css.min @@ -0,0 +1 @@ +.foo,#AABBCC{background-color:#abc;border-color:#e6a #abcdef #feab2c;filter:chroma(color = #FFFFFF);filter:chroma(color="#AABBCC");filter:chroma(color='#BBDDEE');color:#123} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/color.css b/node_modules/less/node_modules/ycssmin/tests/files/color.css new file mode 100644 index 0000000..030b8a0 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/color.css @@ -0,0 +1,46 @@ +.color { + me: rgb(123, 123, 123); + impressed: #FfEedD; + again: #ABCDEF; + andagain:#aa66cc; + background-color:#aa66ccc; + filter: chroma(color="#FFFFFF"); + background: none repeat scroll 0 0 rgb(255, 0,0); + alpha: rgba(1, 2, 3, 4); + color:#1122aa +} + +#AABBCC { + background-color:#ffee11; + filter: chroma(color = #FFFFFF ); + color:#441122; + foo:#00fF11 #ABC #AABbCc #123344; + border-color:#aa66ccC +} + +.foo #AABBCC { + background-color:#fFEe11; + color:#441122; + border-color:#AbC; + filter: chroma(color= #FFFFFF) +} + +.bar, #AABBCC { + background-color:#FFee11; + border-color:#00fF11 #ABCDEF; + filter: chroma(color=#11FFFFFF); + color:#441122; +} + +.foo, #AABBCC.foobar { + background-color:#ffee11; + border-color:#00fF11 #ABCDEF #AABbCc; + color:#441122; +} + +@media screen { + .bar, #AABBCC { + background-color:#ffEE11; + color:#441122 + } +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/color.css.min b/node_modules/less/node_modules/ycssmin/tests/files/color.css.min new file mode 100644 index 0000000..cf2103a --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/color.css.min @@ -0,0 +1 @@ +.color{me:#7b7b7b;impressed:#fed;again:#abcdef;andagain:#a6c;background-color:#aa66ccc;filter:chroma(color="#FFFFFF");background:none repeat scroll 0 0 #f00;alpha:rgba(1,2,3,4);color:#12a}#AABBCC{background-color:#fe1;filter:chroma(color = #FFFFFF);color:#412;foo:#0f1 #ABC #abc #123344;border-color:#aa66ccC}.foo #AABBCC{background-color:#fe1;color:#412;border-color:#AbC;filter:chroma(color= #FFFFFF)}.bar,#AABBCC{background-color:#fe1;border-color:#0f1 #abcdef;filter:chroma(color=#11FFFFFF);color:#412}.foo,#AABBCC.foobar{background-color:#fe1;border-color:#0f1 #abcdef #abc;color:#412}@media screen{.bar,#AABBCC{background-color:#fe1;color:#412}} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/comment.css b/node_modules/less/node_modules/ycssmin/tests/files/comment.css new file mode 100644 index 0000000..7073b9e --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/comment.css @@ -0,0 +1,3 @@ +html >/**/ body p { + color: blue; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/comment.css.min b/node_modules/less/node_modules/ycssmin/tests/files/comment.css.min new file mode 100644 index 0000000..b280371 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/comment.css.min @@ -0,0 +1 @@ +html>/**/body p{color:blue} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css b/node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css new file mode 100644 index 0000000..87ca565 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css @@ -0,0 +1,15 @@ +/* This is invalid CSS, but frequently happens as a result of concatenation. */ +@charset "utf-8"; +#foo { + border-width:1px; +} +/* +Note that this is erroneous! +The actual CSS file can only have a single charset. +However, this is the job of the author/application. +The compressor should not get involved. +*/ +@charset "another one"; +#bar { + border-width:10px; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css.min b/node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css.min new file mode 100644 index 0000000..73e8d3b --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/concat-charset.css.min @@ -0,0 +1 @@ +@charset "utf-8";#foo{border-width:1px}#bar{border-width:10px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css new file mode 100644 index 0000000..49a1315 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css @@ -0,0 +1,23 @@ +.yui3-skin-night .yui3-dial-ring-vml, +.yui3-skin-night .yui3-dial-center-button-vml, +.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night .yui3-dial-marker-vml, +.yui3-skin-night .yui3-dial-handle-vml { + background: none; + opacity:1; +} + +div.base64-doublequotes { + width:100px; + height:100px; + background-image:url( "data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAgEAZABkAAD%2F4RfJRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAAD0JAAAAnEAAPQkAAACcQQWRvYmUgUGhvdG9zaG9wIENTMiBNYWNpbnRvc2gAMjAwODowNzoxOSAxNDo1ODowNQAAA6ABAAMAAAAB%2F%2F8AAKACAAQAAAABAAABwqADAAQAAAABAAABRQAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABaTAAAAAAAAAEgAAAABAAAASAAAAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMR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0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZ%2F%2B01IlBob3Rvc2hvcCAzLjAAOEJJTQQlAAAAAAAQAAAAAAAAAAAAAAAAAAAAADhCSU0D6gAAAAAYEDw%2FeG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8%2BCjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk%2BCgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk%2BCgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q%2BCgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw%2BMTwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BUE1UaW9nYVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPm5hLWxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk%2BCgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw%2BCgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk%2BCgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk%2BCgkJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk%2BCgkJPGRpY3Q%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw%2BCgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BVVMgTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk%2BCgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJpbmc%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0Pgo4QklNA%2BkAAAAAAHgAAwAAAEgASAAAAAAC3gJA%2F%2B7%2F7gMGAlIDZwUoA%2FwAAgAAAEgASAAAAAAC2AIoAAEAAABkAAAAAQADAwMAAAABf%2F8AAQABAAAAAAAAAAAAAAAAaAgAGQGQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QklNA%2B0AAAAAABAAZAAAAAEAAQBkAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD%2BAAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAE4QklNA%2FUAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA%2FgAAAAAAHAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAAAD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FA%2BgAAAAA%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwPoAAAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1UAAAAGAAAAAAAAAAAAAAFFAAABwgAAABAAcwB3AGkAcwBzAF8AYQByAG0AeQBfAGsAbgBpAGYAZQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABwgAAAUUAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAUUAAAAAUmdodGxvbmcAAAHCAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAFFAAAAAFJnaHRsb25nAAABwgAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE%2F8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAThCSU0EDAAAAAAWrwAAAAEAAACgAAAAdAAAAeAAANmAAAAWkwAYAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1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U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZADhCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAIAAAABAQD%2F4TkjaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu%2B7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI%2FPgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEuMS0xMTIiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI%2BCiAgICAgICAgIDx4YXBNTTpEb2N1bWVudElEPnV1aWQ6RTcxOTVFNTY1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkRvY3VtZW50SUQ%2BCiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6RTcxOTVFNTc1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkluc3RhbmNlSUQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0ZURhdGU%2BMjAwOC0wNy0xOVQxNDo1Nzo0MS0wNTowMDwveGFwOkNyZWF0ZURhdGU%2BCiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTA3LTE5VDE0OjU4OjA1LTA1OjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpNZXRhZGF0YURhdGU%2BMjAwOC0wNy0xOVQxNDo1ODowNS0wNTowMDwveGFwOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1MyIE1hY2ludG9zaDwveGFwOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOkhpc3RvcnkvPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpOYXRpdmVEaWdlc3Q%2BMjU2LDI1NywyNTgsMjU5LDI2MiwyNzQsMjc3LDI4NCw1MzAsNTMxLDI4MiwyODMsMjk2LDMwMSwzMTgsMzE5LDUyOSw1MzIsMzA2LDI3MCwyNzEsMjcyLDMwNSwzMTUsMzM0MzI7QzA1QTE5MDRGRjAwQUJEQzA1MUJERkFGMDIwNEVBNTE8L3RpZmY6TmF0aXZlRGlnZXN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24%2BNDUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24%2BCiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U%2BLTE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtENDYzN0NCOUQ0MUExMEJBN0VGNUVCQ0RCNjMxODMyOTwvZXhpZjpOYXRpdmVEaWdlc3Q%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY%2BCjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8%2B%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQACAYGBgYGCAYGCAwIBwgMDgoICAoOEA0NDg0NEBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEJCAgJCgkLCQkLDgsNCw4RDg4ODhERDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgBRQHCAwEiAAIRAQMRAf%2FdAAQAHf%2FEAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4%2FPE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BCk5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0%2BPzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BDlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq%2Bv%2FaAAwDAQACEQMRAD8A7%2FmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmrlHI2utXn6WltnFESb0RFSp41WjD5q3LCBaslzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2E2rj0LuzvF7PxftUf8AXPLDnC3XI0ewdpOkTK4P08T%2FAMK2Ec1TLNgaxmE9pFIDy%2BEAn3GxwTgV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F%2F0e%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXYUeZpfR0a4kpUAx19h6i74b4X65CbjR76FV5FoJKKe5C1GIVLdDuGhuXs2IKOX4gfsvGdx%2FskKtkiyD6bctHHbXgPImOC4qOpXj6E1ff4Mm4Ndxkpc770BvNmzZFLs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Lv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVokKCT0G%2F3ZgaioNQemANZuhaWLyE0LlY1%2BbGn6sWspA8QA%2FZ%2FUcVRWbNmxV2bNmxV2bNmxV2NZQwKnodj9OOzYqwDT4iiPZsa%2FVLm5sj7I%2F76L%2BOTXTpjPZQSt9pkAb5r8JyKXqfUvMOpIQOFxFDfoP8qFvTl%2F4Q5INDkrFPAf8AdUhI%2FwBV%2FiH8cnLeAPcxHMprmzZsgydmzZsVdmzZsVdmzZsVdmzYyWRIo2kkYKiirMdgAMVX5sjTeaGl1CzsbSAOLuX0w7k14KCzyAD%2BUZJBirebNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F9Pv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVo4CXUFa9e0CbJRWkr%2B0RWlMHZEJ5WtPMtzE5%2BGYJKnyK0%2F4kuEC1ZeM2IW0okjFT8S7H%2BuL4FYz52mMWn2tDTlcpX6FbDHR5ecCH%2BZevywl%2FMM8dJtn7LdJ%2BKvgry9ccrOJ69KVw9E9GS5s2bAh2bNmxV2bNmxV2bNmxVi3miFU1LSbxvsStJYzH%2FJnSi%2F8ADYpoEzLcxq1T68FGr%2FvyE8GrgjzdC0mhXEsY%2Fe2pS5i%2F1omDf8RwttJRHdrcDaNbhZVI6endIG%2F4mcnHeJCDzDL82bNkEuzZs2KuzZs2KuzZs2KurkZ843Zhs4bVTQzvVqfyrvg3zHNPb2UMsLtGBPGJSpIqjEqRUb9ch%2BvSSvp0JlcvJCLyMuxJb4JNvi%2F1SuEBVvkaX9L%2BZbm8Sv1fTbf0Y6%2F78lPxH%2FgFzpeRvyPbWcXlyyubWBIXuoxJOUG7uKjk5%2FaOSSoxPNXZs2bArs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FU7%2FmzZsVQ2osyWM7o3FlQkMOxGPtZhPBHKCDyUE08e%2BM1Bedjcr4xPT%2FgThV5cvBJbpGergEfMDcYa2PkqfZs2bArs2bNirs2bNirs2bNirshfnRGtb7T9TX7LcoJD2qDzSv3vk0wl81WDajodzDGKzRj1oR35R%2FFT6RthHNXaVcrKsUtftDi304dZz7yrqPrQCIncdMnsEnqRK%2Fcjf54yVjP5gwtJ5ckcD%2B5mik%2BivH%2FAI3wD5RnEtpwrWgw983RGby1qiqKlYGkA%2F4x%2FvP%2BNchnke5BIUGoPQ%2FPEJHJ6XG3JFbxAOPxOA1iX7sUwIdmzZsVdmzZsVdmzZsVUbqBbq2mtm%2BzMjRn5MKZDLP4rC2UVq9qYj7SWshWn%2BtxOTnIVG4ttWvdNaiiK7FxGDtWG6Ti%2FwDwMuShzRLky%2B1lE9vFMP8AdiK33gYscKtBmDWhtq%2FHbOyMp68SeSH5UOGpyJ5pYde3moWPmW5KzH0pIo2WNt0A3Wv0ts2D73zJ6FgzxqqXpKpHG9eDMx7EYXed45VeC4gPCdYyqua0I5q5VgOv2cAW8sWo2QMqhwwoyHcVyQFhVOLzvrNrdf6fFHLFX4kVeBH%2Br1%2F4bJlp%2Bt2GqWrXFnICyKWeJtnUgV3XOP67qFjaFLHUrprecy%2BlZajxPDmN1jn8Dv8Aa%2By%2BIaXrclrdtZ34NrfR1USofgeo2K06c%2F8AgcBCXr%2FlvXRrdnzk4rcoSJFXYfMbnDzOV%2BTr82eqAOQIpaBq7AV2r%2BOdTriRSEp8z8RoN9I5AWJPV5HYD0yHr%2BGQg3Ntq1lcLazx3CiZviiYOKzQo9Kjb7YzoWqRevpt5AOskEij5lCOmc60%2BWCK0j9ONYo5IYp%2BEahQWBeNjRafEcMVTvTb%2B80fyHZ3FugE9vSORJBUqPVZW%2BEHw3yVaXeC%2FsobulGkX41HQMNmH%2FBZzC%2B1iTTbadZUkjtJjzkQqSKqNm5fsdMPfyr1%2FRdT8vra2E5N5C8kl3bSMTKpkctz%2BL7SP9peOA7fFkIkgkCwOfkz7NlA1y8DF2bNmxV2bEJLy1injtpJVWeavpREjk3Hc8V64virs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Xv%2BbNmxVplDqUbcMKH5HIPokjWsstqx%2BK2lZPf4Wpk5yF6nF9R8xswHGO8QSj%2FAFh8D%2Fqrkoc6VmSMHUOOjAEfTjsAaZMXhMRPxRnYf5J6YPyJV2bNmxV2bNmxVQuzOtu729PVUclBFa07U98DafqsF6i9EkI6ePywwyF6vG2i6oJRUWl6xZCP2JOrr%2FsvtLhG6s0yiK4X6Zfi4QI7Vb9lv5h%2FXDHrgV5c8B0LzLc2Q%2BGF29WDw4SfF%2Fwp%2BHOg6ZMHi4j2YfTkZ%2FMGwpFaazGDytm9GYj%2FAH25%2BEn%2FAFX%2FAOJ4N8uXwliicnps305LmFZDewrc2dxbt0lieNvkylc45%2BX10UCQzHjLATE4P%2BQeNc6L55e5i0J57WVonikRmZDSq7jf2yB2Op%2FVYor2%2FwBNjktpAGjv7ZvU%2BInoy8Vao%2Fa44xCQ9as25RVBqKnfBGRby9rBEsljcIY0aQ%2Bg5FCCQD6bj9lslGAikN5s2bArs2bGyOI0aRuiAsfoFcVS%2B%2F1q2sJltyrSytuyp%2ByDsC3zwxBqAfHfI%2Fodmt2z6pcjnJK5dAexPT%2FgRkhxV2c782mSy82WUgNIdUhNs4PTmlXQ%2FwDBDOiZAvzLb6nHpOrlFkjs7lWdG9yvxVG%2FwiuGJ3Up3YTJFr7op%2BC8t1ljHjxodv8AYtkiyHbxx6XfKx%2FcXBilJ3%2BAsVUV8FRlyYA4Z80DkkPmq3EtlHJSpR%2BJPgHBH66ZBtIufqt9Np8pALHnEpO5p1oM6Xq0P1jTriPoePIfNdxnLtZtrGZluBcG3vF%2BFJYuJfx40IIxHJKzzb5et9ZtZYp1LwygcgPtKy%2FZkT%2FKWuRKKCOC6tNH1CblcWiILDUWHH6wg6wyDejx9Fw4sfOMjEBY5biH1HgLy8VYulOfJV%2By38q4ndH9LlL219K4iilHrWzLxlhI6SgE1%2F2SnFKo0Czxy28zMqcSzspIYBPj2I%2F1cd%2FytnVZdNQ2D1I%2BESMoPw%2FzMftdMG20TSQyyblmjenzoc4TY6ld6ddyKwMUsbFZoHqNwd1KnGXRXs9n5%2Fv7lg98GlWhMjwk1A%2Fm4k%2FF7jDSwSPULTTJI3PGBphGNwG4OHVW%2BgnONX%2BsWFpDFPaSSJcTESG3TcRlf2uRK%2Fazq%2BkR3aeT7e%2BjnX6yoW8ibht%2B9i9Tg%2B%2FQ98QVZHqstutowuSPSdSpV91IPVWzif1i98t%2BZ7m40FjbSWUrNCqEmkex4EH7acT9lv2c6lonmbTvMUTWdwgiumWktrLQhge6H9of6uRLzd5ZurDVP8Q2KetYFUW7jXeSKi%2Bm0hH7UZH7X7OCY4g2YM0sMrjvexB5SHcXsnkPz3Y%2BcdPqKQ6lAB9bta%2F8lI69Y2%2F4XJeDXPJlvPe6JqMeq6NMYLuE842To6ntToyuv2k%2Faz0J5E8%2B2HnGyI2t9VgA%2Bt2ZP0epH%2FNEf%2BEyESeUuff3tmbFAx8bB9H8Uf4sZ8%2F6P82TMMLNb1iDRrQ3EpBkkPC3j7s5%2FwCNV%2B0%2BGVc4n5m8yfpnzJcsr%2F6HYsLe232PBv3j0%2Fy3%2BH%2FY5JxkLourX175%2Ftb28maSZrloqsdlQ1Tgo%2FZUDO755%2B8uxlvPcMI6i6LAe2zZ6BwlS7NmzYFdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVf%2FW7%2FmzZsVdkb83W5%2BrW1%2Bg%2BK1kAc%2F5D%2FCf%2BG45JMC6jare2FxaEf3qMo%2BdPh%2F4bCNiqV6VOOcTV%2BGReB37%2FaX9WHoyFaJMz23BqiWE7juCh%2FsyaRsHRXHRgCPpwy52gLs2bNkUuzZs2Kuwu1rS49W06Wzb4XI5Qv8Ayuu6nDHMemKvONE1KWGVrG7rHPCxRgeqsppk7sb0XC8W2lUbjxHiMhnnnTHtLmPXrZfgakd1TsR9iQ%2FP7LYtomq%2FWI0Iakybof4H55LmFZdqNlFqNjcWMwqk6FD8z9k%2FQc515XuZbW4l0%2B5%2BGWFzE6n%2BZTTOlW063EQkXY9GXwPhnO%2FNsS6T5qtbofBHqaniexmi%2B2v%2BsU4v%2FlfFgHcrPTFbanZNb3caywyApLE3Qj3zjutwW%2FljzBc6Pp6fV9JHpsLNSSgR1HIorV3Vvizq2jXQk%2BAndlBA9xnNvzRiWPzJBJWnr2gJP%2FGNyv8AHAdikJ3YGf0o5pZDIboSD1GJJ9aAgh6%2F5aUzoFnN9YtYZ6gmRFY06VI3zlXk%2FVI5bi2hnlBgdBuxFFahhfr0rSNsnHlXU4JI5NJaSt1avIQm%2B8RaquD0I%2BLjkpbgIZJmzZsirsDagC1jcqvUxOB%2FwJwTjXUMrK32WBB%2BWKpfofE6Xb8f5d%2FnhjkMPmvR%2FKlrJBqkxBSVkjC0PIDpTfI15s%2FMNbu3jbR5plsZVp69swRi9N0eSjMnH%2BRcVpm669cWWtXGnatwjgKma2uPsj0x%2FNXw%2FayOfmLr%2BhX3l%2BPTYrkXM%2BpGtm1uPUUceX7yRx8KLtx%2F1s5xoN%2FefpVr6C8muVVfUuLO8kMrEIeTem7faRk5Iy5FdTuZ9B169trGZvqkc5eFD8SmJzzUcTtsrceWHzTT3fRJv0p5UZvtOYYrgCu%2FJV4P%2FwANHnPrj83vM2lX9zpWoBJYInaJ540pOi1%2BGRQDxf4cln5Z3qT2stjWrK0iexEgE60%2F2XLOUfmHYNZeZbhWP94Ayn%2FV%2BD%2FjVclLlbEdQn955q1wTiU3huLadeQCsfSljO9VNev%2FAA0bYHub1Z7V5yWkhHxpcVHJNwGiuP8AKStVk%2FbyGafqLQxyafO5S2lPJWUAmGQ%2F7uiB8f8Ad0X%2B7F%2Fy8Ctd6jpl3Lb3v%2BkQTpxniqTDcQn7LoR%2FwUb%2FALDZCyyekWl9ZyaFLPelZGN2tqDEtZJHenEs67ckpVXwq1bU7G1iKWvqtcCR4bkkhFYx%2FCHXhvvX48C%2BU7H1SbK3k9Wya5hv4HchSBF8FxBL2WeOJ1k%2F4s9P4cu%2F0j%2Fc1FphmFxPLeOhZBxAiL8jt40%2Fa5YegV6PprvLpcE8sfpTNbh3QVoGK12zluoQ2PnZih42fmWIVt5z8Md4q9I5P5J17Z2A8YrWVl%2BERoaDwoNvupnLtb02LzREdR0hBba7bVe4tEPFZwpr6s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xKXcslu7tXb1%2BSBq%2FwCSzZK9c06xuNUutStkBls5IFkAIAMoHqUUfzNRkbCPW5Xs70rZcVtL0%2BtCoAFVc1oK%2FwArni2RIShdD0rU9Z0g2UNW1DR5JLG%2BirRlQuXhmp1ZP72M%2FwCph75g0K2sra21G8ch5baGJUpt6yARuvL6OWEQk1eJrq9s55YLxBzuGhJEjr3LKvxSqv7WISanq2oQRXGryvd2MtVhuSQ8aNQch8OyNjsqElhK1hbcr%2Fcv3K%2FyV%2FycRSQBmUiifsfQM6FpfljSbrR0mCy3EjDlDIzN9sGnphU%2FZ%2FlbIrqnl%2F6jM3Cb1VRqOoU8078XoOHPISIiQCd5ckgE3tyS4StK6xSy%2FDJ%2B7HqseO%2FYVw0W2thatp10he2b7YH21cfZljP86f8AD%2FYxO4tbO4so4I7ZUvG5Lpl3PssprUws392JD%2Fut%2FwCbAOh6sLuU6VqYMF4hKRu2x5DrFID0YY7rsh4tMn06%2FkspjzjniaS1nQfDIE%2BJWXwdafEv7Od0ugnmL8tmYipWEOB1oGWp%2FwCH5Zy4hoT9WuU5BTzj7FHp%2FeIe3%2BX%2FADrnR%2FysvRfaHeaJIwZ4RJGo8QDzQ%2F8AAy5OPVBfPNxbpMpifYqaBu4IwFYWlx9fEIJU7lmH7S%2F83ZJ9e0x7K9unRg8azMkoHWJySVR%2F9YH4W%2Bzj%2FKtvFdaxBDLQKzAVO243G%2F8ArYPJUXb2NvDZtdyWxe3B4meCQ%2BtG37Jkjb9lafaXHRXl9q2r6etnWJ7Yxx28h%2B1UNyMjt%2FlH4myX6lp1poPm57CIFLG8jikCsKisqqXWncc2%2BzhLZW0Om35hCuLiCeSgIHFY67KT9rl4YaV63IwMVSakg1pt27eGRuzvrTWILdYbnlcIWXSdQc8W5pXlp91%2FLIP91M%2F94mG9tcfW3AQ14xgsPH4c4Zp%2Btz6HqN2rJ61nNIy3loTTkA54yIf91zR%2FailyRNUinpV0iXqyyxw%2BjdW5Md%2FaN1iPdqf74f8A5Jtka1ZZ4LWYxsySKpaCRT8QI%2BIxkj2Hw5KLe6%2FTsUF%2Fp1wsmrRRk2l0QAL6Fft290g%2Fu7uP7Lo395hFquqaL9XZmmWCRwySWTgs8MgG6Oo%2FY5fZbAUhC%2BZ9JsfMl1SKYW%2BqyQRT2DMf3UvJeTwt4M5%2BJchKyrOr6D5gQwTQEpFK%2FwDeQv8Ayn%2BZDk%2B1Gyj1ew0SaC4gS5ntmCtX0ELQtQAM%2FEcv5Fwv1bQxr%2Bnhr4oms2ymP6xuCStSIbof6v8AdzYOaGAQ%2BXdTm1NdLjj5SN8QkG6FOvqBu%2BTjTrS2sbZLCMcVUmkpFGLn7Rf%2FAFv%2BFxTTme102DTuILIwZpKksW%2BzxWtW41%2FZyU2XlW41HhcahytOQJZVHKaXw%2Fd%2F7rY%2FzviAqQ21ldXtytrDG0k524qKmnj8sO736roNmNIltfVv7hFeaMnkUqTwpxNA2S2MaT5etS9w6WdtEvx1b42A7Symh%2F2C5zTzb%2BZun3swOjacGVKwrqMgoajeiJSr%2FOTDVdVZPYa3pOj%2BW7u31uKKzuZGP1dePP1Iz1UovxtJ%2FlYU%2Fl%2F5hOtyS%2BWrlis1Gm0pyfiR4%2Fi9Kv7SumcrvNYnu5DcXH7yToamrfSf6YL8ratLZ%2BZtJvoT6bwXMbEjuCwVh8uJauPFuFe%2Bx%2BYJ4NMawQiOFzyZOlDX4h%2FwQyQeVtAn1BY9R1QN9WU1toG%2Fa3qGYeGE3lnRLPVfM19LdAyWkTtcW8a7xOGaq1kGz7k%2FAM6moAACigA2AxJ7lojn72wANgKAbDLzZsirs2bNirs2bNirs2bNirs2bNir%2F9Hv%2BbNmxV2bNmxV2Qzz3p3P6rqKbFKwyt%2Fkn4lJPseWTPOVfnX5gmstNtdBtnMbajykuXHX0YyPh%2F2b%2FwDEcbrfm24MRzZI447GR59w6pMfNyWl7EdD1KM3Cp6dwoKldj%2B1zHE%2FRko0rz1rUtz9SvLe2lm2Hp8jC7BhWqV5xvUb%2FDnn01jPEin8pHgckemXmsTaHcxANw05o57O7IIKxliJYll%2FaRT%2B84%2FsNkIZhIkSjRDl6zs%2FwIjJCXFHkb5gp3%2Ba2r%2BbdPuEvYLVbLRpiFL27c2EvWkj0%2Fd8v2VpkGsfN2p3Kra3V2XicgEsQeQJ3qSNs7d%2BkdO1rSbKw1LhN%2BlbRXVJKFZyq8ZV3%2F3YGHLOEecvKFx5TvTLDym0idv3EvdG%2FwB9yf5a%2Fst%2B3lpHUOvsua4iNwbWCruHK%2FB0qN9j0zoy%2BarW48r2Oq3l1Le2sSizuGkqk6zgUVXMda8F%2FwCDTOO2M01rIs0XCRQ4kHqCqGnZl74NgkTlMqSOIZpPVNrXjGG8Qvfj2wXzSyqz1eO%2FtNSjQM8sVubhFbbkIpPiI%2BUR5Yca3q17IdPmtZ2js7yztriONNhyAKSciPtMJUfIZaXDWL%2Bra0jcq0ZYAV4yAq6mv8ynJf5Yex1PRjpUsfO%2F0pnuLJWNPUgkNZ4l%2Fm9Nh6vH%2BVpMRa2uvBcXej2Gp2rSC5tJJbOZkqW4v%2B%2FgY%2Bx%2FeJhtBB5sOi313boLa9ihMlo3EB5ClGkULy%2B16XJk4rhlZarBFAbZljtrS5Tg%2FoIF4fyOT1JjbC1L%2BbSbowyMwu4WrzJryX9h1PQpxw%2FFWFXNut9PB6srS6frlqI4JZHJ%2Br30bCsbOf5phx3%2FAN1T%2FwCRgPQbtreVrEFrW8gfnDU0dJUPF09unHD%2FAFeygjjvbi2haTQbpxcXlpHvLp9x9n6xClfjtjXi1P2P3b%2FGseE99ol9qtyjIKamYlktb6Mn0L5QKJ8Zp6d3x%2BH4vt8OD%2FvciTXPZaZ%2Bkdp5%2Bgt19Yad5p0%2Fe0vU2Y8T0NPiaM%2FtJ%2FuvOj6lcGysFaRlYxJWUjfkUXk3z5MM5p%2BV2l3U2pPdalFHK1sOLyqQxSZaFOdDWOT7W%2F7eTTzK8UdlcxREhXBTf%2BdzWg%2B7JxNji70HnTz%2B51GXyrrFxaapD69nfcRqSftqxHL1oj%2FOjPjtQ0GNYCfrCXWi3QMtlelhyjkYbFfdvsyx4M87Wy6zqemTq4X9KwQnmegkK%2Bmf%2BSi5G9M1PVfLUt3od3CJIGDEQS7iKUD4Zov8%2FjyErqrruPNkK58%2FJN7Sx0%2B0sDe3k0k9xA6JBJACGqwPHiKp8S8fts2F0mrDS3nubPThH6ZLa5YcQsnBvs3kSsCnJeXJuK%2FB%2FwAYmwQ%2FrXdjEsQRizhvjKCrUp8If4uW%2FwCyuK3Fs893p1nezfVdeDCOxmHFi8ZH%2B89wSeBjP2YuX%2BVFiYggA70Pmt9QzfyjdxXeiPeaY3rNYt9ZjdKUkgP2gyj7L8ftL%2FPgTz2tuLdJIT6cN1JFcxzJ2U7Sb%2Fs%2Fa5BsKfLEMvlPXby2sJI40uF%2F0izVuUcb05n0z3gkTlw%2F3237vHeddXN5pEMdnbmOys4BFcy0qDcF6GJa%2FwDFacmyX8Pu2R1QOi6Yupabd2F78dj6xjLVFUlpySaHwkUf7F0%2BDIrrvl6dr42N0eOtRIHs7ldkv4B9ijf8tKgfB%2FP%2FAHX28mPluyb0Vs7OdTL6SSReoK8%2FTZqN%2FrqOPL%2FJwTqdhFr9m1lqUhjnhcm2uv8AdltN%2FMKf7pb9tP8AZrjVhWHaHrEWqxjTb9gt9GKQytsXptxNf2sl35d3J0jznJbCojuQlR26cT%2Btc55qthdyXcyyJ9X8wWfx3ESbC6UbrcwfzS8fjfj%2FAHyfvPt88N%2FKuq3F3q1hqBIEyc4pWZuCkoAwck9MA50VPJV%2FMq2k0TznfCJQUmPJom%2BzJG%2FxcW9t%2FwDY4Q6cILa6ZY2eKRwslv6goaDfjy%2FaK4f%2FAJleadM80a8t1pcZ9GCJYmuG2MrD7TAfsqv2V%2Fmwr0WyuNXUw%2FVxci1%2BKLt%2Fw23wrg6qGVanr1vrK2t3csIry1aESBjxJEYYOQff4cjvm3zLbpZXLWTGC5vr%2FwCswRjfjBGoC8yfi%2BIjCPX2vNMu%2FqZDRNGKSAgUqxqgqKruF%2BH4sjsyPPIZZSXJ7knfG1e9%2Flxrdt5ksbqdSFu7eMLcW5O4%2BE0cV6xvnF75uVzcb14yyBW7%2FaO2KeS9RutC8yWd7DMYLfn6d3L%2Bx6D7SLJ7YhdkNd3UkRDRSXErxMDUFGclT9IwndCtpWrz6ZN8MskcDsGdojxkjcfZmip%2B2v8AL%2B3iWoySfXbiHUmFy14frKXqH4nL14zK%2FVuX7cbYEeJWDPQVpU0Pj0x6yqLL0pJUW4tXE1o5O9SaSRbeP28Cob1Z1T6vPKzxjeNSSQK9aV%2BznXLfUrdtDt9T1U%2BjeRxpa3iMvF5V41jcg%2Ftrx%2BLOd6VbaTqJlS7lMl5Iri3hHwRiQj920snhzODppWsii6zcGeSZg3po3NSy%2FD%2Fen4K9V542r0LyheaXcm5uaCCWNhxkl%2FvClOqcvs4rrn5g2enI9tpKi4uqlWck0rSvxP8Atf7HITazpc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2FLhpr3nLTKJ9UT19TB4zNHtCe3Jj3b2XIssp1Y8bUfFOQsix7SCSlAXpTmj4av5OnsdM%2BuzB3Zm9OWaNGD2%2FMgRTolP3sXP4Zv92fyYi6oITDVrG28x6NBeBvqWoWS1ivSeIikU8jFI%2BzLA6%2FGn%2B%2B3yFaq1pcXix28ZUGi3U2wadx%2FuziAEWv8Aq%2FH9vDLV7TzXeWrqbaWO4VhHeNHtFdCP7EhX5D4v9%2BfbwpC3liGgvIoVdSqt6pLPGr0pTj%2Bz8Xw4CUkEGil7RwRu9ZzwjPx8UZiKePShyb%2BRfMdhHM2kLEV%2BsDlDLQFncUCxcRX7WEF1DCs63zCs6r6c1Nkencr7rgXSpFsb5zCForepC9PiUEfZr4DADRVD%2BddUkPmPU4lUgVNtNG4qDw2Bof2kP2GyK1LECpY%2BAqTnUFhsta1Ce%2B1G3inuZCrySsgqwqFNRkwu9R8m%2BWIwscEHrharDBGjSH5tT4f9kcIoop4da6Vqt2GW0tbiQHbikbkH57UwHNFLbSvb3CNFLExSSJxxKsuzKwPQjOu3%2Fmq%2B1mFo1C2NmFMjhTQLGu%2FKRtumQfU%2FMWh3uoTXx0r1pJePKSWSnJlVU5lQNufHnhQxmOYxklSPiFCDvUZQKUIpUn7Jr0%2B7D8eYrBP7nRbUf61W%2FhmPmtkBFvptnEezCMkj78CpRZOY5w%2FBmWhBCjseuSyyn0pIpIr2CSr2gtbYTQt6aylufPp8PBWbCZPNurROskYgVkYOv7tSAVNRtg2780%2BYPNd5CdWuRJHEWkWONFjRaih%2BFAPljsqLeRrVh%2BjQt3GBRoXBBKAfFwag%2BLJ15B17yfealE2taTHcXMG63Eq%2FvbYL%2FvyH%2B6eFK%2F3iJyT9vAXkPygPNEuoxx3KQ3VrAHtYWP8AeOxpv%2FxWqijMv2WZMLdS8vBLx4pg9jqVqTFJIvwup6fvP5lP%2FDLillv5i%2BStPtL867pEEcem6hxkivLWjIk%2FevHb05ftZF9Okd5Et5mayvoWEtrdRmnCUfYmhYfzftp%2B3k3%2FAC68zLfx%2FwCFdWt1eElrbUoW%2BwGIrDPGv7CyU%2BLj%2B18eIeavKM3lq7WqfWNOkYizuXFeNesE9P8AiX7WNbqCncfm2f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V1PpOsrBduRLFcPb3JY9VditW%2F2XxZ0%2B91O2spIoJWL3E54wW0Y5SOf9UdF%2Fmdvhzm%2Fm2w%2BoeapJlBVdRjWdCDsZE2cfeuHdvfQW0BngZptVvEH1u%2FlG6gj%2B5hH7Kr0xHc0pD%2BYg8wa1NDFZWjSWtsrCRoiGJcn46b1YdF2yFWemzxsW1CN4Ej%2FZlUofubOs2WpxpNGl2oMP2eSbEe5yTXGkadqFpJaT26T2860YEVBB6EHx8MeCzdpunlEtpHYQ38GqRrFNaPA8EgJcFa%2FGqhadao2XBGlmbe2uCzevbGeRo2PcNJx%2F2S%2FDht51s3sLpYLoH6ncIq21wRU1UceLt9Hxf8Hhj5f8pXerWc%2Bq2VrHqE1oqQWdvNLwUoijmJB%2FO9W4%2Fs8cjVH3LezEvM2mXWqyabNozB7SS1WJ5SwBrHWnLv8A3ZUbfy4onlazmtrKC%2BJlNoHFFNFbmQaHvtTJ9rPlzU7GOO6vrRbeNioQQMrRxmn938IXj4YE0fQLnXBdQ2062l1CP3SSry9Xav7og0%2F4LDsikps7C3s1WK2iWJB%2Bygpg5lNOX0YAVr7TL0xXsxcxsVlhktwpFPtLVWwbf%2Ban0e8tp7LTYrmyILlpyT6hoRw2%2Fu%2FTbdlw3taoK4v7a1dY2dW5GjQ1qVHj%2FwA24Vah5a03VlNxZEQTtvyX7LH%2FAClyfjyfo3nrTrbV9PRNI1i6gM8qRENC8gb05OUI%2BNR6nR1%2F4HIRqOj655Vu%2FQ1SBogT%2B7mU1ikA7pJ0%2FwBi3xZGwdizhOeOXFCRBSPSZNX8maml1MhNsfgldPijdD1H%2BS37S8s6ZLrEEZt2uEe1W6VWtLsg%2BlKGHIGOReS%2F6wOR9dWtRp11dSQ%2FWHt4Wk%2Br93IGyU%2Fysk%2Fk%2FW5INATT9Z0eAWczGT6gr%2BoIlfcgBxsf2vT%2FAGMYxMSeE2D07m7PqBmjEzjWSO3EOUo%2BY72M%2BYfLcd3FJeQRxyo7EzQU792GQ60bU9Hkf9HTAwts1jdVeNl%2FyX%2B2n%2FEc7ZL5XstVSS58p6kYZqVbTrysif6tWPrRr%2FspVzmuvaDq2jzsup2JtA5NCfjtmNf91Tjb%2FYyccJ8tmgJPqV4JJLJpI3sYLq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FFMx2imJJSvhHLXj%2Fr4N%2FO9G%2FwAJ28o%2FYvY69%2BqOMgdlYzqPmWy8xr615aouoxAA3dk4dJB0%2FfRGjofBl54U%2BnCySRNSa1l%2B2vQq3861%2By65GPKcztqxjY7NEw4jYbU32zoNppF1qfrw2JX6yierHExoJivWIf5fH7DYYnZaY3pN9N5N1n9JJEbuIwyRoisY1kDbpVu3F%2FidM7xpl3Y%2BadFt7m5tle3vIUkaCYBx8Qowof5WB%2BPONG0jvLY28qlRUgqwoyOOu37LpiXl3XbjyZqk7XglmtZIfTEKNQGh5REFvsxr8XLjgIrdWQedvy7GiQPrfl4SNaxVe5s1q7Rp3ki%2FaaNf20%2B1kT07WGCqwcMjdJFNQc9C2N9BqNvHc29WiljSVGI2KyCopkFv%2FwAotHu9cOq2d1JYW0x53dhAo4O53JQt8MYf9ocMFyB23ZwGOQIkeCQGxqwfIsatNQSQrIrmOUbrIhoQfEEb5LLHzPP6X1TV4RqFo4ozFVL0%2FwApD8EmFms%2FlxeWBNxoEpuIhubSQj1B%2FqPsHwo0%2B4ltUmW7Ro5ojRo3BVhT2OWCi1t%2BbPJ1pFCfMXlJgtl%2Fx92VCyRHuwjb4kX%2Bdf2ciOlG2huhcX2n8JI2BE8FHHzMTb%2F8TVc6FpWutaySPblJEmHGeCQVVwP1ZGtcsIbe5N3p0Ui2MlWaM7mB%2FwBpQ4%2B1F%2FLkTGulhnDIYnYprf6tYaxaxxCDlxIaG7iko8Z7kGtWr%2B3ywxsdGl1WwitzGbkgkRzugDGnRm34R0%2FZbIJBZwxv9YhAVx8Qp0JPiBnafJl1eXekLNdyrKOXGNgADQD4g3Gg%2BE7Y8WyTLfiHNJbbQvNHle%2Fe50eQX%2BnXAD3Vg53EoWnKImhQmn7Pwv8AyYRX9xql1dmXWOS3XHiqMnp0QEkKq%2BA5fazrQwHqOmWmqQGC7j5D9lxsynxVsFsLeO39hb39tJbXMYlhlHGSNuhB%2FUffOZXy3%2Fl7UV05n5MgrpN1LTjLCT8VncEj%2FYf5Odt1nQbzR3JcerasfgnA2%2BT%2FAMrYB%2F5V3Y%2BdtAvhefubrn%2FuNux1jkQUYkD7Ubnir%2F6uEq8D1rTFk9XUdNgaHix%2Bu2XVoHPcD%2FfbfstnQfyAeb%2FFktC%2FptaSF1VgFNGTiXFfiA%2BLj%2FlZC9WuNd8p6kNM1e04anYsY2mY7TW%2FZG2pKjfsS4K003mkCHzl5WmDLazercWoB9WCvX1FB%2FeQt9lv8nIofYNRl5FPI3njTfO2li7taRXkQUXlp3Rj0Zf5on%2FYbJXirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FW7%2FmzZsVdmzZsVdmzZsVdgHVY9PmtHi1JlW3cgEuQBUbr1wdgPUdNttTtzb3IJWoZSOoYdxirzHztP%2Bi20aTyvdm6uDcJSCMJIPTVhRWKj7Bbbi2B9b8keZrnV3FvberbsQsVwHUKFJ6tU8hSvhk%2B%2FwAPGy1GwvLOkqK5ju0cIP3YQ%2BnItAPiif8A4nkkphKQaQOk6eml6ba6fGQVt4whPif2j%2FwWO1LTbPVrGfTr%2BITWtyhSWMjqD%2FEfs4MzEVwIsg2Ni%2BVPOHlm58p65NpU1XhP72znP%2B7IWPwn%2FXX7En%2BVgW28s63f2kWr29m76Ys6xyXQpxUggNUfa4iv2uOen9c8t6J5it0t9as0uo4zyjLVDKf8l1oy5EL7TriGW30Lytp7Q6Dbs0d7xI4Oz%2FFWPlycmNvib%2BfKziufETs7WXahOn8Ph9dVIn6a7%2FewDzPd3ukNplzYtxtEhW2adVBKzRktTkalOdf%2BBw60bydZ%2BaNR%2FwARaPq0VjOIw509bcLIkw%2B16yh%2FjRm%2F3an28de6dLYTXGk6xDztpx8aHoyn7Lqfb9nI3YX%2BreQ9ThS3pcWhcvazMBWSE%2FbgaQ%2FF8P8AJlrrDvunvmryB9buFvzAtnrkQD84z%2B6mKHkGRtu%2F82HWnO%2BoadLpU5aC4ZeUL9Gil%2B0jKR0aOYZOLO80jzho0d3Zv6kMn2WFPUhlGxVh%2By6H7WQWaO80rV1hvwBMjcfUAoskTbLIP%2BNsIr5oSu10tfOt7Ikt4th5ijQC6hkSsdz6fwfWIiCCr7UmTj%2Fl5JG%2FKTSdTjg%2FxDILh4UCUgHD7P8Axafj45GPMdkYtRkvbWf6jewEXNhcr9ppT9pEVatJWnxJx%2BznRPIfmz%2FFujfW5Y%2FSvLZ%2Fq94gBCmQCvNQfiVX%2B1xb7OA2NleaX%2Fkr%2FA19Jb2rO%2BlXbc7UvuFbuvL%2Bb%2FiWC7M7HOuarpdrq9jLY3i8o5Bse6t2df8AKXOP6jbaj5dvpLK5USBd0fcB07Ov8cMT3qkP5l6trkWp2kNi8sVr6CShoyVDyH7RJHXj8OQpfNfmCN1%2BsXcsnBeCrOfUAUdFHP4uP052ny%2Fq2g6veR6T5hgX94Almsp%2Fdsw%2F3W%2F%2BU37GSHUfyp8n6hUpavZse8DkD%2FgH5p%2BGCXNeTwM%2BbzeWxtr%2B3SVHFGMZKMP8oBqr%2FwANh9qv5gpr3kVfLV9zk1O3uIjFOwrzt4w1GZhUeqn2P8rJD5i%2FJJrK2lvNKufrSx%2FEYCnCXiOtCpKPx%2F1M503lq7tpDxDNUUUGlPwyJtWQflfpMWseaFtLgssZtZnDJ1VhxCn3651e38qanp%2Bs2ZX95brKG%2BtR7UVfio6%2Fs16YS%2Fk3pGmWxvNR%2BspJqfEW7WnR4kryLFW3PqN%2FL%2FLnW8I2UsW8x%2BVo71n1LT0CXp3mjGwlp3%2F4yD%2Fhsgl9oyXUaxX1u8LoCY2dStV%2FaG%2Fgc7JTEbiztrr0zcRrIYmDxlhWjDJCXQoeVeW9Rv8Ay1PKL25kuNO9ELEo%2BIjgaoKk%2FAqJyzqtrdQXkCXNs3qQyqGjcdCCK7ZFPMPl1Yg95aLWA7zQjfjXqw%2FycB6JrNzY3BW7uAbARKgUqSQVIC8KfCq8K8vhxq9wlntK4DvtJ07UgBfW6TU6FhvTwqN8FRyRyoHiYOjCoZTUEHH5FDC9Y%2FL6wuSZ9Ic2M3X0tzEfo6p%2FscL9B%2FLy8XVJNS8y3Yuo41aKz0%2BEkQrGwoWlO3N2zomVTDZV4l5n8s3Plq94oS%2BnTk%2FVZj27%2Bk5%2FnX%2FhsMNI893Wj2ht2thNVSEp8PGSlBK%2F%2BSf286nqOnWmqWcllexiSGQbg9QezKf2WGco13yhdaVMUT95A39zL0DDwPg%2BIZc3pPlzU5dStGa4IaeNgGZaAFWHJWoMOc5v5E1B7Wf6tcAoD%2B5PLb3jP0fYzo4xIYrZIo5UaOVQ6MKMrCoIPtidrZ29lAttaoI4UrxQdBU1OL5sCsO8%2FwD5e6V5708RXNINQgB%2Bp3oFStf2JAKc4m%2F4XOIWX5R%2FmVoOpummwIySAxNMssZhZG2q3Mqen80eeoKZqYq8l8h%2Fk%2FceW9Qt9Z1DU3W4gPJLS0JCEGvwTytT1U3%2Bx6arnWs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F1%2B%2F5s2bFXZs2bFXZs2bFXZs2bFXUzZs2KuzZs2KoXUjILG49E0k4EKetK43TYkhsoQp5EqGZvEnvgp1DKVbdW2I9jhDdaDqT%2FuLLWJbOzP8AulEVnAPVVkb4hiqB8wWUXmS%2BXTYWQi3ikZphuUlqOKmn7P8ANnOtRsiPW0TWUKqD9ofajYfZkQ%2B3%2FDLnYtH0Wy0W3aC0BJc8pJHPJ2J8ThV5u8tJrdoZrdQL6EH0z0Lj%2BQ%2F8a4bTbxXQPMGq%2Fl9r7mSs9jcUN3Cv2Zo%2B1xD4Sp%2FzZnaNYhtfNmgRaho7JcMwE1pKCASP246%2Fsn%2BZf58gsugWWtaPFp1xRL21qFkFCyP3U96YR%2BUfMt7%2BX%2BqvpmqEtpUsnGeOtQjE0FxD%2FwAzUxOy%2B5kHmGCOa1s7%2BVeEsFYpHI3SvwyBvDi647RtH1by3qEXmPT5VlgnWmo2C1Amj6rIrH4RMnVcCz3FvJ5x1pIqX2h30cVy3ouv2nQEeka9XZW5ZJNPult7dbZpTLasP9HlYUalP7uVf2JlH2v%2BEw891ZzY3tvqNtHdWz84pBUHoQe6sP2WX9rC7zJoEOu2Xp7LdRVa3lPY90b%2FACHwi0IahBqtdOo9hKf9LjY0Vf8ALU%2F78ybZFD591jS3R3gnRo5Ymp4MjA9snHkr8weRi0LzJII7pQEtdQc0SYdFWQ%2Fsy%2F5X7eH%2FAJw8uLqMDX9qg%2BtRL%2B8Uf7sQf8bLnJbuyjcNFKnND1U%2Fw8Dh5pfQo3Gc487eVFhMmq2KfuHNbmNR%2Fdsf92KP5G%2Fa%2FlyPeXPM%2Fmfy2Y4pmk1PRqfBBKpNwiDr6E3%2B7OH8j51%2B1ubXU7JLiKklvcJWjDqrDdWH%2FEsV5PntoFiuUuQOFxFvHKpKsPpWnLJZ5b8w65p1xEguXuIp3q8d07P1%2FZVm%2Bx%2Fkccbr%2Bhm2125sbPggX95AZq8FRhy3p%2FL8Srk181aDHqempqtvRLu2hDngPheMDmV%2F2P2ozjsrKLW5ju4Eni%2By4rQ9Qe4OL5D%2FACp5hgu7iOwkkUXFxD6yx9DWM8HNMmGJFFDRFRQioPUHIhrmgrAXubdK2z19WOleFepH%2BRkwymCkUIqD1BxBpWIaNq09o31WURrZoiem32ePEheCIB8VV%2BLJcGB3BBHtka1LQXVne0XnC9eUQ%2B0tevHxXA2lxazHfW620rx2atW4gkSqFOPCgdvjDClVwkA7hWYZswzZFXYnNBFPG0UyCSNvtKwqDimbFWE6voE1hIbu0Be3BrQVLIP8rxXJRo92b3T4Z2%2B1Ti3zG1cGkAih3B7ZSRpGvCNQqjsooN8NquzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxViPmbyo91cfpvQiINVT%2B%2Bh6RXSD9iXwl%2F33N%2FwWQzW9AXXo%2FXaFg7L%2B%2BhK0mjdBuafzACjrnYcDTWNrPKk8kYMsZDI42NR40w3tRW3z1p2l6ho%2BotLAfXVE5OgDVljA%2BLj%2FxZGv7OS2BbeaRbscpI5YuLQq3ETIfiQcv2ZVP90%2F8AsMk3mi1FjqBnt0CpcIHIUU%2BNT8RFP5tuWRDTFEulwPaP9YjVSfVjBIFGPM%2F7BvHCOSXqXlu6trnTI1t7Y2Zj%2BGW1YhmQ%2BJcfb5fzYcZBPKl1I7GRXHKGi3AY%2FajPRvdsnQNd8BFFDjnL%2FPWhJaXguIKRw33KngklPi%2F2Pxcs6jkY892Ul3onqwoZJLWRZeAHIlT8D7fJsAVBaLpUeueS9PtriYPcWykQXkfZ4yVDD%2FJP2WwX5X1NJ2NrQIGXkoXpzQ8JP65GPJfmOTR5G0zXLmGCzlYmzhZPSeE05ceP7UTjfliOhagkWs3CW0gkUXbPZjoZVkY8kQHr8OSHUJZD540vmYtVRBIAvoTo260JrGzU7cvhzaJ5jgm0t9O1u7giu%2FRdY%2BJ48oyCg%2Fd9QyfZ%2FwArJhPBFcwvbzqHikBV0PQg9sgt%2FwCSLpJy9pxniPRiQsgH8rfzYB5ql%2Fkq1hXU4ZigNwjsizftemU3Uf5Jzp%2BRXyloF%2Fpj3FzqYiR3YraxREsyx%2FzTOaL6j%2Fyp8CZKsSUOzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Hv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVg35iPrMEFld6XbR3CRM%2Fro1fUIIHwx%2Fs4U%2FlrqOkz3c1lYQmENFJI8DCgRzIDIg5b1JavTOiajZLf2cls1KsKofBh9k5ydpJPL%2FmzT9ZcBIWY2t5sFoD8Ls5C1%2FwCDkyQ5KyjWdLGi6ml3brSyvKxuo6I58P8AJPVclOiXZurPi5rLAfTf5fsn7sE3drBqFq9vLR4pV2I7dwy%2B%2BF2j6Xf2F5dS3EqNbyhViVa8iV%2Fbfag6%2FZXBdj3KnWURXLzYFYV5n8n3us6ut7btEITGsbc6hl418B8WFd75Ym8svHqVqPrQiCsJSPiikH2jQfsNnScayhwVYBlOxB3BGG1Sby7rf6YgZ5KCZftIBSmHeFllodlp95LeWqlDMKGIfYB7kDDPE%2BSuzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F%2F0u%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZFfM%2BipLW%2BSJZAf71CtaMPsygf8SyVZRAIIO4PbCDW6pP5YvDd6Wiu1Zbc%2Bi%2B9Tt9mv%2Bxw5xG3tbe1Vlt41jDHkwUUqfE4tgPNXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Pv%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV%2F%2FZ" ); + background-position:center center; + border:1px solid #00aa00; +} + +.yui-skin-sam .yui-h-slider { + background: url(bg-h.gif) no-repeat 5px 0; + height: 28px; + width: 228px; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css.min new file mode 100644 index 0000000..223d27a --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-doublequotes.css.min @@ -0,0 +1 @@ +.yui3-skin-night .yui3-dial-ring-vml,.yui3-skin-night .yui3-dial-center-button-vml,.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-night v\:oval.yui3-dial-marker-max-min,.yui3-skin-night .yui3-dial-marker-vml,.yui3-skin-night .yui3-dial-handle-vml{background:0;opacity:1}div.base64-doublequotes{width:100px;height:100px;background-image:url("data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAgEAZABkAAD%2F4RfJRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAAD0JAAAAnEAAPQkAAACcQQWRvYmUgUGhvdG9zaG9wIENTMiBNYWNpbnRvc2gAMjAwODowNzoxOSAxNDo1ODowNQAAA6ABAAMAAAAB%2F%2F8AAKACAAQAAAABAAABwqADAAQAAAABAAABRQAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABaTAAAAAAAAAEgAAAABAAAASAAAAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkklKSSSSUs4uDSWiXRoOJKFi3Ovx2Wvbse4e5gMwRo5soypdOyN9mTSRHpWvj4Oc4%2FwDVf9WkpupJJJKUkkkkpSSSSSlJJJJKUkkkkp%2F%2F0PVUklCqxttbbG%2FReA4fApKZpJJJKUo2WNrrdY8w1gLnHyAlVOsWvowXZDZ%2FQOZa8D9xrmm3%2FNr3PUswm%2FpmQGamyl4bHiWuhJTYqsFtTLBw9od94U1Q6FkfaOk4tszuqYfwV9JSll1%2FoOt2sOguDXgeTm7f%2FPmN%2FwCCLUWZ1VhrysbKA%2Bjua7zgtuZ%2F1FqIUXTSQcvKZi47sh7XOY0tBDYJhzms3akfR3blVd13prMtuI%2Bwse%2F6L3Ahm7n0%2FU%2Bi2zafzkFOgq9%2Bdj0ZFOM4k3ZDtrGNEnhzt7v3WbWPU8bJpyavVpduZuc2eNWONb2%2F2XtXOY2VU7rA6hnO9RuJS%2Br1hO1lguGJbuYz2extvv3fzLPU%2FwCESU9QkkkkpSSSSSlJJJJKf%2F%2FR9VWf0iwiu3Ff9LGsewT%2B6D7P%2FAyxy0FmunH6xPDMpgd%2FbZFT%2FwDoOx%2F%2B20Qp0lC02CtxqALwDtB4J8FNJBTVovx%2Bo4jvbLLGlltTuRMssrf%2FANJiz%2BhZDqMO%2FEyCX2dOc6t%2Bkuc1gmt%2B3%2FhaPTeoZ5s6R1IZrBGDlkNvI%2BjXcYYyx%2F7tWV9B%2FwDw%2FwDwlyD1LqWH0jq2N1O55rxOogY1rwC4C9uuP6mzdt9Wl1v6T%2Bb%2FAFdFS%2F1Myq%2F2VThusa%2B2tst2k6sPuY73Brm%2Fo3Vv2fy%2F3F0S4TAzq%2Bm%2FWDquKGnbhWOya62DUUlrcmyulktZ6f2ey19Wz8%2F2Ls2Z%2BFYx1jL6yxgBe%2FcIAI3CXfNIqZX3ursqqrZ6j7TqJgNY2PUsPP0dypfWJ%2Fo9NOT2xrarHTxs3tZkf%2By77VR6v9bejdNsbkb3Zbqm2sfVjgOOhrdZFljqsffXs%2FmvV9V%2F%2BDXHdZ%2BuvU8zA6i%2Bj02Y1zawaZLt2LY21tltb7XOb6j6%2FwDR1V%2FzV36v6rPVYFU%2BiCs5PS7cd43O2WUOB77d1X%2FT27lwvVnNyKK8d15q6hij207o9dg3DHdW9m9zLv8AQ%2F4Wu71K%2FTtr9aqzJ%2BuHV8tmR0zNoyLvsXU8Nr7cdtjmtN1J9K%2B2podsbk1%2Fo%2F8A0YsnG6te%2BnLZbdXXY6pttADNwucwmhv2cWbv0tnr%2FpKnfpKbKf8AtsqD1DvrjnfV70cKlldgzgbqjf7QHB3p2sG0sb6lv0%2FfZ6TEcZg630xz2vezK6jVbfhVtf6biQ%2BxltmNY7a2z9Js3Vu%2FwayvrHh1%2BhhdKv3XubjBhY9wDbHtPpOdXkOH6t1Dd%2FRsl%2F6C%2FwDomV7Fg9Wc%2FF%2Bq3RL6biben5WVjh4lljdxbexltf06La9vvp%2FM%2FwAFZ%2FhEuqn0r6lfXM9WYzpvVoo6wxvcbBcGj9Ltr09LLoj9bxf%2BvU%2Fof5mz9avrJd0%2B2jBwHAZTrcd17iA7bVZa2nY0H%2FCXw9v%2FAAdf%2FWl5zidQZ9ZcY3l3oddwg2z1mHZ6zWfQv3t2%2Bnk0%2FwCn%2FwDRf8xf6Df1DqvXGZ%2Be5tzsi7Gd6lm2kPsqNbqqOG1%2F4Cuxnpt%2FS7%2F9I9ALjR1Gh7f96%2BuJJpA1KZj2WNDmODmnhwMhJaySSSSU%2FwD%2F0vVVn9airFGYSGjEcLXuOkV%2Fzd5J%2FdZU%2FwBX%2Fra0EHM9D7Jf9pE4%2Fpv9YHX2bT6mn9RIKcE9U6lgXnJDv2l0jN%2FS497S39C530sOyxn%2BBc%2F%2Bh5P83%2F2kyfS%2FR5NlPrv16uwczExsPHFozLBRWHz6rriWM9Ouv6Hs9T3vseue6B9buoZF5xBU84BDC%2BtoZYW1PczG%2B02Gxm71Gb2XP2fod7P5mtct167q%2FT87Gdfk%2FbscWHI6V1NrQNGu3O2NZ6fp5FN9dTcrH3epR6f9RKwRYXzhKEuGYo%2FxfSMvM6lZlF%2FVfSobU11Q9MGyqLfa%2BrP9PJsr9Kz09n6bGq%2F7dWN1z9VxC3KfZT0%2B%2BPUyGg5NIaPdU7ezZe7KxPR%2FR5Gyr1sX9Db6%2FwDguZx%2Bv352be4WNwft%2B9tb2n21mza%2F07Xn2%2Fp7qmVep6dbP0vqfolqZD7mY91eDmXh9pBAZDGjT9awvb%2Bkp3W%2Fp2Mdkfpav1b%2BXUb0WulTeP23h5Di3JL3UYWTYzlzbKn1sc5rN7baM3FZ9pw8xrvSvr%2FQf0im6uvH6vY7G6hfS2mx1WFYaq7bnk%2Bo2r0rKPTa7bustxX20%2Bz%2Blf4RW%2FqPXeM403s%2FQ9LpdbQ4v97Wl4DcW1nud6PqfrH2e9nszMavNx%2Fs9%2F2hA6i5r77HZLH24Tn1W4%2BUwj2Pva3Jdj5bfzaHb8n7Fk%2F4P9YxP0tX8wulqaWfb1CzZ6GaM30622WDD%2FSV1mp3sfY6tjWOsY1tf8776a%2FTQ7s27qFNVIrqwAfUsbZRXt9S0N9Ky1tX83%2Bgre%2F1sej%2FAE1lzKltdDtbi9ZJsqqbTaBXdS0TbW68PycUxNj8qrIbR%2FpPU%2FSb6%2FTyv6VWf0qvOrzmsYasnGzHmk7gx1Za6K2XR7sd%2B5v6K79JXi3bPU%2FV8i71RRU5%2FWaLMv6kYj7SGX9L6g%2BqK%2Fosrymeux1cf4B17fYsrpuPmNxftz63Pcwl9DWDQ2sIqZkNJ%2FNZe6luR6f%2FAAX%2FAAS1f2pXX0vq%2BJln7LfkVVta3ZAfl4929myn%2FA76rLq86r%2Bbo%2F4qyhVruoZfSek4ldmM12Pe227D9XQBtvptu3%2B7d6Vr66Xf2PU%2FwiSnsuqnDyLMfFtMZORj%2BrXSPeHFseo2l7g31La%2FV%2Bh%2F2oq%2FwfqfpFznVcd9uDZivaxzDZXa1zztZaXB1LW%2Bv%2Fgb%2FZVXi5tv83%2FRsj9AsLqfXv2j0%2FpXqPFedgNurfa10F3uqsx8lv8Ao3Obvrf%2FAMT6n%2BFQquq59%2FURec1zb7CHXMc8htmw7n47v8BtucPUb6v6P9Ld69iNoS9H6Vk0Zzcpj3tqqeW1AAtuc%2F8Am7Meyhv6WvZ%2FNZX%2FAIEugzuk14eLiN69fbi49u6wgBjyWNb6dP6IOa52V6vt247P0dD%2FAFP0ajjdc6kBeekYQd1DIs2tsZVZbdVXt9tYqsG9%2B3%2FTPZ%2Bl%2FwBCsajpXV%2BtX2Zwo%2Fal7Wuvv9S0Mea2%2FT2%2BvZ7m1e1j6GV76PZ%2FpK0NE7avpH1Z69ndU6Ti4mP6mVZktBdbkP3uqbWTRkjKuYGb9t1e6v2776rP9Iuyw8VuJjtoaS8tkueeXOcdz3%2F2nLyb6vdZv6DjDKwmVt3lzbsZz3VsZcHluTgX499hfRYxuzJwn%2FznsyKrLLv8H2vT%2Fr9hODK%2BsM%2FZuSWkvrtFjC1wLmvr%2FWKqW%2Fm%2BzbZ%2BkRR4vVpKn03q%2FTeq47Mnp%2BQy%2Bt7WvG0%2B4Bw3N9Ss%2FpK%2F%2BuNVxBT%2FAP%2FT9VTOa17SxwDmuBDmnUEHsU6SSnxf6x9CzPqt1ECix7GMeben5Q0caneyylzvouto3MruZ%2Fhav0np%2FpFUryaMjFvrzps6dkPbZmUsHvx7zFber4f7rbLP6Wz%2FAEln%2BivYvY%2Bu9L6f1Xpl2H1GG0OG71SQ01uH0b2Pd9B7P%2FUb%2FwBGvH8vpF3T7%2FQpcH5NIea7az6leXSd2%2BzHjdW70qHbMnE%2FwlSZrE2NuzfjKHMY%2BGfpzR2n%2FL9H95wM%2FByOk5hxsgiyuwb6rm613VH6N1X%2FAKMrW10jqbrmHDyHl8MhjY3G6sHd6PO318dv6eiz07fW9P0v%2BOHiPxc6n9j552Ydh3YmVy7FtP5%2Bvvfiu%2Fw%2F%2FB%2Fpf5zehYv1a6pVk5WLnh%2BJZhML6rmiWvsBY6t1Fn0n1NY77Tvp%2FSf8WnijqNWnOEscjGQ4ZB7Oig0fV7Lf01rr8rqR2tez3XPbBx67XsYzayxjbMl9m38%2F9J%2Bl%2FS%2BpzrvUxMWqvqNVuJksx3402zW5oosbdScig725OHd9qY6v%2Bc2ZOLT6Nn88y3e6X1uyk9NexznYd%2BPdi2Mc1lTxl4ztznWu3bKfWZZXbs9T06f0ypdY6J1Hr%2FVH9Wrtpsx6mMqFDS%2F1WisF30XNa5%2B577bf0eyz%2FRV%2BqnHwW1RotDF6xay49Tviks9OHNBAc9g2sfc1m7Zu2%2FoG%2FQxv3PST9Lw2dTblM%2B1W1sdDixoM2vu3f0936Ot3pOZsurp%2FQ5H%2Bj%2FwaJj4GXf052ZjepRjbmOrywNzNjHulh9Meg5zN%2B1lrn%2F4R9fp%2FpFYxcHD6ey6nItdSGAOtdlFwhlh%2FRuHpN3Ppbv8A5xnqemgFOZ1%2FDyMW77T1DIOQy4vra91bqC00en%2BiYx%2F06Nrqnev%2FAIf%2FAEj1WxaG2sxKOo9Mu6iK32UYeOLHML3vLrNrrmu3%2Blv%2FAPRi1cvpl1PUqW3Nfh5VJ34%2BNmO9XEurHu%2FV7t1jGMsYf0noP9n%2FAANqv9Q6W84w630hn2cuFd1jcYGysjS6qzLxmiu3Fyadv896NX%2Bl%2B2eqhSSBQ1u%2Fwed6z9X%2BrtFJH1dZj1agENsqZuIB9EPsvbkW7Wj6eS%2F6fq%2Bj%2BjWOcbNw8hnqdNxq3tizZYXOa4Ty7fkWbmNd%2FObfof4RdpT1fqHUs1rc%2FLfktyRU2vGa4bSHNePtFL3el6VmLlVejZ7f0m%2F1cj%2BZ%2B0WbvSfqn0%2Fq1eTjdRIdlVspsqcxwBqc8PbfW%2BrX376%2FTtf%2FAKH0bcS6v2WJXqulj4YCXEDZqurxn1dxXdRosuw78hnXcR5dSWu22OrY2bqsdn03ZFTt932Oz2ZWL6lVLPWoXS19Hzup9Pq%2BsfTMYty8kn7ZRXDCy5hdVb1DEre%2F9NU79LvxHbLclj7Kf5rIspXE5mPm9J6q%2FLqa82YrmvfVJHqUsd%2BgyqLatln0a%2F03pP8AWxLmerV%2B5j%2Bz%2FU7qvR%2Bp9Cot6QNlLJbZQ5xdZXb9O1l73S99jnu3%2Bq7%2Be%2FnEmN57qv1X6b9c%2Fq99oxWNx%2BuYxcyx7g9rjc2PXxM5t36x6djmt9H1v02L%2Bi9L%2FCVWcz9VPr51npPWX9H%2Bsxuy8bItFNoyDvtot9tIcN%2F06He316P%2FAEKo%2FwAJ9p9hbXW17ntaA98b3AQXQIbuP5y43%2FGB9Q2dfp%2FaXTWtZ1iloEGGjIY3%2FAPe7%2BayG%2F8AafJ%2F6zb%2Bi%2FSUJT2TK66xtraGAAABoAEAbW8fyVJecfUbqP8AjHPV31dXxMjJ6c%2Fay27LaMd1JaNgsoDxX9o9rf0zaW2%2Br%2FPep%2FpPR0lP%2F9T1VJJJJSDNL%2Fsr9geXGABW1rnakD6F36P%2BsuAwumV%2FWXNrxHvcymqh2S7IqLnRa%2B7Jfj2UPcGtqdvyfVspZ7K%2FQ%2By1%2FoaV6Ffj05FZqvYLKyQS13Eg7m%2F9JKimvHprorEV1NDGDwDRtakkEg2NCNnxDqdGb0Lru3qFDHX41rLTWGxVeyR7626tdVmNa%2F1P3LPWr9i2cmzrpY5tdB6gzpL7Kq7WGXPqqf6D8HIc1gZ9upo%2F7T%2FzmVX%2FADXqr0brOF0%2B4135bWVFgc05kD1WMP06ari17q25P81Z%2B%2FX%2Bi%2BnauTysfqnQeoM6h06l91eW2H4jwf1uhgc70Lq3DdV1XGxm78d7%2FwCfo%2FQXfpK7GIRFX4s2fN7vAeGpRjwk93IyOj5VDnN6U5%2FUMa%2FflYlLGuLm%2BqxnpfadrG1tdk302Ufav%2Bs2en%2FNrQ%2Brd9%2BNlNdfS%2FDuDXMy8e7R1bmjfJ%2FkNhl9Nv59KtOeLbMDO6FktJte%2B%2FCstLh%2Bhcaxm4mY5oc5tLMr08XK3st9H7TRd%2FSqPWW11fA%2Fa%2BOOpdOc6jqeMNllYjcdvudjWt9zfVr3b8d%2F%2Fom%2F1E%2B2F5jpf1u6Dj9RyLKcqu3peaf1rF1aGh%2Bhym0XMr91TfZksr%2Fncb%2FSWY9bFTwftfUOpdQwRZvxsDLOLh2uBexrLH21YzLLAHv9K3ZX%2FwAH%2FOLUw%2BnfU%2F6xVDB6lg4%2FTutEFrLaG%2BgLXD%2FC42zY2x%2F%2Blw7f01f8ur9On%2BroyPqllZfThhMsqBZblWhxFjahFLLWE%2B27HZv3sbsr9H9N63%2FBjW1L9J9PDa%2F6udcx%2FU6Ta7bSH6uxLT7W0Oc0%2Fo6HT6mFl1fzX%2BnV9n1R6v07bbhZv2za4w149K0Vk6enkMeWPu2fzn8xVb%2Fwf0F1GVh4mdSW3MD2vbAfA3AH9xyoYmRZ0o%2FY894%2BztBNGS7QbR%2Ba8n6Oz%2FwH%2FttLyRbyPUcXMqzznY2Nfh9TrbZbkkVyxzQBvzm%2Bm04vr7f0d%2Fo2frX%2BD%2FTV2rc%2BrmH0bqHT8fcW%2Fb2Ned1FrmWsaXOZLfRLH01W%2Bpu9L%2BaXUiCJHBWGegM6d1IdU6WzbJi%2FFbAaWuPvdV%2FV%2FnPTStN6U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZ%2F%2B01IlBob3Rvc2hvcCAzLjAAOEJJTQQlAAAAAAAQAAAAAAAAAAAAAAAAAAAAADhCSU0D6gAAAAAYEDw%2FeG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8%2BCjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk%2BCgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk%2BCgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q%2BCgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw%2BMTwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BUE1UaW9nYVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPm5hLWxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk%2BCgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw%2BCgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk%2BCgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk%2BCgkJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk%2BCgkJPGRpY3Q%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw%2BCgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BVVMgTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk%2BCgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJpbmc%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0Pgo4QklNA%2BkAAAAAAHgAAwAAAEgASAAAAAAC3gJA%2F%2B7%2F7gMGAlIDZwUoA%2FwAAgAAAEgASAAAAAAC2AIoAAEAAABkAAAAAQADAwMAAAABf%2F8AAQABAAAAAAAAAAAAAAAAaAgAGQGQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QklNA%2B0AAAAAABAAZAAAAAEAAQBkAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD%2BAAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAE4QklNA%2FUAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA%2FgAAAAAAHAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAAAD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FA%2BgAAAAA%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwPoAAAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1UAAAAGAAAAAAAAAAAAAAFFAAABwgAAABAAcwB3AGkAcwBzAF8AYQByAG0AeQBfAGsAbgBpAGYAZQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABwgAAAUUAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAUUAAAAAUmdodGxvbmcAAAHCAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAFFAAAAAFJnaHRsb25nAAABwgAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE%2F8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAThCSU0EDAAAAAAWrwAAAAEAAACgAAAAdAAAAeAAANmAAAAWkwAYAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1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U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZADhCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAIAAAABAQD%2F4TkjaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu%2B7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI%2FPgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEuMS0xMTIiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI%2BCiAgICAgICAgIDx4YXBNTTpEb2N1bWVudElEPnV1aWQ6RTcxOTVFNTY1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkRvY3VtZW50SUQ%2BCiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6RTcxOTVFNTc1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkluc3RhbmNlSUQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0ZURhdGU%2BMjAwOC0wNy0xOVQxNDo1Nzo0MS0wNTowMDwveGFwOkNyZWF0ZURhdGU%2BCiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTA3LTE5VDE0OjU4OjA1LTA1OjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpNZXRhZGF0YURhdGU%2BMjAwOC0wNy0xOVQxNDo1ODowNS0wNTowMDwveGFwOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1MyIE1hY2ludG9zaDwveGFwOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOkhpc3RvcnkvPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpOYXRpdmVEaWdlc3Q%2BMjU2LDI1NywyNTgsMjU5LDI2MiwyNzQsMjc3LDI4NCw1MzAsNTMxLDI4MiwyODMsMjk2LDMwMSwzMTgsMzE5LDUyOSw1MzIsMzA2LDI3MCwyNzEsMjcyLDMwNSwzMTUsMzM0MzI7QzA1QTE5MDRGRjAwQUJEQzA1MUJERkFGMDIwNEVBNTE8L3RpZmY6TmF0aXZlRGlnZXN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24%2BNDUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24%2BCiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U%2BLTE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtENDYzN0NCOUQ0MUExMEJBN0VGNUVCQ0RCNjMxODMyOTwvZXhpZjpOYXRpdmVEaWdlc3Q%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY%2BCjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8%2B%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQACAYGBgYGCAYGCAwIBwgMDgoICAoOEA0NDg0NEBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEJCAgJCgkLCQkLDgsNCw4RDg4ODhERDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgBRQHCAwEiAAIRAQMRAf%2FdAAQAHf%2FEAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4%2FPE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BCk5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0%2BPzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BDlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq%2Bv%2FaAAwDAQACEQMRAD8A7%2FmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmrlHI2utXn6WltnFESb0RFSp41WjD5q3LCBaslzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2E2rj0LuzvF7PxftUf8AXPLDnC3XI0ewdpOkTK4P08T%2FAMK2Ec1TLNgaxmE9pFIDy%2BEAn3GxwTgV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F%2F0e%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXYUeZpfR0a4kpUAx19h6i74b4X65CbjR76FV5FoJKKe5C1GIVLdDuGhuXs2IKOX4gfsvGdx%2FskKtkiyD6bctHHbXgPImOC4qOpXj6E1ff4Mm4Ndxkpc770BvNmzZFLs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Lv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVokKCT0G%2F3ZgaioNQemANZuhaWLyE0LlY1%2BbGn6sWspA8QA%2FZ%2FUcVRWbNmxV2bNmxV2bNmxV2NZQwKnodj9OOzYqwDT4iiPZsa%2FVLm5sj7I%2F76L%2BOTXTpjPZQSt9pkAb5r8JyKXqfUvMOpIQOFxFDfoP8qFvTl%2F4Q5INDkrFPAf8AdUhI%2FwBV%2FiH8cnLeAPcxHMprmzZsgydmzZsVdmzZsVdmzZsVdmzYyWRIo2kkYKiirMdgAMVX5sjTeaGl1CzsbSAOLuX0w7k14KCzyAD%2BUZJBirebNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F9Pv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVo4CXUFa9e0CbJRWkr%2B0RWlMHZEJ5WtPMtzE5%2BGYJKnyK0%2F4kuEC1ZeM2IW0okjFT8S7H%2BuL4FYz52mMWn2tDTlcpX6FbDHR5ecCH%2BZevywl%2FMM8dJtn7LdJ%2BKvgry9ccrOJ69KVw9E9GS5s2bAh2bNmxV2bNmxV2bNmxVi3miFU1LSbxvsStJYzH%2FJnSi%2F8ADYpoEzLcxq1T68FGr%2FvyE8GrgjzdC0mhXEsY%2Fe2pS5i%2F1omDf8RwttJRHdrcDaNbhZVI6endIG%2F4mcnHeJCDzDL82bNkEuzZs2KuzZs2KuzZs2KurkZ843Zhs4bVTQzvVqfyrvg3zHNPb2UMsLtGBPGJSpIqjEqRUb9ch%2BvSSvp0JlcvJCLyMuxJb4JNvi%2F1SuEBVvkaX9L%2BZbm8Sv1fTbf0Y6%2F78lPxH%2FgFzpeRvyPbWcXlyyubWBIXuoxJOUG7uKjk5%2FaOSSoxPNXZs2bArs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FU7%2FmzZsVQ2osyWM7o3FlQkMOxGPtZhPBHKCDyUE08e%2BM1Bedjcr4xPT%2FgThV5cvBJbpGergEfMDcYa2PkqfZs2bArs2bNirs2bNirs2bNirshfnRGtb7T9TX7LcoJD2qDzSv3vk0wl81WDajodzDGKzRj1oR35R%2FFT6RthHNXaVcrKsUtftDi304dZz7yrqPrQCIncdMnsEnqRK%2Fcjf54yVjP5gwtJ5ckcD%2B5mik%2BivH%2FAI3wD5RnEtpwrWgw983RGby1qiqKlYGkA%2F4x%2FvP%2BNchnke5BIUGoPQ%2FPEJHJ6XG3JFbxAOPxOA1iX7sUwIdmzZsVdmzZsVdmzZsVUbqBbq2mtm%2BzMjRn5MKZDLP4rC2UVq9qYj7SWshWn%2BtxOTnIVG4ttWvdNaiiK7FxGDtWG6Ti%2FwDwMuShzRLky%2B1lE9vFMP8AdiK33gYscKtBmDWhtq%2FHbOyMp68SeSH5UOGpyJ5pYde3moWPmW5KzH0pIo2WNt0A3Wv0ts2D73zJ6FgzxqqXpKpHG9eDMx7EYXed45VeC4gPCdYyqua0I5q5VgOv2cAW8sWo2QMqhwwoyHcVyQFhVOLzvrNrdf6fFHLFX4kVeBH%2Br1%2F4bJlp%2Bt2GqWrXFnICyKWeJtnUgV3XOP67qFjaFLHUrprecy%2BlZajxPDmN1jn8Dv8Aa%2By%2BIaXrclrdtZ34NrfR1USofgeo2K06c%2F8AgcBCXr%2FlvXRrdnzk4rcoSJFXYfMbnDzOV%2BTr82eqAOQIpaBq7AV2r%2BOdTriRSEp8z8RoN9I5AWJPV5HYD0yHr%2BGQg3Ntq1lcLazx3CiZviiYOKzQo9Kjb7YzoWqRevpt5AOskEij5lCOmc60%2BWCK0j9ONYo5IYp%2BEahQWBeNjRafEcMVTvTb%2B80fyHZ3FugE9vSORJBUqPVZW%2BEHw3yVaXeC%2FsobulGkX41HQMNmH%2FBZzC%2B1iTTbadZUkjtJjzkQqSKqNm5fsdMPfyr1%2FRdT8vra2E5N5C8kl3bSMTKpkctz%2BL7SP9peOA7fFkIkgkCwOfkz7NlA1y8DF2bNmxV2bEJLy1injtpJVWeavpREjk3Hc8V64virs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Xv%2BbNmxVplDqUbcMKH5HIPokjWsstqx%2BK2lZPf4Wpk5yF6nF9R8xswHGO8QSj%2FAFh8D%2Fqrkoc6VmSMHUOOjAEfTjsAaZMXhMRPxRnYf5J6YPyJV2bNmxV2bNmxVQuzOtu729PVUclBFa07U98DafqsF6i9EkI6ePywwyF6vG2i6oJRUWl6xZCP2JOrr%2FsvtLhG6s0yiK4X6Zfi4QI7Vb9lv5h%2FXDHrgV5c8B0LzLc2Q%2BGF29WDw4SfF%2Fwp%2BHOg6ZMHi4j2YfTkZ%2FMGwpFaazGDytm9GYj%2FAH25%2BEn%2FAFX%2FAOJ4N8uXwliicnps305LmFZDewrc2dxbt0lieNvkylc45%2BX10UCQzHjLATE4P%2BQeNc6L55e5i0J57WVonikRmZDSq7jf2yB2Op%2FVYor2%2FwBNjktpAGjv7ZvU%2BInoy8Vao%2Fa44xCQ9as25RVBqKnfBGRby9rBEsljcIY0aQ%2Bg5FCCQD6bj9lslGAikN5s2bArs2bGyOI0aRuiAsfoFcVS%2B%2F1q2sJltyrSytuyp%2ByDsC3zwxBqAfHfI%2Fodmt2z6pcjnJK5dAexPT%2FgRkhxV2c782mSy82WUgNIdUhNs4PTmlXQ%2FwDBDOiZAvzLb6nHpOrlFkjs7lWdG9yvxVG%2FwiuGJ3Up3YTJFr7op%2BC8t1ljHjxodv8AYtkiyHbxx6XfKx%2FcXBilJ3%2BAsVUV8FRlyYA4Z80DkkPmq3EtlHJSpR%2BJPgHBH66ZBtIufqt9Np8pALHnEpO5p1oM6Xq0P1jTriPoePIfNdxnLtZtrGZluBcG3vF%2BFJYuJfx40IIxHJKzzb5et9ZtZYp1LwygcgPtKy%2FZkT%2FKWuRKKCOC6tNH1CblcWiILDUWHH6wg6wyDejx9Fw4sfOMjEBY5biH1HgLy8VYulOfJV%2By38q4ndH9LlL219K4iilHrWzLxlhI6SgE1%2F2SnFKo0Czxy28zMqcSzspIYBPj2I%2F1cd%2FytnVZdNQ2D1I%2BESMoPw%2FzMftdMG20TSQyyblmjenzoc4TY6ld6ddyKwMUsbFZoHqNwd1KnGXRXs9n5%2Fv7lg98GlWhMjwk1A%2Fm4k%2FF7jDSwSPULTTJI3PGBphGNwG4OHVW%2BgnONX%2BsWFpDFPaSSJcTESG3TcRlf2uRK%2Fazq%2BkR3aeT7e%2BjnX6yoW8ibht%2B9i9Tg%2B%2FQ98QVZHqstutowuSPSdSpV91IPVWzif1i98t%2BZ7m40FjbSWUrNCqEmkex4EH7acT9lv2c6lonmbTvMUTWdwgiumWktrLQhge6H9of6uRLzd5ZurDVP8Q2KetYFUW7jXeSKi%2Bm0hH7UZH7X7OCY4g2YM0sMrjvexB5SHcXsnkPz3Y%2BcdPqKQ6lAB9bta%2F8lI69Y2%2F4XJeDXPJlvPe6JqMeq6NMYLuE842To6ntToyuv2k%2Faz0J5E8%2B2HnGyI2t9VgA%2Bt2ZP0epH%2FNEf%2BEyESeUuff3tmbFAx8bB9H8Uf4sZ8%2F6P82TMMLNb1iDRrQ3EpBkkPC3j7s5%2FwCNV%2B0%2BGVc4n5m8yfpnzJcsr%2F6HYsLe232PBv3j0%2Fy3%2BH%2FY5JxkLourX175%2Ftb28maSZrloqsdlQ1Tgo%2FZUDO755%2B8uxlvPcMI6i6LAe2zZ6BwlS7NmzYFdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVf%2FW7%2FmzZsVdkb83W5%2BrW1%2Bg%2BK1kAc%2F5D%2FCf%2BG45JMC6jare2FxaEf3qMo%2BdPh%2F4bCNiqV6VOOcTV%2BGReB37%2FaX9WHoyFaJMz23BqiWE7juCh%2FsyaRsHRXHRgCPpwy52gLs2bNkUuzZs2Kuwu1rS49W06Wzb4XI5Qv8Ayuu6nDHMemKvONE1KWGVrG7rHPCxRgeqsppk7sb0XC8W2lUbjxHiMhnnnTHtLmPXrZfgakd1TsR9iQ%2FP7LYtomq%2FWI0Iakybof4H55LmFZdqNlFqNjcWMwqk6FD8z9k%2FQc515XuZbW4l0%2B5%2BGWFzE6n%2BZTTOlW063EQkXY9GXwPhnO%2FNsS6T5qtbofBHqaniexmi%2B2v%2BsU4v%2FlfFgHcrPTFbanZNb3caywyApLE3Qj3zjutwW%2FljzBc6Pp6fV9JHpsLNSSgR1HIorV3Vvizq2jXQk%2BAndlBA9xnNvzRiWPzJBJWnr2gJP%2FGNyv8AHAdikJ3YGf0o5pZDIboSD1GJJ9aAgh6%2F5aUzoFnN9YtYZ6gmRFY06VI3zlXk%2FVI5bi2hnlBgdBuxFFahhfr0rSNsnHlXU4JI5NJaSt1avIQm%2B8RaquD0I%2BLjkpbgIZJmzZsirsDagC1jcqvUxOB%2FwJwTjXUMrK32WBB%2BWKpfofE6Xb8f5d%2FnhjkMPmvR%2FKlrJBqkxBSVkjC0PIDpTfI15s%2FMNbu3jbR5plsZVp69swRi9N0eSjMnH%2BRcVpm669cWWtXGnatwjgKma2uPsj0x%2FNXw%2FayOfmLr%2BhX3l%2BPTYrkXM%2BpGtm1uPUUceX7yRx8KLtx%2F1s5xoN%2FefpVr6C8muVVfUuLO8kMrEIeTem7faRk5Iy5FdTuZ9B169trGZvqkc5eFD8SmJzzUcTtsrceWHzTT3fRJv0p5UZvtOYYrgCu%2FJV4P%2FwANHnPrj83vM2lX9zpWoBJYInaJ540pOi1%2BGRQDxf4cln5Z3qT2stjWrK0iexEgE60%2F2XLOUfmHYNZeZbhWP94Ayn%2FV%2BD%2FjVclLlbEdQn955q1wTiU3huLadeQCsfSljO9VNev%2FAA0bYHub1Z7V5yWkhHxpcVHJNwGiuP8AKStVk%2FbyGafqLQxyafO5S2lPJWUAmGQ%2F7uiB8f8Ad0X%2B7F%2Fy8Ctd6jpl3Lb3v%2BkQTpxniqTDcQn7LoR%2FwUb%2FALDZCyyekWl9ZyaFLPelZGN2tqDEtZJHenEs67ckpVXwq1bU7G1iKWvqtcCR4bkkhFYx%2FCHXhvvX48C%2BU7H1SbK3k9Wya5hv4HchSBF8FxBL2WeOJ1k%2F4s9P4cu%2F0j%2Fc1FphmFxPLeOhZBxAiL8jt40%2Fa5YegV6PprvLpcE8sfpTNbh3QVoGK12zluoQ2PnZih42fmWIVt5z8Md4q9I5P5J17Z2A8YrWVl%2BERoaDwoNvupnLtb02LzREdR0hBba7bVe4tEPFZwpr6s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xKXcslu7tXb1%2BSBq%2FwCSzZK9c06xuNUutStkBls5IFkAIAMoHqUUfzNRkbCPW5Xs70rZcVtL0%2BtCoAFVc1oK%2FwArni2RIShdD0rU9Z0g2UNW1DR5JLG%2BirRlQuXhmp1ZP72M%2FwCph75g0K2sra21G8ch5baGJUpt6yARuvL6OWEQk1eJrq9s55YLxBzuGhJEjr3LKvxSqv7WISanq2oQRXGryvd2MtVhuSQ8aNQch8OyNjsqElhK1hbcr%2Fcv3K%2FyV%2FycRSQBmUiifsfQM6FpfljSbrR0mCy3EjDlDIzN9sGnphU%2FZ%2FlbIrqnl%2F6jM3Cb1VRqOoU8078XoOHPISIiQCd5ckgE3tyS4StK6xSy%2FDJ%2B7HqseO%2FYVw0W2thatp10he2b7YH21cfZljP86f8AD%2FYxO4tbO4so4I7ZUvG5Lpl3PssprUws392JD%2Fut%2FwCbAOh6sLuU6VqYMF4hKRu2x5DrFID0YY7rsh4tMn06%2FkspjzjniaS1nQfDIE%2BJWXwdafEv7Od0ugnmL8tmYipWEOB1oGWp%2FwCH5Zy4hoT9WuU5BTzj7FHp%2FeIe3%2BX%2FADrnR%2FysvRfaHeaJIwZ4RJGo8QDzQ%2F8AAy5OPVBfPNxbpMpifYqaBu4IwFYWlx9fEIJU7lmH7S%2F83ZJ9e0x7K9unRg8azMkoHWJySVR%2F9YH4W%2Bzj%2FKtvFdaxBDLQKzAVO243G%2F8ArYPJUXb2NvDZtdyWxe3B4meCQ%2BtG37Jkjb9lafaXHRXl9q2r6etnWJ7Yxx28h%2B1UNyMjt%2FlH4myX6lp1poPm57CIFLG8jikCsKisqqXWncc2%2BzhLZW0Om35hCuLiCeSgIHFY67KT9rl4YaV63IwMVSakg1pt27eGRuzvrTWILdYbnlcIWXSdQc8W5pXlp91%2FLIP91M%2F94mG9tcfW3AQ14xgsPH4c4Zp%2Btz6HqN2rJ61nNIy3loTTkA54yIf91zR%2FailyRNUinpV0iXqyyxw%2BjdW5Md%2FaN1iPdqf74f8A5Jtka1ZZ4LWYxsySKpaCRT8QI%2BIxkj2Hw5KLe6%2FTsUF%2Fp1wsmrRRk2l0QAL6Fft290g%2Fu7uP7Lo395hFquqaL9XZmmWCRwySWTgs8MgG6Oo%2FY5fZbAUhC%2BZ9JsfMl1SKYW%2BqyQRT2DMf3UvJeTwt4M5%2BJchKyrOr6D5gQwTQEpFK%2FwDeQv8Ayn%2BZDk%2B1Gyj1ew0SaC4gS5ntmCtX0ELQtQAM%2FEcv5Fwv1bQxr%2Bnhr4oms2ymP6xuCStSIbof6v8AdzYOaGAQ%2BXdTm1NdLjj5SN8QkG6FOvqBu%2BTjTrS2sbZLCMcVUmkpFGLn7Rf%2FAFv%2BFxTTme102DTuILIwZpKksW%2BzxWtW41%2FZyU2XlW41HhcahytOQJZVHKaXw%2Fd%2F7rY%2FzviAqQ21ldXtytrDG0k524qKmnj8sO736roNmNIltfVv7hFeaMnkUqTwpxNA2S2MaT5etS9w6WdtEvx1b42A7Symh%2F2C5zTzb%2BZun3swOjacGVKwrqMgoajeiJSr%2FOTDVdVZPYa3pOj%2BW7u31uKKzuZGP1dePP1Iz1UovxtJ%2FlYU%2Fl%2F5hOtyS%2BWrlis1Gm0pyfiR4%2Fi9Kv7SumcrvNYnu5DcXH7yToamrfSf6YL8ratLZ%2BZtJvoT6bwXMbEjuCwVh8uJauPFuFe%2Bx%2BYJ4NMawQiOFzyZOlDX4h%2FwQyQeVtAn1BY9R1QN9WU1toG%2Fa3qGYeGE3lnRLPVfM19LdAyWkTtcW8a7xOGaq1kGz7k%2FAM6moAACigA2AxJ7lojn72wANgKAbDLzZsirs2bNirs2bNirs2bNirs2bNir%2F9Hv%2BbNmxV2bNmxV2Qzz3p3P6rqKbFKwyt%2Fkn4lJPseWTPOVfnX5gmstNtdBtnMbajykuXHX0YyPh%2F2b%2FwDEcbrfm24MRzZI447GR59w6pMfNyWl7EdD1KM3Cp6dwoKldj%2B1zHE%2FRko0rz1rUtz9SvLe2lm2Hp8jC7BhWqV5xvUb%2FDnn01jPEin8pHgckemXmsTaHcxANw05o57O7IIKxliJYll%2FaRT%2B84%2FsNkIZhIkSjRDl6zs%2FwIjJCXFHkb5gp3%2Ba2r%2BbdPuEvYLVbLRpiFL27c2EvWkj0%2Fd8v2VpkGsfN2p3Kra3V2XicgEsQeQJ3qSNs7d%2BkdO1rSbKw1LhN%2BlbRXVJKFZyq8ZV3%2F3YGHLOEecvKFx5TvTLDym0idv3EvdG%2FwB9yf5a%2Fst%2B3lpHUOvsua4iNwbWCruHK%2FB0qN9j0zoy%2BarW48r2Oq3l1Le2sSizuGkqk6zgUVXMda8F%2FwCDTOO2M01rIs0XCRQ4kHqCqGnZl74NgkTlMqSOIZpPVNrXjGG8Qvfj2wXzSyqz1eO%2FtNSjQM8sVubhFbbkIpPiI%2BUR5Yca3q17IdPmtZ2js7yztriONNhyAKSciPtMJUfIZaXDWL%2Bra0jcq0ZYAV4yAq6mv8ynJf5Yex1PRjpUsfO%2F0pnuLJWNPUgkNZ4l%2Fm9Nh6vH%2BVpMRa2uvBcXej2Gp2rSC5tJJbOZkqW4v%2B%2FgY%2Bx%2FeJhtBB5sOi313boLa9ihMlo3EB5ClGkULy%2B16XJk4rhlZarBFAbZljtrS5Tg%2FoIF4fyOT1JjbC1L%2BbSbowyMwu4WrzJryX9h1PQpxw%2FFWFXNut9PB6srS6frlqI4JZHJ%2Br30bCsbOf5phx3%2FAN1T%2FwCRgPQbtreVrEFrW8gfnDU0dJUPF09unHD%2FAFeygjjvbi2haTQbpxcXlpHvLp9x9n6xClfjtjXi1P2P3b%2FGseE99ol9qtyjIKamYlktb6Mn0L5QKJ8Zp6d3x%2BH4vt8OD%2FvciTXPZaZ%2Bkdp5%2Bgt19Yad5p0%2Fe0vU2Y8T0NPiaM%2FtJ%2FuvOj6lcGysFaRlYxJWUjfkUXk3z5MM5p%2BV2l3U2pPdalFHK1sOLyqQxSZaFOdDWOT7W%2F7eTTzK8UdlcxREhXBTf%2BdzWg%2B7JxNji70HnTz%2B51GXyrrFxaapD69nfcRqSftqxHL1oj%2FOjPjtQ0GNYCfrCXWi3QMtlelhyjkYbFfdvsyx4M87Wy6zqemTq4X9KwQnmegkK%2Bmf%2BSi5G9M1PVfLUt3od3CJIGDEQS7iKUD4Zov8%2FjyErqrruPNkK58%2FJN7Sx0%2B0sDe3k0k9xA6JBJACGqwPHiKp8S8fts2F0mrDS3nubPThH6ZLa5YcQsnBvs3kSsCnJeXJuK%2FB%2FwAYmwQ%2FrXdjEsQRizhvjKCrUp8If4uW%2FwCyuK3Fs893p1nezfVdeDCOxmHFi8ZH%2B89wSeBjP2YuX%2BVFiYggA70Pmt9QzfyjdxXeiPeaY3rNYt9ZjdKUkgP2gyj7L8ftL%2FPgTz2tuLdJIT6cN1JFcxzJ2U7Sb%2Fs%2Fa5BsKfLEMvlPXby2sJI40uF%2F0izVuUcb05n0z3gkTlw%2F3237vHeddXN5pEMdnbmOys4BFcy0qDcF6GJa%2FwDFacmyX8Pu2R1QOi6Yupabd2F78dj6xjLVFUlpySaHwkUf7F0%2BDIrrvl6dr42N0eOtRIHs7ldkv4B9ijf8tKgfB%2FP%2FAHX28mPluyb0Vs7OdTL6SSReoK8%2FTZqN%2FrqOPL%2FJwTqdhFr9m1lqUhjnhcm2uv8AdltN%2FMKf7pb9tP8AZrjVhWHaHrEWqxjTb9gt9GKQytsXptxNf2sl35d3J0jznJbCojuQlR26cT%2Btc55qthdyXcyyJ9X8wWfx3ESbC6UbrcwfzS8fjfj%2FAHyfvPt88N%2FKuq3F3q1hqBIEyc4pWZuCkoAwck9MA50VPJV%2FMq2k0TznfCJQUmPJom%2BzJG%2FxcW9t%2FwDY4Q6cILa6ZY2eKRwslv6goaDfjy%2FaK4f%2FAJleadM80a8t1pcZ9GCJYmuG2MrD7TAfsqv2V%2Fmwr0WyuNXUw%2FVxci1%2BKLt%2Fw23wrg6qGVanr1vrK2t3csIry1aESBjxJEYYOQff4cjvm3zLbpZXLWTGC5vr%2FwCswRjfjBGoC8yfi%2BIjCPX2vNMu%2FqZDRNGKSAgUqxqgqKruF%2BH4sjsyPPIZZSXJ7knfG1e9%2Flxrdt5ksbqdSFu7eMLcW5O4%2BE0cV6xvnF75uVzcb14yyBW7%2FaO2KeS9RutC8yWd7DMYLfn6d3L%2Bx6D7SLJ7YhdkNd3UkRDRSXErxMDUFGclT9IwndCtpWrz6ZN8MskcDsGdojxkjcfZmip%2B2v8AL%2B3iWoySfXbiHUmFy14frKXqH4nL14zK%2FVuX7cbYEeJWDPQVpU0Pj0x6yqLL0pJUW4tXE1o5O9SaSRbeP28Cob1Z1T6vPKzxjeNSSQK9aV%2BznXLfUrdtDt9T1U%2BjeRxpa3iMvF5V41jcg%2Ftrx%2BLOd6VbaTqJlS7lMl5Iri3hHwRiQj920snhzODppWsii6zcGeSZg3po3NSy%2FD%2Fen4K9V542r0LyheaXcm5uaCCWNhxkl%2FvClOqcvs4rrn5g2enI9tpKi4uqlWck0rSvxP8Atf7HITazpc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2FLhpr3nLTKJ9UT19TB4zNHtCe3Jj3b2XIssp1Y8bUfFOQsix7SCSlAXpTmj4av5OnsdM%2BuzB3Zm9OWaNGD2%2FMgRTolP3sXP4Zv92fyYi6oITDVrG28x6NBeBvqWoWS1ivSeIikU8jFI%2BzLA6%2FGn%2B%2B3yFaq1pcXix28ZUGi3U2wadx%2FuziAEWv8Aq%2FH9vDLV7TzXeWrqbaWO4VhHeNHtFdCP7EhX5D4v9%2BfbwpC3liGgvIoVdSqt6pLPGr0pTj%2Bz8Xw4CUkEGil7RwRu9ZzwjPx8UZiKePShyb%2BRfMdhHM2kLEV%2BsDlDLQFncUCxcRX7WEF1DCs63zCs6r6c1Nkencr7rgXSpFsb5zCForepC9PiUEfZr4DADRVD%2BddUkPmPU4lUgVNtNG4qDw2Bof2kP2GyK1LECpY%2BAqTnUFhsta1Ce%2B1G3inuZCrySsgqwqFNRkwu9R8m%2BWIwscEHrharDBGjSH5tT4f9kcIoop4da6Vqt2GW0tbiQHbikbkH57UwHNFLbSvb3CNFLExSSJxxKsuzKwPQjOu3%2Fmq%2B1mFo1C2NmFMjhTQLGu%2FKRtumQfU%2FMWh3uoTXx0r1pJePKSWSnJlVU5lQNufHnhQxmOYxklSPiFCDvUZQKUIpUn7Jr0%2B7D8eYrBP7nRbUf61W%2FhmPmtkBFvptnEezCMkj78CpRZOY5w%2FBmWhBCjseuSyyn0pIpIr2CSr2gtbYTQt6aylufPp8PBWbCZPNurROskYgVkYOv7tSAVNRtg2780%2BYPNd5CdWuRJHEWkWONFjRaih%2BFAPljsqLeRrVh%2BjQt3GBRoXBBKAfFwag%2BLJ15B17yfealE2taTHcXMG63Eq%2FvbYL%2FvyH%2B6eFK%2F3iJyT9vAXkPygPNEuoxx3KQ3VrAHtYWP8AeOxpv%2FxWqijMv2WZMLdS8vBLx4pg9jqVqTFJIvwup6fvP5lP%2FDLillv5i%2BStPtL867pEEcem6hxkivLWjIk%2FevHb05ftZF9Okd5Et5mayvoWEtrdRmnCUfYmhYfzftp%2B3k3%2FAC68zLfx%2FwCFdWt1eElrbUoW%2BwGIrDPGv7CyU%2BLj%2B18eIeavKM3lq7WqfWNOkYizuXFeNesE9P8AiX7WNbqCncfm2fzRoUmg6zEqa7ZPDPPCv93eQRMC00A%2Fa%2FZaWLCHzf8Al7oOra5b6h5KuBHe3rj61Ywr%2B5Xlu0%2FL%2FdDfzx%2F8Qwpup4VWBrORhfW7iS0YkrJbkdRLKv2om%2FY4fbzsvkXU7fWNHju3jhj1ZAI9UEKhSJvEmg%2BF1%2BPEhXgPm%2B98y%2BWriTyxrM0iCMBo5VVW9aDoJIZm%2BLif5ftRthN5X8zxWXm%2FTZ9dHq6HH%2Foz2z1eNLd1Kq4TvwY%2Bo2el%2FPXkjTPPGkNY3n7q7hq9jeqPjikp%2FwANE%2F8AuxM8mazo%2Bq%2BV9UuNI1KL07y2PFlbdWU%2FZljP7UTfstih9Jy6d%2BVV3f2dja3ltHe6ipezS2mrzAFfh%2B2iMf2K%2FE2Xcfk5ojoTZ311bz1JEjFXG%2FitE%2F4lnlh3USLKCY7lSGLQ7UI3DA9mz0L%2BVP5wLqxi8s%2BaZRHqIpHZX0hAE9NljlPaf%2FK%2F3Z%2FrYqqal%2BS%2BoXb2EYvraWG3kcyvLG3IRuwY%2BkgPFW2PfJjZ%2BRruwuFa21iRYFACKFKsKf6r%2Bmf%2BReTUDxy6Yqo20LQQpE8rzso3lkpyb58QBi2bNirs2bNirs2bNir%2FAP%2FT7%2FmzZsVdmzZsVdlEA9cvNirzb8zvIf6bhOu6REP0tbL%2B%2BjUb3EQ%2FZ%2F4yp%2Bx%2FP9jOHagvqWsMw%2B1ETGwPWh33z1znI%2FzL8hqEutf0qP4JRzvrdR9lwR%2FpCDw%2F37%2FweRnGxTtNBreExw5DsD6Sen9F4gpphto2prYSSQ3Ketp11RbyAiu3QSoP50%2F4ZcK5YzG5Q7eGPEUyRpMykRSEhH7MV2IzGAkDY5h3OSEMkDjyCxL8beaZaglxoOpxTW7qLSWkmn3cX2eJ34nx%2FwApclMsen%2BcdIeC4QCZQPXjH2kanwyxe2RjT7%2B2e0bRtVHLT5SWhl%2Fat5Ozr%2FxWx%2B2uJWtxe6HqSw8wtxDvBL%2BxLGegP8yOMyceQEbcuo7nnNVpZ4JmMtwd4y%2FnD9bENU0y80C%2BazuRyTrHIPsunZh%2FTKil4kSIaj%2BGdZ1HTtM846SXUenKv2gN3glp1%2FykP%2FD5yO9s7vRb2SxvU4sh3I6MOzp7NkyOo5OKmSuGUMvQ9MMdF1m40S%2FjvoAHUfDPA32ZIz9pGH%2FDIf2Gwjt5Qh3%2Bw3%2BdcFnrir0GW5Kyx6hav6ltfqDHddW5Dbi1do5V%2Bw6%2FzZLPLbQ6nP8AWrpAby3oJGI2kXqkrfyyqR9rOU6HrKWHq2N8Gl0y6p66Lu0bjZZ4v%2BLF%2FaX%2FAHYmda8p2i2tk8sjrI7miTITxkj%2B1HJQ7huJ%2BLJR3K3snuq3fo2ruoqQC3idvsgD%2FWpnMJ%2FJ%2Fme4Msq2jC9tuUaXcXER3drJ1japH72NW%2BFmX%2Fit%2FwB5nTdIksyzW0c%2FryxVZgzBmCsa4eCZAKHDIWgbPDvK9jquh6xaW%2BtW81rDL6lozTKaFJQVAB%2BKtfhwvs47myvL%2BNQfTs2kD9UK8gQKlv2Xp8StnR%2FzQ1GW08u%2BlZO0d3dTxxQshKsKHm7hh9jiq%2Fazi6MxEiI5YOa3NyxJMjVrux%2BIrlctmQ3TS91E3jCG2jHI09R1qOdOgFf91r%2Fw2CLKFYxyJBIFZJOwHgMC2NryG3wRnq56t%2FZhusZiihu7cMWt5ir2zpyikUAU9T%2BYcuWR5pdPqiacQrWqXCzR1USVBAb%2FAHYp%2FnwutdVhtdTa%2FgWVBOAk8BcNG9BTqyk4c6rc2dxe2F3c2kcKJGI7qx4kUjpyR0B6Vr%2FNhBqc9haSxpHERaXRaWIt%2FuvcoTRa75PlyQn%2FAJZvYI%2FMUS2SNELiVTEygUjnVW9OlftI8hVWVsnSXVxfTGS6laSViCS2wodjsNs5%2Fo8rrL69qwd6pIrqAw%2Fd%2FYPw9OmSua51GVJ762swQXLCD1AiryNQrMfi2%2FyVwxKkIjW7%2BezjR7PTpr%2BUbv6WyUH8zfa6duOEPnjT7SEWmrxxkSXatazowA5KY%2BScgD9qIrxwQ3mPX7EetqFhAtqPtegzySAewA45F%2FMHm1dcRIGjMdvC%2FqRIKcuVCvJ2%2BR%2BzglLY2yhjnLaESfcEquburW8M5HpzKvIr1FaDl79cRbRr6S8%2Br245GCoac%2FCjKp67%2FwAww%2F8AL3li01qBLgPJO8f7t4wP7s%2FsE9fhOHer%2BVtfgg%2BvabcJe1FJrPjwZVUU%2Fdy%2FR9llyIFixuEzjKEjCYojmGM6jaajZ28RjBiEisJzULTi3iSKR0wboHkTXdWt21OLT5ru2A5RlN1k8SrsVWT%2FAGD5ena1aXA%2Bo6pD%2B9J2WcenL%2FlBJR8D%2FwCrnSfy880W%2Flyzl0m7uJZtJR%2BVmXSsltyNXhYD7cP7ScfiT%2BXDXcxosR1D8rvP2qWUdlZadHZW7kPcPcXEYeSn2EKR8%2BKJ9rh%2FNkRu%2FwArtc026ey1FooJo9yKs4IP7StQclz0brf5jeXtKhR7eYX0sieoiQHYL29Rv2Cf5T8WQ7W%2FMj%2BZrOKd0t1Ct%2B6eDk7xMaj05CaNxb%2FVwEgCy249PlyECMefJ4235fXQ63Uf%2FAt%2FXC7VvKsmkfV7iab1dPlISW7jTeFz%2BxJHWoPg37edQ5kyNDIvpyx%2FbQ%2B%2FQg91OB7hFCurIssUq8JoHFUdD%2Byw%2FU2IIIsMMmKeOZhkiYyHMF5g%2BhCNipcyFf3nwD7cH%2B%2FoT%2B1x%2FwB2J%2BziNyW01%2BNseVtMoMc4G7VH82TCbyxfWMxtUMlnDIPrOli55JIh%2FwCK2ZeMqthYYOMVxBNb%2Fu2HK%2Fsl6JU7Xlp%2B1xDfbT%2FdeFgmPknW7q0eC%2FsZ%2BOoWTck5ftRnrG9PtIfstnatY0iw%2FMfQ4%2FMWh8bfXbdSjxnbmyD47S4%2F5ky55gWcaZqDPp1yZo42Ppz8SvIePHOn%2BTfO2qaXML%2FSHiPqcRf2M9fTYf78Xj8XIfs4qoWsGsQ64Tpp%2Bo31zGbK9WYfFE8Z9TceI4FP9lnpNbWDVdGit9RRbiO4gT1g3QkqCW9jX4lzksE1z5382DU7WzEKoqq5UVAoOIeV9uR%2BL%2Fgc7RDGsMMcS%2FZjUIPkopj0UvHtQ%2FKnV9H1F9X8vXCajyYt9TuQoYLSijkx9OTj%2FlcMS8q%2BaLny95guoNYs2s%2FrfEXsLLxKyJXjLH4pxOdpwl1zy1p%2BvCOSctDcw19K5ioHAOxU1HxJ%2Fk4otNoZYriJJoWDxSKGRh0II2IyF%2FmN%2BXll550z4OMGs2oJsLynfr6Mv80L%2FwDCfayU6RYNplhDYNMZxACqyEBSVqSoIH8uDj0xV8NappV7pd7Np%2BoQNbX9qxSaJuoYfrr9pWwuSNg4NSHBqKbEHxrnrL80Py2g86WX1%2BwCw69aJS3kOyzoN%2Fq8x%2F5NP%2Bw2eXm0q8guZoblGglicpNA4pIroaMjfy0OKvpf8lvMusa5ol1ZazOLqXS3jiiuTvIyOvJRIf2ylKc86eM8y%2Fk35usfK2r3FtfyMtjqoRZZ3qRFNGT6bP4IQ7I%2F%2BxztF1%2BaHke01SDR31aN7mZ%2FTLRVeKNu3qTD4F5dMVZlmylIZQwNQdwRuMvFXZs2bFXZs2bFX%2F%2FU7%2FmzZsVdmzZsVdmzZsVdjXVXVlYclIIIPQg47GSOsaNI5oqgsx9h1xV4R%2BZvkA6VK2r6VH%2FuPlarIv8Aulz%2Bz%2Fxjb%2Fdf%2FA5EoJLK%2FwBFh0yOJU1AyrH6oABboqJItebtyJkjZP8AKVs73qnm%2FwAsyW89les7xzwtSMxMRKG%2BHghpx55w%2FwAy%2BWpbIHWNNjeGKFkDjlVw5%2BIPGwp8S%2FtcfsZGUauQHvdvpNWJxjhyyMZA%2BiXQ%2BUmMXNtcWVzJaXSGOeJisiHsRtll1uLf6rcMeKb20vVoW%2F6pP%2B0v7GHsLr5ptvq7mOPU4ElmEhHH1eCII4kp%2Bz6aO7%2FtephBNBPbytDcRtFNGaPG4oR7EZVKJHrhz%2B92JjDPA4cw3HMdR%2FSiiNG1m7028EiEC4j%2BGWMn4JU7qf8AjVslmvaBp3nLSFvbCiTKCY2P2opP24pKfs%2F9d5BTFFIys5ZGX9pKch9B65JvKmrSaVdevxea1m%2BCcEFQyj9tR%2FvxMtxZBIV8x3Oi1eknp5Ud4n6Zd%2F7XmskVxp11JY3sZikjbiyHsf8Amk%2Fs4caPay6peQadE6rJMwVXboF6k%2B%2FEDOn%2BdPIkfmSyGp6QA12qc4JFpSVPtcG9%2FwDjfI35a8qzaFNa3urKrXLmscfI1gP7NSv2n%2FmywxouIN1DWPKDW95DY6K0t5IfgnaUKgD05cl49I6H7TZ0bynBAmmjSVvhcz2qEM60%2BHnVRw9om%2BH%2FAFsItfhndg1q%2FpNdxmIuDQVU%2FECf8oYReSLk6R5nWBw1bmT6sSD8FGBb4h%2FNyXDyPvbsWITE9%2FVGJkB30jPKV1PpOsrBduRLFcPb3JY9VditW%2F2XxZ0%2B91O2spIoJWL3E54wW0Y5SOf9UdF%2Fmdvhzm%2Fm2w%2BoeapJlBVdRjWdCDsZE2cfeuHdvfQW0BngZptVvEH1u%2FlG6gj%2B5hH7Kr0xHc0pD%2BYg8wa1NDFZWjSWtsrCRoiGJcn46b1YdF2yFWemzxsW1CN4Ej%2FZlUofubOs2WpxpNGl2oMP2eSbEe5yTXGkadqFpJaT26T2860YEVBB6EHx8MeCzdpunlEtpHYQ38GqRrFNaPA8EgJcFa%2FGqhadao2XBGlmbe2uCzevbGeRo2PcNJx%2F2S%2FDht51s3sLpYLoH6ncIq21wRU1UceLt9Hxf8Hhj5f8pXerWc%2Bq2VrHqE1oqQWdvNLwUoijmJB%2FO9W4%2Fs8cjVH3LezEvM2mXWqyabNozB7SS1WJ5SwBrHWnLv8A3ZUbfy4onlazmtrKC%2BJlNoHFFNFbmQaHvtTJ9rPlzU7GOO6vrRbeNioQQMrRxmn938IXj4YE0fQLnXBdQ2062l1CP3SSry9Xav7og0%2F4LDsikps7C3s1WK2iWJB%2Bygpg5lNOX0YAVr7TL0xXsxcxsVlhktwpFPtLVWwbf%2Ban0e8tp7LTYrmyILlpyT6hoRw2%2Fu%2FTbdlw3taoK4v7a1dY2dW5GjQ1qVHj%2FwA24Vah5a03VlNxZEQTtvyX7LH%2FAClyfjyfo3nrTrbV9PRNI1i6gM8qRENC8gb05OUI%2BNR6nR1%2F4HIRqOj655Vu%2FQ1SBogT%2B7mU1ikA7pJ0%2FwBi3xZGwdizhOeOXFCRBSPSZNX8maml1MhNsfgldPijdD1H%2BS37S8s6ZLrEEZt2uEe1W6VWtLsg%2BlKGHIGOReS%2F6wOR9dWtRp11dSQ%2FWHt4Wk%2Br93IGyU%2Fysk%2Fk%2FW5INATT9Z0eAWczGT6gr%2BoIlfcgBxsf2vT%2FAGMYxMSeE2D07m7PqBmjEzjWSO3EOUo%2BY72M%2BYfLcd3FJeQRxyo7EzQU792GQ60bU9Hkf9HTAwts1jdVeNl%2FyX%2B2n%2FEc7ZL5XstVSS58p6kYZqVbTrysif6tWPrRr%2FspVzmuvaDq2jzsup2JtA5NCfjtmNf91Tjb%2FYyccJ8tmgJPqV4JJLJpI3sYLq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FFMx2imJJSvhHLXj%2Fr4N%2FO9G%2FwAJ28o%2FYvY69%2BqOMgdlYzqPmWy8xr615aouoxAA3dk4dJB0%2FfRGjofBl54U%2BnCySRNSa1l%2B2vQq3861%2By65GPKcztqxjY7NEw4jYbU32zoNppF1qfrw2JX6yierHExoJivWIf5fH7DYYnZaY3pN9N5N1n9JJEbuIwyRoisY1kDbpVu3F%2FidM7xpl3Y%2BadFt7m5tle3vIUkaCYBx8Qowof5WB%2BPONG0jvLY28qlRUgqwoyOOu37LpiXl3XbjyZqk7XglmtZIfTEKNQGh5REFvsxr8XLjgIrdWQedvy7GiQPrfl4SNaxVe5s1q7Rp3ki%2FaaNf20%2B1kT07WGCqwcMjdJFNQc9C2N9BqNvHc29WiljSVGI2KyCopkFv%2FwAotHu9cOq2d1JYW0x53dhAo4O53JQt8MYf9ocMFyB23ZwGOQIkeCQGxqwfIsatNQSQrIrmOUbrIhoQfEEb5LLHzPP6X1TV4RqFo4ozFVL0%2FwApD8EmFms%2FlxeWBNxoEpuIhubSQj1B%2FqPsHwo0%2B4ltUmW7Ro5ojRo3BVhT2OWCi1t%2BbPJ1pFCfMXlJgtl%2Fx92VCyRHuwjb4kX%2Bdf2ciOlG2huhcX2n8JI2BE8FHHzMTb%2F8TVc6FpWutaySPblJEmHGeCQVVwP1ZGtcsIbe5N3p0Ui2MlWaM7mB%2FwBpQ4%2B1F%2FLkTGulhnDIYnYprf6tYaxaxxCDlxIaG7iko8Z7kGtWr%2B3ywxsdGl1WwitzGbkgkRzugDGnRm34R0%2FZbIJBZwxv9YhAVx8Qp0JPiBnafJl1eXekLNdyrKOXGNgADQD4g3Gg%2BE7Y8WyTLfiHNJbbQvNHle%2Fe50eQX%2BnXAD3Vg53EoWnKImhQmn7Pwv8AyYRX9xql1dmXWOS3XHiqMnp0QEkKq%2BA5fazrQwHqOmWmqQGC7j5D9lxsynxVsFsLeO39hb39tJbXMYlhlHGSNuhB%2FUffOZXy3%2Fl7UV05n5MgrpN1LTjLCT8VncEj%2FYf5Odt1nQbzR3JcerasfgnA2%2BT%2FAMrYB%2F5V3Y%2BdtAvhefubrn%2FuNux1jkQUYkD7Ubnir%2F6uEq8D1rTFk9XUdNgaHix%2Bu2XVoHPcD%2FfbfstnQfyAeb%2FFktC%2FptaSF1VgFNGTiXFfiA%2BLj%2FlZC9WuNd8p6kNM1e04anYsY2mY7TW%2FZG2pKjfsS4K003mkCHzl5WmDLazercWoB9WCvX1FB%2FeQt9lv8nIofYNRl5FPI3njTfO2li7taRXkQUXlp3Rj0Zf5on%2FYbJXirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FW7%2FmzZsVdmzZsVdmzZsVdgHVY9PmtHi1JlW3cgEuQBUbr1wdgPUdNttTtzb3IJWoZSOoYdxirzHztP%2Bi20aTyvdm6uDcJSCMJIPTVhRWKj7Bbbi2B9b8keZrnV3FvberbsQsVwHUKFJ6tU8hSvhk%2B%2FwAPGy1GwvLOkqK5ju0cIP3YQ%2BnItAPiif8A4nkkphKQaQOk6eml6ba6fGQVt4whPif2j%2FwWO1LTbPVrGfTr%2BITWtyhSWMjqD%2FEfs4MzEVwIsg2Ni%2BVPOHlm58p65NpU1XhP72znP%2B7IWPwn%2FXX7En%2BVgW28s63f2kWr29m76Ys6xyXQpxUggNUfa4iv2uOen9c8t6J5it0t9as0uo4zyjLVDKf8l1oy5EL7TriGW30Lytp7Q6Dbs0d7xI4Oz%2FFWPlycmNvib%2BfKziufETs7WXahOn8Ph9dVIn6a7%2FewDzPd3ukNplzYtxtEhW2adVBKzRktTkalOdf%2BBw60bydZ%2BaNR%2FwARaPq0VjOIw509bcLIkw%2B16yh%2FjRm%2F3an28de6dLYTXGk6xDztpx8aHoyn7Lqfb9nI3YX%2BreQ9ThS3pcWhcvazMBWSE%2FbgaQ%2FF8P8AJlrrDvunvmryB9buFvzAtnrkQD84z%2B6mKHkGRtu%2F82HWnO%2BoadLpU5aC4ZeUL9Gil%2B0jKR0aOYZOLO80jzho0d3Zv6kMn2WFPUhlGxVh%2By6H7WQWaO80rV1hvwBMjcfUAoskTbLIP%2BNsIr5oSu10tfOt7Ikt4th5ijQC6hkSsdz6fwfWIiCCr7UmTj%2Fl5JG%2FKTSdTjg%2FxDILh4UCUgHD7P8Axafj45GPMdkYtRkvbWf6jewEXNhcr9ppT9pEVatJWnxJx%2BznRPIfmz%2FFujfW5Y%2FSvLZ%2Fq94gBCmQCvNQfiVX%2B1xb7OA2NleaX%2Fkr%2FA19Jb2rO%2BlXbc7UvuFbuvL%2Bb%2FiWC7M7HOuarpdrq9jLY3i8o5Bse6t2df8AKXOP6jbaj5dvpLK5USBd0fcB07Ov8cMT3qkP5l6trkWp2kNi8sVr6CShoyVDyH7RJHXj8OQpfNfmCN1%2BsXcsnBeCrOfUAUdFHP4uP052ny%2Fq2g6veR6T5hgX94Almsp%2Fdsw%2F3W%2F%2BU37GSHUfyp8n6hUpavZse8DkD%2FgH5p%2BGCXNeTwM%2BbzeWxtr%2B3SVHFGMZKMP8oBqr%2FwANh9qv5gpr3kVfLV9zk1O3uIjFOwrzt4w1GZhUeqn2P8rJD5i%2FJJrK2lvNKufrSx%2FEYCnCXiOtCpKPx%2F1M503lq7tpDxDNUUUGlPwyJtWQflfpMWseaFtLgssZtZnDJ1VhxCn3651e38qanp%2Bs2ZX95brKG%2BtR7UVfio6%2Fs16YS%2Fk3pGmWxvNR%2BspJqfEW7WnR4kryLFW3PqN%2FL%2FLnW8I2UsW8x%2BVo71n1LT0CXp3mjGwlp3%2F4yD%2Fhsgl9oyXUaxX1u8LoCY2dStV%2FaG%2Fgc7JTEbiztrr0zcRrIYmDxlhWjDJCXQoeVeW9Rv8Ay1PKL25kuNO9ELEo%2BIjgaoKk%2FAqJyzqtrdQXkCXNs3qQyqGjcdCCK7ZFPMPl1Yg95aLWA7zQjfjXqw%2FycB6JrNzY3BW7uAbARKgUqSQVIC8KfCq8K8vhxq9wlntK4DvtJ07UgBfW6TU6FhvTwqN8FRyRyoHiYOjCoZTUEHH5FDC9Y%2FL6wuSZ9Ic2M3X0tzEfo6p%2FscL9B%2FLy8XVJNS8y3Yuo41aKz0%2BEkQrGwoWlO3N2zomVTDZV4l5n8s3Plq94oS%2BnTk%2FVZj27%2Bk5%2FnX%2FhsMNI893Wj2ht2thNVSEp8PGSlBK%2F%2BSf286nqOnWmqWcllexiSGQbg9QezKf2WGco13yhdaVMUT95A39zL0DDwPg%2BIZc3pPlzU5dStGa4IaeNgGZaAFWHJWoMOc5v5E1B7Wf6tcAoD%2B5PLb3jP0fYzo4xIYrZIo5UaOVQ6MKMrCoIPtidrZ29lAttaoI4UrxQdBU1OL5sCsO8%2FwD5e6V5708RXNINQgB%2Bp3oFStf2JAKc4m%2F4XOIWX5R%2FmVoOpummwIySAxNMssZhZG2q3Mqen80eeoKZqYq8l8h%2Fk%2FceW9Qt9Z1DU3W4gPJLS0JCEGvwTytT1U3%2Bx6arnWs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F1%2B%2F5s2bFXZs2bFXZs2bFXZs2bFXUzZs2KuzZs2KoXUjILG49E0k4EKetK43TYkhsoQp5EqGZvEnvgp1DKVbdW2I9jhDdaDqT%2FuLLWJbOzP8AulEVnAPVVkb4hiqB8wWUXmS%2BXTYWQi3ikZphuUlqOKmn7P8ANnOtRsiPW0TWUKqD9ofajYfZkQ%2B3%2FDLnYtH0Wy0W3aC0BJc8pJHPJ2J8ThV5u8tJrdoZrdQL6EH0z0Lj%2BQ%2F8a4bTbxXQPMGq%2Fl9r7mSs9jcUN3Cv2Zo%2B1xD4Sp%2FzZnaNYhtfNmgRaho7JcMwE1pKCASP246%2Fsn%2BZf58gsugWWtaPFp1xRL21qFkFCyP3U96YR%2BUfMt7%2BX%2BqvpmqEtpUsnGeOtQjE0FxD%2FwAzUxOy%2B5kHmGCOa1s7%2BVeEsFYpHI3SvwyBvDi647RtH1by3qEXmPT5VlgnWmo2C1Amj6rIrH4RMnVcCz3FvJ5x1pIqX2h30cVy3ouv2nQEeka9XZW5ZJNPult7dbZpTLasP9HlYUalP7uVf2JlH2v%2BEw891ZzY3tvqNtHdWz84pBUHoQe6sP2WX9rC7zJoEOu2Xp7LdRVa3lPY90b%2FACHwi0IahBqtdOo9hKf9LjY0Vf8ALU%2F78ybZFD591jS3R3gnRo5Ymp4MjA9snHkr8weRi0LzJII7pQEtdQc0SYdFWQ%2Fsy%2F5X7eH%2FAJw8uLqMDX9qg%2BtRL%2B8Uf7sQf8bLnJbuyjcNFKnND1U%2Fw8Dh5pfQo3Gc487eVFhMmq2KfuHNbmNR%2Fdsf92KP5G%2Fa%2FlyPeXPM%2Fmfy2Y4pmk1PRqfBBKpNwiDr6E3%2B7OH8j51%2B1ubXU7JLiKklvcJWjDqrDdWH%2FEsV5PntoFiuUuQOFxFvHKpKsPpWnLJZ5b8w65p1xEguXuIp3q8d07P1%2FZVm%2Bx%2Fkccbr%2Bhm2125sbPggX95AZq8FRhy3p%2FL8Srk181aDHqempqtvRLu2hDngPheMDmV%2F2P2ozjsrKLW5ju4Eni%2By4rQ9Qe4OL5D%2FACp5hgu7iOwkkUXFxD6yx9DWM8HNMmGJFFDRFRQioPUHIhrmgrAXubdK2z19WOleFepH%2BRkwymCkUIqD1BxBpWIaNq09o31WURrZoiem32ePEheCIB8VV%2BLJcGB3BBHtka1LQXVne0XnC9eUQ%2B0tevHxXA2lxazHfW620rx2atW4gkSqFOPCgdvjDClVwkA7hWYZswzZFXYnNBFPG0UyCSNvtKwqDimbFWE6voE1hIbu0Be3BrQVLIP8rxXJRo92b3T4Z2%2B1Ti3zG1cGkAih3B7ZSRpGvCNQqjsooN8NquzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxViPmbyo91cfpvQiINVT%2B%2Bh6RXSD9iXwl%2F33N%2FwWQzW9AXXo%2FXaFg7L%2B%2BhK0mjdBuafzACjrnYcDTWNrPKk8kYMsZDI42NR40w3tRW3z1p2l6ho%2BotLAfXVE5OgDVljA%2BLj%2FxZGv7OS2BbeaRbscpI5YuLQq3ETIfiQcv2ZVP90%2F8AsMk3mi1FjqBnt0CpcIHIUU%2BNT8RFP5tuWRDTFEulwPaP9YjVSfVjBIFGPM%2F7BvHCOSXqXlu6trnTI1t7Y2Zj%2BGW1YhmQ%2BJcfb5fzYcZBPKl1I7GRXHKGi3AY%2FajPRvdsnQNd8BFFDjnL%2FPWhJaXguIKRw33KngklPi%2F2Pxcs6jkY892Ul3onqwoZJLWRZeAHIlT8D7fJsAVBaLpUeueS9PtriYPcWykQXkfZ4yVDD%2FJP2WwX5X1NJ2NrQIGXkoXpzQ8JP65GPJfmOTR5G0zXLmGCzlYmzhZPSeE05ceP7UTjfliOhagkWs3CW0gkUXbPZjoZVkY8kQHr8OSHUJZD540vmYtVRBIAvoTo260JrGzU7cvhzaJ5jgm0t9O1u7giu%2FRdY%2BJ48oyCg%2Fd9QyfZ%2FwArJhPBFcwvbzqHikBV0PQg9sgt%2FwCSLpJy9pxniPRiQsgH8rfzYB5ql%2Fkq1hXU4ZigNwjsizftemU3Uf5Jzp%2BRXyloF%2Fpj3FzqYiR3YraxREsyx%2FzTOaL6j%2Fyp8CZKsSUOzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Hv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVg35iPrMEFld6XbR3CRM%2Fro1fUIIHwx%2Fs4U%2FlrqOkz3c1lYQmENFJI8DCgRzIDIg5b1JavTOiajZLf2cls1KsKofBh9k5ydpJPL%2FmzT9ZcBIWY2t5sFoD8Ls5C1%2FwCDkyQ5KyjWdLGi6ml3brSyvKxuo6I58P8AJPVclOiXZurPi5rLAfTf5fsn7sE3drBqFq9vLR4pV2I7dwy%2B%2BF2j6Xf2F5dS3EqNbyhViVa8iV%2Fbfag6%2FZXBdj3KnWURXLzYFYV5n8n3us6ut7btEITGsbc6hl418B8WFd75Ym8svHqVqPrQiCsJSPiikH2jQfsNnScayhwVYBlOxB3BGG1Sby7rf6YgZ5KCZftIBSmHeFllodlp95LeWqlDMKGIfYB7kDDPE%2BSuzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F%2F0u%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZFfM%2BipLW%2BSJZAf71CtaMPsygf8SyVZRAIIO4PbCDW6pP5YvDd6Wiu1Zbc%2Bi%2B9Tt9mv%2Bxw5xG3tbe1Vlt41jDHkwUUqfE4tgPNXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Pv%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV%2F%2FZ");background-position:center center;border:1px solid #0a0}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css new file mode 100644 index 0000000..a50ad77 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css @@ -0,0 +1,10 @@ +div.base64-singlequotes { + width:100px; + height:100px; + background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QAAAAAAAD5Q7t%2FAAAACXBIWXMAAA3WAAAN1gGQb3mcAAAFrUlEQVRYw%2B2Xz28kRxXHP%2B9Vdc8vj2fG9uIkm2yUeFGEhNCKQwBpj1yRUBAnpJU4ceZP4MxfkBxy2GO45bQXuEGQohUKigQ%2BsBBE1sbYXv8Yz%2FRMd9fjUN09PV5nFZA4kZZa79W3quu9er%2FqNfy%2FPwJgZty%2Ffz%2FZ29vrpmmqhlWTgmFg1UpbfWhYhG6Yq2cFi%2FNrj9nJyWnx%2BPHjeafbMTEzPvjVB9%2B6d%2B%2FezweDwV1BfHubivkC3lZya%2F4m7Np8UZYXhweHH7733rvvC0Kyv7%2F%2F7p07d34qIjyvr63RNb4l4CbsRUrNrq6OfvfRRz%2FxDx486A%2F6g7vXhX9ZIf%2Bp4JomaToZj8d7Pk1SFRFXb1aWodq09l%2F9YZu%2FCWMVL9e%2FaVFVQVUREEG8r3VUEZ4cX%2FHL30%2B5shRtAhFq4wggNb6GrXgVa2K2jYtACIHv7Sz54TfHjWWagBOBy0Xgt%2BcjLtwQxVCpNwURQat1DdYaT7pwdwKDFA6ncHgFizJmSb3WLPDa7PMIVlb2daqZxdONUnAetEojEdBGiXXhTmAjhZ0%2B3N6AlzeEROH1TXiWGf%2BcwmkWZYnAfAkdx1pq%2BhUbT9z3IElUJlVhI4WsgCLUyggi4MQYd4VXNmCYRqXOspV7UoHbQ3hpEMeLAk5mkFYRYlWI%2BHZ6CTDwkKSQqrA7gFeHMF3C6VyYLmFZGiKCE6GrMFsaWb7yuVOh66N1FkUUpBJ3TyvFovToBl9XMbNY2bZ70BsKfW94hbyErosmXpQwy4VgkCjMizjvRRik0EtiLNwagBf465lwOqtkETEn60XT1%2BlTazrpKlR%2BKkooy3Xfb3Wj3wGWJRQhnni7B53q5FqZ4%2FUR7PYhGMxyuMwgWVqTxrYWAwZYQX78J5i8ie9txSAkoOqqQAqk3pBgKLDhlY5XVKPCi3w97YRoKSFaceCgF2hqSXRBPQAIOcXRH8hP%2F0y6%2BRpWLrEyg3SbS9tmzggzJQSLQZo4xoOE8UbCsJfQ7zi6iaIizZ5OBVfXDKPireWC%2BvAYWOBqeszl9Jg03afbH6OqGH%2FBSUrqbrFIXiHoiEDC%2FPySi2d9nnZHJE7opY7dcY%2FdcZej84zpPGfY9Uw2ErYGCf2O4mUVEzELWtqUxZKjf3zK2cURzicMRy%2BzvbuH8ylFPqXIPqNczClKY1mUZFcnSDKkv%2FUNuptbWG%2BLw%2FMh%2FzrYpKBHKV3ONOXzYxeV20z49qhs7gaMWIjqQQiBxVXB4irg05yz4u%2FMpieoJuTLjDJfUJYBzBAFUUHkhMvLvzFPuvQ2JvQ3duh0R%2FjuiDQdIn6MJdvkxTafZUPuaN6UaOo6UNtgNl9weboguwqoA5fCjEusNCzE8LJQFRuNrzpQD%2BrmZNM55%2F4A5z1J2iHtDEg6fZK0j0uHlDrh2N4i3Ptuc%2BH5tjp5HliWQmmOUAhlYe0rqUqWSEOhcZ05AvE1UdColSQJaHWlSUYgJy%2FO2fFfo%2F34piphFOZ4OrvNdL5EJZbcmE8OQzFxIJEGEgIeE1%2FhrjJLxZcOrIVpVC7TW00WmLWyAMDEs%2Bi9wVJDtG17Y21vVmNxLKqIOkQqqoq2qHORmgj9UQcza7mgFm4GmiDjO5C72DSoQ6uPVTW%2BzuFUcQ2teKd4pzhd8b6Nu6jg7vZsrb1rClEIxhu7Q37x47fIy3j%2Fi8iqqlUuEWTFN%2FOrMU3fEEuhUM8FIPDqZgcRIVhsAXxtjGDGS5M%2BP%2Fv%2Bm7yopVrRVsPabsW%2BYG1T%2Fy3KahqSg6cHRb5cTmt5ZXhxQ7nS6yZsVWOajDFbw2JSCSGEIsuyC%2F%2Fo0aPp%2Fv7%2Br9NO5%2F5gMOhJLNn%2FpQLrLfw6tkKKorCDg4NPP%2Fnkjx%2FLOz96h2enzyZvf%2BftH9za2fm6qLrnO9tGk2vY86f%2FMliWZRdPnjz5zcOHDz%2B%2B%2Fifimorzv31C9X718G%2FYrCYSNJa5LgAAACJ6VFh0U29mdHdhcmUAAHjaKy8v18vMyy5OTixI1csvSgcANtgGWBBTylwAAAAASUVORK5CYII%3D'); + background-position:center center; + border:1px solid #00aa00; +} +div.otherdataurl { + background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kFBQ0WDWwqwjwAAANMSURBVEjHrdZbaFxVFAbgb2aSTG6GTi6mVIwxNxF9qFI0RQnFUqiYamutVutLa2t9EY0oPggFoYgPRR%2FaghYviA%2BiIAYvmBJKoYWiiBCigVTT1FisbUhrEtNkJpc5PuQkjGEmJqkLFmdz2Hv%2Fa%2F3rX3tvlm95oS%2FLokuZtIpbdvAs7KFtL22wjb3V1C41upy2ke1DXC2k%2FBjv1HHXDrbkEamg7lX2P8QTldQ2UtfOB8uiJsHNiB%2Fik0GmO%2BgZIxgnGA59nGCMoJPeQaYP047iBDXZEohkAYof4%2FNyKlZRdR%2F1ASZCnoOMhWkUheMz9F1laJSRZ3gEqVw1ipZQjcoBRrbT3Ez9OJLhZkHG5CD8l8Q47qXhMZp%2FYxhVFaxBLBtQejdtA%2FTtZPMIJnOknI2WSYzicTYN8OtTvICZbECxdr5Pkm6iPL0C3c%2BgkfIJgi%2F4LnP%2FudRKD3K4jf1VJGLEAiuz6VnA4AGam1h7gpNIzSFe66D3NurLKVhJNkHo07N9V9BE3XHOYmyeuirqG1l9mdHgOkDSGd8%2FGWtg9Roa56lrYdchDtRQPLlCkEywKVRScDfrurnwC2diiPTRe47iVtbnLZDxckGCkKYpPM%2FRr3kbyRhsYOtRDiQonFoBSHrBOI18rOeOPvr76YrCeUbf5fTvjOddJ0gQ1uMPku9z6hwjiEZhgOMn%2BaaUeHQJIOkMD7KMA5QQP01HP18hPbfvDTvZPETqb2YiS1BWrozM6jk9SPJJHkZZ5qFagtoaNnbyZg1FE4sUPRdlAQpwkdSjvDZAJ%2FoxNt%2Bw6NlGbQVFl5iKLKKsXCAwyFQZ8S3ciu65ho1lBJ5%2FkZk3OBGjpJWGmVCmsjTkQvA8JHCUU7s5eImevzg%2Fd7BGFhzCARIf8uVN3J5Heh1VM%2BHlko2y%2FHBxF0NJolfo38eDuJJxbf0ro%2FnMurh8hM%2FupH4tdT8zciOFsTC8SAgQoJfRxKzCuvfw0k%2F8MDx7xqUyez%2BS48ESIN7Ky6OUpfAtrxzhx03UR4m0c%2FZF7tnKW2mma4l9yuthTSIZIvxPi6EcpZW0PM0xtOzjo%2Bf4GPfv4r1qNqAUFYs9diJLBC1CIa7FZx8fUlwI22LuNv%2FfLbKMAOftH9TwRXg6%2FiCDAAAAAElFTkSuQmCC"); +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css.min new file mode 100644 index 0000000..1f6d2e2 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-eof.css.min @@ -0,0 +1 @@ +div.base64-singlequotes{width:100px;height:100px;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QAAAAAAAD5Q7t%2FAAAACXBIWXMAAA3WAAAN1gGQb3mcAAAFrUlEQVRYw%2B2Xz28kRxXHP%2B9Vdc8vj2fG9uIkm2yUeFGEhNCKQwBpj1yRUBAnpJU4ceZP4MxfkBxy2GO45bQXuEGQohUKigQ%2BsBBE1sbYXv8Yz%2FRMd9fjUN09PV5nFZA4kZZa79W3quu9er%2FqNfy%2FPwJgZty%2Ffz%2FZ29vrpmmqhlWTgmFg1UpbfWhYhG6Yq2cFi%2FNrj9nJyWnx%2BPHjeafbMTEzPvjVB9%2B6d%2B%2FezweDwV1BfHubivkC3lZya%2F4m7Np8UZYXhweHH7733rvvC0Kyv7%2F%2F7p07d34qIjyvr63RNb4l4CbsRUrNrq6OfvfRRz%2FxDx486A%2F6g7vXhX9ZIf%2Bp4JomaToZj8d7Pk1SFRFXb1aWodq09l%2F9YZu%2FCWMVL9e%2FaVFVQVUREEG8r3VUEZ4cX%2FHL30%2B5shRtAhFq4wggNb6GrXgVa2K2jYtACIHv7Sz54TfHjWWagBOBy0Xgt%2BcjLtwQxVCpNwURQat1DdYaT7pwdwKDFA6ncHgFizJmSb3WLPDa7PMIVlb2daqZxdONUnAetEojEdBGiXXhTmAjhZ0%2B3N6AlzeEROH1TXiWGf%2BcwmkWZYnAfAkdx1pq%2BhUbT9z3IElUJlVhI4WsgCLUyggi4MQYd4VXNmCYRqXOspV7UoHbQ3hpEMeLAk5mkFYRYlWI%2BHZ6CTDwkKSQqrA7gFeHMF3C6VyYLmFZGiKCE6GrMFsaWb7yuVOh66N1FkUUpBJ3TyvFovToBl9XMbNY2bZ70BsKfW94hbyErosmXpQwy4VgkCjMizjvRRik0EtiLNwagBf465lwOqtkETEn60XT1%2BlTazrpKlR%2BKkooy3Xfb3Wj3wGWJRQhnni7B53q5FqZ4%2FUR7PYhGMxyuMwgWVqTxrYWAwZYQX78J5i8ie9txSAkoOqqQAqk3pBgKLDhlY5XVKPCi3w97YRoKSFaceCgF2hqSXRBPQAIOcXRH8hP%2F0y6%2BRpWLrEyg3SbS9tmzggzJQSLQZo4xoOE8UbCsJfQ7zi6iaIizZ5OBVfXDKPireWC%2BvAYWOBqeszl9Jg03afbH6OqGH%2FBSUrqbrFIXiHoiEDC%2FPySi2d9nnZHJE7opY7dcY%2FdcZej84zpPGfY9Uw2ErYGCf2O4mUVEzELWtqUxZKjf3zK2cURzicMRy%2BzvbuH8ylFPqXIPqNczClKY1mUZFcnSDKkv%2FUNuptbWG%2BLw%2FMh%2FzrYpKBHKV3ONOXzYxeV20z49qhs7gaMWIjqQQiBxVXB4irg05yz4u%2FMpieoJuTLjDJfUJYBzBAFUUHkhMvLvzFPuvQ2JvQ3duh0R%2FjuiDQdIn6MJdvkxTafZUPuaN6UaOo6UNtgNl9weboguwqoA5fCjEusNCzE8LJQFRuNrzpQD%2BrmZNM55%2F4A5z1J2iHtDEg6fZK0j0uHlDrh2N4i3Ptuc%2BH5tjp5HliWQmmOUAhlYe0rqUqWSEOhcZ05AvE1UdColSQJaHWlSUYgJy%2FO2fFfo%2F34piphFOZ4OrvNdL5EJZbcmE8OQzFxIJEGEgIeE1%2FhrjJLxZcOrIVpVC7TW00WmLWyAMDEs%2Bi9wVJDtG17Y21vVmNxLKqIOkQqqoq2qHORmgj9UQcza7mgFm4GmiDjO5C72DSoQ6uPVTW%2BzuFUcQ2teKd4pzhd8b6Nu6jg7vZsrb1rClEIxhu7Q37x47fIy3j%2Fi8iqqlUuEWTFN%2FOrMU3fEEuhUM8FIPDqZgcRIVhsAXxtjGDGS5M%2BP%2Fv%2Bm7yopVrRVsPabsW%2BYG1T%2Fy3KahqSg6cHRb5cTmt5ZXhxQ7nS6yZsVWOajDFbw2JSCSGEIsuyC%2F%2Fo0aPp%2Fv7%2Br9NO5%2F5gMOhJLNn%2FpQLrLfw6tkKKorCDg4NPP%2Fnkjx%2FLOz96h2enzyZvf%2BftH9za2fm6qLrnO9tGk2vY86f%2FMliWZRdPnjz5zcOHDz%2B%2B%2Fifimorzv31C9X718G%2FYrCYSNJa5LgAAACJ6VFh0U29mdHdhcmUAAHjaKy8v18vMyy5OTixI1csvSgcANtgGWBBTylwAAAAASUVORK5CYII%3D');background-position:center center;border:1px solid #0a0}div.otherdataurl{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kFBQ0WDWwqwjwAAANMSURBVEjHrdZbaFxVFAbgb2aSTG6GTi6mVIwxNxF9qFI0RQnFUqiYamutVutLa2t9EY0oPggFoYgPRR%2FaghYviA%2BiIAYvmBJKoYWiiBCigVTT1FisbUhrEtNkJpc5PuQkjGEmJqkLFmdz2Hv%2Fa%2F3rX3tvlm95oS%2FLokuZtIpbdvAs7KFtL22wjb3V1C41upy2ke1DXC2k%2FBjv1HHXDrbkEamg7lX2P8QTldQ2UtfOB8uiJsHNiB%2Fik0GmO%2BgZIxgnGA59nGCMoJPeQaYP047iBDXZEohkAYof4%2FNyKlZRdR%2F1ASZCnoOMhWkUheMz9F1laJSRZ3gEqVw1ipZQjcoBRrbT3Ez9OJLhZkHG5CD8l8Q47qXhMZp%2FYxhVFaxBLBtQejdtA%2FTtZPMIJnOknI2WSYzicTYN8OtTvICZbECxdr5Pkm6iPL0C3c%2BgkfIJgi%2F4LnP%2FudRKD3K4jf1VJGLEAiuz6VnA4AGam1h7gpNIzSFe66D3NurLKVhJNkHo07N9V9BE3XHOYmyeuirqG1l9mdHgOkDSGd8%2FGWtg9Roa56lrYdchDtRQPLlCkEywKVRScDfrurnwC2diiPTRe47iVtbnLZDxckGCkKYpPM%2FRr3kbyRhsYOtRDiQonFoBSHrBOI18rOeOPvr76YrCeUbf5fTvjOddJ0gQ1uMPku9z6hwjiEZhgOMn%2BaaUeHQJIOkMD7KMA5QQP01HP18hPbfvDTvZPETqb2YiS1BWrozM6jk9SPJJHkZZ5qFagtoaNnbyZg1FE4sUPRdlAQpwkdSjvDZAJ%2FoxNt%2Bw6NlGbQVFl5iKLKKsXCAwyFQZ8S3ciu65ho1lBJ5%2FkZk3OBGjpJWGmVCmsjTkQvA8JHCUU7s5eImevzg%2Fd7BGFhzCARIf8uVN3J5Heh1VM%2BHlko2y%2FHBxF0NJolfo38eDuJJxbf0ro%2FnMurh8hM%2FupH4tdT8zciOFsTC8SAgQoJfRxKzCuvfw0k%2F8MDx7xqUyez%2BS48ESIN7Ky6OUpfAtrxzhx03UR4m0c%2FZF7tnKW2mma4l9yuthTSIZIvxPi6EcpZW0PM0xtOzjo%2Bf4GPfv4r1qNqAUFYs9diJLBC1CIa7FZx8fUlwI22LuNv%2FfLbKMAOftH9TwRXg6%2FiCDAAAAAElFTkSuQmCC")} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css new file mode 100644 index 0000000..c3f686f --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css @@ -0,0 +1,34 @@ +.yui3-skin-night .yui3-dial-ring-vml, +.yui3-skin-night .yui3-dial-center-button-vml, +.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night .yui3-dial-marker-vml, +.yui3-skin-night .yui3-dial-handle-vml { + background: none; + opacity:1; +} + +div.base64-doublequotes { + width:100px; + height:100px; + background-image:url( "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kFBQ0WDWwq + wjwAAANMSURBVEjHrdZbaFxVFAbgb2aSTG6GTi6mVIwxNxF9qFI0RQnFUqiYamutVutLa2t9EY0oPggFoYgPRR%2FaghYviA%2BiIAYvmBJKoYWi + iBCigVTT1FisbUhrEtNkJpc5PuQkjGEmJqkLFmdz2Hv%2Fa%2F3rX3tvlm95oS%2FLokuZtIpbdvAs7KFtL22wjb3V1C41upy2ke1DXC2k%2FBjv + 1HHXDrbkEamg7lX2P8QTldQ2UtfOB8uiJsHNiB%2Fik0GmO%2BgZIxgnGA59nGCMoJPeQaYP047iBDXZEohkAYof4%2FNyKlZRdR%2F1ASZCnoOM + hWkUheMz9F1laJSRZ3gEqVw1ipZQjcoBRrbT3Ez9OJLhZkHG5CD8l8Q47qXhMZp%2FYxhVFaxBLBtQejdtA%2FTtZPMIJnOknI2WSYzicTYN8OtT + vICZbECxdr5Pkm6iPL0C3c%2BgkfIJgi%2F4LnP%2FudRKD3K4jf1VJGLEAiuz6VnA4AGam1h7gpNIzSFe66D3NurLKVhJNkHo07N9V9BE3XHOYm + yeuirqG1l9mdHgOkDSGd8%2FGWtg9Roa56lrYdchDtRQPLlCkEywKVRScDfrurnwC2diiPTRe47iVtbnLZDxckGCkKYpPM%2FRr3kbyRhsYOtRDi + QonFoBSHrBOI18rOeOPvr76YrCeUbf5fTvjOddJ0gQ1uMPku9z6hwjiEZhgOMn%2BaaUeHQJIOkMD7KMA5QQP01HP18hPbfvDTvZPETqb2YiS1BW + rozM6jk9SPJJHkZZ5qFagtoaNnbyZg1FE4sUPRdlAQpwkdSjvDZAJ%2FoxNt%2Bw6NlGbQVFl5iKLKKsXCAwyFQZ8S3ciu65ho1lBJ5%2FkZk3OB + GjpJWGmVCmsjTkQvA8JHCUU7s5eImevzg%2Fd7BGFhzCARIf8uVN3J5Heh1VM%2BHlko2y%2FHBxF0NJolfo38eDuJJxbf0ro%2FnMurh8hM%2Fu + pH4tdT8zciOFsTC8SAgQoJfRxKzCuvfw0k%2F8MDx7xqUyez%2BS48ESIN7Ky6OUpfAtrxzhx03UR4m0c%2FZF7tnKW2mma4l9yuthTSIZIvxPi6 + EcpZW0PM0xtOzjo%2Bf4GPfv4r1qNqAUFYs9diJLBC1CIa7FZx8fUlwI22LuNv%2FfLbKMAOftH9TwRXg6%2FiCDAAAAAElFTkSuQmCC" ); + background-position:center center; + border:1px solid #00aa00; +} + +.yui-skin-sam .yui-h-slider { + background: url(bg-h.gif) no-repeat 5px 0; + height: 28px; + width: 228px; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css.min new file mode 100644 index 0000000..1ac0e17 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-linebreakindata.css.min @@ -0,0 +1 @@ +.yui3-skin-night .yui3-dial-ring-vml,.yui3-skin-night .yui3-dial-center-button-vml,.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-night v\:oval.yui3-dial-marker-max-min,.yui3-skin-night .yui3-dial-marker-vml,.yui3-skin-night .yui3-dial-handle-vml{background:0;opacity:1}div.base64-doublequotes{width:100px;height:100px;background-image:url("data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kFBQ0WDWwqwjwAAANMSURBVEjHrdZbaFxVFAbgb2aSTG6GTi6mVIwxNxF9qFI0RQnFUqiYamutVutLa2t9EY0oPggFoYgPRR%2FaghYviA%2BiIAYvmBJKoYWiiBCigVTT1FisbUhrEtNkJpc5PuQkjGEmJqkLFmdz2Hv%2Fa%2F3rX3tvlm95oS%2FLokuZtIpbdvAs7KFtL22wjb3V1C41upy2ke1DXC2k%2FBjv1HHXDrbkEamg7lX2P8QTldQ2UtfOB8uiJsHNiB%2Fik0GmO%2BgZIxgnGA59nGCMoJPeQaYP047iBDXZEohkAYof4%2FNyKlZRdR%2F1ASZCnoOMhWkUheMz9F1laJSRZ3gEqVw1ipZQjcoBRrbT3Ez9OJLhZkHG5CD8l8Q47qXhMZp%2FYxhVFaxBLBtQejdtA%2FTtZPMIJnOknI2WSYzicTYN8OtTvICZbECxdr5Pkm6iPL0C3c%2BgkfIJgi%2F4LnP%2FudRKD3K4jf1VJGLEAiuz6VnA4AGam1h7gpNIzSFe66D3NurLKVhJNkHo07N9V9BE3XHOYmyeuirqG1l9mdHgOkDSGd8%2FGWtg9Roa56lrYdchDtRQPLlCkEywKVRScDfrurnwC2diiPTRe47iVtbnLZDxckGCkKYpPM%2FRr3kbyRhsYOtRDiQonFoBSHrBOI18rOeOPvr76YrCeUbf5fTvjOddJ0gQ1uMPku9z6hwjiEZhgOMn%2BaaUeHQJIOkMD7KMA5QQP01HP18hPbfvDTvZPETqb2YiS1BWrozM6jk9SPJJHkZZ5qFagtoaNnbyZg1FE4sUPRdlAQpwkdSjvDZAJ%2FoxNt%2Bw6NlGbQVFl5iKLKKsXCAwyFQZ8S3ciu65ho1lBJ5%2FkZk3OBGjpJWGmVCmsjTkQvA8JHCUU7s5eImevzg%2Fd7BGFhzCARIf8uVN3J5Heh1VM%2BHlko2y%2FHBxF0NJolfo38eDuJJxbf0ro%2FnMurh8hM%2FupH4tdT8zciOFsTC8SAgQoJfRxKzCuvfw0k%2F8MDx7xqUyez%2BS48ESIN7Ky6OUpfAtrxzhx03UR4m0c%2FZF7tnKW2mma4l9yuthTSIZIvxPi6EcpZW0PM0xtOzjo%2Bf4GPfv4r1qNqAUFYs9diJLBC1CIa7FZx8fUlwI22LuNv%2FfLbKMAOftH9TwRXg6%2FiCDAAAAAElFTkSuQmCC");background-position:center center;border:1px solid #0a0}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css new file mode 100644 index 0000000..71b0962 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css @@ -0,0 +1,26 @@ +.yui3-skin-night .yui3-dial-ring-vml, +.yui3-skin-night .yui3-dial-center-button-vml, +.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night .yui3-dial-marker-vml, +.yui3-skin-night .yui3-dial-handle-vml { + background: none; + opacity:1; +} + +div.base64-noquotes { + width:100px; + height:100px; + background-image:url( + data:image/jpeg;base64, + %2F9j%2F4AAQSkZJRgABAgEAZABkAAD%2F4RfJRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAAD0JAAAAnEAAPQkAAACcQQWRvYmUgUGhvdG9zaG9wIENTMiBNYWNpbnRvc2gAMjAwODowNzoxOSAxNDo1ODowNQAAA6ABAAMAAAAB%2F%2F8AAKACAAQAAAABAAABwqADAAQAAAABAAABRQAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABaTAAAAAAAAAEgAAAABAAAASAAAAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMR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0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZ%2F%2B01IlBob3Rvc2hvcCAzLjAAOEJJTQQlAAAAAAAQAAAAAAAAAAAAAAAAAAAAADhCSU0D6gAAAAAYEDw%2FeG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8%2BCjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk%2BCgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk%2BCgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q%2BCgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw%2BMTwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BUE1UaW9nYVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPm5hLWxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk%2BCgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw%2BCgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk%2BCgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk%2BCgkJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk%2BCgkJPGRpY3Q%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw%2BCgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BVVMgTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk%2BCgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJpbmc%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0Pgo4QklNA%2BkAAAAAAHgAAwAAAEgASAAAAAAC3gJA%2F%2B7%2F7gMGAlIDZwUoA%2FwAAgAAAEgASAAAAAAC2AIoAAEAAABkAAAAAQADAwMAAAABf%2F8AAQABAAAAAAAAAAAAAAAAaAgAGQGQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QklNA%2B0AAAAAABAAZAAAAAEAAQBkAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD%2BAAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAE4QklNA%2FUAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA%2FgAAAAAAHAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAAAD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FA%2BgAAAAA%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwPoAAAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1UAAAAGAAAAAAAAAAAAAAFFAAABwgAAABAAcwB3AGkAcwBzAF8AYQByAG0AeQBfAGsAbgBpAGYAZQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABwgAAAUUAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAUUAAAAAUmdodGxvbmcAAAHCAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAFFAAAAAFJnaHRsb25nAAABwgAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE%2F8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAThCSU0EDAAAAAAWrwAAAAEAAACgAAAAdAAAAeAAANmAAAAWkwAYAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkklKSSSSUs4uDSWiXRoOJKFi3Ovx2Wvbse4e5gMwRo5soypdOyN9mTSRHpWvj4Oc4%2FwDVf9WkpupJJJKUkkkkpSSSSSlJJJJKUkkkkp%2F%2F0PVUklCqxttbbG%2FReA4fApKZpJJJKUo2WNrrdY8w1gLnHyAlVOsWvowXZDZ%2FQOZa8D9xrmm3%2FNr3PUswm%2FpmQGamyl4bHiWuhJTYqsFtTLBw9od94U1Q6FkfaOk4tszuqYfwV9JSll1%2FoOt2sOguDXgeTm7f%2FPmN%2FwCCLUWZ1VhrysbKA%2Bjua7zgtuZ%2F1FqIUXTSQcvKZi47sh7XOY0tBDYJhzms3akfR3blVd13prMtuI%2Bwse%2F6L3Ahm7n0%2FU%2Bi2zafzkFOgq9%2Bdj0ZFOM4k3ZDtrGNEnhzt7v3WbWPU8bJpyavVpduZuc2eNWONb2%2F2XtXOY2VU7rA6hnO9RuJS%2Br1hO1lguGJbuYz2extvv3fzLPU%2FwCESU9QkkkkpSSSSSlJJJJKf%2F%2FR9VWf0iwiu3Ff9LGsewT%2B6D7P%2FAyxy0FmunH6xPDMpgd%2FbZFT%2FwDoOx%2F%2B20Qp0lC02CtxqALwDtB4J8FNJBTVovx%2Bo4jvbLLGlltTuRMssrf%2FANJiz%2BhZDqMO%2FEyCX2dOc6t%2Bkuc1gmt%2B3%2FhaPTeoZ5s6R1IZrBGDlkNvI%2BjXcYYyx%2F7tWV9B%2FwDw%2FwDwlyD1LqWH0jq2N1O55rxOogY1rwC4C9uuP6mzdt9Wl1v6T%2Bb%2FAFdFS%2F1Myq%2F2VThusa%2B2tst2k6sPuY73Brm%2Fo3Vv2fy%2F3F0S4TAzq%2Bm%2FWDquKGnbhWOya62DUUlrcmyulktZ6f2ey19Wz8%2F2Ls2Z%2BFYx1jL6yxgBe%2FcIAI3CXfNIqZX3ursqqrZ6j7TqJgNY2PUsPP0dypfWJ%2Fo9NOT2xrarHTxs3tZkf%2By77VR6v9bejdNsbkb3Zbqm2sfVjgOOhrdZFljqsffXs%2FmvV9V%2F%2BDXHdZ%2BuvU8zA6i%2Bj02Y1zawaZLt2LY21tltb7XOb6j6%2FwDR1V%2FzV36v6rPVYFU%2BiCs5PS7cd43O2WUOB77d1X%2FT27lwvVnNyKK8d15q6hij207o9dg3DHdW9m9zLv8AQ%2F4Wu71K%2FTtr9aqzJ%2BuHV8tmR0zNoyLvsXU8Nr7cdtjmtN1J9K%2B2podsbk1%2Fo%2F8A0YsnG6te%2BnLZbdXXY6pttADNwucwmhv2cWbv0tnr%2FpKnfpKbKf8AtsqD1DvrjnfV70cKlldgzgbqjf7QHB3p2sG0sb6lv0%2FfZ6TEcZg630xz2vezK6jVbfhVtf6biQ%2BxltmNY7a2z9Js3Vu%2FwayvrHh1%2BhhdKv3XubjBhY9wDbHtPpOdXkOH6t1Dd%2FRsl%2F6C%2FwDomV7Fg9Wc%2FF%2Bq3RL6biben5WVjh4lljdxbexltf06La9vvp%2FM%2FwAFZ%2FhEuqn0r6lfXM9WYzpvVoo6wxvcbBcGj9Ltr09LLoj9bxf%2BvU%2Fof5mz9avrJd0%2B2jBwHAZTrcd17iA7bVZa2nY0H%2FCXw9v%2FAAdf%2FWl5zidQZ9ZcY3l3oddwg2z1mHZ6zWfQv3t2%2Bnk0%2FwCn%2FwDRf8xf6Df1DqvXGZ%2Be5tzsi7Gd6lm2kPsqNbqqOG1%2F4Cuxnpt%2FS7%2F9I9ALjR1Gh7f96%2BuJJpA1KZj2WNDmODmnhwMhJaySSSSU%2FwD%2F0vVVn9airFGYSGjEcLXuOkV%2Fzd5J%2FdZU%2FwBX%2Fra0EHM9D7Jf9pE4%2Fpv9YHX2bT6mn9RIKcE9U6lgXnJDv2l0jN%2FS497S39C530sOyxn%2BBc%2F%2Bh5P83%2F2kyfS%2FR5NlPrv16uwczExsPHFozLBRWHz6rriWM9Ouv6Hs9T3vseue6B9buoZF5xBU84BDC%2BtoZYW1PczG%2B02Gxm71Gb2XP2fod7P5mtct167q%2FT87Gdfk%2FbscWHI6V1NrQNGu3O2NZ6fp5FN9dTcrH3epR6f9RKwRYXzhKEuGYo%2FxfSMvM6lZlF%2FVfSobU11Q9MGyqLfa%2BrP9PJsr9Kz09n6bGq%2F7dWN1z9VxC3KfZT0%2B%2BPUyGg5NIaPdU7ezZe7KxPR%2FR5Gyr1sX9Db6%2FwDguZx%2Bv352be4WNwft%2B9tb2n21mza%2F07Xn2%2Fp7qmVep6dbP0vqfolqZD7mY91eDmXh9pBAZDGjT9awvb%2Bkp3W%2Fp2Mdkfpav1b%2BXUb0WulTeP23h5Di3JL3UYWTYzlzbKn1sc5rN7baM3FZ9pw8xrvSvr%2FQf0im6uvH6vY7G6hfS2mx1WFYaq7bnk%2Bo2r0rKPTa7bustxX20%2Bz%2Blf4RW%2FqPXeM403s%2FQ9LpdbQ4v97Wl4DcW1nud6PqfrH2e9nszMavNx%2Fs9%2F2hA6i5r77HZLH24Tn1W4%2BUwj2Pva3Jdj5bfzaHb8n7Fk%2F4P9YxP0tX8wulqaWfb1CzZ6GaM30622WDD%2FSV1mp3sfY6tjWOsY1tf8776a%2FTQ7s27qFNVIrqwAfUsbZRXt9S0N9Ky1tX83%2Bgre%2F1sej%2FAE1lzKltdDtbi9ZJsqqbTaBXdS0TbW68PycUxNj8qrIbR%2FpPU%2FSb6%2FTyv6VWf0qvOrzmsYasnGzHmk7gx1Za6K2XR7sd%2B5v6K79JXi3bPU%2FV8i71RRU5%2FWaLMv6kYj7SGX9L6g%2BqK%2Fosrymeux1cf4B17fYsrpuPmNxftz63Pcwl9DWDQ2sIqZkNJ%2FNZe6luR6f%2FAAX%2FAAS1f2pXX0vq%2BJln7LfkVVta3ZAfl4929myn%2FA76rLq86r%2Bbo%2F4qyhVruoZfSek4ldmM12Pe227D9XQBtvptu3%2B7d6Vr66Xf2PU%2FwiSnsuqnDyLMfFtMZORj%2BrXSPeHFseo2l7g31La%2FV%2Bh%2F2oq%2FwfqfpFznVcd9uDZivaxzDZXa1zztZaXB1LW%2Bv%2Fgb%2FZVXi5tv83%2FRsj9AsLqfXv2j0%2FpXqPFedgNurfa10F3uqsx8lv8Ao3Obvrf%2FAMT6n%2BFQquq59%2FURec1zb7CHXMc8htmw7n47v8BtucPUb6v6P9Ld69iNoS9H6Vk0Zzcpj3tqqeW1AAtuc%2F8Am7Meyhv6WvZ%2FNZX%2FAIEugzuk14eLiN69fbi49u6wgBjyWNb6dP6IOa52V6vt247P0dD%2FAFP0ajjdc6kBeekYQd1DIs2tsZVZbdVXt9tYqsG9%2B3%2FTPZ%2Bl%2FwBCsajpXV%2BtX2Zwo%2Fal7Wuvv9S0Mea2%2FT2%2BvZ7m1e1j6GV76PZ%2FpK0NE7avpH1Z69ndU6Ti4mP6mVZktBdbkP3uqbWTRkjKuYGb9t1e6v2776rP9Iuyw8VuJjtoaS8tkueeXOcdz3%2F2nLyb6vdZv6DjDKwmVt3lzbsZz3VsZcHluTgX499hfRYxuzJwn%2FznsyKrLLv8H2vT%2Fr9hODK%2BsM%2FZuSWkvrtFjC1wLmvr%2FWKqW%2Fm%2BzbZ%2BkRR4vVpKn03q%2FTeq47Mnp%2BQy%2Bt7WvG0%2B4Bw3N9Ss%2FpK%2F%2BuNVxBT%2FAP%2FT9VTOa17SxwDmuBDmnUEHsU6SSnxf6x9CzPqt1ECix7GMeben5Q0caneyylzvouto3MruZ%2Fhav0np%2FpFUryaMjFvrzps6dkPbZmUsHvx7zFber4f7rbLP6Wz%2FAEln%2BivYvY%2Bu9L6f1Xpl2H1GG0OG71SQ01uH0b2Pd9B7P%2FUb%2FwBGvH8vpF3T7%2FQpcH5NIea7az6leXSd2%2BzHjdW70qHbMnE%2FwlSZrE2NuzfjKHMY%2BGfpzR2n%2FL9H95wM%2FByOk5hxsgiyuwb6rm613VH6N1X%2FAKMrW10jqbrmHDyHl8MhjY3G6sHd6PO318dv6eiz07fW9P0v%2BOHiPxc6n9j552Ydh3YmVy7FtP5%2Bvvfiu%2Fw%2F%2FB%2Fpf5zehYv1a6pVk5WLnh%2BJZhML6rmiWvsBY6t1Fn0n1NY77Tvp%2FSf8WnijqNWnOEscjGQ4ZB7Oig0fV7Lf01rr8rqR2tez3XPbBx67XsYzayxjbMl9m38%2F9J%2Bl%2FS%2BpzrvUxMWqvqNVuJksx3402zW5oosbdScig725OHd9qY6v%2Bc2ZOLT6Nn88y3e6X1uyk9NexznYd%2BPdi2Mc1lTxl4ztznWu3bKfWZZXbs9T06f0ypdY6J1Hr%2FVH9Wrtpsx6mMqFDS%2F1WisF30XNa5%2B577bf0eyz%2FRV%2BqnHwW1RotDF6xay49Tviks9OHNBAc9g2sfc1m7Zu2%2FoG%2FQxv3PST9Lw2dTblM%2B1W1sdDixoM2vu3f0936Ot3pOZsurp%2FQ5H%2Bj%2FwaJj4GXf052ZjepRjbmOrywNzNjHulh9Meg5zN%2B1lrn%2F4R9fp%2FpFYxcHD6ey6nItdSGAOtdlFwhlh%2FRuHpN3Ppbv8A5xnqemgFOZ1%2FDyMW77T1DIOQy4vra91bqC00en%2BiYx%2F06Nrqnev%2FAIf%2FAEj1WxaG2sxKOo9Mu6iK32UYeOLHML3vLrNrrmu3%2Blv%2FAPRi1cvpl1PUqW3Nfh5VJ34%2BNmO9XEurHu%2FV7t1jGMsYf0noP9n%2FAANqv9Q6W84w630hn2cuFd1jcYGysjS6qzLxmiu3Fyadv896NX%2Bl%2B2eqhSSBQ1u%2Fwed6z9X%2BrtFJH1dZj1agENsqZuIB9EPsvbkW7Wj6eS%2F6fq%2Bj%2BjWOcbNw8hnqdNxq3tizZYXOa4Ty7fkWbmNd%2FObfof4RdpT1fqHUs1rc%2FLfktyRU2vGa4bSHNePtFL3el6VmLlVejZ7f0m%2F1cj%2BZ%2B0WbvSfqn0%2Fq1eTjdRIdlVspsqcxwBqc8PbfW%2BrX376%2FTtf%2FAKH0bcS6v2WJXqulj4YCXEDZqurxn1dxXdRosuw78hnXcR5dSWu22OrY2bqsdn03ZFTt932Oz2ZWL6lVLPWoXS19Hzup9Pq%2BsfTMYty8kn7ZRXDCy5hdVb1DEre%2F9NU79LvxHbLclj7Kf5rIspXE5mPm9J6q%2FLqa82YrmvfVJHqUsd%2BgyqLatln0a%2F03pP8AWxLmerV%2B5j%2Bz%2FU7qvR%2Bp9Cot6QNlLJbZQ5xdZXb9O1l73S99jnu3%2Bq7%2Be%2FnEmN57qv1X6b9c%2Fq99oxWNx%2BuYxcyx7g9rjc2PXxM5t36x6djmt9H1v02L%2Bi9L%2FCVWcz9VPr51npPWX9H%2Bsxuy8bItFNoyDvtot9tIcN%2F06He316P%2FAEKo%2FwAJ9p9hbXW17ntaA98b3AQXQIbuP5y43%2FGB9Q2dfp%2FaXTWtZ1iloEGGjIY3%2FAPe7%2BayG%2F8AafJ%2F6zb%2Bi%2FSUJT2TK66xtraGAAABoAEAbW8fyVJecfUbqP8AjHPV31dXxMjJ6c%2Fay27LaMd1JaNgsoDxX9o9rf0zaW2%2Br%2FPep%2FpPR0lP%2F9T1VJJJJSDNL%2Fsr9geXGABW1rnakD6F36P%2BsuAwumV%2FWXNrxHvcymqh2S7IqLnRa%2B7Jfj2UPcGtqdvyfVspZ7K%2FQ%2By1%2FoaV6Ffj05FZqvYLKyQS13Eg7m%2F9JKimvHprorEV1NDGDwDRtakkEg2NCNnxDqdGb0Lru3qFDHX41rLTWGxVeyR7626tdVmNa%2F1P3LPWr9i2cmzrpY5tdB6gzpL7Kq7WGXPqqf6D8HIc1gZ9upo%2F7T%2FzmVX%2FADXqr0brOF0%2B4135bWVFgc05kD1WMP06ari17q25P81Z%2B%2FX%2Bi%2BnauTysfqnQeoM6h06l91eW2H4jwf1uhgc70Lq3DdV1XGxm78d7%2FwCfo%2FQXfpK7GIRFX4s2fN7vAeGpRjwk93IyOj5VDnN6U5%2FUMa%2FflYlLGuLm%2BqxnpfadrG1tdk302Ufav%2Bs2en%2FNrQ%2Brd9%2BNlNdfS%2FDuDXMy8e7R1bmjfJ%2FkNhl9Nv59KtOeLbMDO6FktJte%2B%2FCstLh%2Bhcaxm4mY5oc5tLMr08XK3st9H7TRd%2FSqPWW11fA%2Fa%2BOOpdOc6jqeMNllYjcdvudjWt9zfVr3b8d%2F%2Fom%2F1E%2B2F5jpf1u6Dj9RyLKcqu3peaf1rF1aGh%2Bhym0XMr91TfZksr%2Fncb%2FSWY9bFTwftfUOpdQwRZvxsDLOLh2uBexrLH21YzLLAHv9K3ZX%2FwAH%2FOLUw%2BnfU%2F6xVDB6lg4%2FTutEFrLaG%2BgLXD%2FC42zY2x%2F%2Blw7f01f8ur9On%2BroyPqllZfThhMsqBZblWhxFjahFLLWE%2B27HZv3sbsr9H9N63%2FBjW1L9J9PDa%2F6udcx%2FU6Ta7bSH6uxLT7W0Oc0%2Fo6HT6mFl1fzX%2BnV9n1R6v07bbhZv2za4w149K0Vk6enkMeWPu2fzn8xVb%2Fwf0F1GVh4mdSW3MD2vbAfA3AH9xyoYmRZ0o%2FY894%2BztBNGS7QbR%2Ba8n6Oz%2FwH%2FttLyRbyPUcXMqzznY2Nfh9TrbZbkkVyxzQBvzm%2Bm04vr7f0d%2Fo2frX%2BD%2FTV2rc%2BrmH0bqHT8fcW%2Fb2Ned1FrmWsaXOZLfRLH01W%2Bpu9L%2BaXUiCJHBWGegM6d1IdU6WzbJi%2FFbAaWuPvdV%2FV%2FnPTStN6U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZADhCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAIAAAABAQD%2F4TkjaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu%2B7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI%2FPgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEuMS0xMTIiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI%2BCiAgICAgICAgIDx4YXBNTTpEb2N1bWVudElEPnV1aWQ6RTcxOTVFNTY1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkRvY3VtZW50SUQ%2BCiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6RTcxOTVFNTc1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkluc3RhbmNlSUQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0ZURhdGU%2BMjAwOC0wNy0xOVQxNDo1Nzo0MS0wNTowMDwveGFwOkNyZWF0ZURhdGU%2BCiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTA3LTE5VDE0OjU4OjA1LTA1OjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpNZXRhZGF0YURhdGU%2BMjAwOC0wNy0xOVQxNDo1ODowNS0wNTowMDwveGFwOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1MyIE1hY2ludG9zaDwveGFwOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOkhpc3RvcnkvPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpOYXRpdmVEaWdlc3Q%2BMjU2LDI1NywyNTgsMjU5LDI2MiwyNzQsMjc3LDI4NCw1MzAsNTMxLDI4MiwyODMsMjk2LDMwMSwzMTgsMzE5LDUyOSw1MzIsMzA2LDI3MCwyNzEsMjcyLDMwNSwzMTUsMzM0MzI7QzA1QTE5MDRGRjAwQUJEQzA1MUJERkFGMDIwNEVBNTE8L3RpZmY6TmF0aXZlRGlnZXN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24%2BNDUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24%2BCiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U%2BLTE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtENDYzN0NCOUQ0MUExMEJBN0VGNUVCQ0RCNjMxODMyOTwvZXhpZjpOYXRpdmVEaWdlc3Q%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY%2BCjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8%2B%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQACAYGBgYGCAYGCAwIBwgMDgoICAoOEA0NDg0NEBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEJCAgJCgkLCQkLDgsNCw4RDg4ODhERDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgBRQHCAwEiAAIRAQMRAf%2FdAAQAHf%2FEAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4%2FPE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BCk5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0%2BPzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BDlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq%2Bv%2FaAAwDAQACEQMRAD8A7%2FmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmrlHI2utXn6WltnFESb0RFSp41WjD5q3LCBaslzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2E2rj0LuzvF7PxftUf8AXPLDnC3XI0ewdpOkTK4P08T%2FAMK2Ec1TLNgaxmE9pFIDy%2BEAn3GxwTgV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F%2F0e%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXYUeZpfR0a4kpUAx19h6i74b4X65CbjR76FV5FoJKKe5C1GIVLdDuGhuXs2IKOX4gfsvGdx%2FskKtkiyD6bctHHbXgPImOC4qOpXj6E1ff4Mm4Ndxkpc770BvNmzZFLs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Lv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVokKCT0G%2F3ZgaioNQemANZuhaWLyE0LlY1%2BbGn6sWspA8QA%2FZ%2FUcVRWbNmxV2bNmxV2bNmxV2NZQwKnodj9OOzYqwDT4iiPZsa%2FVLm5sj7I%2F76L%2BOTXTpjPZQSt9pkAb5r8JyKXqfUvMOpIQOFxFDfoP8qFvTl%2F4Q5INDkrFPAf8AdUhI%2FwBV%2FiH8cnLeAPcxHMprmzZsgydmzZsVdmzZsVdmzZsVdmzYyWRIo2kkYKiirMdgAMVX5sjTeaGl1CzsbSAOLuX0w7k14KCzyAD%2BUZJBirebNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F9Pv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVo4CXUFa9e0CbJRWkr%2B0RWlMHZEJ5WtPMtzE5%2BGYJKnyK0%2F4kuEC1ZeM2IW0okjFT8S7H%2BuL4FYz52mMWn2tDTlcpX6FbDHR5ecCH%2BZevywl%2FMM8dJtn7LdJ%2BKvgry9ccrOJ69KVw9E9GS5s2bAh2bNmxV2bNmxV2bNmxVi3miFU1LSbxvsStJYzH%2FJnSi%2F8ADYpoEzLcxq1T68FGr%2FvyE8GrgjzdC0mhXEsY%2Fe2pS5i%2F1omDf8RwttJRHdrcDaNbhZVI6endIG%2F4mcnHeJCDzDL82bNkEuzZs2KuzZs2KuzZs2KurkZ843Zhs4bVTQzvVqfyrvg3zHNPb2UMsLtGBPGJSpIqjEqRUb9ch%2BvSSvp0JlcvJCLyMuxJb4JNvi%2F1SuEBVvkaX9L%2BZbm8Sv1fTbf0Y6%2F78lPxH%2FgFzpeRvyPbWcXlyyubWBIXuoxJOUG7uKjk5%2FaOSSoxPNXZs2bArs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FU7%2FmzZsVQ2osyWM7o3FlQkMOxGPtZhPBHKCDyUE08e%2BM1Bedjcr4xPT%2FgThV5cvBJbpGergEfMDcYa2PkqfZs2bArs2bNirs2bNirs2bNirshfnRGtb7T9TX7LcoJD2qDzSv3vk0wl81WDajodzDGKzRj1oR35R%2FFT6RthHNXaVcrKsUtftDi304dZz7yrqPrQCIncdMnsEnqRK%2Fcjf54yVjP5gwtJ5ckcD%2B5mik%2BivH%2FAI3wD5RnEtpwrWgw983RGby1qiqKlYGkA%2F4x%2FvP%2BNchnke5BIUGoPQ%2FPEJHJ6XG3JFbxAOPxOA1iX7sUwIdmzZsVdmzZsVdmzZsVUbqBbq2mtm%2BzMjRn5MKZDLP4rC2UVq9qYj7SWshWn%2BtxOTnIVG4ttWvdNaiiK7FxGDtWG6Ti%2FwDwMuShzRLky%2B1lE9vFMP8AdiK33gYscKtBmDWhtq%2FHbOyMp68SeSH5UOGpyJ5pYde3moWPmW5KzH0pIo2WNt0A3Wv0ts2D73zJ6FgzxqqXpKpHG9eDMx7EYXed45VeC4gPCdYyqua0I5q5VgOv2cAW8sWo2QMqhwwoyHcVyQFhVOLzvrNrdf6fFHLFX4kVeBH%2Br1%2F4bJlp%2Bt2GqWrXFnICyKWeJtnUgV3XOP67qFjaFLHUrprecy%2BlZajxPDmN1jn8Dv8Aa%2By%2BIaXrclrdtZ34NrfR1USofgeo2K06c%2F8AgcBCXr%2FlvXRrdnzk4rcoSJFXYfMbnDzOV%2BTr82eqAOQIpaBq7AV2r%2BOdTriRSEp8z8RoN9I5AWJPV5HYD0yHr%2BGQg3Ntq1lcLazx3CiZviiYOKzQo9Kjb7YzoWqRevpt5AOskEij5lCOmc60%2BWCK0j9ONYo5IYp%2BEahQWBeNjRafEcMVTvTb%2B80fyHZ3FugE9vSORJBUqPVZW%2BEHw3yVaXeC%2FsobulGkX41HQMNmH%2FBZzC%2B1iTTbadZUkjtJjzkQqSKqNm5fsdMPfyr1%2FRdT8vra2E5N5C8kl3bSMTKpkctz%2BL7SP9peOA7fFkIkgkCwOfkz7NlA1y8DF2bNmxV2bEJLy1injtpJVWeavpREjk3Hc8V64virs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Xv%2BbNmxVplDqUbcMKH5HIPokjWsstqx%2BK2lZPf4Wpk5yF6nF9R8xswHGO8QSj%2FAFh8D%2Fqrkoc6VmSMHUOOjAEfTjsAaZMXhMRPxRnYf5J6YPyJV2bNmxV2bNmxVQuzOtu729PVUclBFa07U98DafqsF6i9EkI6ePywwyF6vG2i6oJRUWl6xZCP2JOrr%2FsvtLhG6s0yiK4X6Zfi4QI7Vb9lv5h%2FXDHrgV5c8B0LzLc2Q%2BGF29WDw4SfF%2Fwp%2BHOg6ZMHi4j2YfTkZ%2FMGwpFaazGDytm9GYj%2FAH25%2BEn%2FAFX%2FAOJ4N8uXwliicnps305LmFZDewrc2dxbt0lieNvkylc45%2BX10UCQzHjLATE4P%2BQeNc6L55e5i0J57WVonikRmZDSq7jf2yB2Op%2FVYor2%2FwBNjktpAGjv7ZvU%2BInoy8Vao%2Fa44xCQ9as25RVBqKnfBGRby9rBEsljcIY0aQ%2Bg5FCCQD6bj9lslGAikN5s2bArs2bGyOI0aRuiAsfoFcVS%2B%2F1q2sJltyrSytuyp%2ByDsC3zwxBqAfHfI%2Fodmt2z6pcjnJK5dAexPT%2FgRkhxV2c782mSy82WUgNIdUhNs4PTmlXQ%2FwDBDOiZAvzLb6nHpOrlFkjs7lWdG9yvxVG%2FwiuGJ3Up3YTJFr7op%2BC8t1ljHjxodv8AYtkiyHbxx6XfKx%2FcXBilJ3%2BAsVUV8FRlyYA4Z80DkkPmq3EtlHJSpR%2BJPgHBH66ZBtIufqt9Np8pALHnEpO5p1oM6Xq0P1jTriPoePIfNdxnLtZtrGZluBcG3vF%2BFJYuJfx40IIxHJKzzb5et9ZtZYp1LwygcgPtKy%2FZkT%2FKWuRKKCOC6tNH1CblcWiILDUWHH6wg6wyDejx9Fw4sfOMjEBY5biH1HgLy8VYulOfJV%2By38q4ndH9LlL219K4iilHrWzLxlhI6SgE1%2F2SnFKo0Czxy28zMqcSzspIYBPj2I%2F1cd%2FytnVZdNQ2D1I%2BESMoPw%2FzMftdMG20TSQyyblmjenzoc4TY6ld6ddyKwMUsbFZoHqNwd1KnGXRXs9n5%2Fv7lg98GlWhMjwk1A%2Fm4k%2FF7jDSwSPULTTJI3PGBphGNwG4OHVW%2BgnONX%2BsWFpDFPaSSJcTESG3TcRlf2uRK%2Fazq%2BkR3aeT7e%2BjnX6yoW8ibht%2B9i9Tg%2B%2FQ98QVZHqstutowuSPSdSpV91IPVWzif1i98t%2BZ7m40FjbSWUrNCqEmkex4EH7acT9lv2c6lonmbTvMUTWdwgiumWktrLQhge6H9of6uRLzd5ZurDVP8Q2KetYFUW7jXeSKi%2Bm0hH7UZH7X7OCY4g2YM0sMrjvexB5SHcXsnkPz3Y%2BcdPqKQ6lAB9bta%2F8lI69Y2%2F4XJeDXPJlvPe6JqMeq6NMYLuE842To6ntToyuv2k%2Faz0J5E8%2B2HnGyI2t9VgA%2Bt2ZP0epH%2FNEf%2BEyESeUuff3tmbFAx8bB9H8Uf4sZ8%2F6P82TMMLNb1iDRrQ3EpBkkPC3j7s5%2FwCNV%2B0%2BGVc4n5m8yfpnzJcsr%2F6HYsLe232PBv3j0%2Fy3%2BH%2FY5JxkLourX175%2Ftb28maSZrloqsdlQ1Tgo%2FZUDO755%2B8uxlvPcMI6i6LAe2zZ6BwlS7NmzYFdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVf%2FW7%2FmzZsVdkb83W5%2BrW1%2Bg%2BK1kAc%2F5D%2FCf%2BG45JMC6jare2FxaEf3qMo%2BdPh%2F4bCNiqV6VOOcTV%2BGReB37%2FaX9WHoyFaJMz23BqiWE7juCh%2FsyaRsHRXHRgCPpwy52gLs2bNkUuzZs2Kuwu1rS49W06Wzb4XI5Qv8Ayuu6nDHMemKvONE1KWGVrG7rHPCxRgeqsppk7sb0XC8W2lUbjxHiMhnnnTHtLmPXrZfgakd1TsR9iQ%2FP7LYtomq%2FWI0Iakybof4H55LmFZdqNlFqNjcWMwqk6FD8z9k%2FQc515XuZbW4l0%2B5%2BGWFzE6n%2BZTTOlW063EQkXY9GXwPhnO%2FNsS6T5qtbofBHqaniexmi%2B2v%2BsU4v%2FlfFgHcrPTFbanZNb3caywyApLE3Qj3zjutwW%2FljzBc6Pp6fV9JHpsLNSSgR1HIorV3Vvizq2jXQk%2BAndlBA9xnNvzRiWPzJBJWnr2gJP%2FGNyv8AHAdikJ3YGf0o5pZDIboSD1GJJ9aAgh6%2F5aUzoFnN9YtYZ6gmRFY06VI3zlXk%2FVI5bi2hnlBgdBuxFFahhfr0rSNsnHlXU4JI5NJaSt1avIQm%2B8RaquD0I%2BLjkpbgIZJmzZsirsDagC1jcqvUxOB%2FwJwTjXUMrK32WBB%2BWKpfofE6Xb8f5d%2FnhjkMPmvR%2FKlrJBqkxBSVkjC0PIDpTfI15s%2FMNbu3jbR5plsZVp69swRi9N0eSjMnH%2BRcVpm669cWWtXGnatwjgKma2uPsj0x%2FNXw%2FayOfmLr%2BhX3l%2BPTYrkXM%2BpGtm1uPUUceX7yRx8KLtx%2F1s5xoN%2FefpVr6C8muVVfUuLO8kMrEIeTem7faRk5Iy5FdTuZ9B169trGZvqkc5eFD8SmJzzUcTtsrceWHzTT3fRJv0p5UZvtOYYrgCu%2FJV4P%2FwANHnPrj83vM2lX9zpWoBJYInaJ540pOi1%2BGRQDxf4cln5Z3qT2stjWrK0iexEgE60%2F2XLOUfmHYNZeZbhWP94Ayn%2FV%2BD%2FjVclLlbEdQn955q1wTiU3huLadeQCsfSljO9VNev%2FAA0bYHub1Z7V5yWkhHxpcVHJNwGiuP8AKStVk%2FbyGafqLQxyafO5S2lPJWUAmGQ%2F7uiB8f8Ad0X%2B7F%2Fy8Ctd6jpl3Lb3v%2BkQTpxniqTDcQn7LoR%2FwUb%2FALDZCyyekWl9ZyaFLPelZGN2tqDEtZJHenEs67ckpVXwq1bU7G1iKWvqtcCR4bkkhFYx%2FCHXhvvX48C%2BU7H1SbK3k9Wya5hv4HchSBF8FxBL2WeOJ1k%2F4s9P4cu%2F0j%2Fc1FphmFxPLeOhZBxAiL8jt40%2Fa5YegV6PprvLpcE8sfpTNbh3QVoGK12zluoQ2PnZih42fmWIVt5z8Md4q9I5P5J17Z2A8YrWVl%2BERoaDwoNvupnLtb02LzREdR0hBba7bVe4tEPFZwpr6s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xKXcslu7tXb1%2BSBq%2FwCSzZK9c06xuNUutStkBls5IFkAIAMoHqUUfzNRkbCPW5Xs70rZcVtL0%2BtCoAFVc1oK%2FwArni2RIShdD0rU9Z0g2UNW1DR5JLG%2BirRlQuXhmp1ZP72M%2FwCph75g0K2sra21G8ch5baGJUpt6yARuvL6OWEQk1eJrq9s55YLxBzuGhJEjr3LKvxSqv7WISanq2oQRXGryvd2MtVhuSQ8aNQch8OyNjsqElhK1hbcr%2Fcv3K%2FyV%2FycRSQBmUiifsfQM6FpfljSbrR0mCy3EjDlDIzN9sGnphU%2FZ%2FlbIrqnl%2F6jM3Cb1VRqOoU8078XoOHPISIiQCd5ckgE3tyS4StK6xSy%2FDJ%2B7HqseO%2FYVw0W2thatp10he2b7YH21cfZljP86f8AD%2FYxO4tbO4so4I7ZUvG5Lpl3PssprUws392JD%2Fut%2FwCbAOh6sLuU6VqYMF4hKRu2x5DrFID0YY7rsh4tMn06%2FkspjzjniaS1nQfDIE%2BJWXwdafEv7Od0ugnmL8tmYipWEOB1oGWp%2FwCH5Zy4hoT9WuU5BTzj7FHp%2FeIe3%2BX%2FADrnR%2FysvRfaHeaJIwZ4RJGo8QDzQ%2F8AAy5OPVBfPNxbpMpifYqaBu4IwFYWlx9fEIJU7lmH7S%2F83ZJ9e0x7K9unRg8azMkoHWJySVR%2F9YH4W%2Bzj%2FKtvFdaxBDLQKzAVO243G%2F8ArYPJUXb2NvDZtdyWxe3B4meCQ%2BtG37Jkjb9lafaXHRXl9q2r6etnWJ7Yxx28h%2B1UNyMjt%2FlH4myX6lp1poPm57CIFLG8jikCsKisqqXWncc2%2BzhLZW0Om35hCuLiCeSgIHFY67KT9rl4YaV63IwMVSakg1pt27eGRuzvrTWILdYbnlcIWXSdQc8W5pXlp91%2FLIP91M%2F94mG9tcfW3AQ14xgsPH4c4Zp%2Btz6HqN2rJ61nNIy3loTTkA54yIf91zR%2FailyRNUinpV0iXqyyxw%2BjdW5Md%2FaN1iPdqf74f8A5Jtka1ZZ4LWYxsySKpaCRT8QI%2BIxkj2Hw5KLe6%2FTsUF%2Fp1wsmrRRk2l0QAL6Fft290g%2Fu7uP7Lo395hFquqaL9XZmmWCRwySWTgs8MgG6Oo%2FY5fZbAUhC%2BZ9JsfMl1SKYW%2BqyQRT2DMf3UvJeTwt4M5%2BJchKyrOr6D5gQwTQEpFK%2FwDeQv8Ayn%2BZDk%2B1Gyj1ew0SaC4gS5ntmCtX0ELQtQAM%2FEcv5Fwv1bQxr%2Bnhr4oms2ymP6xuCStSIbof6v8AdzYOaGAQ%2BXdTm1NdLjj5SN8QkG6FOvqBu%2BTjTrS2sbZLCMcVUmkpFGLn7Rf%2FAFv%2BFxTTme102DTuILIwZpKksW%2BzxWtW41%2FZyU2XlW41HhcahytOQJZVHKaXw%2Fd%2F7rY%2FzviAqQ21ldXtytrDG0k524qKmnj8sO736roNmNIltfVv7hFeaMnkUqTwpxNA2S2MaT5etS9w6WdtEvx1b42A7Symh%2F2C5zTzb%2BZun3swOjacGVKwrqMgoajeiJSr%2FOTDVdVZPYa3pOj%2BW7u31uKKzuZGP1dePP1Iz1UovxtJ%2FlYU%2Fl%2F5hOtyS%2BWrlis1Gm0pyfiR4%2Fi9Kv7SumcrvNYnu5DcXH7yToamrfSf6YL8ratLZ%2BZtJvoT6bwXMbEjuCwVh8uJauPFuFe%2Bx%2BYJ4NMawQiOFzyZOlDX4h%2FwQyQeVtAn1BY9R1QN9WU1toG%2Fa3qGYeGE3lnRLPVfM19LdAyWkTtcW8a7xOGaq1kGz7k%2FAM6moAACigA2AxJ7lojn72wANgKAbDLzZsirs2bNirs2bNirs2bNirs2bNir%2F9Hv%2BbNmxV2bNmxV2Qzz3p3P6rqKbFKwyt%2Fkn4lJPseWTPOVfnX5gmstNtdBtnMbajykuXHX0YyPh%2F2b%2FwDEcbrfm24MRzZI447GR59w6pMfNyWl7EdD1KM3Cp6dwoKldj%2B1zHE%2FRko0rz1rUtz9SvLe2lm2Hp8jC7BhWqV5xvUb%2FDnn01jPEin8pHgckemXmsTaHcxANw05o57O7IIKxliJYll%2FaRT%2B84%2FsNkIZhIkSjRDl6zs%2FwIjJCXFHkb5gp3%2Ba2r%2BbdPuEvYLVbLRpiFL27c2EvWkj0%2Fd8v2VpkGsfN2p3Kra3V2XicgEsQeQJ3qSNs7d%2BkdO1rSbKw1LhN%2BlbRXVJKFZyq8ZV3%2F3YGHLOEecvKFx5TvTLDym0idv3EvdG%2FwB9yf5a%2Fst%2B3lpHUOvsua4iNwbWCruHK%2FB0qN9j0zoy%2BarW48r2Oq3l1Le2sSizuGkqk6zgUVXMda8F%2FwCDTOO2M01rIs0XCRQ4kHqCqGnZl74NgkTlMqSOIZpPVNrXjGG8Qvfj2wXzSyqz1eO%2FtNSjQM8sVubhFbbkIpPiI%2BUR5Yca3q17IdPmtZ2js7yztriONNhyAKSciPtMJUfIZaXDWL%2Bra0jcq0ZYAV4yAq6mv8ynJf5Yex1PRjpUsfO%2F0pnuLJWNPUgkNZ4l%2Fm9Nh6vH%2BVpMRa2uvBcXej2Gp2rSC5tJJbOZkqW4v%2B%2FgY%2Bx%2FeJhtBB5sOi313boLa9ihMlo3EB5ClGkULy%2B16XJk4rhlZarBFAbZljtrS5Tg%2FoIF4fyOT1JjbC1L%2BbSbowyMwu4WrzJryX9h1PQpxw%2FFWFXNut9PB6srS6frlqI4JZHJ%2Br30bCsbOf5phx3%2FAN1T%2FwCRgPQbtreVrEFrW8gfnDU0dJUPF09unHD%2FAFeygjjvbi2haTQbpxcXlpHvLp9x9n6xClfjtjXi1P2P3b%2FGseE99ol9qtyjIKamYlktb6Mn0L5QKJ8Zp6d3x%2BH4vt8OD%2FvciTXPZaZ%2Bkdp5%2Bgt19Yad5p0%2Fe0vU2Y8T0NPiaM%2FtJ%2FuvOj6lcGysFaRlYxJWUjfkUXk3z5MM5p%2BV2l3U2pPdalFHK1sOLyqQxSZaFOdDWOT7W%2F7eTTzK8UdlcxREhXBTf%2BdzWg%2B7JxNji70HnTz%2B51GXyrrFxaapD69nfcRqSftqxHL1oj%2FOjPjtQ0GNYCfrCXWi3QMtlelhyjkYbFfdvsyx4M87Wy6zqemTq4X9KwQnmegkK%2Bmf%2BSi5G9M1PVfLUt3od3CJIGDEQS7iKUD4Zov8%2FjyErqrruPNkK58%2FJN7Sx0%2B0sDe3k0k9xA6JBJACGqwPHiKp8S8fts2F0mrDS3nubPThH6ZLa5YcQsnBvs3kSsCnJeXJuK%2FB%2FwAYmwQ%2FrXdjEsQRizhvjKCrUp8If4uW%2FwCyuK3Fs893p1nezfVdeDCOxmHFi8ZH%2B89wSeBjP2YuX%2BVFiYggA70Pmt9QzfyjdxXeiPeaY3rNYt9ZjdKUkgP2gyj7L8ftL%2FPgTz2tuLdJIT6cN1JFcxzJ2U7Sb%2Fs%2Fa5BsKfLEMvlPXby2sJI40uF%2F0izVuUcb05n0z3gkTlw%2F3237vHeddXN5pEMdnbmOys4BFcy0qDcF6GJa%2FwDFacmyX8Pu2R1QOi6Yupabd2F78dj6xjLVFUlpySaHwkUf7F0%2BDIrrvl6dr42N0eOtRIHs7ldkv4B9ijf8tKgfB%2FP%2FAHX28mPluyb0Vs7OdTL6SSReoK8%2FTZqN%2FrqOPL%2FJwTqdhFr9m1lqUhjnhcm2uv8AdltN%2FMKf7pb9tP8AZrjVhWHaHrEWqxjTb9gt9GKQytsXptxNf2sl35d3J0jznJbCojuQlR26cT%2Btc55qthdyXcyyJ9X8wWfx3ESbC6UbrcwfzS8fjfj%2FAHyfvPt88N%2FKuq3F3q1hqBIEyc4pWZuCkoAwck9MA50VPJV%2FMq2k0TznfCJQUmPJom%2BzJG%2FxcW9t%2FwDY4Q6cILa6ZY2eKRwslv6goaDfjy%2FaK4f%2FAJleadM80a8t1pcZ9GCJYmuG2MrD7TAfsqv2V%2Fmwr0WyuNXUw%2FVxci1%2BKLt%2Fw23wrg6qGVanr1vrK2t3csIry1aESBjxJEYYOQff4cjvm3zLbpZXLWTGC5vr%2FwCswRjfjBGoC8yfi%2BIjCPX2vNMu%2FqZDRNGKSAgUqxqgqKruF%2BH4sjsyPPIZZSXJ7knfG1e9%2Flxrdt5ksbqdSFu7eMLcW5O4%2BE0cV6xvnF75uVzcb14yyBW7%2FaO2KeS9RutC8yWd7DMYLfn6d3L%2Bx6D7SLJ7YhdkNd3UkRDRSXErxMDUFGclT9IwndCtpWrz6ZN8MskcDsGdojxkjcfZmip%2B2v8AL%2B3iWoySfXbiHUmFy14frKXqH4nL14zK%2FVuX7cbYEeJWDPQVpU0Pj0x6yqLL0pJUW4tXE1o5O9SaSRbeP28Cob1Z1T6vPKzxjeNSSQK9aV%2BznXLfUrdtDt9T1U%2BjeRxpa3iMvF5V41jcg%2Ftrx%2BLOd6VbaTqJlS7lMl5Iri3hHwRiQj920snhzODppWsii6zcGeSZg3po3NSy%2FD%2Fen4K9V542r0LyheaXcm5uaCCWNhxkl%2FvClOqcvs4rrn5g2enI9tpKi4uqlWck0rSvxP8Atf7HITazpc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2FLhpr3nLTKJ9UT19TB4zNHtCe3Jj3b2XIssp1Y8bUfFOQsix7SCSlAXpTmj4av5OnsdM%2BuzB3Zm9OWaNGD2%2FMgRTolP3sXP4Zv92fyYi6oITDVrG28x6NBeBvqWoWS1ivSeIikU8jFI%2BzLA6%2FGn%2B%2B3yFaq1pcXix28ZUGi3U2wadx%2FuziAEWv8Aq%2FH9vDLV7TzXeWrqbaWO4VhHeNHtFdCP7EhX5D4v9%2BfbwpC3liGgvIoVdSqt6pLPGr0pTj%2Bz8Xw4CUkEGil7RwRu9ZzwjPx8UZiKePShyb%2BRfMdhHM2kLEV%2BsDlDLQFncUCxcRX7WEF1DCs63zCs6r6c1Nkencr7rgXSpFsb5zCForepC9PiUEfZr4DADRVD%2BddUkPmPU4lUgVNtNG4qDw2Bof2kP2GyK1LECpY%2BAqTnUFhsta1Ce%2B1G3inuZCrySsgqwqFNRkwu9R8m%2BWIwscEHrharDBGjSH5tT4f9kcIoop4da6Vqt2GW0tbiQHbikbkH57UwHNFLbSvb3CNFLExSSJxxKsuzKwPQjOu3%2Fmq%2B1mFo1C2NmFMjhTQLGu%2FKRtumQfU%2FMWh3uoTXx0r1pJePKSWSnJlVU5lQNufHnhQxmOYxklSPiFCDvUZQKUIpUn7Jr0%2B7D8eYrBP7nRbUf61W%2FhmPmtkBFvptnEezCMkj78CpRZOY5w%2FBmWhBCjseuSyyn0pIpIr2CSr2gtbYTQt6aylufPp8PBWbCZPNurROskYgVkYOv7tSAVNRtg2780%2BYPNd5CdWuRJHEWkWONFjRaih%2BFAPljsqLeRrVh%2BjQt3GBRoXBBKAfFwag%2BLJ15B17yfealE2taTHcXMG63Eq%2FvbYL%2FvyH%2B6eFK%2F3iJyT9vAXkPygPNEuoxx3KQ3VrAHtYWP8AeOxpv%2FxWqijMv2WZMLdS8vBLx4pg9jqVqTFJIvwup6fvP5lP%2FDLillv5i%2BStPtL867pEEcem6hxkivLWjIk%2FevHb05ftZF9Okd5Et5mayvoWEtrdRmnCUfYmhYfzftp%2B3k3%2FAC68zLfx%2FwCFdWt1eElrbUoW%2BwGIrDPGv7CyU%2BLj%2B18eIeavKM3lq7WqfWNOkYizuXFeNesE9P8AiX7WNbqCncfm2f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V1PpOsrBduRLFcPb3JY9VditW%2F2XxZ0%2B91O2spIoJWL3E54wW0Y5SOf9UdF%2Fmdvhzm%2Fm2w%2BoeapJlBVdRjWdCDsZE2cfeuHdvfQW0BngZptVvEH1u%2FlG6gj%2B5hH7Kr0xHc0pD%2BYg8wa1NDFZWjSWtsrCRoiGJcn46b1YdF2yFWemzxsW1CN4Ej%2FZlUofubOs2WpxpNGl2oMP2eSbEe5yTXGkadqFpJaT26T2860YEVBB6EHx8MeCzdpunlEtpHYQ38GqRrFNaPA8EgJcFa%2FGqhadao2XBGlmbe2uCzevbGeRo2PcNJx%2F2S%2FDht51s3sLpYLoH6ncIq21wRU1UceLt9Hxf8Hhj5f8pXerWc%2Bq2VrHqE1oqQWdvNLwUoijmJB%2FO9W4%2Fs8cjVH3LezEvM2mXWqyabNozB7SS1WJ5SwBrHWnLv8A3ZUbfy4onlazmtrKC%2BJlNoHFFNFbmQaHvtTJ9rPlzU7GOO6vrRbeNioQQMrRxmn938IXj4YE0fQLnXBdQ2062l1CP3SSry9Xav7og0%2F4LDsikps7C3s1WK2iWJB%2Bygpg5lNOX0YAVr7TL0xXsxcxsVlhktwpFPtLVWwbf%2Ban0e8tp7LTYrmyILlpyT6hoRw2%2Fu%2FTbdlw3taoK4v7a1dY2dW5GjQ1qVHj%2FwA24Vah5a03VlNxZEQTtvyX7LH%2FAClyfjyfo3nrTrbV9PRNI1i6gM8qRENC8gb05OUI%2BNR6nR1%2F4HIRqOj655Vu%2FQ1SBogT%2B7mU1ikA7pJ0%2FwBi3xZGwdizhOeOXFCRBSPSZNX8maml1MhNsfgldPijdD1H%2BS37S8s6ZLrEEZt2uEe1W6VWtLsg%2BlKGHIGOReS%2F6wOR9dWtRp11dSQ%2FWHt4Wk%2Br93IGyU%2Fysk%2Fk%2FW5INATT9Z0eAWczGT6gr%2BoIlfcgBxsf2vT%2FAGMYxMSeE2D07m7PqBmjEzjWSO3EOUo%2BY72M%2BYfLcd3FJeQRxyo7EzQU792GQ60bU9Hkf9HTAwts1jdVeNl%2FyX%2B2n%2FEc7ZL5XstVSS58p6kYZqVbTrysif6tWPrRr%2FspVzmuvaDq2jzsup2JtA5NCfjtmNf91Tjb%2FYyccJ8tmgJPqV4JJLJpI3sYLq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FFMx2imJJSvhHLXj%2Fr4N%2FO9G%2FwAJ28o%2FYvY69%2BqOMgdlYzqPmWy8xr615aouoxAA3dk4dJB0%2FfRGjofBl54U%2BnCySRNSa1l%2B2vQq3861%2By65GPKcztqxjY7NEw4jYbU32zoNppF1qfrw2JX6yierHExoJivWIf5fH7DYYnZaY3pN9N5N1n9JJEbuIwyRoisY1kDbpVu3F%2FidM7xpl3Y%2BadFt7m5tle3vIUkaCYBx8Qowof5WB%2BPONG0jvLY28qlRUgqwoyOOu37LpiXl3XbjyZqk7XglmtZIfTEKNQGh5REFvsxr8XLjgIrdWQedvy7GiQPrfl4SNaxVe5s1q7Rp3ki%2FaaNf20%2B1kT07WGCqwcMjdJFNQc9C2N9BqNvHc29WiljSVGI2KyCopkFv%2FwAotHu9cOq2d1JYW0x53dhAo4O53JQt8MYf9ocMFyB23ZwGOQIkeCQGxqwfIsatNQSQrIrmOUbrIhoQfEEb5LLHzPP6X1TV4RqFo4ozFVL0%2FwApD8EmFms%2FlxeWBNxoEpuIhubSQj1B%2FqPsHwo0%2B4ltUmW7Ro5ojRo3BVhT2OWCi1t%2BbPJ1pFCfMXlJgtl%2Fx92VCyRHuwjb4kX%2Bdf2ciOlG2huhcX2n8JI2BE8FHHzMTb%2F8TVc6FpWutaySPblJEmHGeCQVVwP1ZGtcsIbe5N3p0Ui2MlWaM7mB%2FwBpQ4%2B1F%2FLkTGulhnDIYnYprf6tYaxaxxCDlxIaG7iko8Z7kGtWr%2B3ywxsdGl1WwitzGbkgkRzugDGnRm34R0%2FZbIJBZwxv9YhAVx8Qp0JPiBnafJl1eXekLNdyrKOXGNgADQD4g3Gg%2BE7Y8WyTLfiHNJbbQvNHle%2Fe50eQX%2BnXAD3Vg53EoWnKImhQmn7Pwv8AyYRX9xql1dmXWOS3XHiqMnp0QEkKq%2BA5fazrQwHqOmWmqQGC7j5D9lxsynxVsFsLeO39hb39tJbXMYlhlHGSNuhB%2FUffOZXy3%2Fl7UV05n5MgrpN1LTjLCT8VncEj%2FYf5Odt1nQbzR3JcerasfgnA2%2BT%2FAMrYB%2F5V3Y%2BdtAvhefubrn%2FuNux1jkQUYkD7Ubnir%2F6uEq8D1rTFk9XUdNgaHix%2Bu2XVoHPcD%2FfbfstnQfyAeb%2FFktC%2FptaSF1VgFNGTiXFfiA%2BLj%2FlZC9WuNd8p6kNM1e04anYsY2mY7TW%2FZG2pKjfsS4K003mkCHzl5WmDLazercWoB9WCvX1FB%2FeQt9lv8nIofYNRl5FPI3njTfO2li7taRXkQUXlp3Rj0Zf5on%2FYbJXirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FW7%2FmzZsVdmzZsVdmzZsVdgHVY9PmtHi1JlW3cgEuQBUbr1wdgPUdNttTtzb3IJWoZSOoYdxirzHztP%2Bi20aTyvdm6uDcJSCMJIPTVhRWKj7Bbbi2B9b8keZrnV3FvberbsQsVwHUKFJ6tU8hSvhk%2B%2FwAPGy1GwvLOkqK5ju0cIP3YQ%2BnItAPiif8A4nkkphKQaQOk6eml6ba6fGQVt4whPif2j%2FwWO1LTbPVrGfTr%2BITWtyhSWMjqD%2FEfs4MzEVwIsg2Ni%2BVPOHlm58p65NpU1XhP72znP%2B7IWPwn%2FXX7En%2BVgW28s63f2kWr29m76Ys6xyXQpxUggNUfa4iv2uOen9c8t6J5it0t9as0uo4zyjLVDKf8l1oy5EL7TriGW30Lytp7Q6Dbs0d7xI4Oz%2FFWPlycmNvib%2BfKziufETs7WXahOn8Ph9dVIn6a7%2FewDzPd3ukNplzYtxtEhW2adVBKzRktTkalOdf%2BBw60bydZ%2BaNR%2FwARaPq0VjOIw509bcLIkw%2B16yh%2FjRm%2F3an28de6dLYTXGk6xDztpx8aHoyn7Lqfb9nI3YX%2BreQ9ThS3pcWhcvazMBWSE%2FbgaQ%2FF8P8AJlrrDvunvmryB9buFvzAtnrkQD84z%2B6mKHkGRtu%2F82HWnO%2BoadLpU5aC4ZeUL9Gil%2B0jKR0aOYZOLO80jzho0d3Zv6kMn2WFPUhlGxVh%2By6H7WQWaO80rV1hvwBMjcfUAoskTbLIP%2BNsIr5oSu10tfOt7Ikt4th5ijQC6hkSsdz6fwfWIiCCr7UmTj%2Fl5JG%2FKTSdTjg%2FxDILh4UCUgHD7P8Axafj45GPMdkYtRkvbWf6jewEXNhcr9ppT9pEVatJWnxJx%2BznRPIfmz%2FFujfW5Y%2FSvLZ%2Fq94gBCmQCvNQfiVX%2B1xb7OA2NleaX%2Fkr%2FA19Jb2rO%2BlXbc7UvuFbuvL%2Bb%2FiWC7M7HOuarpdrq9jLY3i8o5Bse6t2df8AKXOP6jbaj5dvpLK5USBd0fcB07Ov8cMT3qkP5l6trkWp2kNi8sVr6CShoyVDyH7RJHXj8OQpfNfmCN1%2BsXcsnBeCrOfUAUdFHP4uP052ny%2Fq2g6veR6T5hgX94Almsp%2Fdsw%2F3W%2F%2BU37GSHUfyp8n6hUpavZse8DkD%2FgH5p%2BGCXNeTwM%2BbzeWxtr%2B3SVHFGMZKMP8oBqr%2FwANh9qv5gpr3kVfLV9zk1O3uIjFOwrzt4w1GZhUeqn2P8rJD5i%2FJJrK2lvNKufrSx%2FEYCnCXiOtCpKPx%2F1M503lq7tpDxDNUUUGlPwyJtWQflfpMWseaFtLgssZtZnDJ1VhxCn3651e38qanp%2Bs2ZX95brKG%2BtR7UVfio6%2Fs16YS%2Fk3pGmWxvNR%2BspJqfEW7WnR4kryLFW3PqN%2FL%2FLnW8I2UsW8x%2BVo71n1LT0CXp3mjGwlp3%2F4yD%2Fhsgl9oyXUaxX1u8LoCY2dStV%2FaG%2Fgc7JTEbiztrr0zcRrIYmDxlhWjDJCXQoeVeW9Rv8Ay1PKL25kuNO9ELEo%2BIjgaoKk%2FAqJyzqtrdQXkCXNs3qQyqGjcdCCK7ZFPMPl1Yg95aLWA7zQjfjXqw%2FycB6JrNzY3BW7uAbARKgUqSQVIC8KfCq8K8vhxq9wlntK4DvtJ07UgBfW6TU6FhvTwqN8FRyRyoHiYOjCoZTUEHH5FDC9Y%2FL6wuSZ9Ic2M3X0tzEfo6p%2FscL9B%2FLy8XVJNS8y3Yuo41aKz0%2BEkQrGwoWlO3N2zomVTDZV4l5n8s3Plq94oS%2BnTk%2FVZj27%2Bk5%2FnX%2FhsMNI893Wj2ht2thNVSEp8PGSlBK%2F%2BSf286nqOnWmqWcllexiSGQbg9QezKf2WGco13yhdaVMUT95A39zL0DDwPg%2BIZc3pPlzU5dStGa4IaeNgGZaAFWHJWoMOc5v5E1B7Wf6tcAoD%2B5PLb3jP0fYzo4xIYrZIo5UaOVQ6MKMrCoIPtidrZ29lAttaoI4UrxQdBU1OL5sCsO8%2FwD5e6V5708RXNINQgB%2Bp3oFStf2JAKc4m%2F4XOIWX5R%2FmVoOpummwIySAxNMssZhZG2q3Mqen80eeoKZqYq8l8h%2Fk%2FceW9Qt9Z1DU3W4gPJLS0JCEGvwTytT1U3%2Bx6arnWs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F1%2B%2F5s2bFXZs2bFXZs2bFXZs2bFXUzZs2KuzZs2KoXUjILG49E0k4EKetK43TYkhsoQp5EqGZvEnvgp1DKVbdW2I9jhDdaDqT%2FuLLWJbOzP8AulEVnAPVVkb4hiqB8wWUXmS%2BXTYWQi3ikZphuUlqOKmn7P8ANnOtRsiPW0TWUKqD9ofajYfZkQ%2B3%2FDLnYtH0Wy0W3aC0BJc8pJHPJ2J8ThV5u8tJrdoZrdQL6EH0z0Lj%2BQ%2F8a4bTbxXQPMGq%2Fl9r7mSs9jcUN3Cv2Zo%2B1xD4Sp%2FzZnaNYhtfNmgRaho7JcMwE1pKCASP246%2Fsn%2BZf58gsugWWtaPFp1xRL21qFkFCyP3U96YR%2BUfMt7%2BX%2BqvpmqEtpUsnGeOtQjE0FxD%2FwAzUxOy%2B5kHmGCOa1s7%2BVeEsFYpHI3SvwyBvDi647RtH1by3qEXmPT5VlgnWmo2C1Amj6rIrH4RMnVcCz3FvJ5x1pIqX2h30cVy3ouv2nQEeka9XZW5ZJNPult7dbZpTLasP9HlYUalP7uVf2JlH2v%2BEw891ZzY3tvqNtHdWz84pBUHoQe6sP2WX9rC7zJoEOu2Xp7LdRVa3lPY90b%2FACHwi0IahBqtdOo9hKf9LjY0Vf8ALU%2F78ybZFD591jS3R3gnRo5Ymp4MjA9snHkr8weRi0LzJII7pQEtdQc0SYdFWQ%2Fsy%2F5X7eH%2FAJw8uLqMDX9qg%2BtRL%2B8Uf7sQf8bLnJbuyjcNFKnND1U%2Fw8Dh5pfQo3Gc487eVFhMmq2KfuHNbmNR%2Fdsf92KP5G%2Fa%2FlyPeXPM%2Fmfy2Y4pmk1PRqfBBKpNwiDr6E3%2B7OH8j51%2B1ubXU7JLiKklvcJWjDqrDdWH%2FEsV5PntoFiuUuQOFxFvHKpKsPpWnLJZ5b8w65p1xEguXuIp3q8d07P1%2FZVm%2Bx%2Fkccbr%2Bhm2125sbPggX95AZq8FRhy3p%2FL8Srk181aDHqempqtvRLu2hDngPheMDmV%2F2P2ozjsrKLW5ju4Eni%2By4rQ9Qe4OL5D%2FACp5hgu7iOwkkUXFxD6yx9DWM8HNMmGJFFDRFRQioPUHIhrmgrAXubdK2z19WOleFepH%2BRkwymCkUIqD1BxBpWIaNq09o31WURrZoiem32ePEheCIB8VV%2BLJcGB3BBHtka1LQXVne0XnC9eUQ%2B0tevHxXA2lxazHfW620rx2atW4gkSqFOPCgdvjDClVwkA7hWYZswzZFXYnNBFPG0UyCSNvtKwqDimbFWE6voE1hIbu0Be3BrQVLIP8rxXJRo92b3T4Z2%2B1Ti3zG1cGkAih3B7ZSRpGvCNQqjsooN8NquzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxViPmbyo91cfpvQiINVT%2B%2Bh6RXSD9iXwl%2F33N%2FwWQzW9AXXo%2FXaFg7L%2B%2BhK0mjdBuafzACjrnYcDTWNrPKk8kYMsZDI42NR40w3tRW3z1p2l6ho%2BotLAfXVE5OgDVljA%2BLj%2FxZGv7OS2BbeaRbscpI5YuLQq3ETIfiQcv2ZVP90%2F8AsMk3mi1FjqBnt0CpcIHIUU%2BNT8RFP5tuWRDTFEulwPaP9YjVSfVjBIFGPM%2F7BvHCOSXqXlu6trnTI1t7Y2Zj%2BGW1YhmQ%2BJcfb5fzYcZBPKl1I7GRXHKGi3AY%2FajPRvdsnQNd8BFFDjnL%2FPWhJaXguIKRw33KngklPi%2F2Pxcs6jkY892Ul3onqwoZJLWRZeAHIlT8D7fJsAVBaLpUeueS9PtriYPcWykQXkfZ4yVDD%2FJP2WwX5X1NJ2NrQIGXkoXpzQ8JP65GPJfmOTR5G0zXLmGCzlYmzhZPSeE05ceP7UTjfliOhagkWs3CW0gkUXbPZjoZVkY8kQHr8OSHUJZD540vmYtVRBIAvoTo260JrGzU7cvhzaJ5jgm0t9O1u7giu%2FRdY%2BJ48oyCg%2Fd9QyfZ%2FwArJhPBFcwvbzqHikBV0PQg9sgt%2FwCSLpJy9pxniPRiQsgH8rfzYB5ql%2Fkq1hXU4ZigNwjsizftemU3Uf5Jzp%2BRXyloF%2Fpj3FzqYiR3YraxREsyx%2FzTOaL6j%2Fyp8CZKsSUOzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Hv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVg35iPrMEFld6XbR3CRM%2Fro1fUIIHwx%2Fs4U%2FlrqOkz3c1lYQmENFJI8DCgRzIDIg5b1JavTOiajZLf2cls1KsKofBh9k5ydpJPL%2FmzT9ZcBIWY2t5sFoD8Ls5C1%2FwCDkyQ5KyjWdLGi6ml3brSyvKxuo6I58P8AJPVclOiXZurPi5rLAfTf5fsn7sE3drBqFq9vLR4pV2I7dwy%2B%2BF2j6Xf2F5dS3EqNbyhViVa8iV%2Fbfag6%2FZXBdj3KnWURXLzYFYV5n8n3us6ut7btEITGsbc6hl418B8WFd75Ym8svHqVqPrQiCsJSPiikH2jQfsNnScayhwVYBlOxB3BGG1Sby7rf6YgZ5KCZftIBSmHeFllodlp95LeWqlDMKGIfYB7kDDPE%2BSuzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F%2F0u%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZFfM%2BipLW%2BSJZAf71CtaMPsygf8SyVZRAIIO4PbCDW6pP5YvDd6Wiu1Zbc%2Bi%2B9Tt9mv%2Bxw5xG3tbe1Vlt41jDHkwUUqfE4tgPNXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Pv%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV%2F%2FZ + ); + background-position:center center; + border:1px solid #00aa00; +} + +.yui-skin-sam .yui-h-slider { + background: url(bg-h.gif) no-repeat 5px 0; + height: 28px; + width: 228px; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css.min new file mode 100644 index 0000000..f57be99 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-noquotes.css.min @@ -0,0 +1 @@ +.yui3-skin-night .yui3-dial-ring-vml,.yui3-skin-night .yui3-dial-center-button-vml,.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-night v\:oval.yui3-dial-marker-max-min,.yui3-skin-night .yui3-dial-marker-vml,.yui3-skin-night .yui3-dial-handle-vml{background:0;opacity:1}div.base64-noquotes{width:100px;height:100px;background-image:url(data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAgEAZABkAAD%2F4RfJRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAAD0JAAAAnEAAPQkAAACcQQWRvYmUgUGhvdG9zaG9wIENTMiBNYWNpbnRvc2gAMjAwODowNzoxOSAxNDo1ODowNQAAA6ABAAMAAAAB%2F%2F8AAKACAAQAAAABAAABwqADAAQAAAABAAABRQAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABaTAAAAAAAAAEgAAAABAAAASAAAAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMR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0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZ%2F%2B01IlBob3Rvc2hvcCAzLjAAOEJJTQQlAAAAAAAQAAAAAAAAAAAAAAAAAAAAADhCSU0D6gAAAAAYEDw%2FeG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8%2BCjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk%2BCgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk%2BCgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q%2BCgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw%2BMTwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BUE1UaW9nYVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPm5hLWxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk%2BCgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw%2BCgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk%2BCgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk%2BCgkJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk%2BCgkJPGRpY3Q%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw%2BCgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BVVMgTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk%2BCgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJpbmc%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0Pgo4QklNA%2BkAAAAAAHgAAwAAAEgASAAAAAAC3gJA%2F%2B7%2F7gMGAlIDZwUoA%2FwAAgAAAEgASAAAAAAC2AIoAAEAAABkAAAAAQADAwMAAAABf%2F8AAQABAAAAAAAAAAAAAAAAaAgAGQGQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QklNA%2B0AAAAAABAAZAAAAAEAAQBkAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD%2BAAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAE4QklNA%2FUAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA%2FgAAAAAAHAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAAAD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FA%2BgAAAAA%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwPoAAAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1UAAAAGAAAAAAAAAAAAAAFFAAABwgAAABAAcwB3AGkAcwBzAF8AYQByAG0AeQBfAGsAbgBpAGYAZQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABwgAAAUUAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAUUAAAAAUmdodGxvbmcAAAHCAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAFFAAAAAFJnaHRsb25nAAABwgAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE%2F8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAThCSU0EDAAAAAAWrwAAAAEAAACgAAAAdAAAAeAAANmAAAAWkwAYAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1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U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZADhCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAIAAAABAQD%2F4TkjaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu%2B7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI%2FPgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEuMS0xMTIiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI%2BCiAgICAgICAgIDx4YXBNTTpEb2N1bWVudElEPnV1aWQ6RTcxOTVFNTY1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkRvY3VtZW50SUQ%2BCiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6RTcxOTVFNTc1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkluc3RhbmNlSUQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0ZURhdGU%2BMjAwOC0wNy0xOVQxNDo1Nzo0MS0wNTowMDwveGFwOkNyZWF0ZURhdGU%2BCiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTA3LTE5VDE0OjU4OjA1LTA1OjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpNZXRhZGF0YURhdGU%2BMjAwOC0wNy0xOVQxNDo1ODowNS0wNTowMDwveGFwOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1MyIE1hY2ludG9zaDwveGFwOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOkhpc3RvcnkvPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpOYXRpdmVEaWdlc3Q%2BMjU2LDI1NywyNTgsMjU5LDI2MiwyNzQsMjc3LDI4NCw1MzAsNTMxLDI4MiwyODMsMjk2LDMwMSwzMTgsMzE5LDUyOSw1MzIsMzA2LDI3MCwyNzEsMjcyLDMwNSwzMTUsMzM0MzI7QzA1QTE5MDRGRjAwQUJEQzA1MUJERkFGMDIwNEVBNTE8L3RpZmY6TmF0aXZlRGlnZXN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24%2BNDUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24%2BCiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U%2BLTE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtENDYzN0NCOUQ0MUExMEJBN0VGNUVCQ0RCNjMxODMyOTwvZXhpZjpOYXRpdmVEaWdlc3Q%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY%2BCjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8%2B%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQACAYGBgYGCAYGCAwIBwgMDgoICAoOEA0NDg0NEBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEJCAgJCgkLCQkLDgsNCw4RDg4ODhERDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgBRQHCAwEiAAIRAQMRAf%2FdAAQAHf%2FEAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4%2FPE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BCk5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0%2BPzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BDlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq%2Bv%2FaAAwDAQACEQMRAD8A7%2FmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmrlHI2utXn6WltnFESb0RFSp41WjD5q3LCBaslzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2E2rj0LuzvF7PxftUf8AXPLDnC3XI0ewdpOkTK4P08T%2FAMK2Ec1TLNgaxmE9pFIDy%2BEAn3GxwTgV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F%2F0e%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXYUeZpfR0a4kpUAx19h6i74b4X65CbjR76FV5FoJKKe5C1GIVLdDuGhuXs2IKOX4gfsvGdx%2FskKtkiyD6bctHHbXgPImOC4qOpXj6E1ff4Mm4Ndxkpc770BvNmzZFLs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Lv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVokKCT0G%2F3ZgaioNQemANZuhaWLyE0LlY1%2BbGn6sWspA8QA%2FZ%2FUcVRWbNmxV2bNmxV2bNmxV2NZQwKnodj9OOzYqwDT4iiPZsa%2FVLm5sj7I%2F76L%2BOTXTpjPZQSt9pkAb5r8JyKXqfUvMOpIQOFxFDfoP8qFvTl%2F4Q5INDkrFPAf8AdUhI%2FwBV%2FiH8cnLeAPcxHMprmzZsgydmzZsVdmzZsVdmzZsVdmzYyWRIo2kkYKiirMdgAMVX5sjTeaGl1CzsbSAOLuX0w7k14KCzyAD%2BUZJBirebNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F9Pv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVo4CXUFa9e0CbJRWkr%2B0RWlMHZEJ5WtPMtzE5%2BGYJKnyK0%2F4kuEC1ZeM2IW0okjFT8S7H%2BuL4FYz52mMWn2tDTlcpX6FbDHR5ecCH%2BZevywl%2FMM8dJtn7LdJ%2BKvgry9ccrOJ69KVw9E9GS5s2bAh2bNmxV2bNmxV2bNmxVi3miFU1LSbxvsStJYzH%2FJnSi%2F8ADYpoEzLcxq1T68FGr%2FvyE8GrgjzdC0mhXEsY%2Fe2pS5i%2F1omDf8RwttJRHdrcDaNbhZVI6endIG%2F4mcnHeJCDzDL82bNkEuzZs2KuzZs2KuzZs2KurkZ843Zhs4bVTQzvVqfyrvg3zHNPb2UMsLtGBPGJSpIqjEqRUb9ch%2BvSSvp0JlcvJCLyMuxJb4JNvi%2F1SuEBVvkaX9L%2BZbm8Sv1fTbf0Y6%2F78lPxH%2FgFzpeRvyPbWcXlyyubWBIXuoxJOUG7uKjk5%2FaOSSoxPNXZs2bArs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FU7%2FmzZsVQ2osyWM7o3FlQkMOxGPtZhPBHKCDyUE08e%2BM1Bedjcr4xPT%2FgThV5cvBJbpGergEfMDcYa2PkqfZs2bArs2bNirs2bNirs2bNirshfnRGtb7T9TX7LcoJD2qDzSv3vk0wl81WDajodzDGKzRj1oR35R%2FFT6RthHNXaVcrKsUtftDi304dZz7yrqPrQCIncdMnsEnqRK%2Fcjf54yVjP5gwtJ5ckcD%2B5mik%2BivH%2FAI3wD5RnEtpwrWgw983RGby1qiqKlYGkA%2F4x%2FvP%2BNchnke5BIUGoPQ%2FPEJHJ6XG3JFbxAOPxOA1iX7sUwIdmzZsVdmzZsVdmzZsVUbqBbq2mtm%2BzMjRn5MKZDLP4rC2UVq9qYj7SWshWn%2BtxOTnIVG4ttWvdNaiiK7FxGDtWG6Ti%2FwDwMuShzRLky%2B1lE9vFMP8AdiK33gYscKtBmDWhtq%2FHbOyMp68SeSH5UOGpyJ5pYde3moWPmW5KzH0pIo2WNt0A3Wv0ts2D73zJ6FgzxqqXpKpHG9eDMx7EYXed45VeC4gPCdYyqua0I5q5VgOv2cAW8sWo2QMqhwwoyHcVyQFhVOLzvrNrdf6fFHLFX4kVeBH%2Br1%2F4bJlp%2Bt2GqWrXFnICyKWeJtnUgV3XOP67qFjaFLHUrprecy%2BlZajxPDmN1jn8Dv8Aa%2By%2BIaXrclrdtZ34NrfR1USofgeo2K06c%2F8AgcBCXr%2FlvXRrdnzk4rcoSJFXYfMbnDzOV%2BTr82eqAOQIpaBq7AV2r%2BOdTriRSEp8z8RoN9I5AWJPV5HYD0yHr%2BGQg3Ntq1lcLazx3CiZviiYOKzQo9Kjb7YzoWqRevpt5AOskEij5lCOmc60%2BWCK0j9ONYo5IYp%2BEahQWBeNjRafEcMVTvTb%2B80fyHZ3FugE9vSORJBUqPVZW%2BEHw3yVaXeC%2FsobulGkX41HQMNmH%2FBZzC%2B1iTTbadZUkjtJjzkQqSKqNm5fsdMPfyr1%2FRdT8vra2E5N5C8kl3bSMTKpkctz%2BL7SP9peOA7fFkIkgkCwOfkz7NlA1y8DF2bNmxV2bEJLy1injtpJVWeavpREjk3Hc8V64virs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Xv%2BbNmxVplDqUbcMKH5HIPokjWsstqx%2BK2lZPf4Wpk5yF6nF9R8xswHGO8QSj%2FAFh8D%2Fqrkoc6VmSMHUOOjAEfTjsAaZMXhMRPxRnYf5J6YPyJV2bNmxV2bNmxVQuzOtu729PVUclBFa07U98DafqsF6i9EkI6ePywwyF6vG2i6oJRUWl6xZCP2JOrr%2FsvtLhG6s0yiK4X6Zfi4QI7Vb9lv5h%2FXDHrgV5c8B0LzLc2Q%2BGF29WDw4SfF%2Fwp%2BHOg6ZMHi4j2YfTkZ%2FMGwpFaazGDytm9GYj%2FAH25%2BEn%2FAFX%2FAOJ4N8uXwliicnps305LmFZDewrc2dxbt0lieNvkylc45%2BX10UCQzHjLATE4P%2BQeNc6L55e5i0J57WVonikRmZDSq7jf2yB2Op%2FVYor2%2FwBNjktpAGjv7ZvU%2BInoy8Vao%2Fa44xCQ9as25RVBqKnfBGRby9rBEsljcIY0aQ%2Bg5FCCQD6bj9lslGAikN5s2bArs2bGyOI0aRuiAsfoFcVS%2B%2F1q2sJltyrSytuyp%2ByDsC3zwxBqAfHfI%2Fodmt2z6pcjnJK5dAexPT%2FgRkhxV2c782mSy82WUgNIdUhNs4PTmlXQ%2FwDBDOiZAvzLb6nHpOrlFkjs7lWdG9yvxVG%2FwiuGJ3Up3YTJFr7op%2BC8t1ljHjxodv8AYtkiyHbxx6XfKx%2FcXBilJ3%2BAsVUV8FRlyYA4Z80DkkPmq3EtlHJSpR%2BJPgHBH66ZBtIufqt9Np8pALHnEpO5p1oM6Xq0P1jTriPoePIfNdxnLtZtrGZluBcG3vF%2BFJYuJfx40IIxHJKzzb5et9ZtZYp1LwygcgPtKy%2FZkT%2FKWuRKKCOC6tNH1CblcWiILDUWHH6wg6wyDejx9Fw4sfOMjEBY5biH1HgLy8VYulOfJV%2By38q4ndH9LlL219K4iilHrWzLxlhI6SgE1%2F2SnFKo0Czxy28zMqcSzspIYBPj2I%2F1cd%2FytnVZdNQ2D1I%2BESMoPw%2FzMftdMG20TSQyyblmjenzoc4TY6ld6ddyKwMUsbFZoHqNwd1KnGXRXs9n5%2Fv7lg98GlWhMjwk1A%2Fm4k%2FF7jDSwSPULTTJI3PGBphGNwG4OHVW%2BgnONX%2BsWFpDFPaSSJcTESG3TcRlf2uRK%2Fazq%2BkR3aeT7e%2BjnX6yoW8ibht%2B9i9Tg%2B%2FQ98QVZHqstutowuSPSdSpV91IPVWzif1i98t%2BZ7m40FjbSWUrNCqEmkex4EH7acT9lv2c6lonmbTvMUTWdwgiumWktrLQhge6H9of6uRLzd5ZurDVP8Q2KetYFUW7jXeSKi%2Bm0hH7UZH7X7OCY4g2YM0sMrjvexB5SHcXsnkPz3Y%2BcdPqKQ6lAB9bta%2F8lI69Y2%2F4XJeDXPJlvPe6JqMeq6NMYLuE842To6ntToyuv2k%2Faz0J5E8%2B2HnGyI2t9VgA%2Bt2ZP0epH%2FNEf%2BEyESeUuff3tmbFAx8bB9H8Uf4sZ8%2F6P82TMMLNb1iDRrQ3EpBkkPC3j7s5%2FwCNV%2B0%2BGVc4n5m8yfpnzJcsr%2F6HYsLe232PBv3j0%2Fy3%2BH%2FY5JxkLourX175%2Ftb28maSZrloqsdlQ1Tgo%2FZUDO755%2B8uxlvPcMI6i6LAe2zZ6BwlS7NmzYFdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVf%2FW7%2FmzZsVdkb83W5%2BrW1%2Bg%2BK1kAc%2F5D%2FCf%2BG45JMC6jare2FxaEf3qMo%2BdPh%2F4bCNiqV6VOOcTV%2BGReB37%2FaX9WHoyFaJMz23BqiWE7juCh%2FsyaRsHRXHRgCPpwy52gLs2bNkUuzZs2Kuwu1rS49W06Wzb4XI5Qv8Ayuu6nDHMemKvONE1KWGVrG7rHPCxRgeqsppk7sb0XC8W2lUbjxHiMhnnnTHtLmPXrZfgakd1TsR9iQ%2FP7LYtomq%2FWI0Iakybof4H55LmFZdqNlFqNjcWMwqk6FD8z9k%2FQc515XuZbW4l0%2B5%2BGWFzE6n%2BZTTOlW063EQkXY9GXwPhnO%2FNsS6T5qtbofBHqaniexmi%2B2v%2BsU4v%2FlfFgHcrPTFbanZNb3caywyApLE3Qj3zjutwW%2FljzBc6Pp6fV9JHpsLNSSgR1HIorV3Vvizq2jXQk%2BAndlBA9xnNvzRiWPzJBJWnr2gJP%2FGNyv8AHAdikJ3YGf0o5pZDIboSD1GJJ9aAgh6%2F5aUzoFnN9YtYZ6gmRFY06VI3zlXk%2FVI5bi2hnlBgdBuxFFahhfr0rSNsnHlXU4JI5NJaSt1avIQm%2B8RaquD0I%2BLjkpbgIZJmzZsirsDagC1jcqvUxOB%2FwJwTjXUMrK32WBB%2BWKpfofE6Xb8f5d%2FnhjkMPmvR%2FKlrJBqkxBSVkjC0PIDpTfI15s%2FMNbu3jbR5plsZVp69swRi9N0eSjMnH%2BRcVpm669cWWtXGnatwjgKma2uPsj0x%2FNXw%2FayOfmLr%2BhX3l%2BPTYrkXM%2BpGtm1uPUUceX7yRx8KLtx%2F1s5xoN%2FefpVr6C8muVVfUuLO8kMrEIeTem7faRk5Iy5FdTuZ9B169trGZvqkc5eFD8SmJzzUcTtsrceWHzTT3fRJv0p5UZvtOYYrgCu%2FJV4P%2FwANHnPrj83vM2lX9zpWoBJYInaJ540pOi1%2BGRQDxf4cln5Z3qT2stjWrK0iexEgE60%2F2XLOUfmHYNZeZbhWP94Ayn%2FV%2BD%2FjVclLlbEdQn955q1wTiU3huLadeQCsfSljO9VNev%2FAA0bYHub1Z7V5yWkhHxpcVHJNwGiuP8AKStVk%2FbyGafqLQxyafO5S2lPJWUAmGQ%2F7uiB8f8Ad0X%2B7F%2Fy8Ctd6jpl3Lb3v%2BkQTpxniqTDcQn7LoR%2FwUb%2FALDZCyyekWl9ZyaFLPelZGN2tqDEtZJHenEs67ckpVXwq1bU7G1iKWvqtcCR4bkkhFYx%2FCHXhvvX48C%2BU7H1SbK3k9Wya5hv4HchSBF8FxBL2WeOJ1k%2F4s9P4cu%2F0j%2Fc1FphmFxPLeOhZBxAiL8jt40%2Fa5YegV6PprvLpcE8sfpTNbh3QVoGK12zluoQ2PnZih42fmWIVt5z8Md4q9I5P5J17Z2A8YrWVl%2BERoaDwoNvupnLtb02LzREdR0hBba7bVe4tEPFZwpr6s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xKXcslu7tXb1%2BSBq%2FwCSzZK9c06xuNUutStkBls5IFkAIAMoHqUUfzNRkbCPW5Xs70rZcVtL0%2BtCoAFVc1oK%2FwArni2RIShdD0rU9Z0g2UNW1DR5JLG%2BirRlQuXhmp1ZP72M%2FwCph75g0K2sra21G8ch5baGJUpt6yARuvL6OWEQk1eJrq9s55YLxBzuGhJEjr3LKvxSqv7WISanq2oQRXGryvd2MtVhuSQ8aNQch8OyNjsqElhK1hbcr%2Fcv3K%2FyV%2FycRSQBmUiifsfQM6FpfljSbrR0mCy3EjDlDIzN9sGnphU%2FZ%2FlbIrqnl%2F6jM3Cb1VRqOoU8078XoOHPISIiQCd5ckgE3tyS4StK6xSy%2FDJ%2B7HqseO%2FYVw0W2thatp10he2b7YH21cfZljP86f8AD%2FYxO4tbO4so4I7ZUvG5Lpl3PssprUws392JD%2Fut%2FwCbAOh6sLuU6VqYMF4hKRu2x5DrFID0YY7rsh4tMn06%2FkspjzjniaS1nQfDIE%2BJWXwdafEv7Od0ugnmL8tmYipWEOB1oGWp%2FwCH5Zy4hoT9WuU5BTzj7FHp%2FeIe3%2BX%2FADrnR%2FysvRfaHeaJIwZ4RJGo8QDzQ%2F8AAy5OPVBfPNxbpMpifYqaBu4IwFYWlx9fEIJU7lmH7S%2F83ZJ9e0x7K9unRg8azMkoHWJySVR%2F9YH4W%2Bzj%2FKtvFdaxBDLQKzAVO243G%2F8ArYPJUXb2NvDZtdyWxe3B4meCQ%2BtG37Jkjb9lafaXHRXl9q2r6etnWJ7Yxx28h%2B1UNyMjt%2FlH4myX6lp1poPm57CIFLG8jikCsKisqqXWncc2%2BzhLZW0Om35hCuLiCeSgIHFY67KT9rl4YaV63IwMVSakg1pt27eGRuzvrTWILdYbnlcIWXSdQc8W5pXlp91%2FLIP91M%2F94mG9tcfW3AQ14xgsPH4c4Zp%2Btz6HqN2rJ61nNIy3loTTkA54yIf91zR%2FailyRNUinpV0iXqyyxw%2BjdW5Md%2FaN1iPdqf74f8A5Jtka1ZZ4LWYxsySKpaCRT8QI%2BIxkj2Hw5KLe6%2FTsUF%2Fp1wsmrRRk2l0QAL6Fft290g%2Fu7uP7Lo395hFquqaL9XZmmWCRwySWTgs8MgG6Oo%2FY5fZbAUhC%2BZ9JsfMl1SKYW%2BqyQRT2DMf3UvJeTwt4M5%2BJchKyrOr6D5gQwTQEpFK%2FwDeQv8Ayn%2BZDk%2B1Gyj1ew0SaC4gS5ntmCtX0ELQtQAM%2FEcv5Fwv1bQxr%2Bnhr4oms2ymP6xuCStSIbof6v8AdzYOaGAQ%2BXdTm1NdLjj5SN8QkG6FOvqBu%2BTjTrS2sbZLCMcVUmkpFGLn7Rf%2FAFv%2BFxTTme102DTuILIwZpKksW%2BzxWtW41%2FZyU2XlW41HhcahytOQJZVHKaXw%2Fd%2F7rY%2FzviAqQ21ldXtytrDG0k524qKmnj8sO736roNmNIltfVv7hFeaMnkUqTwpxNA2S2MaT5etS9w6WdtEvx1b42A7Symh%2F2C5zTzb%2BZun3swOjacGVKwrqMgoajeiJSr%2FOTDVdVZPYa3pOj%2BW7u31uKKzuZGP1dePP1Iz1UovxtJ%2FlYU%2Fl%2F5hOtyS%2BWrlis1Gm0pyfiR4%2Fi9Kv7SumcrvNYnu5DcXH7yToamrfSf6YL8ratLZ%2BZtJvoT6bwXMbEjuCwVh8uJauPFuFe%2Bx%2BYJ4NMawQiOFzyZOlDX4h%2FwQyQeVtAn1BY9R1QN9WU1toG%2Fa3qGYeGE3lnRLPVfM19LdAyWkTtcW8a7xOGaq1kGz7k%2FAM6moAACigA2AxJ7lojn72wANgKAbDLzZsirs2bNirs2bNirs2bNirs2bNir%2F9Hv%2BbNmxV2bNmxV2Qzz3p3P6rqKbFKwyt%2Fkn4lJPseWTPOVfnX5gmstNtdBtnMbajykuXHX0YyPh%2F2b%2FwDEcbrfm24MRzZI447GR59w6pMfNyWl7EdD1KM3Cp6dwoKldj%2B1zHE%2FRko0rz1rUtz9SvLe2lm2Hp8jC7BhWqV5xvUb%2FDnn01jPEin8pHgckemXmsTaHcxANw05o57O7IIKxliJYll%2FaRT%2B84%2FsNkIZhIkSjRDl6zs%2FwIjJCXFHkb5gp3%2Ba2r%2BbdPuEvYLVbLRpiFL27c2EvWkj0%2Fd8v2VpkGsfN2p3Kra3V2XicgEsQeQJ3qSNs7d%2BkdO1rSbKw1LhN%2BlbRXVJKFZyq8ZV3%2F3YGHLOEecvKFx5TvTLDym0idv3EvdG%2FwB9yf5a%2Fst%2B3lpHUOvsua4iNwbWCruHK%2FB0qN9j0zoy%2BarW48r2Oq3l1Le2sSizuGkqk6zgUVXMda8F%2FwCDTOO2M01rIs0XCRQ4kHqCqGnZl74NgkTlMqSOIZpPVNrXjGG8Qvfj2wXzSyqz1eO%2FtNSjQM8sVubhFbbkIpPiI%2BUR5Yca3q17IdPmtZ2js7yztriONNhyAKSciPtMJUfIZaXDWL%2Bra0jcq0ZYAV4yAq6mv8ynJf5Yex1PRjpUsfO%2F0pnuLJWNPUgkNZ4l%2Fm9Nh6vH%2BVpMRa2uvBcXej2Gp2rSC5tJJbOZkqW4v%2B%2FgY%2Bx%2FeJhtBB5sOi313boLa9ihMlo3EB5ClGkULy%2B16XJk4rhlZarBFAbZljtrS5Tg%2FoIF4fyOT1JjbC1L%2BbSbowyMwu4WrzJryX9h1PQpxw%2FFWFXNut9PB6srS6frlqI4JZHJ%2Br30bCsbOf5phx3%2FAN1T%2FwCRgPQbtreVrEFrW8gfnDU0dJUPF09unHD%2FAFeygjjvbi2haTQbpxcXlpHvLp9x9n6xClfjtjXi1P2P3b%2FGseE99ol9qtyjIKamYlktb6Mn0L5QKJ8Zp6d3x%2BH4vt8OD%2FvciTXPZaZ%2Bkdp5%2Bgt19Yad5p0%2Fe0vU2Y8T0NPiaM%2FtJ%2FuvOj6lcGysFaRlYxJWUjfkUXk3z5MM5p%2BV2l3U2pPdalFHK1sOLyqQxSZaFOdDWOT7W%2F7eTTzK8UdlcxREhXBTf%2BdzWg%2B7JxNji70HnTz%2B51GXyrrFxaapD69nfcRqSftqxHL1oj%2FOjPjtQ0GNYCfrCXWi3QMtlelhyjkYbFfdvsyx4M87Wy6zqemTq4X9KwQnmegkK%2Bmf%2BSi5G9M1PVfLUt3od3CJIGDEQS7iKUD4Zov8%2FjyErqrruPNkK58%2FJN7Sx0%2B0sDe3k0k9xA6JBJACGqwPHiKp8S8fts2F0mrDS3nubPThH6ZLa5YcQsnBvs3kSsCnJeXJuK%2FB%2FwAYmwQ%2FrXdjEsQRizhvjKCrUp8If4uW%2FwCyuK3Fs893p1nezfVdeDCOxmHFi8ZH%2B89wSeBjP2YuX%2BVFiYggA70Pmt9QzfyjdxXeiPeaY3rNYt9ZjdKUkgP2gyj7L8ftL%2FPgTz2tuLdJIT6cN1JFcxzJ2U7Sb%2Fs%2Fa5BsKfLEMvlPXby2sJI40uF%2F0izVuUcb05n0z3gkTlw%2F3237vHeddXN5pEMdnbmOys4BFcy0qDcF6GJa%2FwDFacmyX8Pu2R1QOi6Yupabd2F78dj6xjLVFUlpySaHwkUf7F0%2BDIrrvl6dr42N0eOtRIHs7ldkv4B9ijf8tKgfB%2FP%2FAHX28mPluyb0Vs7OdTL6SSReoK8%2FTZqN%2FrqOPL%2FJwTqdhFr9m1lqUhjnhcm2uv8AdltN%2FMKf7pb9tP8AZrjVhWHaHrEWqxjTb9gt9GKQytsXptxNf2sl35d3J0jznJbCojuQlR26cT%2Btc55qthdyXcyyJ9X8wWfx3ESbC6UbrcwfzS8fjfj%2FAHyfvPt88N%2FKuq3F3q1hqBIEyc4pWZuCkoAwck9MA50VPJV%2FMq2k0TznfCJQUmPJom%2BzJG%2FxcW9t%2FwDY4Q6cILa6ZY2eKRwslv6goaDfjy%2FaK4f%2FAJleadM80a8t1pcZ9GCJYmuG2MrD7TAfsqv2V%2Fmwr0WyuNXUw%2FVxci1%2BKLt%2Fw23wrg6qGVanr1vrK2t3csIry1aESBjxJEYYOQff4cjvm3zLbpZXLWTGC5vr%2FwCswRjfjBGoC8yfi%2BIjCPX2vNMu%2FqZDRNGKSAgUqxqgqKruF%2BH4sjsyPPIZZSXJ7knfG1e9%2Flxrdt5ksbqdSFu7eMLcW5O4%2BE0cV6xvnF75uVzcb14yyBW7%2FaO2KeS9RutC8yWd7DMYLfn6d3L%2Bx6D7SLJ7YhdkNd3UkRDRSXErxMDUFGclT9IwndCtpWrz6ZN8MskcDsGdojxkjcfZmip%2B2v8AL%2B3iWoySfXbiHUmFy14frKXqH4nL14zK%2FVuX7cbYEeJWDPQVpU0Pj0x6yqLL0pJUW4tXE1o5O9SaSRbeP28Cob1Z1T6vPKzxjeNSSQK9aV%2BznXLfUrdtDt9T1U%2BjeRxpa3iMvF5V41jcg%2Ftrx%2BLOd6VbaTqJlS7lMl5Iri3hHwRiQj920snhzODppWsii6zcGeSZg3po3NSy%2FD%2Fen4K9V542r0LyheaXcm5uaCCWNhxkl%2FvClOqcvs4rrn5g2enI9tpKi4uqlWck0rSvxP8Atf7HITazpc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2FLhpr3nLTKJ9UT19TB4zNHtCe3Jj3b2XIssp1Y8bUfFOQsix7SCSlAXpTmj4av5OnsdM%2BuzB3Zm9OWaNGD2%2FMgRTolP3sXP4Zv92fyYi6oITDVrG28x6NBeBvqWoWS1ivSeIikU8jFI%2BzLA6%2FGn%2B%2B3yFaq1pcXix28ZUGi3U2wadx%2FuziAEWv8Aq%2FH9vDLV7TzXeWrqbaWO4VhHeNHtFdCP7EhX5D4v9%2BfbwpC3liGgvIoVdSqt6pLPGr0pTj%2Bz8Xw4CUkEGil7RwRu9ZzwjPx8UZiKePShyb%2BRfMdhHM2kLEV%2BsDlDLQFncUCxcRX7WEF1DCs63zCs6r6c1Nkencr7rgXSpFsb5zCForepC9PiUEfZr4DADRVD%2BddUkPmPU4lUgVNtNG4qDw2Bof2kP2GyK1LECpY%2BAqTnUFhsta1Ce%2B1G3inuZCrySsgqwqFNRkwu9R8m%2BWIwscEHrharDBGjSH5tT4f9kcIoop4da6Vqt2GW0tbiQHbikbkH57UwHNFLbSvb3CNFLExSSJxxKsuzKwPQjOu3%2Fmq%2B1mFo1C2NmFMjhTQLGu%2FKRtumQfU%2FMWh3uoTXx0r1pJePKSWSnJlVU5lQNufHnhQxmOYxklSPiFCDvUZQKUIpUn7Jr0%2B7D8eYrBP7nRbUf61W%2FhmPmtkBFvptnEezCMkj78CpRZOY5w%2FBmWhBCjseuSyyn0pIpIr2CSr2gtbYTQt6aylufPp8PBWbCZPNurROskYgVkYOv7tSAVNRtg2780%2BYPNd5CdWuRJHEWkWONFjRaih%2BFAPljsqLeRrVh%2BjQt3GBRoXBBKAfFwag%2BLJ15B17yfealE2taTHcXMG63Eq%2FvbYL%2FvyH%2B6eFK%2F3iJyT9vAXkPygPNEuoxx3KQ3VrAHtYWP8AeOxpv%2FxWqijMv2WZMLdS8vBLx4pg9jqVqTFJIvwup6fvP5lP%2FDLillv5i%2BStPtL867pEEcem6hxkivLWjIk%2FevHb05ftZF9Okd5Et5mayvoWEtrdRmnCUfYmhYfzftp%2B3k3%2FAC68zLfx%2FwCFdWt1eElrbUoW%2BwGIrDPGv7CyU%2BLj%2B18eIeavKM3lq7WqfWNOkYizuXFeNesE9P8AiX7WNbqCncfm2f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V1PpOsrBduRLFcPb3JY9VditW%2F2XxZ0%2B91O2spIoJWL3E54wW0Y5SOf9UdF%2Fmdvhzm%2Fm2w%2BoeapJlBVdRjWdCDsZE2cfeuHdvfQW0BngZptVvEH1u%2FlG6gj%2B5hH7Kr0xHc0pD%2BYg8wa1NDFZWjSWtsrCRoiGJcn46b1YdF2yFWemzxsW1CN4Ej%2FZlUofubOs2WpxpNGl2oMP2eSbEe5yTXGkadqFpJaT26T2860YEVBB6EHx8MeCzdpunlEtpHYQ38GqRrFNaPA8EgJcFa%2FGqhadao2XBGlmbe2uCzevbGeRo2PcNJx%2F2S%2FDht51s3sLpYLoH6ncIq21wRU1UceLt9Hxf8Hhj5f8pXerWc%2Bq2VrHqE1oqQWdvNLwUoijmJB%2FO9W4%2Fs8cjVH3LezEvM2mXWqyabNozB7SS1WJ5SwBrHWnLv8A3ZUbfy4onlazmtrKC%2BJlNoHFFNFbmQaHvtTJ9rPlzU7GOO6vrRbeNioQQMrRxmn938IXj4YE0fQLnXBdQ2062l1CP3SSry9Xav7og0%2F4LDsikps7C3s1WK2iWJB%2Bygpg5lNOX0YAVr7TL0xXsxcxsVlhktwpFPtLVWwbf%2Ban0e8tp7LTYrmyILlpyT6hoRw2%2Fu%2FTbdlw3taoK4v7a1dY2dW5GjQ1qVHj%2FwA24Vah5a03VlNxZEQTtvyX7LH%2FAClyfjyfo3nrTrbV9PRNI1i6gM8qRENC8gb05OUI%2BNR6nR1%2F4HIRqOj655Vu%2FQ1SBogT%2B7mU1ikA7pJ0%2FwBi3xZGwdizhOeOXFCRBSPSZNX8maml1MhNsfgldPijdD1H%2BS37S8s6ZLrEEZt2uEe1W6VWtLsg%2BlKGHIGOReS%2F6wOR9dWtRp11dSQ%2FWHt4Wk%2Br93IGyU%2Fysk%2Fk%2FW5INATT9Z0eAWczGT6gr%2BoIlfcgBxsf2vT%2FAGMYxMSeE2D07m7PqBmjEzjWSO3EOUo%2BY72M%2BYfLcd3FJeQRxyo7EzQU792GQ60bU9Hkf9HTAwts1jdVeNl%2FyX%2B2n%2FEc7ZL5XstVSS58p6kYZqVbTrysif6tWPrRr%2FspVzmuvaDq2jzsup2JtA5NCfjtmNf91Tjb%2FYyccJ8tmgJPqV4JJLJpI3sYLq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FFMx2imJJSvhHLXj%2Fr4N%2FO9G%2FwAJ28o%2FYvY69%2BqOMgdlYzqPmWy8xr615aouoxAA3dk4dJB0%2FfRGjofBl54U%2BnCySRNSa1l%2B2vQq3861%2By65GPKcztqxjY7NEw4jYbU32zoNppF1qfrw2JX6yierHExoJivWIf5fH7DYYnZaY3pN9N5N1n9JJEbuIwyRoisY1kDbpVu3F%2FidM7xpl3Y%2BadFt7m5tle3vIUkaCYBx8Qowof5WB%2BPONG0jvLY28qlRUgqwoyOOu37LpiXl3XbjyZqk7XglmtZIfTEKNQGh5REFvsxr8XLjgIrdWQedvy7GiQPrfl4SNaxVe5s1q7Rp3ki%2FaaNf20%2B1kT07WGCqwcMjdJFNQc9C2N9BqNvHc29WiljSVGI2KyCopkFv%2FwAotHu9cOq2d1JYW0x53dhAo4O53JQt8MYf9ocMFyB23ZwGOQIkeCQGxqwfIsatNQSQrIrmOUbrIhoQfEEb5LLHzPP6X1TV4RqFo4ozFVL0%2FwApD8EmFms%2FlxeWBNxoEpuIhubSQj1B%2FqPsHwo0%2B4ltUmW7Ro5ojRo3BVhT2OWCi1t%2BbPJ1pFCfMXlJgtl%2Fx92VCyRHuwjb4kX%2Bdf2ciOlG2huhcX2n8JI2BE8FHHzMTb%2F8TVc6FpWutaySPblJEmHGeCQVVwP1ZGtcsIbe5N3p0Ui2MlWaM7mB%2FwBpQ4%2B1F%2FLkTGulhnDIYnYprf6tYaxaxxCDlxIaG7iko8Z7kGtWr%2B3ywxsdGl1WwitzGbkgkRzugDGnRm34R0%2FZbIJBZwxv9YhAVx8Qp0JPiBnafJl1eXekLNdyrKOXGNgADQD4g3Gg%2BE7Y8WyTLfiHNJbbQvNHle%2Fe50eQX%2BnXAD3Vg53EoWnKImhQmn7Pwv8AyYRX9xql1dmXWOS3XHiqMnp0QEkKq%2BA5fazrQwHqOmWmqQGC7j5D9lxsynxVsFsLeO39hb39tJbXMYlhlHGSNuhB%2FUffOZXy3%2Fl7UV05n5MgrpN1LTjLCT8VncEj%2FYf5Odt1nQbzR3JcerasfgnA2%2BT%2FAMrYB%2F5V3Y%2BdtAvhefubrn%2FuNux1jkQUYkD7Ubnir%2F6uEq8D1rTFk9XUdNgaHix%2Bu2XVoHPcD%2FfbfstnQfyAeb%2FFktC%2FptaSF1VgFNGTiXFfiA%2BLj%2FlZC9WuNd8p6kNM1e04anYsY2mY7TW%2FZG2pKjfsS4K003mkCHzl5WmDLazercWoB9WCvX1FB%2FeQt9lv8nIofYNRl5FPI3njTfO2li7taRXkQUXlp3Rj0Zf5on%2FYbJXirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FW7%2FmzZsVdmzZsVdmzZsVdgHVY9PmtHi1JlW3cgEuQBUbr1wdgPUdNttTtzb3IJWoZSOoYdxirzHztP%2Bi20aTyvdm6uDcJSCMJIPTVhRWKj7Bbbi2B9b8keZrnV3FvberbsQsVwHUKFJ6tU8hSvhk%2B%2FwAPGy1GwvLOkqK5ju0cIP3YQ%2BnItAPiif8A4nkkphKQaQOk6eml6ba6fGQVt4whPif2j%2FwWO1LTbPVrGfTr%2BITWtyhSWMjqD%2FEfs4MzEVwIsg2Ni%2BVPOHlm58p65NpU1XhP72znP%2B7IWPwn%2FXX7En%2BVgW28s63f2kWr29m76Ys6xyXQpxUggNUfa4iv2uOen9c8t6J5it0t9as0uo4zyjLVDKf8l1oy5EL7TriGW30Lytp7Q6Dbs0d7xI4Oz%2FFWPlycmNvib%2BfKziufETs7WXahOn8Ph9dVIn6a7%2FewDzPd3ukNplzYtxtEhW2adVBKzRktTkalOdf%2BBw60bydZ%2BaNR%2FwARaPq0VjOIw509bcLIkw%2B16yh%2FjRm%2F3an28de6dLYTXGk6xDztpx8aHoyn7Lqfb9nI3YX%2BreQ9ThS3pcWhcvazMBWSE%2FbgaQ%2FF8P8AJlrrDvunvmryB9buFvzAtnrkQD84z%2B6mKHkGRtu%2F82HWnO%2BoadLpU5aC4ZeUL9Gil%2B0jKR0aOYZOLO80jzho0d3Zv6kMn2WFPUhlGxVh%2By6H7WQWaO80rV1hvwBMjcfUAoskTbLIP%2BNsIr5oSu10tfOt7Ikt4th5ijQC6hkSsdz6fwfWIiCCr7UmTj%2Fl5JG%2FKTSdTjg%2FxDILh4UCUgHD7P8Axafj45GPMdkYtRkvbWf6jewEXNhcr9ppT9pEVatJWnxJx%2BznRPIfmz%2FFujfW5Y%2FSvLZ%2Fq94gBCmQCvNQfiVX%2B1xb7OA2NleaX%2Fkr%2FA19Jb2rO%2BlXbc7UvuFbuvL%2Bb%2FiWC7M7HOuarpdrq9jLY3i8o5Bse6t2df8AKXOP6jbaj5dvpLK5USBd0fcB07Ov8cMT3qkP5l6trkWp2kNi8sVr6CShoyVDyH7RJHXj8OQpfNfmCN1%2BsXcsnBeCrOfUAUdFHP4uP052ny%2Fq2g6veR6T5hgX94Almsp%2Fdsw%2F3W%2F%2BU37GSHUfyp8n6hUpavZse8DkD%2FgH5p%2BGCXNeTwM%2BbzeWxtr%2B3SVHFGMZKMP8oBqr%2FwANh9qv5gpr3kVfLV9zk1O3uIjFOwrzt4w1GZhUeqn2P8rJD5i%2FJJrK2lvNKufrSx%2FEYCnCXiOtCpKPx%2F1M503lq7tpDxDNUUUGlPwyJtWQflfpMWseaFtLgssZtZnDJ1VhxCn3651e38qanp%2Bs2ZX95brKG%2BtR7UVfio6%2Fs16YS%2Fk3pGmWxvNR%2BspJqfEW7WnR4kryLFW3PqN%2FL%2FLnW8I2UsW8x%2BVo71n1LT0CXp3mjGwlp3%2F4yD%2Fhsgl9oyXUaxX1u8LoCY2dStV%2FaG%2Fgc7JTEbiztrr0zcRrIYmDxlhWjDJCXQoeVeW9Rv8Ay1PKL25kuNO9ELEo%2BIjgaoKk%2FAqJyzqtrdQXkCXNs3qQyqGjcdCCK7ZFPMPl1Yg95aLWA7zQjfjXqw%2FycB6JrNzY3BW7uAbARKgUqSQVIC8KfCq8K8vhxq9wlntK4DvtJ07UgBfW6TU6FhvTwqN8FRyRyoHiYOjCoZTUEHH5FDC9Y%2FL6wuSZ9Ic2M3X0tzEfo6p%2FscL9B%2FLy8XVJNS8y3Yuo41aKz0%2BEkQrGwoWlO3N2zomVTDZV4l5n8s3Plq94oS%2BnTk%2FVZj27%2Bk5%2FnX%2FhsMNI893Wj2ht2thNVSEp8PGSlBK%2F%2BSf286nqOnWmqWcllexiSGQbg9QezKf2WGco13yhdaVMUT95A39zL0DDwPg%2BIZc3pPlzU5dStGa4IaeNgGZaAFWHJWoMOc5v5E1B7Wf6tcAoD%2B5PLb3jP0fYzo4xIYrZIo5UaOVQ6MKMrCoIPtidrZ29lAttaoI4UrxQdBU1OL5sCsO8%2FwD5e6V5708RXNINQgB%2Bp3oFStf2JAKc4m%2F4XOIWX5R%2FmVoOpummwIySAxNMssZhZG2q3Mqen80eeoKZqYq8l8h%2Fk%2FceW9Qt9Z1DU3W4gPJLS0JCEGvwTytT1U3%2Bx6arnWs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F1%2B%2F5s2bFXZs2bFXZs2bFXZs2bFXUzZs2KuzZs2KoXUjILG49E0k4EKetK43TYkhsoQp5EqGZvEnvgp1DKVbdW2I9jhDdaDqT%2FuLLWJbOzP8AulEVnAPVVkb4hiqB8wWUXmS%2BXTYWQi3ikZphuUlqOKmn7P8ANnOtRsiPW0TWUKqD9ofajYfZkQ%2B3%2FDLnYtH0Wy0W3aC0BJc8pJHPJ2J8ThV5u8tJrdoZrdQL6EH0z0Lj%2BQ%2F8a4bTbxXQPMGq%2Fl9r7mSs9jcUN3Cv2Zo%2B1xD4Sp%2FzZnaNYhtfNmgRaho7JcMwE1pKCASP246%2Fsn%2BZf58gsugWWtaPFp1xRL21qFkFCyP3U96YR%2BUfMt7%2BX%2BqvpmqEtpUsnGeOtQjE0FxD%2FwAzUxOy%2B5kHmGCOa1s7%2BVeEsFYpHI3SvwyBvDi647RtH1by3qEXmPT5VlgnWmo2C1Amj6rIrH4RMnVcCz3FvJ5x1pIqX2h30cVy3ouv2nQEeka9XZW5ZJNPult7dbZpTLasP9HlYUalP7uVf2JlH2v%2BEw891ZzY3tvqNtHdWz84pBUHoQe6sP2WX9rC7zJoEOu2Xp7LdRVa3lPY90b%2FACHwi0IahBqtdOo9hKf9LjY0Vf8ALU%2F78ybZFD591jS3R3gnRo5Ymp4MjA9snHkr8weRi0LzJII7pQEtdQc0SYdFWQ%2Fsy%2F5X7eH%2FAJw8uLqMDX9qg%2BtRL%2B8Uf7sQf8bLnJbuyjcNFKnND1U%2Fw8Dh5pfQo3Gc487eVFhMmq2KfuHNbmNR%2Fdsf92KP5G%2Fa%2FlyPeXPM%2Fmfy2Y4pmk1PRqfBBKpNwiDr6E3%2B7OH8j51%2B1ubXU7JLiKklvcJWjDqrDdWH%2FEsV5PntoFiuUuQOFxFvHKpKsPpWnLJZ5b8w65p1xEguXuIp3q8d07P1%2FZVm%2Bx%2Fkccbr%2Bhm2125sbPggX95AZq8FRhy3p%2FL8Srk181aDHqempqtvRLu2hDngPheMDmV%2F2P2ozjsrKLW5ju4Eni%2By4rQ9Qe4OL5D%2FACp5hgu7iOwkkUXFxD6yx9DWM8HNMmGJFFDRFRQioPUHIhrmgrAXubdK2z19WOleFepH%2BRkwymCkUIqD1BxBpWIaNq09o31WURrZoiem32ePEheCIB8VV%2BLJcGB3BBHtka1LQXVne0XnC9eUQ%2B0tevHxXA2lxazHfW620rx2atW4gkSqFOPCgdvjDClVwkA7hWYZswzZFXYnNBFPG0UyCSNvtKwqDimbFWE6voE1hIbu0Be3BrQVLIP8rxXJRo92b3T4Z2%2B1Ti3zG1cGkAih3B7ZSRpGvCNQqjsooN8NquzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxViPmbyo91cfpvQiINVT%2B%2Bh6RXSD9iXwl%2F33N%2FwWQzW9AXXo%2FXaFg7L%2B%2BhK0mjdBuafzACjrnYcDTWNrPKk8kYMsZDI42NR40w3tRW3z1p2l6ho%2BotLAfXVE5OgDVljA%2BLj%2FxZGv7OS2BbeaRbscpI5YuLQq3ETIfiQcv2ZVP90%2F8AsMk3mi1FjqBnt0CpcIHIUU%2BNT8RFP5tuWRDTFEulwPaP9YjVSfVjBIFGPM%2F7BvHCOSXqXlu6trnTI1t7Y2Zj%2BGW1YhmQ%2BJcfb5fzYcZBPKl1I7GRXHKGi3AY%2FajPRvdsnQNd8BFFDjnL%2FPWhJaXguIKRw33KngklPi%2F2Pxcs6jkY892Ul3onqwoZJLWRZeAHIlT8D7fJsAVBaLpUeueS9PtriYPcWykQXkfZ4yVDD%2FJP2WwX5X1NJ2NrQIGXkoXpzQ8JP65GPJfmOTR5G0zXLmGCzlYmzhZPSeE05ceP7UTjfliOhagkWs3CW0gkUXbPZjoZVkY8kQHr8OSHUJZD540vmYtVRBIAvoTo260JrGzU7cvhzaJ5jgm0t9O1u7giu%2FRdY%2BJ48oyCg%2Fd9QyfZ%2FwArJhPBFcwvbzqHikBV0PQg9sgt%2FwCSLpJy9pxniPRiQsgH8rfzYB5ql%2Fkq1hXU4ZigNwjsizftemU3Uf5Jzp%2BRXyloF%2Fpj3FzqYiR3YraxREsyx%2FzTOaL6j%2Fyp8CZKsSUOzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Hv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVg35iPrMEFld6XbR3CRM%2Fro1fUIIHwx%2Fs4U%2FlrqOkz3c1lYQmENFJI8DCgRzIDIg5b1JavTOiajZLf2cls1KsKofBh9k5ydpJPL%2FmzT9ZcBIWY2t5sFoD8Ls5C1%2FwCDkyQ5KyjWdLGi6ml3brSyvKxuo6I58P8AJPVclOiXZurPi5rLAfTf5fsn7sE3drBqFq9vLR4pV2I7dwy%2B%2BF2j6Xf2F5dS3EqNbyhViVa8iV%2Fbfag6%2FZXBdj3KnWURXLzYFYV5n8n3us6ut7btEITGsbc6hl418B8WFd75Ym8svHqVqPrQiCsJSPiikH2jQfsNnScayhwVYBlOxB3BGG1Sby7rf6YgZ5KCZftIBSmHeFllodlp95LeWqlDMKGIfYB7kDDPE%2BSuzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F%2F0u%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZFfM%2BipLW%2BSJZAf71CtaMPsygf8SyVZRAIIO4PbCDW6pP5YvDd6Wiu1Zbc%2Bi%2B9Tt9mv%2Bxw5xG3tbe1Vlt41jDHkwUUqfE4tgPNXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Pv%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV%2F%2FZ);background-position:center center;border:1px solid #0a0}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css new file mode 100644 index 0000000..1ec9f67 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css @@ -0,0 +1,23 @@ +.yui3-skin-night .yui3-dial-ring-vml, +.yui3-skin-night .yui3-dial-center-button-vml, +.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night .yui3-dial-marker-vml, +.yui3-skin-night .yui3-dial-handle-vml { + background: none; + opacity:1; +} + +div.base64-singlequotes { + width:100px; + height:100px; + background-image:url('data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAgEAZABkAAD%2F4RfJRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAAD0JAAAAnEAAPQkAAACcQQWRvYmUgUGhvdG9zaG9wIENTMiBNYWNpbnRvc2gAMjAwODowNzoxOSAxNDo1ODowNQAAA6ABAAMAAAAB%2F%2F8AAKACAAQAAAABAAABwqADAAQAAAABAAABRQAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABaTAAAAAAAAAEgAAAABAAAASAAAAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMR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0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZ%2F%2B01IlBob3Rvc2hvcCAzLjAAOEJJTQQlAAAAAAAQAAAAAAAAAAAAAAAAAAAAADhCSU0D6gAAAAAYEDw%2FeG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8%2BCjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk%2BCgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk%2BCgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q%2BCgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw%2BMTwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BUE1UaW9nYVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPm5hLWxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk%2BCgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw%2BCgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk%2BCgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk%2BCgkJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk%2BCgkJPGRpY3Q%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw%2BCgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BVVMgTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk%2BCgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJpbmc%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0Pgo4QklNA%2BkAAAAAAHgAAwAAAEgASAAAAAAC3gJA%2F%2B7%2F7gMGAlIDZwUoA%2FwAAgAAAEgASAAAAAAC2AIoAAEAAABkAAAAAQADAwMAAAABf%2F8AAQABAAAAAAAAAAAAAAAAaAgAGQGQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QklNA%2B0AAAAAABAAZAAAAAEAAQBkAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD%2BAAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAE4QklNA%2FUAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA%2FgAAAAAAHAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAAAD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FA%2BgAAAAA%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwPoAAAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1UAAAAGAAAAAAAAAAAAAAFFAAABwgAAABAAcwB3AGkAcwBzAF8AYQByAG0AeQBfAGsAbgBpAGYAZQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABwgAAAUUAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAUUAAAAAUmdodGxvbmcAAAHCAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAFFAAAAAFJnaHRsb25nAAABwgAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE%2F8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAThCSU0EDAAAAAAWrwAAAAEAAACgAAAAdAAAAeAAANmAAAAWkwAYAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1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U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZADhCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAIAAAABAQD%2F4TkjaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu%2B7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI%2FPgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEuMS0xMTIiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI%2BCiAgICAgICAgIDx4YXBNTTpEb2N1bWVudElEPnV1aWQ6RTcxOTVFNTY1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkRvY3VtZW50SUQ%2BCiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6RTcxOTVFNTc1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkluc3RhbmNlSUQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0ZURhdGU%2BMjAwOC0wNy0xOVQxNDo1Nzo0MS0wNTowMDwveGFwOkNyZWF0ZURhdGU%2BCiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTA3LTE5VDE0OjU4OjA1LTA1OjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpNZXRhZGF0YURhdGU%2BMjAwOC0wNy0xOVQxNDo1ODowNS0wNTowMDwveGFwOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1MyIE1hY2ludG9zaDwveGFwOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOkhpc3RvcnkvPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpOYXRpdmVEaWdlc3Q%2BMjU2LDI1NywyNTgsMjU5LDI2MiwyNzQsMjc3LDI4NCw1MzAsNTMxLDI4MiwyODMsMjk2LDMwMSwzMTgsMzE5LDUyOSw1MzIsMzA2LDI3MCwyNzEsMjcyLDMwNSwzMTUsMzM0MzI7QzA1QTE5MDRGRjAwQUJEQzA1MUJERkFGMDIwNEVBNTE8L3RpZmY6TmF0aXZlRGlnZXN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24%2BNDUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24%2BCiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U%2BLTE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtENDYzN0NCOUQ0MUExMEJBN0VGNUVCQ0RCNjMxODMyOTwvZXhpZjpOYXRpdmVEaWdlc3Q%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY%2BCjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8%2B%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQACAYGBgYGCAYGCAwIBwgMDgoICAoOEA0NDg0NEBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEJCAgJCgkLCQkLDgsNCw4RDg4ODhERDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgBRQHCAwEiAAIRAQMRAf%2FdAAQAHf%2FEAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4%2FPE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BCk5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0%2BPzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BDlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq%2Bv%2FaAAwDAQACEQMRAD8A7%2FmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmrlHI2utXn6WltnFESb0RFSp41WjD5q3LCBaslzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2E2rj0LuzvF7PxftUf8AXPLDnC3XI0ewdpOkTK4P08T%2FAMK2Ec1TLNgaxmE9pFIDy%2BEAn3GxwTgV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F%2F0e%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXYUeZpfR0a4kpUAx19h6i74b4X65CbjR76FV5FoJKKe5C1GIVLdDuGhuXs2IKOX4gfsvGdx%2FskKtkiyD6bctHHbXgPImOC4qOpXj6E1ff4Mm4Ndxkpc770BvNmzZFLs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Lv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVokKCT0G%2F3ZgaioNQemANZuhaWLyE0LlY1%2BbGn6sWspA8QA%2FZ%2FUcVRWbNmxV2bNmxV2bNmxV2NZQwKnodj9OOzYqwDT4iiPZsa%2FVLm5sj7I%2F76L%2BOTXTpjPZQSt9pkAb5r8JyKXqfUvMOpIQOFxFDfoP8qFvTl%2F4Q5INDkrFPAf8AdUhI%2FwBV%2FiH8cnLeAPcxHMprmzZsgydmzZsVdmzZsVdmzZsVdmzYyWRIo2kkYKiirMdgAMVX5sjTeaGl1CzsbSAOLuX0w7k14KCzyAD%2BUZJBirebNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F9Pv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVo4CXUFa9e0CbJRWkr%2B0RWlMHZEJ5WtPMtzE5%2BGYJKnyK0%2F4kuEC1ZeM2IW0okjFT8S7H%2BuL4FYz52mMWn2tDTlcpX6FbDHR5ecCH%2BZevywl%2FMM8dJtn7LdJ%2BKvgry9ccrOJ69KVw9E9GS5s2bAh2bNmxV2bNmxV2bNmxVi3miFU1LSbxvsStJYzH%2FJnSi%2F8ADYpoEzLcxq1T68FGr%2FvyE8GrgjzdC0mhXEsY%2Fe2pS5i%2F1omDf8RwttJRHdrcDaNbhZVI6endIG%2F4mcnHeJCDzDL82bNkEuzZs2KuzZs2KuzZs2KurkZ843Zhs4bVTQzvVqfyrvg3zHNPb2UMsLtGBPGJSpIqjEqRUb9ch%2BvSSvp0JlcvJCLyMuxJb4JNvi%2F1SuEBVvkaX9L%2BZbm8Sv1fTbf0Y6%2F78lPxH%2FgFzpeRvyPbWcXlyyubWBIXuoxJOUG7uKjk5%2FaOSSoxPNXZs2bArs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FU7%2FmzZsVQ2osyWM7o3FlQkMOxGPtZhPBHKCDyUE08e%2BM1Bedjcr4xPT%2FgThV5cvBJbpGergEfMDcYa2PkqfZs2bArs2bNirs2bNirs2bNirshfnRGtb7T9TX7LcoJD2qDzSv3vk0wl81WDajodzDGKzRj1oR35R%2FFT6RthHNXaVcrKsUtftDi304dZz7yrqPrQCIncdMnsEnqRK%2Fcjf54yVjP5gwtJ5ckcD%2B5mik%2BivH%2FAI3wD5RnEtpwrWgw983RGby1qiqKlYGkA%2F4x%2FvP%2BNchnke5BIUGoPQ%2FPEJHJ6XG3JFbxAOPxOA1iX7sUwIdmzZsVdmzZsVdmzZsVUbqBbq2mtm%2BzMjRn5MKZDLP4rC2UVq9qYj7SWshWn%2BtxOTnIVG4ttWvdNaiiK7FxGDtWG6Ti%2FwDwMuShzRLky%2B1lE9vFMP8AdiK33gYscKtBmDWhtq%2FHbOyMp68SeSH5UOGpyJ5pYde3moWPmW5KzH0pIo2WNt0A3Wv0ts2D73zJ6FgzxqqXpKpHG9eDMx7EYXed45VeC4gPCdYyqua0I5q5VgOv2cAW8sWo2QMqhwwoyHcVyQFhVOLzvrNrdf6fFHLFX4kVeBH%2Br1%2F4bJlp%2Bt2GqWrXFnICyKWeJtnUgV3XOP67qFjaFLHUrprecy%2BlZajxPDmN1jn8Dv8Aa%2By%2BIaXrclrdtZ34NrfR1USofgeo2K06c%2F8AgcBCXr%2FlvXRrdnzk4rcoSJFXYfMbnDzOV%2BTr82eqAOQIpaBq7AV2r%2BOdTriRSEp8z8RoN9I5AWJPV5HYD0yHr%2BGQg3Ntq1lcLazx3CiZviiYOKzQo9Kjb7YzoWqRevpt5AOskEij5lCOmc60%2BWCK0j9ONYo5IYp%2BEahQWBeNjRafEcMVTvTb%2B80fyHZ3FugE9vSORJBUqPVZW%2BEHw3yVaXeC%2FsobulGkX41HQMNmH%2FBZzC%2B1iTTbadZUkjtJjzkQqSKqNm5fsdMPfyr1%2FRdT8vra2E5N5C8kl3bSMTKpkctz%2BL7SP9peOA7fFkIkgkCwOfkz7NlA1y8DF2bNmxV2bEJLy1injtpJVWeavpREjk3Hc8V64virs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Xv%2BbNmxVplDqUbcMKH5HIPokjWsstqx%2BK2lZPf4Wpk5yF6nF9R8xswHGO8QSj%2FAFh8D%2Fqrkoc6VmSMHUOOjAEfTjsAaZMXhMRPxRnYf5J6YPyJV2bNmxV2bNmxVQuzOtu729PVUclBFa07U98DafqsF6i9EkI6ePywwyF6vG2i6oJRUWl6xZCP2JOrr%2FsvtLhG6s0yiK4X6Zfi4QI7Vb9lv5h%2FXDHrgV5c8B0LzLc2Q%2BGF29WDw4SfF%2Fwp%2BHOg6ZMHi4j2YfTkZ%2FMGwpFaazGDytm9GYj%2FAH25%2BEn%2FAFX%2FAOJ4N8uXwliicnps305LmFZDewrc2dxbt0lieNvkylc45%2BX10UCQzHjLATE4P%2BQeNc6L55e5i0J57WVonikRmZDSq7jf2yB2Op%2FVYor2%2FwBNjktpAGjv7ZvU%2BInoy8Vao%2Fa44xCQ9as25RVBqKnfBGRby9rBEsljcIY0aQ%2Bg5FCCQD6bj9lslGAikN5s2bArs2bGyOI0aRuiAsfoFcVS%2B%2F1q2sJltyrSytuyp%2ByDsC3zwxBqAfHfI%2Fodmt2z6pcjnJK5dAexPT%2FgRkhxV2c782mSy82WUgNIdUhNs4PTmlXQ%2FwDBDOiZAvzLb6nHpOrlFkjs7lWdG9yvxVG%2FwiuGJ3Up3YTJFr7op%2BC8t1ljHjxodv8AYtkiyHbxx6XfKx%2FcXBilJ3%2BAsVUV8FRlyYA4Z80DkkPmq3EtlHJSpR%2BJPgHBH66ZBtIufqt9Np8pALHnEpO5p1oM6Xq0P1jTriPoePIfNdxnLtZtrGZluBcG3vF%2BFJYuJfx40IIxHJKzzb5et9ZtZYp1LwygcgPtKy%2FZkT%2FKWuRKKCOC6tNH1CblcWiILDUWHH6wg6wyDejx9Fw4sfOMjEBY5biH1HgLy8VYulOfJV%2By38q4ndH9LlL219K4iilHrWzLxlhI6SgE1%2F2SnFKo0Czxy28zMqcSzspIYBPj2I%2F1cd%2FytnVZdNQ2D1I%2BESMoPw%2FzMftdMG20TSQyyblmjenzoc4TY6ld6ddyKwMUsbFZoHqNwd1KnGXRXs9n5%2Fv7lg98GlWhMjwk1A%2Fm4k%2FF7jDSwSPULTTJI3PGBphGNwG4OHVW%2BgnONX%2BsWFpDFPaSSJcTESG3TcRlf2uRK%2Fazq%2BkR3aeT7e%2BjnX6yoW8ibht%2B9i9Tg%2B%2FQ98QVZHqstutowuSPSdSpV91IPVWzif1i98t%2BZ7m40FjbSWUrNCqEmkex4EH7acT9lv2c6lonmbTvMUTWdwgiumWktrLQhge6H9of6uRLzd5ZurDVP8Q2KetYFUW7jXeSKi%2Bm0hH7UZH7X7OCY4g2YM0sMrjvexB5SHcXsnkPz3Y%2BcdPqKQ6lAB9bta%2F8lI69Y2%2F4XJeDXPJlvPe6JqMeq6NMYLuE842To6ntToyuv2k%2Faz0J5E8%2B2HnGyI2t9VgA%2Bt2ZP0epH%2FNEf%2BEyESeUuff3tmbFAx8bB9H8Uf4sZ8%2F6P82TMMLNb1iDRrQ3EpBkkPC3j7s5%2FwCNV%2B0%2BGVc4n5m8yfpnzJcsr%2F6HYsLe232PBv3j0%2Fy3%2BH%2FY5JxkLourX175%2Ftb28maSZrloqsdlQ1Tgo%2FZUDO755%2B8uxlvPcMI6i6LAe2zZ6BwlS7NmzYFdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVf%2FW7%2FmzZsVdkb83W5%2BrW1%2Bg%2BK1kAc%2F5D%2FCf%2BG45JMC6jare2FxaEf3qMo%2BdPh%2F4bCNiqV6VOOcTV%2BGReB37%2FaX9WHoyFaJMz23BqiWE7juCh%2FsyaRsHRXHRgCPpwy52gLs2bNkUuzZs2Kuwu1rS49W06Wzb4XI5Qv8Ayuu6nDHMemKvONE1KWGVrG7rHPCxRgeqsppk7sb0XC8W2lUbjxHiMhnnnTHtLmPXrZfgakd1TsR9iQ%2FP7LYtomq%2FWI0Iakybof4H55LmFZdqNlFqNjcWMwqk6FD8z9k%2FQc515XuZbW4l0%2B5%2BGWFzE6n%2BZTTOlW063EQkXY9GXwPhnO%2FNsS6T5qtbofBHqaniexmi%2B2v%2BsU4v%2FlfFgHcrPTFbanZNb3caywyApLE3Qj3zjutwW%2FljzBc6Pp6fV9JHpsLNSSgR1HIorV3Vvizq2jXQk%2BAndlBA9xnNvzRiWPzJBJWnr2gJP%2FGNyv8AHAdikJ3YGf0o5pZDIboSD1GJJ9aAgh6%2F5aUzoFnN9YtYZ6gmRFY06VI3zlXk%2FVI5bi2hnlBgdBuxFFahhfr0rSNsnHlXU4JI5NJaSt1avIQm%2B8RaquD0I%2BLjkpbgIZJmzZsirsDagC1jcqvUxOB%2FwJwTjXUMrK32WBB%2BWKpfofE6Xb8f5d%2FnhjkMPmvR%2FKlrJBqkxBSVkjC0PIDpTfI15s%2FMNbu3jbR5plsZVp69swRi9N0eSjMnH%2BRcVpm669cWWtXGnatwjgKma2uPsj0x%2FNXw%2FayOfmLr%2BhX3l%2BPTYrkXM%2BpGtm1uPUUceX7yRx8KLtx%2F1s5xoN%2FefpVr6C8muVVfUuLO8kMrEIeTem7faRk5Iy5FdTuZ9B169trGZvqkc5eFD8SmJzzUcTtsrceWHzTT3fRJv0p5UZvtOYYrgCu%2FJV4P%2FwANHnPrj83vM2lX9zpWoBJYInaJ540pOi1%2BGRQDxf4cln5Z3qT2stjWrK0iexEgE60%2F2XLOUfmHYNZeZbhWP94Ayn%2FV%2BD%2FjVclLlbEdQn955q1wTiU3huLadeQCsfSljO9VNev%2FAA0bYHub1Z7V5yWkhHxpcVHJNwGiuP8AKStVk%2FbyGafqLQxyafO5S2lPJWUAmGQ%2F7uiB8f8Ad0X%2B7F%2Fy8Ctd6jpl3Lb3v%2BkQTpxniqTDcQn7LoR%2FwUb%2FALDZCyyekWl9ZyaFLPelZGN2tqDEtZJHenEs67ckpVXwq1bU7G1iKWvqtcCR4bkkhFYx%2FCHXhvvX48C%2BU7H1SbK3k9Wya5hv4HchSBF8FxBL2WeOJ1k%2F4s9P4cu%2F0j%2Fc1FphmFxPLeOhZBxAiL8jt40%2Fa5YegV6PprvLpcE8sfpTNbh3QVoGK12zluoQ2PnZih42fmWIVt5z8Md4q9I5P5J17Z2A8YrWVl%2BERoaDwoNvupnLtb02LzREdR0hBba7bVe4tEPFZwpr6s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xKXcslu7tXb1%2BSBq%2FwCSzZK9c06xuNUutStkBls5IFkAIAMoHqUUfzNRkbCPW5Xs70rZcVtL0%2BtCoAFVc1oK%2FwArni2RIShdD0rU9Z0g2UNW1DR5JLG%2BirRlQuXhmp1ZP72M%2FwCph75g0K2sra21G8ch5baGJUpt6yARuvL6OWEQk1eJrq9s55YLxBzuGhJEjr3LKvxSqv7WISanq2oQRXGryvd2MtVhuSQ8aNQch8OyNjsqElhK1hbcr%2Fcv3K%2FyV%2FycRSQBmUiifsfQM6FpfljSbrR0mCy3EjDlDIzN9sGnphU%2FZ%2FlbIrqnl%2F6jM3Cb1VRqOoU8078XoOHPISIiQCd5ckgE3tyS4StK6xSy%2FDJ%2B7HqseO%2FYVw0W2thatp10he2b7YH21cfZljP86f8AD%2FYxO4tbO4so4I7ZUvG5Lpl3PssprUws392JD%2Fut%2FwCbAOh6sLuU6VqYMF4hKRu2x5DrFID0YY7rsh4tMn06%2FkspjzjniaS1nQfDIE%2BJWXwdafEv7Od0ugnmL8tmYipWEOB1oGWp%2FwCH5Zy4hoT9WuU5BTzj7FHp%2FeIe3%2BX%2FADrnR%2FysvRfaHeaJIwZ4RJGo8QDzQ%2F8AAy5OPVBfPNxbpMpifYqaBu4IwFYWlx9fEIJU7lmH7S%2F83ZJ9e0x7K9unRg8azMkoHWJySVR%2F9YH4W%2Bzj%2FKtvFdaxBDLQKzAVO243G%2F8ArYPJUXb2NvDZtdyWxe3B4meCQ%2BtG37Jkjb9lafaXHRXl9q2r6etnWJ7Yxx28h%2B1UNyMjt%2FlH4myX6lp1poPm57CIFLG8jikCsKisqqXWncc2%2BzhLZW0Om35hCuLiCeSgIHFY67KT9rl4YaV63IwMVSakg1pt27eGRuzvrTWILdYbnlcIWXSdQc8W5pXlp91%2FLIP91M%2F94mG9tcfW3AQ14xgsPH4c4Zp%2Btz6HqN2rJ61nNIy3loTTkA54yIf91zR%2FailyRNUinpV0iXqyyxw%2BjdW5Md%2FaN1iPdqf74f8A5Jtka1ZZ4LWYxsySKpaCRT8QI%2BIxkj2Hw5KLe6%2FTsUF%2Fp1wsmrRRk2l0QAL6Fft290g%2Fu7uP7Lo395hFquqaL9XZmmWCRwySWTgs8MgG6Oo%2FY5fZbAUhC%2BZ9JsfMl1SKYW%2BqyQRT2DMf3UvJeTwt4M5%2BJchKyrOr6D5gQwTQEpFK%2FwDeQv8Ayn%2BZDk%2B1Gyj1ew0SaC4gS5ntmCtX0ELQtQAM%2FEcv5Fwv1bQxr%2Bnhr4oms2ymP6xuCStSIbof6v8AdzYOaGAQ%2BXdTm1NdLjj5SN8QkG6FOvqBu%2BTjTrS2sbZLCMcVUmkpFGLn7Rf%2FAFv%2BFxTTme102DTuILIwZpKksW%2BzxWtW41%2FZyU2XlW41HhcahytOQJZVHKaXw%2Fd%2F7rY%2FzviAqQ21ldXtytrDG0k524qKmnj8sO736roNmNIltfVv7hFeaMnkUqTwpxNA2S2MaT5etS9w6WdtEvx1b42A7Symh%2F2C5zTzb%2BZun3swOjacGVKwrqMgoajeiJSr%2FOTDVdVZPYa3pOj%2BW7u31uKKzuZGP1dePP1Iz1UovxtJ%2FlYU%2Fl%2F5hOtyS%2BWrlis1Gm0pyfiR4%2Fi9Kv7SumcrvNYnu5DcXH7yToamrfSf6YL8ratLZ%2BZtJvoT6bwXMbEjuCwVh8uJauPFuFe%2Bx%2BYJ4NMawQiOFzyZOlDX4h%2FwQyQeVtAn1BY9R1QN9WU1toG%2Fa3qGYeGE3lnRLPVfM19LdAyWkTtcW8a7xOGaq1kGz7k%2FAM6moAACigA2AxJ7lojn72wANgKAbDLzZsirs2bNirs2bNirs2bNirs2bNir%2F9Hv%2BbNmxV2bNmxV2Qzz3p3P6rqKbFKwyt%2Fkn4lJPseWTPOVfnX5gmstNtdBtnMbajykuXHX0YyPh%2F2b%2FwDEcbrfm24MRzZI447GR59w6pMfNyWl7EdD1KM3Cp6dwoKldj%2B1zHE%2FRko0rz1rUtz9SvLe2lm2Hp8jC7BhWqV5xvUb%2FDnn01jPEin8pHgckemXmsTaHcxANw05o57O7IIKxliJYll%2FaRT%2B84%2FsNkIZhIkSjRDl6zs%2FwIjJCXFHkb5gp3%2Ba2r%2BbdPuEvYLVbLRpiFL27c2EvWkj0%2Fd8v2VpkGsfN2p3Kra3V2XicgEsQeQJ3qSNs7d%2BkdO1rSbKw1LhN%2BlbRXVJKFZyq8ZV3%2F3YGHLOEecvKFx5TvTLDym0idv3EvdG%2FwB9yf5a%2Fst%2B3lpHUOvsua4iNwbWCruHK%2FB0qN9j0zoy%2BarW48r2Oq3l1Le2sSizuGkqk6zgUVXMda8F%2FwCDTOO2M01rIs0XCRQ4kHqCqGnZl74NgkTlMqSOIZpPVNrXjGG8Qvfj2wXzSyqz1eO%2FtNSjQM8sVubhFbbkIpPiI%2BUR5Yca3q17IdPmtZ2js7yztriONNhyAKSciPtMJUfIZaXDWL%2Bra0jcq0ZYAV4yAq6mv8ynJf5Yex1PRjpUsfO%2F0pnuLJWNPUgkNZ4l%2Fm9Nh6vH%2BVpMRa2uvBcXej2Gp2rSC5tJJbOZkqW4v%2B%2FgY%2Bx%2FeJhtBB5sOi313boLa9ihMlo3EB5ClGkULy%2B16XJk4rhlZarBFAbZljtrS5Tg%2FoIF4fyOT1JjbC1L%2BbSbowyMwu4WrzJryX9h1PQpxw%2FFWFXNut9PB6srS6frlqI4JZHJ%2Br30bCsbOf5phx3%2FAN1T%2FwCRgPQbtreVrEFrW8gfnDU0dJUPF09unHD%2FAFeygjjvbi2haTQbpxcXlpHvLp9x9n6xClfjtjXi1P2P3b%2FGseE99ol9qtyjIKamYlktb6Mn0L5QKJ8Zp6d3x%2BH4vt8OD%2FvciTXPZaZ%2Bkdp5%2Bgt19Yad5p0%2Fe0vU2Y8T0NPiaM%2FtJ%2FuvOj6lcGysFaRlYxJWUjfkUXk3z5MM5p%2BV2l3U2pPdalFHK1sOLyqQxSZaFOdDWOT7W%2F7eTTzK8UdlcxREhXBTf%2BdzWg%2B7JxNji70HnTz%2B51GXyrrFxaapD69nfcRqSftqxHL1oj%2FOjPjtQ0GNYCfrCXWi3QMtlelhyjkYbFfdvsyx4M87Wy6zqemTq4X9KwQnmegkK%2Bmf%2BSi5G9M1PVfLUt3od3CJIGDEQS7iKUD4Zov8%2FjyErqrruPNkK58%2FJN7Sx0%2B0sDe3k0k9xA6JBJACGqwPHiKp8S8fts2F0mrDS3nubPThH6ZLa5YcQsnBvs3kSsCnJeXJuK%2FB%2FwAYmwQ%2FrXdjEsQRizhvjKCrUp8If4uW%2FwCyuK3Fs893p1nezfVdeDCOxmHFi8ZH%2B89wSeBjP2YuX%2BVFiYggA70Pmt9QzfyjdxXeiPeaY3rNYt9ZjdKUkgP2gyj7L8ftL%2FPgTz2tuLdJIT6cN1JFcxzJ2U7Sb%2Fs%2Fa5BsKfLEMvlPXby2sJI40uF%2F0izVuUcb05n0z3gkTlw%2F3237vHeddXN5pEMdnbmOys4BFcy0qDcF6GJa%2FwDFacmyX8Pu2R1QOi6Yupabd2F78dj6xjLVFUlpySaHwkUf7F0%2BDIrrvl6dr42N0eOtRIHs7ldkv4B9ijf8tKgfB%2FP%2FAHX28mPluyb0Vs7OdTL6SSReoK8%2FTZqN%2FrqOPL%2FJwTqdhFr9m1lqUhjnhcm2uv8AdltN%2FMKf7pb9tP8AZrjVhWHaHrEWqxjTb9gt9GKQytsXptxNf2sl35d3J0jznJbCojuQlR26cT%2Btc55qthdyXcyyJ9X8wWfx3ESbC6UbrcwfzS8fjfj%2FAHyfvPt88N%2FKuq3F3q1hqBIEyc4pWZuCkoAwck9MA50VPJV%2FMq2k0TznfCJQUmPJom%2BzJG%2FxcW9t%2FwDY4Q6cILa6ZY2eKRwslv6goaDfjy%2FaK4f%2FAJleadM80a8t1pcZ9GCJYmuG2MrD7TAfsqv2V%2Fmwr0WyuNXUw%2FVxci1%2BKLt%2Fw23wrg6qGVanr1vrK2t3csIry1aESBjxJEYYOQff4cjvm3zLbpZXLWTGC5vr%2FwCswRjfjBGoC8yfi%2BIjCPX2vNMu%2FqZDRNGKSAgUqxqgqKruF%2BH4sjsyPPIZZSXJ7knfG1e9%2Flxrdt5ksbqdSFu7eMLcW5O4%2BE0cV6xvnF75uVzcb14yyBW7%2FaO2KeS9RutC8yWd7DMYLfn6d3L%2Bx6D7SLJ7YhdkNd3UkRDRSXErxMDUFGclT9IwndCtpWrz6ZN8MskcDsGdojxkjcfZmip%2B2v8AL%2B3iWoySfXbiHUmFy14frKXqH4nL14zK%2FVuX7cbYEeJWDPQVpU0Pj0x6yqLL0pJUW4tXE1o5O9SaSRbeP28Cob1Z1T6vPKzxjeNSSQK9aV%2BznXLfUrdtDt9T1U%2BjeRxpa3iMvF5V41jcg%2Ftrx%2BLOd6VbaTqJlS7lMl5Iri3hHwRiQj920snhzODppWsii6zcGeSZg3po3NSy%2FD%2Fen4K9V542r0LyheaXcm5uaCCWNhxkl%2FvClOqcvs4rrn5g2enI9tpKi4uqlWck0rSvxP8Atf7HITazpc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2FLhpr3nLTKJ9UT19TB4zNHtCe3Jj3b2XIssp1Y8bUfFOQsix7SCSlAXpTmj4av5OnsdM%2BuzB3Zm9OWaNGD2%2FMgRTolP3sXP4Zv92fyYi6oITDVrG28x6NBeBvqWoWS1ivSeIikU8jFI%2BzLA6%2FGn%2B%2B3yFaq1pcXix28ZUGi3U2wadx%2FuziAEWv8Aq%2FH9vDLV7TzXeWrqbaWO4VhHeNHtFdCP7EhX5D4v9%2BfbwpC3liGgvIoVdSqt6pLPGr0pTj%2Bz8Xw4CUkEGil7RwRu9ZzwjPx8UZiKePShyb%2BRfMdhHM2kLEV%2BsDlDLQFncUCxcRX7WEF1DCs63zCs6r6c1Nkencr7rgXSpFsb5zCForepC9PiUEfZr4DADRVD%2BddUkPmPU4lUgVNtNG4qDw2Bof2kP2GyK1LECpY%2BAqTnUFhsta1Ce%2B1G3inuZCrySsgqwqFNRkwu9R8m%2BWIwscEHrharDBGjSH5tT4f9kcIoop4da6Vqt2GW0tbiQHbikbkH57UwHNFLbSvb3CNFLExSSJxxKsuzKwPQjOu3%2Fmq%2B1mFo1C2NmFMjhTQLGu%2FKRtumQfU%2FMWh3uoTXx0r1pJePKSWSnJlVU5lQNufHnhQxmOYxklSPiFCDvUZQKUIpUn7Jr0%2B7D8eYrBP7nRbUf61W%2FhmPmtkBFvptnEezCMkj78CpRZOY5w%2FBmWhBCjseuSyyn0pIpIr2CSr2gtbYTQt6aylufPp8PBWbCZPNurROskYgVkYOv7tSAVNRtg2780%2BYPNd5CdWuRJHEWkWONFjRaih%2BFAPljsqLeRrVh%2BjQt3GBRoXBBKAfFwag%2BLJ15B17yfealE2taTHcXMG63Eq%2FvbYL%2FvyH%2B6eFK%2F3iJyT9vAXkPygPNEuoxx3KQ3VrAHtYWP8AeOxpv%2FxWqijMv2WZMLdS8vBLx4pg9jqVqTFJIvwup6fvP5lP%2FDLillv5i%2BStPtL867pEEcem6hxkivLWjIk%2FevHb05ftZF9Okd5Et5mayvoWEtrdRmnCUfYmhYfzftp%2B3k3%2FAC68zLfx%2FwCFdWt1eElrbUoW%2BwGIrDPGv7CyU%2BLj%2B18eIeavKM3lq7WqfWNOkYizuXFeNesE9P8AiX7WNbqCncfm2f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V1PpOsrBduRLFcPb3JY9VditW%2F2XxZ0%2B91O2spIoJWL3E54wW0Y5SOf9UdF%2Fmdvhzm%2Fm2w%2BoeapJlBVdRjWdCDsZE2cfeuHdvfQW0BngZptVvEH1u%2FlG6gj%2B5hH7Kr0xHc0pD%2BYg8wa1NDFZWjSWtsrCRoiGJcn46b1YdF2yFWemzxsW1CN4Ej%2FZlUofubOs2WpxpNGl2oMP2eSbEe5yTXGkadqFpJaT26T2860YEVBB6EHx8MeCzdpunlEtpHYQ38GqRrFNaPA8EgJcFa%2FGqhadao2XBGlmbe2uCzevbGeRo2PcNJx%2F2S%2FDht51s3sLpYLoH6ncIq21wRU1UceLt9Hxf8Hhj5f8pXerWc%2Bq2VrHqE1oqQWdvNLwUoijmJB%2FO9W4%2Fs8cjVH3LezEvM2mXWqyabNozB7SS1WJ5SwBrHWnLv8A3ZUbfy4onlazmtrKC%2BJlNoHFFNFbmQaHvtTJ9rPlzU7GOO6vrRbeNioQQMrRxmn938IXj4YE0fQLnXBdQ2062l1CP3SSry9Xav7og0%2F4LDsikps7C3s1WK2iWJB%2Bygpg5lNOX0YAVr7TL0xXsxcxsVlhktwpFPtLVWwbf%2Ban0e8tp7LTYrmyILlpyT6hoRw2%2Fu%2FTbdlw3taoK4v7a1dY2dW5GjQ1qVHj%2FwA24Vah5a03VlNxZEQTtvyX7LH%2FAClyfjyfo3nrTrbV9PRNI1i6gM8qRENC8gb05OUI%2BNR6nR1%2F4HIRqOj655Vu%2FQ1SBogT%2B7mU1ikA7pJ0%2FwBi3xZGwdizhOeOXFCRBSPSZNX8maml1MhNsfgldPijdD1H%2BS37S8s6ZLrEEZt2uEe1W6VWtLsg%2BlKGHIGOReS%2F6wOR9dWtRp11dSQ%2FWHt4Wk%2Br93IGyU%2Fysk%2Fk%2FW5INATT9Z0eAWczGT6gr%2BoIlfcgBxsf2vT%2FAGMYxMSeE2D07m7PqBmjEzjWSO3EOUo%2BY72M%2BYfLcd3FJeQRxyo7EzQU792GQ60bU9Hkf9HTAwts1jdVeNl%2FyX%2B2n%2FEc7ZL5XstVSS58p6kYZqVbTrysif6tWPrRr%2FspVzmuvaDq2jzsup2JtA5NCfjtmNf91Tjb%2FYyccJ8tmgJPqV4JJLJpI3sYLq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FFMx2imJJSvhHLXj%2Fr4N%2FO9G%2FwAJ28o%2FYvY69%2BqOMgdlYzqPmWy8xr615aouoxAA3dk4dJB0%2FfRGjofBl54U%2BnCySRNSa1l%2B2vQq3861%2By65GPKcztqxjY7NEw4jYbU32zoNppF1qfrw2JX6yierHExoJivWIf5fH7DYYnZaY3pN9N5N1n9JJEbuIwyRoisY1kDbpVu3F%2FidM7xpl3Y%2BadFt7m5tle3vIUkaCYBx8Qowof5WB%2BPONG0jvLY28qlRUgqwoyOOu37LpiXl3XbjyZqk7XglmtZIfTEKNQGh5REFvsxr8XLjgIrdWQedvy7GiQPrfl4SNaxVe5s1q7Rp3ki%2FaaNf20%2B1kT07WGCqwcMjdJFNQc9C2N9BqNvHc29WiljSVGI2KyCopkFv%2FwAotHu9cOq2d1JYW0x53dhAo4O53JQt8MYf9ocMFyB23ZwGOQIkeCQGxqwfIsatNQSQrIrmOUbrIhoQfEEb5LLHzPP6X1TV4RqFo4ozFVL0%2FwApD8EmFms%2FlxeWBNxoEpuIhubSQj1B%2FqPsHwo0%2B4ltUmW7Ro5ojRo3BVhT2OWCi1t%2BbPJ1pFCfMXlJgtl%2Fx92VCyRHuwjb4kX%2Bdf2ciOlG2huhcX2n8JI2BE8FHHzMTb%2F8TVc6FpWutaySPblJEmHGeCQVVwP1ZGtcsIbe5N3p0Ui2MlWaM7mB%2FwBpQ4%2B1F%2FLkTGulhnDIYnYprf6tYaxaxxCDlxIaG7iko8Z7kGtWr%2B3ywxsdGl1WwitzGbkgkRzugDGnRm34R0%2FZbIJBZwxv9YhAVx8Qp0JPiBnafJl1eXekLNdyrKOXGNgADQD4g3Gg%2BE7Y8WyTLfiHNJbbQvNHle%2Fe50eQX%2BnXAD3Vg53EoWnKImhQmn7Pwv8AyYRX9xql1dmXWOS3XHiqMnp0QEkKq%2BA5fazrQwHqOmWmqQGC7j5D9lxsynxVsFsLeO39hb39tJbXMYlhlHGSNuhB%2FUffOZXy3%2Fl7UV05n5MgrpN1LTjLCT8VncEj%2FYf5Odt1nQbzR3JcerasfgnA2%2BT%2FAMrYB%2F5V3Y%2BdtAvhefubrn%2FuNux1jkQUYkD7Ubnir%2F6uEq8D1rTFk9XUdNgaHix%2Bu2XVoHPcD%2FfbfstnQfyAeb%2FFktC%2FptaSF1VgFNGTiXFfiA%2BLj%2FlZC9WuNd8p6kNM1e04anYsY2mY7TW%2FZG2pKjfsS4K003mkCHzl5WmDLazercWoB9WCvX1FB%2FeQt9lv8nIofYNRl5FPI3njTfO2li7taRXkQUXlp3Rj0Zf5on%2FYbJXirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FW7%2FmzZsVdmzZsVdmzZsVdgHVY9PmtHi1JlW3cgEuQBUbr1wdgPUdNttTtzb3IJWoZSOoYdxirzHztP%2Bi20aTyvdm6uDcJSCMJIPTVhRWKj7Bbbi2B9b8keZrnV3FvberbsQsVwHUKFJ6tU8hSvhk%2B%2FwAPGy1GwvLOkqK5ju0cIP3YQ%2BnItAPiif8A4nkkphKQaQOk6eml6ba6fGQVt4whPif2j%2FwWO1LTbPVrGfTr%2BITWtyhSWMjqD%2FEfs4MzEVwIsg2Ni%2BVPOHlm58p65NpU1XhP72znP%2B7IWPwn%2FXX7En%2BVgW28s63f2kWr29m76Ys6xyXQpxUggNUfa4iv2uOen9c8t6J5it0t9as0uo4zyjLVDKf8l1oy5EL7TriGW30Lytp7Q6Dbs0d7xI4Oz%2FFWPlycmNvib%2BfKziufETs7WXahOn8Ph9dVIn6a7%2FewDzPd3ukNplzYtxtEhW2adVBKzRktTkalOdf%2BBw60bydZ%2BaNR%2FwARaPq0VjOIw509bcLIkw%2B16yh%2FjRm%2F3an28de6dLYTXGk6xDztpx8aHoyn7Lqfb9nI3YX%2BreQ9ThS3pcWhcvazMBWSE%2FbgaQ%2FF8P8AJlrrDvunvmryB9buFvzAtnrkQD84z%2B6mKHkGRtu%2F82HWnO%2BoadLpU5aC4ZeUL9Gil%2B0jKR0aOYZOLO80jzho0d3Zv6kMn2WFPUhlGxVh%2By6H7WQWaO80rV1hvwBMjcfUAoskTbLIP%2BNsIr5oSu10tfOt7Ikt4th5ijQC6hkSsdz6fwfWIiCCr7UmTj%2Fl5JG%2FKTSdTjg%2FxDILh4UCUgHD7P8Axafj45GPMdkYtRkvbWf6jewEXNhcr9ppT9pEVatJWnxJx%2BznRPIfmz%2FFujfW5Y%2FSvLZ%2Fq94gBCmQCvNQfiVX%2B1xb7OA2NleaX%2Fkr%2FA19Jb2rO%2BlXbc7UvuFbuvL%2Bb%2FiWC7M7HOuarpdrq9jLY3i8o5Bse6t2df8AKXOP6jbaj5dvpLK5USBd0fcB07Ov8cMT3qkP5l6trkWp2kNi8sVr6CShoyVDyH7RJHXj8OQpfNfmCN1%2BsXcsnBeCrOfUAUdFHP4uP052ny%2Fq2g6veR6T5hgX94Almsp%2Fdsw%2F3W%2F%2BU37GSHUfyp8n6hUpavZse8DkD%2FgH5p%2BGCXNeTwM%2BbzeWxtr%2B3SVHFGMZKMP8oBqr%2FwANh9qv5gpr3kVfLV9zk1O3uIjFOwrzt4w1GZhUeqn2P8rJD5i%2FJJrK2lvNKufrSx%2FEYCnCXiOtCpKPx%2F1M503lq7tpDxDNUUUGlPwyJtWQflfpMWseaFtLgssZtZnDJ1VhxCn3651e38qanp%2Bs2ZX95brKG%2BtR7UVfio6%2Fs16YS%2Fk3pGmWxvNR%2BspJqfEW7WnR4kryLFW3PqN%2FL%2FLnW8I2UsW8x%2BVo71n1LT0CXp3mjGwlp3%2F4yD%2Fhsgl9oyXUaxX1u8LoCY2dStV%2FaG%2Fgc7JTEbiztrr0zcRrIYmDxlhWjDJCXQoeVeW9Rv8Ay1PKL25kuNO9ELEo%2BIjgaoKk%2FAqJyzqtrdQXkCXNs3qQyqGjcdCCK7ZFPMPl1Yg95aLWA7zQjfjXqw%2FycB6JrNzY3BW7uAbARKgUqSQVIC8KfCq8K8vhxq9wlntK4DvtJ07UgBfW6TU6FhvTwqN8FRyRyoHiYOjCoZTUEHH5FDC9Y%2FL6wuSZ9Ic2M3X0tzEfo6p%2FscL9B%2FLy8XVJNS8y3Yuo41aKz0%2BEkQrGwoWlO3N2zomVTDZV4l5n8s3Plq94oS%2BnTk%2FVZj27%2Bk5%2FnX%2FhsMNI893Wj2ht2thNVSEp8PGSlBK%2F%2BSf286nqOnWmqWcllexiSGQbg9QezKf2WGco13yhdaVMUT95A39zL0DDwPg%2BIZc3pPlzU5dStGa4IaeNgGZaAFWHJWoMOc5v5E1B7Wf6tcAoD%2B5PLb3jP0fYzo4xIYrZIo5UaOVQ6MKMrCoIPtidrZ29lAttaoI4UrxQdBU1OL5sCsO8%2FwD5e6V5708RXNINQgB%2Bp3oFStf2JAKc4m%2F4XOIWX5R%2FmVoOpummwIySAxNMssZhZG2q3Mqen80eeoKZqYq8l8h%2Fk%2FceW9Qt9Z1DU3W4gPJLS0JCEGvwTytT1U3%2Bx6arnWs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F1%2B%2F5s2bFXZs2bFXZs2bFXZs2bFXUzZs2KuzZs2KoXUjILG49E0k4EKetK43TYkhsoQp5EqGZvEnvgp1DKVbdW2I9jhDdaDqT%2FuLLWJbOzP8AulEVnAPVVkb4hiqB8wWUXmS%2BXTYWQi3ikZphuUlqOKmn7P8ANnOtRsiPW0TWUKqD9ofajYfZkQ%2B3%2FDLnYtH0Wy0W3aC0BJc8pJHPJ2J8ThV5u8tJrdoZrdQL6EH0z0Lj%2BQ%2F8a4bTbxXQPMGq%2Fl9r7mSs9jcUN3Cv2Zo%2B1xD4Sp%2FzZnaNYhtfNmgRaho7JcMwE1pKCASP246%2Fsn%2BZf58gsugWWtaPFp1xRL21qFkFCyP3U96YR%2BUfMt7%2BX%2BqvpmqEtpUsnGeOtQjE0FxD%2FwAzUxOy%2B5kHmGCOa1s7%2BVeEsFYpHI3SvwyBvDi647RtH1by3qEXmPT5VlgnWmo2C1Amj6rIrH4RMnVcCz3FvJ5x1pIqX2h30cVy3ouv2nQEeka9XZW5ZJNPult7dbZpTLasP9HlYUalP7uVf2JlH2v%2BEw891ZzY3tvqNtHdWz84pBUHoQe6sP2WX9rC7zJoEOu2Xp7LdRVa3lPY90b%2FACHwi0IahBqtdOo9hKf9LjY0Vf8ALU%2F78ybZFD591jS3R3gnRo5Ymp4MjA9snHkr8weRi0LzJII7pQEtdQc0SYdFWQ%2Fsy%2F5X7eH%2FAJw8uLqMDX9qg%2BtRL%2B8Uf7sQf8bLnJbuyjcNFKnND1U%2Fw8Dh5pfQo3Gc487eVFhMmq2KfuHNbmNR%2Fdsf92KP5G%2Fa%2FlyPeXPM%2Fmfy2Y4pmk1PRqfBBKpNwiDr6E3%2B7OH8j51%2B1ubXU7JLiKklvcJWjDqrDdWH%2FEsV5PntoFiuUuQOFxFvHKpKsPpWnLJZ5b8w65p1xEguXuIp3q8d07P1%2FZVm%2Bx%2Fkccbr%2Bhm2125sbPggX95AZq8FRhy3p%2FL8Srk181aDHqempqtvRLu2hDngPheMDmV%2F2P2ozjsrKLW5ju4Eni%2By4rQ9Qe4OL5D%2FACp5hgu7iOwkkUXFxD6yx9DWM8HNMmGJFFDRFRQioPUHIhrmgrAXubdK2z19WOleFepH%2BRkwymCkUIqD1BxBpWIaNq09o31WURrZoiem32ePEheCIB8VV%2BLJcGB3BBHtka1LQXVne0XnC9eUQ%2B0tevHxXA2lxazHfW620rx2atW4gkSqFOPCgdvjDClVwkA7hWYZswzZFXYnNBFPG0UyCSNvtKwqDimbFWE6voE1hIbu0Be3BrQVLIP8rxXJRo92b3T4Z2%2B1Ti3zG1cGkAih3B7ZSRpGvCNQqjsooN8NquzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxViPmbyo91cfpvQiINVT%2B%2Bh6RXSD9iXwl%2F33N%2FwWQzW9AXXo%2FXaFg7L%2B%2BhK0mjdBuafzACjrnYcDTWNrPKk8kYMsZDI42NR40w3tRW3z1p2l6ho%2BotLAfXVE5OgDVljA%2BLj%2FxZGv7OS2BbeaRbscpI5YuLQq3ETIfiQcv2ZVP90%2F8AsMk3mi1FjqBnt0CpcIHIUU%2BNT8RFP5tuWRDTFEulwPaP9YjVSfVjBIFGPM%2F7BvHCOSXqXlu6trnTI1t7Y2Zj%2BGW1YhmQ%2BJcfb5fzYcZBPKl1I7GRXHKGi3AY%2FajPRvdsnQNd8BFFDjnL%2FPWhJaXguIKRw33KngklPi%2F2Pxcs6jkY892Ul3onqwoZJLWRZeAHIlT8D7fJsAVBaLpUeueS9PtriYPcWykQXkfZ4yVDD%2FJP2WwX5X1NJ2NrQIGXkoXpzQ8JP65GPJfmOTR5G0zXLmGCzlYmzhZPSeE05ceP7UTjfliOhagkWs3CW0gkUXbPZjoZVkY8kQHr8OSHUJZD540vmYtVRBIAvoTo260JrGzU7cvhzaJ5jgm0t9O1u7giu%2FRdY%2BJ48oyCg%2Fd9QyfZ%2FwArJhPBFcwvbzqHikBV0PQg9sgt%2FwCSLpJy9pxniPRiQsgH8rfzYB5ql%2Fkq1hXU4ZigNwjsizftemU3Uf5Jzp%2BRXyloF%2Fpj3FzqYiR3YraxREsyx%2FzTOaL6j%2Fyp8CZKsSUOzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Hv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVg35iPrMEFld6XbR3CRM%2Fro1fUIIHwx%2Fs4U%2FlrqOkz3c1lYQmENFJI8DCgRzIDIg5b1JavTOiajZLf2cls1KsKofBh9k5ydpJPL%2FmzT9ZcBIWY2t5sFoD8Ls5C1%2FwCDkyQ5KyjWdLGi6ml3brSyvKxuo6I58P8AJPVclOiXZurPi5rLAfTf5fsn7sE3drBqFq9vLR4pV2I7dwy%2B%2BF2j6Xf2F5dS3EqNbyhViVa8iV%2Fbfag6%2FZXBdj3KnWURXLzYFYV5n8n3us6ut7btEITGsbc6hl418B8WFd75Ym8svHqVqPrQiCsJSPiikH2jQfsNnScayhwVYBlOxB3BGG1Sby7rf6YgZ5KCZftIBSmHeFllodlp95LeWqlDMKGIfYB7kDDPE%2BSuzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F%2F0u%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZFfM%2BipLW%2BSJZAf71CtaMPsygf8SyVZRAIIO4PbCDW6pP5YvDd6Wiu1Zbc%2Bi%2B9Tt9mv%2Bxw5xG3tbe1Vlt41jDHkwUUqfE4tgPNXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Pv%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV%2F%2FZ'); + background-position:center center; + border:1px solid #00aa00; +} + +.yui-skin-sam .yui-h-slider { + background: url(bg-h.gif) no-repeat 5px 0; + height: 28px; + width: 228px; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css.min new file mode 100644 index 0000000..8f3398d --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-singlequotes.css.min @@ -0,0 +1 @@ +.yui3-skin-night .yui3-dial-ring-vml,.yui3-skin-night .yui3-dial-center-button-vml,.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-night v\:oval.yui3-dial-marker-max-min,.yui3-skin-night .yui3-dial-marker-vml,.yui3-skin-night .yui3-dial-handle-vml{background:0;opacity:1}div.base64-singlequotes{width:100px;height:100px;background-image:url('data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAgEAZABkAAD%2F4RfJRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAAD0JAAAAnEAAPQkAAACcQQWRvYmUgUGhvdG9zaG9wIENTMiBNYWNpbnRvc2gAMjAwODowNzoxOSAxNDo1ODowNQAAA6ABAAMAAAAB%2F%2F8AAKACAAQAAAABAAABwqADAAQAAAABAAABRQAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEAAgAAAgEABAAAAAEAAAEuAgIABAAAAAEAABaTAAAAAAAAAEgAAAABAAAASAAAAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14%2FNGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x%2F%2FaAAwDAQACEQMR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0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZ%2F%2B01IlBob3Rvc2hvcCAzLjAAOEJJTQQlAAAAAAAQAAAAAAAAAAAAAAAAAAAAADhCSU0D6gAAAAAYEDw%2FeG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8%2BCjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJU1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk%2BCgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk%2BCgkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk%2BCgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q%2BCgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxTY2FsaW5nPC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk%2BCgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw%2BMTwvcmVhbD4KCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9rZXk%2BCgk8ZGljdD4KCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNUFBEUGFwZXJDb2RlTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BUE1UaW9nYVBhcGVyTmFtZTwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPm5hLWxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk%2BCgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk%2BCgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw%2BCgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk%2BCgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk%2BCgkJCQkJPGludGVnZXI%2BMDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q%2BCgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk%2BCgkJPGRpY3Q%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk%2BCgkJCTxzdHJpbmc%2BY29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk%2BCgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BMC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3JlYWw%2BCgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw%2BLTE4PC9yZWFsPgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw%2BCgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJPHJlYWw%2BNTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc%2BCgkJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc%2BVVMgTGV0dGVyPC9zdHJpbmc%2BCgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI%2BCgkJCQk8L2RpY3Q%2BCgkJCTwvYXJyYXk%2BCgkJPC9kaWN0PgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk%2BCgkJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk%2BY29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk%2BCgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJpbmc%2BCgk8L2RpY3Q%2BCgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc%2BY29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0Pgo4QklNA%2BkAAAAAAHgAAwAAAEgASAAAAAAC3gJA%2F%2B7%2F7gMGAlIDZwUoA%2FwAAgAAAEgASAAAAAAC2AIoAAEAAABkAAAAAQADAwMAAAABf%2F8AAQABAAAAAAAAAAAAAAAAaAgAGQGQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QklNA%2B0AAAAAABAAZAAAAAEAAQBkAAAAAQABOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD%2BAAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAE4QklNA%2FUAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA%2FgAAAAAAHAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAAAD%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FA%2BgAAAAA%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwPoAAAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1UAAAAGAAAAAAAAAAAAAAFFAAABwgAAABAAcwB3AGkAcwBzAF8AYQByAG0AeQBfAGsAbgBpAGYAZQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABwgAAAUUAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAUUAAAAAUmdodGxvbmcAAAHCAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAFFAAAAAFJnaHRsb25nAAABwgAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE%2F8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAAThCSU0EDAAAAAAWrwAAAAEAAACgAAAAdAAAAeAAANmAAAAWkwAYAAH%2F2P%2FgABBKRklGAAECAABIAEgAAP%2FtAAxBZG9iZV9DTQAC%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgAdACgAwEiAAIRAQMRAf%2FdAAQACv%2FEAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5%2FcRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1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U4%2FWfqPk5jhRj2BorDrMXLOjqnge2m1rNrnV3e1lnpf8b%2FO1Urm%2FqLlZH1a%2BseT03IwLa7s97K8nFrY%2Bx9fp%2Bp6OfjupZ6VvT3%2BrY3I%2F0P6Oyn9F%2BjXrKSCFJJJJKUkkkkp%2F%2F9X1VJJJJSkkkklKQM3Dpzcd2PbuAdBa9hLXscNWWVPb9CxjkdJJTxHVfq4Ol5bc%2Bq55dlvLLq2Dax1lprY7IFbP5i63b77Kf9H%2Bk%2FQrpPq%2FcLMAVlgrupcWXM4duBj9I0y7f%2F1f00vrB0hnVunPo%2BjkMmzFtGjq7QC1tlb9Njvd%2FqxS6dWMj0upH9FfbXsyqwIabGwx30%2Ff%2BifW9n9RHopwvrBh4eF1V%2BXkU%2FqmZQQLSB6deYxwux7HAfpGvs9L%2FB%2F8J6ivWVZ2dj4vV8FgfbkY%2Fo5WO8hosrdr3%2Bi6t7nrefWx8b2h20hzZEwR9Fw%2FlIOLg4%2BI652OCxt7vUfWD7Q4%2FScxv5m%2F89K1IujYj8PpWLjWDa%2BusB7SZIcfc5u6XfnFW31seIe0OEzBE6%2FNSSQUpJJJJSkkkklKSSSSUpJJJJT%2FAP%2FW9VSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2Bqkl8qpJKfqpJfKqSSn6qSXyqkkp%2F%2FZADhCSU0EIQAAAAAAVQAAAAEBAAAADwBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAAABMAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAFMAMgAAAAEAOEJJTQQGAAAAAAAHAAIAAAABAQD%2F4TkjaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu%2B7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI%2FPgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSIzLjEuMS0xMTIiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI%2BCiAgICAgICAgIDx4YXBNTTpEb2N1bWVudElEPnV1aWQ6RTcxOTVFNTY1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkRvY3VtZW50SUQ%2BCiAgICAgICAgIDx4YXBNTTpJbnN0YW5jZUlEPnV1aWQ6RTcxOTVFNTc1NzMzMTFERDlFNzJGQ0E2QjkwQUZBRjU8L3hhcE1NOkluc3RhbmNlSUQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0ZURhdGU%2BMjAwOC0wNy0xOVQxNDo1Nzo0MS0wNTowMDwveGFwOkNyZWF0ZURhdGU%2BCiAgICAgICAgIDx4YXA6TW9kaWZ5RGF0ZT4yMDA4LTA3LTE5VDE0OjU4OjA1LTA1OjAwPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhhcDpNZXRhZGF0YURhdGU%2BMjAwOC0wNy0xOVQxNDo1ODowNS0wNTowMDwveGFwOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhhcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1MyIE1hY2ludG9zaDwveGFwOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOkhpc3RvcnkvPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xMDAwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpOYXRpdmVEaWdlc3Q%2BMjU2LDI1NywyNTgsMjU5LDI2MiwyNzQsMjc3LDI4NCw1MzAsNTMxLDI4MiwyODMsMjk2LDMwMSwzMTgsMzE5LDUyOSw1MzIsMzA2LDI3MCwyNzEsMjcyLDMwNSwzMTUsMzM0MzI7QzA1QTE5MDRGRjAwQUJEQzA1MUJERkFGMDIwNEVBNTE8L3RpZmY6TmF0aXZlRGlnZXN0PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24%2BNDUwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyNTwvZXhpZjpQaXhlbFlEaW1lbnNpb24%2BCiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U%2BLTE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtENDYzN0NCOUQ0MUExMEJBN0VGNUVCQ0RCNjMxODMyOTwvZXhpZjpOYXRpdmVEaWdlc3Q%2BCiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY%2BCjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8%2B%2F%2B4ADkFkb2JlAGSAAAAAAf%2FbAIQACAYGBgYGCAYGCAwIBwgMDgoICAoOEA0NDg0NEBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEJCAgJCgkLCQkLDgsNCw4RDg4ODhERDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM%2F8AAEQgBRQHCAwEiAAIRAQMRAf%2FdAAQAHf%2FEAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4%2FPE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BCk5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0%2BPzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1%2Bf3OEhYaHiImKi4yNjo%2BDlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq%2Bv%2FaAAwDAQACEQMRAD8A7%2FmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVdmrlHI2utXn6WltnFESb0RFSp41WjD5q3LCBaslzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2E2rj0LuzvF7PxftUf8AXPLDnC3XI0ewdpOkTK4P08T%2FAMK2Ec1TLNgaxmE9pFIDy%2BEAn3GxwTgV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F%2F0e%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXYUeZpfR0a4kpUAx19h6i74b4X65CbjR76FV5FoJKKe5C1GIVLdDuGhuXs2IKOX4gfsvGdx%2FskKtkiyD6bctHHbXgPImOC4qOpXj6E1ff4Mm4Ndxkpc770BvNmzZFLs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Lv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVokKCT0G%2F3ZgaioNQemANZuhaWLyE0LlY1%2BbGn6sWspA8QA%2FZ%2FUcVRWbNmxV2bNmxV2bNmxV2NZQwKnodj9OOzYqwDT4iiPZsa%2FVLm5sj7I%2F76L%2BOTXTpjPZQSt9pkAb5r8JyKXqfUvMOpIQOFxFDfoP8qFvTl%2F4Q5INDkrFPAf8AdUhI%2FwBV%2FiH8cnLeAPcxHMprmzZsgydmzZsVdmzZsVdmzZsVdmzYyWRIo2kkYKiirMdgAMVX5sjTeaGl1CzsbSAOLuX0w7k14KCzyAD%2BUZJBirebNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV%2F9Pv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVo4CXUFa9e0CbJRWkr%2B0RWlMHZEJ5WtPMtzE5%2BGYJKnyK0%2F4kuEC1ZeM2IW0okjFT8S7H%2BuL4FYz52mMWn2tDTlcpX6FbDHR5ecCH%2BZevywl%2FMM8dJtn7LdJ%2BKvgry9ccrOJ69KVw9E9GS5s2bAh2bNmxV2bNmxV2bNmxVi3miFU1LSbxvsStJYzH%2FJnSi%2F8ADYpoEzLcxq1T68FGr%2FvyE8GrgjzdC0mhXEsY%2Fe2pS5i%2F1omDf8RwttJRHdrcDaNbhZVI6endIG%2F4mcnHeJCDzDL82bNkEuzZs2KuzZs2KuzZs2KurkZ843Zhs4bVTQzvVqfyrvg3zHNPb2UMsLtGBPGJSpIqjEqRUb9ch%2BvSSvp0JlcvJCLyMuxJb4JNvi%2F1SuEBVvkaX9L%2BZbm8Sv1fTbf0Y6%2F78lPxH%2FgFzpeRvyPbWcXlyyubWBIXuoxJOUG7uKjk5%2FaOSSoxPNXZs2bArs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FU7%2FmzZsVQ2osyWM7o3FlQkMOxGPtZhPBHKCDyUE08e%2BM1Bedjcr4xPT%2FgThV5cvBJbpGergEfMDcYa2PkqfZs2bArs2bNirs2bNirs2bNirshfnRGtb7T9TX7LcoJD2qDzSv3vk0wl81WDajodzDGKzRj1oR35R%2FFT6RthHNXaVcrKsUtftDi304dZz7yrqPrQCIncdMnsEnqRK%2Fcjf54yVjP5gwtJ5ckcD%2B5mik%2BivH%2FAI3wD5RnEtpwrWgw983RGby1qiqKlYGkA%2F4x%2FvP%2BNchnke5BIUGoPQ%2FPEJHJ6XG3JFbxAOPxOA1iX7sUwIdmzZsVdmzZsVdmzZsVUbqBbq2mtm%2BzMjRn5MKZDLP4rC2UVq9qYj7SWshWn%2BtxOTnIVG4ttWvdNaiiK7FxGDtWG6Ti%2FwDwMuShzRLky%2B1lE9vFMP8AdiK33gYscKtBmDWhtq%2FHbOyMp68SeSH5UOGpyJ5pYde3moWPmW5KzH0pIo2WNt0A3Wv0ts2D73zJ6FgzxqqXpKpHG9eDMx7EYXed45VeC4gPCdYyqua0I5q5VgOv2cAW8sWo2QMqhwwoyHcVyQFhVOLzvrNrdf6fFHLFX4kVeBH%2Br1%2F4bJlp%2Bt2GqWrXFnICyKWeJtnUgV3XOP67qFjaFLHUrprecy%2BlZajxPDmN1jn8Dv8Aa%2By%2BIaXrclrdtZ34NrfR1USofgeo2K06c%2F8AgcBCXr%2FlvXRrdnzk4rcoSJFXYfMbnDzOV%2BTr82eqAOQIpaBq7AV2r%2BOdTriRSEp8z8RoN9I5AWJPV5HYD0yHr%2BGQg3Ntq1lcLazx3CiZviiYOKzQo9Kjb7YzoWqRevpt5AOskEij5lCOmc60%2BWCK0j9ONYo5IYp%2BEahQWBeNjRafEcMVTvTb%2B80fyHZ3FugE9vSORJBUqPVZW%2BEHw3yVaXeC%2FsobulGkX41HQMNmH%2FBZzC%2B1iTTbadZUkjtJjzkQqSKqNm5fsdMPfyr1%2FRdT8vra2E5N5C8kl3bSMTKpkctz%2BL7SP9peOA7fFkIkgkCwOfkz7NlA1y8DF2bNmxV2bEJLy1injtpJVWeavpREjk3Hc8V64virs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F9Xv%2BbNmxVplDqUbcMKH5HIPokjWsstqx%2BK2lZPf4Wpk5yF6nF9R8xswHGO8QSj%2FAFh8D%2Fqrkoc6VmSMHUOOjAEfTjsAaZMXhMRPxRnYf5J6YPyJV2bNmxV2bNmxVQuzOtu729PVUclBFa07U98DafqsF6i9EkI6ePywwyF6vG2i6oJRUWl6xZCP2JOrr%2FsvtLhG6s0yiK4X6Zfi4QI7Vb9lv5h%2FXDHrgV5c8B0LzLc2Q%2BGF29WDw4SfF%2Fwp%2BHOg6ZMHi4j2YfTkZ%2FMGwpFaazGDytm9GYj%2FAH25%2BEn%2FAFX%2FAOJ4N8uXwliicnps305LmFZDewrc2dxbt0lieNvkylc45%2BX10UCQzHjLATE4P%2BQeNc6L55e5i0J57WVonikRmZDSq7jf2yB2Op%2FVYor2%2FwBNjktpAGjv7ZvU%2BInoy8Vao%2Fa44xCQ9as25RVBqKnfBGRby9rBEsljcIY0aQ%2Bg5FCCQD6bj9lslGAikN5s2bArs2bGyOI0aRuiAsfoFcVS%2B%2F1q2sJltyrSytuyp%2ByDsC3zwxBqAfHfI%2Fodmt2z6pcjnJK5dAexPT%2FgRkhxV2c782mSy82WUgNIdUhNs4PTmlXQ%2FwDBDOiZAvzLb6nHpOrlFkjs7lWdG9yvxVG%2FwiuGJ3Up3YTJFr7op%2BC8t1ljHjxodv8AYtkiyHbxx6XfKx%2FcXBilJ3%2BAsVUV8FRlyYA4Z80DkkPmq3EtlHJSpR%2BJPgHBH66ZBtIufqt9Np8pALHnEpO5p1oM6Xq0P1jTriPoePIfNdxnLtZtrGZluBcG3vF%2BFJYuJfx40IIxHJKzzb5et9ZtZYp1LwygcgPtKy%2FZkT%2FKWuRKKCOC6tNH1CblcWiILDUWHH6wg6wyDejx9Fw4sfOMjEBY5biH1HgLy8VYulOfJV%2By38q4ndH9LlL219K4iilHrWzLxlhI6SgE1%2F2SnFKo0Czxy28zMqcSzspIYBPj2I%2F1cd%2FytnVZdNQ2D1I%2BESMoPw%2FzMftdMG20TSQyyblmjenzoc4TY6ld6ddyKwMUsbFZoHqNwd1KnGXRXs9n5%2Fv7lg98GlWhMjwk1A%2Fm4k%2FF7jDSwSPULTTJI3PGBphGNwG4OHVW%2BgnONX%2BsWFpDFPaSSJcTESG3TcRlf2uRK%2Fazq%2BkR3aeT7e%2BjnX6yoW8ibht%2B9i9Tg%2B%2FQ98QVZHqstutowuSPSdSpV91IPVWzif1i98t%2BZ7m40FjbSWUrNCqEmkex4EH7acT9lv2c6lonmbTvMUTWdwgiumWktrLQhge6H9of6uRLzd5ZurDVP8Q2KetYFUW7jXeSKi%2Bm0hH7UZH7X7OCY4g2YM0sMrjvexB5SHcXsnkPz3Y%2BcdPqKQ6lAB9bta%2F8lI69Y2%2F4XJeDXPJlvPe6JqMeq6NMYLuE842To6ntToyuv2k%2Faz0J5E8%2B2HnGyI2t9VgA%2Bt2ZP0epH%2FNEf%2BEyESeUuff3tmbFAx8bB9H8Uf4sZ8%2F6P82TMMLNb1iDRrQ3EpBkkPC3j7s5%2FwCNV%2B0%2BGVc4n5m8yfpnzJcsr%2F6HYsLe232PBv3j0%2Fy3%2BH%2FY5JxkLourX175%2Ftb28maSZrloqsdlQ1Tgo%2FZUDO755%2B8uxlvPcMI6i6LAe2zZ6BwlS7NmzYFdmzZsVdmzZsVdmzZsVdmzZsVdmzZsVf%2FW7%2FmzZsVdkb83W5%2BrW1%2Bg%2BK1kAc%2F5D%2FCf%2BG45JMC6jare2FxaEf3qMo%2BdPh%2F4bCNiqV6VOOcTV%2BGReB37%2FaX9WHoyFaJMz23BqiWE7juCh%2FsyaRsHRXHRgCPpwy52gLs2bNkUuzZs2Kuwu1rS49W06Wzb4XI5Qv8Ayuu6nDHMemKvONE1KWGVrG7rHPCxRgeqsppk7sb0XC8W2lUbjxHiMhnnnTHtLmPXrZfgakd1TsR9iQ%2FP7LYtomq%2FWI0Iakybof4H55LmFZdqNlFqNjcWMwqk6FD8z9k%2FQc515XuZbW4l0%2B5%2BGWFzE6n%2BZTTOlW063EQkXY9GXwPhnO%2FNsS6T5qtbofBHqaniexmi%2B2v%2BsU4v%2FlfFgHcrPTFbanZNb3caywyApLE3Qj3zjutwW%2FljzBc6Pp6fV9JHpsLNSSgR1HIorV3Vvizq2jXQk%2BAndlBA9xnNvzRiWPzJBJWnr2gJP%2FGNyv8AHAdikJ3YGf0o5pZDIboSD1GJJ9aAgh6%2F5aUzoFnN9YtYZ6gmRFY06VI3zlXk%2FVI5bi2hnlBgdBuxFFahhfr0rSNsnHlXU4JI5NJaSt1avIQm%2B8RaquD0I%2BLjkpbgIZJmzZsirsDagC1jcqvUxOB%2FwJwTjXUMrK32WBB%2BWKpfofE6Xb8f5d%2FnhjkMPmvR%2FKlrJBqkxBSVkjC0PIDpTfI15s%2FMNbu3jbR5plsZVp69swRi9N0eSjMnH%2BRcVpm669cWWtXGnatwjgKma2uPsj0x%2FNXw%2FayOfmLr%2BhX3l%2BPTYrkXM%2BpGtm1uPUUceX7yRx8KLtx%2F1s5xoN%2FefpVr6C8muVVfUuLO8kMrEIeTem7faRk5Iy5FdTuZ9B169trGZvqkc5eFD8SmJzzUcTtsrceWHzTT3fRJv0p5UZvtOYYrgCu%2FJV4P%2FwANHnPrj83vM2lX9zpWoBJYInaJ540pOi1%2BGRQDxf4cln5Z3qT2stjWrK0iexEgE60%2F2XLOUfmHYNZeZbhWP94Ayn%2FV%2BD%2FjVclLlbEdQn955q1wTiU3huLadeQCsfSljO9VNev%2FAA0bYHub1Z7V5yWkhHxpcVHJNwGiuP8AKStVk%2FbyGafqLQxyafO5S2lPJWUAmGQ%2F7uiB8f8Ad0X%2B7F%2Fy8Ctd6jpl3Lb3v%2BkQTpxniqTDcQn7LoR%2FwUb%2FALDZCyyekWl9ZyaFLPelZGN2tqDEtZJHenEs67ckpVXwq1bU7G1iKWvqtcCR4bkkhFYx%2FCHXhvvX48C%2BU7H1SbK3k9Wya5hv4HchSBF8FxBL2WeOJ1k%2F4s9P4cu%2F0j%2Fc1FphmFxPLeOhZBxAiL8jt40%2Fa5YegV6PprvLpcE8sfpTNbh3QVoGK12zluoQ2PnZih42fmWIVt5z8Md4q9I5P5J17Z2A8YrWVl%2BERoaDwoNvupnLtb02LzREdR0hBba7bVe4tEPFZwpr6s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xKXcslu7tXb1%2BSBq%2FwCSzZK9c06xuNUutStkBls5IFkAIAMoHqUUfzNRkbCPW5Xs70rZcVtL0%2BtCoAFVc1oK%2FwArni2RIShdD0rU9Z0g2UNW1DR5JLG%2BirRlQuXhmp1ZP72M%2FwCph75g0K2sra21G8ch5baGJUpt6yARuvL6OWEQk1eJrq9s55YLxBzuGhJEjr3LKvxSqv7WISanq2oQRXGryvd2MtVhuSQ8aNQch8OyNjsqElhK1hbcr%2Fcv3K%2FyV%2FycRSQBmUiifsfQM6FpfljSbrR0mCy3EjDlDIzN9sGnphU%2FZ%2FlbIrqnl%2F6jM3Cb1VRqOoU8078XoOHPISIiQCd5ckgE3tyS4StK6xSy%2FDJ%2B7HqseO%2FYVw0W2thatp10he2b7YH21cfZljP86f8AD%2FYxO4tbO4so4I7ZUvG5Lpl3PssprUws392JD%2Fut%2FwCbAOh6sLuU6VqYMF4hKRu2x5DrFID0YY7rsh4tMn06%2FkspjzjniaS1nQfDIE%2BJWXwdafEv7Od0ugnmL8tmYipWEOB1oGWp%2FwCH5Zy4hoT9WuU5BTzj7FHp%2FeIe3%2BX%2FADrnR%2FysvRfaHeaJIwZ4RJGo8QDzQ%2F8AAy5OPVBfPNxbpMpifYqaBu4IwFYWlx9fEIJU7lmH7S%2F83ZJ9e0x7K9unRg8azMkoHWJySVR%2F9YH4W%2Bzj%2FKtvFdaxBDLQKzAVO243G%2F8ArYPJUXb2NvDZtdyWxe3B4meCQ%2BtG37Jkjb9lafaXHRXl9q2r6etnWJ7Yxx28h%2B1UNyMjt%2FlH4myX6lp1poPm57CIFLG8jikCsKisqqXWncc2%2BzhLZW0Om35hCuLiCeSgIHFY67KT9rl4YaV63IwMVSakg1pt27eGRuzvrTWILdYbnlcIWXSdQc8W5pXlp91%2FLIP91M%2F94mG9tcfW3AQ14xgsPH4c4Zp%2Btz6HqN2rJ61nNIy3loTTkA54yIf91zR%2FailyRNUinpV0iXqyyxw%2BjdW5Md%2FaN1iPdqf74f8A5Jtka1ZZ4LWYxsySKpaCRT8QI%2BIxkj2Hw5KLe6%2FTsUF%2Fp1wsmrRRk2l0QAL6Fft290g%2Fu7uP7Lo395hFquqaL9XZmmWCRwySWTgs8MgG6Oo%2FY5fZbAUhC%2BZ9JsfMl1SKYW%2BqyQRT2DMf3UvJeTwt4M5%2BJchKyrOr6D5gQwTQEpFK%2FwDeQv8Ayn%2BZDk%2B1Gyj1ew0SaC4gS5ntmCtX0ELQtQAM%2FEcv5Fwv1bQxr%2Bnhr4oms2ymP6xuCStSIbof6v8AdzYOaGAQ%2BXdTm1NdLjj5SN8QkG6FOvqBu%2BTjTrS2sbZLCMcVUmkpFGLn7Rf%2FAFv%2BFxTTme102DTuILIwZpKksW%2BzxWtW41%2FZyU2XlW41HhcahytOQJZVHKaXw%2Fd%2F7rY%2FzviAqQ21ldXtytrDG0k524qKmnj8sO736roNmNIltfVv7hFeaMnkUqTwpxNA2S2MaT5etS9w6WdtEvx1b42A7Symh%2F2C5zTzb%2BZun3swOjacGVKwrqMgoajeiJSr%2FOTDVdVZPYa3pOj%2BW7u31uKKzuZGP1dePP1Iz1UovxtJ%2FlYU%2Fl%2F5hOtyS%2BWrlis1Gm0pyfiR4%2Fi9Kv7SumcrvNYnu5DcXH7yToamrfSf6YL8ratLZ%2BZtJvoT6bwXMbEjuCwVh8uJauPFuFe%2Bx%2BYJ4NMawQiOFzyZOlDX4h%2FwQyQeVtAn1BY9R1QN9WU1toG%2Fa3qGYeGE3lnRLPVfM19LdAyWkTtcW8a7xOGaq1kGz7k%2FAM6moAACigA2AxJ7lojn72wANgKAbDLzZsirs2bNirs2bNirs2bNirs2bNir%2F9Hv%2BbNmxV2bNmxV2Qzz3p3P6rqKbFKwyt%2Fkn4lJPseWTPOVfnX5gmstNtdBtnMbajykuXHX0YyPh%2F2b%2FwDEcbrfm24MRzZI447GR59w6pMfNyWl7EdD1KM3Cp6dwoKldj%2B1zHE%2FRko0rz1rUtz9SvLe2lm2Hp8jC7BhWqV5xvUb%2FDnn01jPEin8pHgckemXmsTaHcxANw05o57O7IIKxliJYll%2FaRT%2B84%2FsNkIZhIkSjRDl6zs%2FwIjJCXFHkb5gp3%2Ba2r%2BbdPuEvYLVbLRpiFL27c2EvWkj0%2Fd8v2VpkGsfN2p3Kra3V2XicgEsQeQJ3qSNs7d%2BkdO1rSbKw1LhN%2BlbRXVJKFZyq8ZV3%2F3YGHLOEecvKFx5TvTLDym0idv3EvdG%2FwB9yf5a%2Fst%2B3lpHUOvsua4iNwbWCruHK%2FB0qN9j0zoy%2BarW48r2Oq3l1Le2sSizuGkqk6zgUVXMda8F%2FwCDTOO2M01rIs0XCRQ4kHqCqGnZl74NgkTlMqSOIZpPVNrXjGG8Qvfj2wXzSyqz1eO%2FtNSjQM8sVubhFbbkIpPiI%2BUR5Yca3q17IdPmtZ2js7yztriONNhyAKSciPtMJUfIZaXDWL%2Bra0jcq0ZYAV4yAq6mv8ynJf5Yex1PRjpUsfO%2F0pnuLJWNPUgkNZ4l%2Fm9Nh6vH%2BVpMRa2uvBcXej2Gp2rSC5tJJbOZkqW4v%2B%2FgY%2Bx%2FeJhtBB5sOi313boLa9ihMlo3EB5ClGkULy%2B16XJk4rhlZarBFAbZljtrS5Tg%2FoIF4fyOT1JjbC1L%2BbSbowyMwu4WrzJryX9h1PQpxw%2FFWFXNut9PB6srS6frlqI4JZHJ%2Br30bCsbOf5phx3%2FAN1T%2FwCRgPQbtreVrEFrW8gfnDU0dJUPF09unHD%2FAFeygjjvbi2haTQbpxcXlpHvLp9x9n6xClfjtjXi1P2P3b%2FGseE99ol9qtyjIKamYlktb6Mn0L5QKJ8Zp6d3x%2BH4vt8OD%2FvciTXPZaZ%2Bkdp5%2Bgt19Yad5p0%2Fe0vU2Y8T0NPiaM%2FtJ%2FuvOj6lcGysFaRlYxJWUjfkUXk3z5MM5p%2BV2l3U2pPdalFHK1sOLyqQxSZaFOdDWOT7W%2F7eTTzK8UdlcxREhXBTf%2BdzWg%2B7JxNji70HnTz%2B51GXyrrFxaapD69nfcRqSftqxHL1oj%2FOjPjtQ0GNYCfrCXWi3QMtlelhyjkYbFfdvsyx4M87Wy6zqemTq4X9KwQnmegkK%2Bmf%2BSi5G9M1PVfLUt3od3CJIGDEQS7iKUD4Zov8%2FjyErqrruPNkK58%2FJN7Sx0%2B0sDe3k0k9xA6JBJACGqwPHiKp8S8fts2F0mrDS3nubPThH6ZLa5YcQsnBvs3kSsCnJeXJuK%2FB%2FwAYmwQ%2FrXdjEsQRizhvjKCrUp8If4uW%2FwCyuK3Fs893p1nezfVdeDCOxmHFi8ZH%2B89wSeBjP2YuX%2BVFiYggA70Pmt9QzfyjdxXeiPeaY3rNYt9ZjdKUkgP2gyj7L8ftL%2FPgTz2tuLdJIT6cN1JFcxzJ2U7Sb%2Fs%2Fa5BsKfLEMvlPXby2sJI40uF%2F0izVuUcb05n0z3gkTlw%2F3237vHeddXN5pEMdnbmOys4BFcy0qDcF6GJa%2FwDFacmyX8Pu2R1QOi6Yupabd2F78dj6xjLVFUlpySaHwkUf7F0%2BDIrrvl6dr42N0eOtRIHs7ldkv4B9ijf8tKgfB%2FP%2FAHX28mPluyb0Vs7OdTL6SSReoK8%2FTZqN%2FrqOPL%2FJwTqdhFr9m1lqUhjnhcm2uv8AdltN%2FMKf7pb9tP8AZrjVhWHaHrEWqxjTb9gt9GKQytsXptxNf2sl35d3J0jznJbCojuQlR26cT%2Btc55qthdyXcyyJ9X8wWfx3ESbC6UbrcwfzS8fjfj%2FAHyfvPt88N%2FKuq3F3q1hqBIEyc4pWZuCkoAwck9MA50VPJV%2FMq2k0TznfCJQUmPJom%2BzJG%2FxcW9t%2FwDY4Q6cILa6ZY2eKRwslv6goaDfjy%2FaK4f%2FAJleadM80a8t1pcZ9GCJYmuG2MrD7TAfsqv2V%2Fmwr0WyuNXUw%2FVxci1%2BKLt%2Fw23wrg6qGVanr1vrK2t3csIry1aESBjxJEYYOQff4cjvm3zLbpZXLWTGC5vr%2FwCswRjfjBGoC8yfi%2BIjCPX2vNMu%2FqZDRNGKSAgUqxqgqKruF%2BH4sjsyPPIZZSXJ7knfG1e9%2Flxrdt5ksbqdSFu7eMLcW5O4%2BE0cV6xvnF75uVzcb14yyBW7%2FaO2KeS9RutC8yWd7DMYLfn6d3L%2Bx6D7SLJ7YhdkNd3UkRDRSXErxMDUFGclT9IwndCtpWrz6ZN8MskcDsGdojxkjcfZmip%2B2v8AL%2B3iWoySfXbiHUmFy14frKXqH4nL14zK%2FVuX7cbYEeJWDPQVpU0Pj0x6yqLL0pJUW4tXE1o5O9SaSRbeP28Cob1Z1T6vPKzxjeNSSQK9aV%2BznXLfUrdtDt9T1U%2BjeRxpa3iMvF5V41jcg%2Ftrx%2BLOd6VbaTqJlS7lMl5Iri3hHwRiQj920snhzODppWsii6zcGeSZg3po3NSy%2FD%2Fen4K9V542r0LyheaXcm5uaCCWNhxkl%2FvClOqcvs4rrn5g2enI9tpKi4uqlWck0rSvxP8Atf7HITazpc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2FLhpr3nLTKJ9UT19TB4zNHtCe3Jj3b2XIssp1Y8bUfFOQsix7SCSlAXpTmj4av5OnsdM%2BuzB3Zm9OWaNGD2%2FMgRTolP3sXP4Zv92fyYi6oITDVrG28x6NBeBvqWoWS1ivSeIikU8jFI%2BzLA6%2FGn%2B%2B3yFaq1pcXix28ZUGi3U2wadx%2FuziAEWv8Aq%2FH9vDLV7TzXeWrqbaWO4VhHeNHtFdCP7EhX5D4v9%2BfbwpC3liGgvIoVdSqt6pLPGr0pTj%2Bz8Xw4CUkEGil7RwRu9ZzwjPx8UZiKePShyb%2BRfMdhHM2kLEV%2BsDlDLQFncUCxcRX7WEF1DCs63zCs6r6c1Nkencr7rgXSpFsb5zCForepC9PiUEfZr4DADRVD%2BddUkPmPU4lUgVNtNG4qDw2Bof2kP2GyK1LECpY%2BAqTnUFhsta1Ce%2B1G3inuZCrySsgqwqFNRkwu9R8m%2BWIwscEHrharDBGjSH5tT4f9kcIoop4da6Vqt2GW0tbiQHbikbkH57UwHNFLbSvb3CNFLExSSJxxKsuzKwPQjOu3%2Fmq%2B1mFo1C2NmFMjhTQLGu%2FKRtumQfU%2FMWh3uoTXx0r1pJePKSWSnJlVU5lQNufHnhQxmOYxklSPiFCDvUZQKUIpUn7Jr0%2B7D8eYrBP7nRbUf61W%2FhmPmtkBFvptnEezCMkj78CpRZOY5w%2FBmWhBCjseuSyyn0pIpIr2CSr2gtbYTQt6aylufPp8PBWbCZPNurROskYgVkYOv7tSAVNRtg2780%2BYPNd5CdWuRJHEWkWONFjRaih%2BFAPljsqLeRrVh%2BjQt3GBRoXBBKAfFwag%2BLJ15B17yfealE2taTHcXMG63Eq%2FvbYL%2FvyH%2B6eFK%2F3iJyT9vAXkPygPNEuoxx3KQ3VrAHtYWP8AeOxpv%2FxWqijMv2WZMLdS8vBLx4pg9jqVqTFJIvwup6fvP5lP%2FDLillv5i%2BStPtL867pEEcem6hxkivLWjIk%2FevHb05ftZF9Okd5Et5mayvoWEtrdRmnCUfYmhYfzftp%2B3k3%2FAC68zLfx%2FwCFdWt1eElrbUoW%2BwGIrDPGv7CyU%2BLj%2B18eIeavKM3lq7WqfWNOkYizuXFeNesE9P8AiX7WNbqCncfm2f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V1PpOsrBduRLFcPb3JY9VditW%2F2XxZ0%2B91O2spIoJWL3E54wW0Y5SOf9UdF%2Fmdvhzm%2Fm2w%2BoeapJlBVdRjWdCDsZE2cfeuHdvfQW0BngZptVvEH1u%2FlG6gj%2B5hH7Kr0xHc0pD%2BYg8wa1NDFZWjSWtsrCRoiGJcn46b1YdF2yFWemzxsW1CN4Ej%2FZlUofubOs2WpxpNGl2oMP2eSbEe5yTXGkadqFpJaT26T2860YEVBB6EHx8MeCzdpunlEtpHYQ38GqRrFNaPA8EgJcFa%2FGqhadao2XBGlmbe2uCzevbGeRo2PcNJx%2F2S%2FDht51s3sLpYLoH6ncIq21wRU1UceLt9Hxf8Hhj5f8pXerWc%2Bq2VrHqE1oqQWdvNLwUoijmJB%2FO9W4%2Fs8cjVH3LezEvM2mXWqyabNozB7SS1WJ5SwBrHWnLv8A3ZUbfy4onlazmtrKC%2BJlNoHFFNFbmQaHvtTJ9rPlzU7GOO6vrRbeNioQQMrRxmn938IXj4YE0fQLnXBdQ2062l1CP3SSry9Xav7og0%2F4LDsikps7C3s1WK2iWJB%2Bygpg5lNOX0YAVr7TL0xXsxcxsVlhktwpFPtLVWwbf%2Ban0e8tp7LTYrmyILlpyT6hoRw2%2Fu%2FTbdlw3taoK4v7a1dY2dW5GjQ1qVHj%2FwA24Vah5a03VlNxZEQTtvyX7LH%2FAClyfjyfo3nrTrbV9PRNI1i6gM8qRENC8gb05OUI%2BNR6nR1%2F4HIRqOj655Vu%2FQ1SBogT%2B7mU1ikA7pJ0%2FwBi3xZGwdizhOeOXFCRBSPSZNX8maml1MhNsfgldPijdD1H%2BS37S8s6ZLrEEZt2uEe1W6VWtLsg%2BlKGHIGOReS%2F6wOR9dWtRp11dSQ%2FWHt4Wk%2Br93IGyU%2Fysk%2Fk%2FW5INATT9Z0eAWczGT6gr%2BoIlfcgBxsf2vT%2FAGMYxMSeE2D07m7PqBmjEzjWSO3EOUo%2BY72M%2BYfLcd3FJeQRxyo7EzQU792GQ60bU9Hkf9HTAwts1jdVeNl%2FyX%2B2n%2FEc7ZL5XstVSS58p6kYZqVbTrysif6tWPrRr%2FspVzmuvaDq2jzsup2JtA5NCfjtmNf91Tjb%2FYyccJ8tmgJPqV4JJLJpI3sYLqJ2uY%2FtBgP91q6jpIy8Vw0sNNn8tG11m8KWNnqTrAums5YhTvyct%2B0R8fw%2FYb%2FWwLdRpfaVEkkPO50r1HhjJALRSg9HpX92%2FwCzgSW4TV9Hga5uppdVspFt7a0FOMNshHJm3VuZY8fV%2B0zfBlZHq3BNigOnm52LIfDHCYwMCJmVXI8IqMYnzI4f85l%2BsRQc7eSKVRPHKts4ruUkPAcv9R%2FiwbZaY1p5gtrHUoipjnjWZOo4lhRv8pGwcPL9pcROZo2S6ZkaXgyqoaFVk4hn%2BJ9uPqNxwVrmsWupvYzalF9S1K1lTi6GscsYYMpV%2FFWUNx%2FlwYoSjd8jybO0suLMcUsdmUQROxRrnH75PQtd8vaT5itBZapAJI0YPE6njJGw%2FajcfZzg%2FwCZWh3GhW%2Fr2wH1vSZ0DXlPia1m%2FuZuK7MV%2FuLj%2BbPQ1pdR3ltHcxGqyCtOtD3H0HIF%2BZFnb3k8EMqhxPBJHOh6MnIUDfSdssDq3zfqWmR6lFJqenRCO6iHK%2Fsk3FD0ng%2FmjfC3SNVudJuUvrKQJdQOrxc1DoafaSRGqrK%2FRlyU32i3XlnU4RHOYrF2Isr1hy9Jm%2F495%2F8AimT%2FACsKte0Zp%2FW1Kxg9KaL%2FAI6Nipr6bH%2Fd0X88En2lfFX0%2FwDlz5x0fzbpAlsIYrO%2BgAF%2FYxBVCOR%2FeIBTlE%2F7Lf7HJpniLyz5m1TyrqVtq2ly8ZYzuvVWX9qOQftI37WeufJnnHTfOekJqViwSZaLd2pNXhk7qf8AJP7D%2FtYFZJmzZsVdmzZsVaOct%2FNj8sx5ntJNb0NfT1uBayxrt9ajUfY%2F4zqP7tv2vsZ1PKOKvhz0CsbwMzqSSHPRgw2%2BL3%2FmwrlheB%2BD9exHQjxGeqfPH5Oad5lupdW0icabqU3xTqV5QTN%2FOyr8SOf2nX%2FgM59H%2BQfmu5nWC9ns4rbl8U6OzMB%2FkpwGKr%2Fyk%2FOBtOMPlnzTMWsyRHY6g5qYq9I5j3i%2Flf8A3XnoxWV1VkIZWAKsNwQehGc68sfkv5Q8vBZriE6rdrQ%2BpdAemCO6wj4f%2BD550VVCqFUUVRQAbAAYq3mzZsVdmzZsVf%2FV7%2FmzZsVdmzZsVdmzZsVdiNzNDbwSTXLBIUUmRj0A98WwNfPaJbSm%2BKi2pSUv9mh2pirAPON5pMWiStoiPJfM1bVI4yy1G8jDkCnwrhDrD6jFb%2BWbC7Wt36Ecl%2BCP%2BKiZHbtyJajf5WDvP9xZRaNCfKtxKb4zj04IOR403JKkfAOfH%2FWws84ajNd3EEklFuSOUtK%2FDRVXiKduQOFIeeatpk0F5PeaUj%2BlATLIYwSYhXd%2Fh%2ByleuLP9U12ykmiWO2vrWOW4n3PxgcAFXmaty3cf77%2Bx9jO1%2Flvo0EejT388SvJqDMjFxXlEvw8TX9ls5h%2BY%2FkSTyne%2FpHTVY6LdsVUj%2FdDt1hf%2Fitv91t%2FsMgRW4dxo9X4vDiySqcfon%2FO%2FoyYJsQGHfJL5FsrXUdZk0m6uTbR3UTvHQAgzRjkONSODla5GgcX0%2FUJNL1S0v41DPFINm8G%2BE%2Frym%2BHMD0k52txeLppjqPUPfF6l5X8xWlm995evZlguLSdkjR9gTWjrXovP4XTEPM6wwzKSKCT4tuoIO%2B3vke80xXU2tW13ZQ%2Bo15bq8npJ8UlELVp%2B3sMBWOsXOtWy2iEyXNuCyIw5Myf8VsaseFP7tvizL4tq%2BTzNUfvT%2BOU6npky9ZrciVAO5Xw%2Ba8sis01rp%2FmC01O5YrSWJ4kXcyFiB9nsK%2Ft5fljzLXzMlg0bRQujQESbVlDcl5IenL4kyeebPIp8y6j5e1DSEjX0XWO4QsqKYk%2FfRgV%2Fb5gx8cHMe5lGUom4mjuPnzSW%2F1OfVL6R7sJW2keKFUGygGhIJ3PKmNVy%2FTAk1pdWc9zBdrwuElcTIezA%2FEMj%2FmjXbvQtaW3tEBgCJM6PuCHFQExtizSKI1DHJv5VuxKrWMp%2BwC8JPh%2B0v0ZCNLvrfUrGG9tjWOVQfkf2lP%2BqcPdHme3vIZV24sKn2Ox%2FDJBSyzzBplrqWnSQSxLI0P76EsoIDqO3%2BsMgmlaxceUdRXU7ZS9jJRb62XoUP7QH80f2k%2F4HOgXdyVYgHp1%2BWQW8g4TzQyoQpJIVh1VuhGJCh7FG9hrempKhW4sryMMp6hlYV%2B%2FOWa%2FbXfk%2FU0ZJOEL1ayu2%2By1P91udv3if8OuCPJ%2FmhPL1xaaJetx0y4rFFMx2imJJSvhHLXj%2Fr4N%2FO9G%2FwAJ28o%2FYvY69%2BqOMgdlYzqPmWy8xr615aouoxAA3dk4dJB0%2FfRGjofBl54U%2BnCySRNSa1l%2B2vQq3861%2By65GPKcztqxjY7NEw4jYbU32zoNppF1qfrw2JX6yierHExoJivWIf5fH7DYYnZaY3pN9N5N1n9JJEbuIwyRoisY1kDbpVu3F%2FidM7xpl3Y%2BadFt7m5tle3vIUkaCYBx8Qowof5WB%2BPONG0jvLY28qlRUgqwoyOOu37LpiXl3XbjyZqk7XglmtZIfTEKNQGh5REFvsxr8XLjgIrdWQedvy7GiQPrfl4SNaxVe5s1q7Rp3ki%2FaaNf20%2B1kT07WGCqwcMjdJFNQc9C2N9BqNvHc29WiljSVGI2KyCopkFv%2FwAotHu9cOq2d1JYW0x53dhAo4O53JQt8MYf9ocMFyB23ZwGOQIkeCQGxqwfIsatNQSQrIrmOUbrIhoQfEEb5LLHzPP6X1TV4RqFo4ozFVL0%2FwApD8EmFms%2FlxeWBNxoEpuIhubSQj1B%2FqPsHwo0%2B4ltUmW7Ro5ojRo3BVhT2OWCi1t%2BbPJ1pFCfMXlJgtl%2Fx92VCyRHuwjb4kX%2Bdf2ciOlG2huhcX2n8JI2BE8FHHzMTb%2F8TVc6FpWutaySPblJEmHGeCQVVwP1ZGtcsIbe5N3p0Ui2MlWaM7mB%2FwBpQ4%2B1F%2FLkTGulhnDIYnYprf6tYaxaxxCDlxIaG7iko8Z7kGtWr%2B3ywxsdGl1WwitzGbkgkRzugDGnRm34R0%2FZbIJBZwxv9YhAVx8Qp0JPiBnafJl1eXekLNdyrKOXGNgADQD4g3Gg%2BE7Y8WyTLfiHNJbbQvNHle%2Fe50eQX%2BnXAD3Vg53EoWnKImhQmn7Pwv8AyYRX9xql1dmXWOS3XHiqMnp0QEkKq%2BA5fazrQwHqOmWmqQGC7j5D9lxsynxVsFsLeO39hb39tJbXMYlhlHGSNuhB%2FUffOZXy3%2Fl7UV05n5MgrpN1LTjLCT8VncEj%2FYf5Odt1nQbzR3JcerasfgnA2%2BT%2FAMrYB%2F5V3Y%2BdtAvhefubrn%2FuNux1jkQUYkD7Ubnir%2F6uEq8D1rTFk9XUdNgaHix%2Bu2XVoHPcD%2FfbfstnQfyAeb%2FFktC%2FptaSF1VgFNGTiXFfiA%2BLj%2FlZC9WuNd8p6kNM1e04anYsY2mY7TW%2FZG2pKjfsS4K003mkCHzl5WmDLazercWoB9WCvX1FB%2FeQt9lv8nIofYNRl5FPI3njTfO2li7taRXkQUXlp3Rj0Zf5on%2FYbJXirs2bNirs2bNirs2bNirs2bNirs2bNirs2bNir%2F%2FW7%2FmzZsVdmzZsVdmzZsVdgHVY9PmtHi1JlW3cgEuQBUbr1wdgPUdNttTtzb3IJWoZSOoYdxirzHztP%2Bi20aTyvdm6uDcJSCMJIPTVhRWKj7Bbbi2B9b8keZrnV3FvberbsQsVwHUKFJ6tU8hSvhk%2B%2FwAPGy1GwvLOkqK5ju0cIP3YQ%2BnItAPiif8A4nkkphKQaQOk6eml6ba6fGQVt4whPif2j%2FwWO1LTbPVrGfTr%2BITWtyhSWMjqD%2FEfs4MzEVwIsg2Ni%2BVPOHlm58p65NpU1XhP72znP%2B7IWPwn%2FXX7En%2BVgW28s63f2kWr29m76Ys6xyXQpxUggNUfa4iv2uOen9c8t6J5it0t9as0uo4zyjLVDKf8l1oy5EL7TriGW30Lytp7Q6Dbs0d7xI4Oz%2FFWPlycmNvib%2BfKziufETs7WXahOn8Ph9dVIn6a7%2FewDzPd3ukNplzYtxtEhW2adVBKzRktTkalOdf%2BBw60bydZ%2BaNR%2FwARaPq0VjOIw509bcLIkw%2B16yh%2FjRm%2F3an28de6dLYTXGk6xDztpx8aHoyn7Lqfb9nI3YX%2BreQ9ThS3pcWhcvazMBWSE%2FbgaQ%2FF8P8AJlrrDvunvmryB9buFvzAtnrkQD84z%2B6mKHkGRtu%2F82HWnO%2BoadLpU5aC4ZeUL9Gil%2B0jKR0aOYZOLO80jzho0d3Zv6kMn2WFPUhlGxVh%2By6H7WQWaO80rV1hvwBMjcfUAoskTbLIP%2BNsIr5oSu10tfOt7Ikt4th5ijQC6hkSsdz6fwfWIiCCr7UmTj%2Fl5JG%2FKTSdTjg%2FxDILh4UCUgHD7P8Axafj45GPMdkYtRkvbWf6jewEXNhcr9ppT9pEVatJWnxJx%2BznRPIfmz%2FFujfW5Y%2FSvLZ%2Fq94gBCmQCvNQfiVX%2B1xb7OA2NleaX%2Fkr%2FA19Jb2rO%2BlXbc7UvuFbuvL%2Bb%2FiWC7M7HOuarpdrq9jLY3i8o5Bse6t2df8AKXOP6jbaj5dvpLK5USBd0fcB07Ov8cMT3qkP5l6trkWp2kNi8sVr6CShoyVDyH7RJHXj8OQpfNfmCN1%2BsXcsnBeCrOfUAUdFHP4uP052ny%2Fq2g6veR6T5hgX94Almsp%2Fdsw%2F3W%2F%2BU37GSHUfyp8n6hUpavZse8DkD%2FgH5p%2BGCXNeTwM%2BbzeWxtr%2B3SVHFGMZKMP8oBqr%2FwANh9qv5gpr3kVfLV9zk1O3uIjFOwrzt4w1GZhUeqn2P8rJD5i%2FJJrK2lvNKufrSx%2FEYCnCXiOtCpKPx%2F1M503lq7tpDxDNUUUGlPwyJtWQflfpMWseaFtLgssZtZnDJ1VhxCn3651e38qanp%2Bs2ZX95brKG%2BtR7UVfio6%2Fs16YS%2Fk3pGmWxvNR%2BspJqfEW7WnR4kryLFW3PqN%2FL%2FLnW8I2UsW8x%2BVo71n1LT0CXp3mjGwlp3%2F4yD%2Fhsgl9oyXUaxX1u8LoCY2dStV%2FaG%2Fgc7JTEbiztrr0zcRrIYmDxlhWjDJCXQoeVeW9Rv8Ay1PKL25kuNO9ELEo%2BIjgaoKk%2FAqJyzqtrdQXkCXNs3qQyqGjcdCCK7ZFPMPl1Yg95aLWA7zQjfjXqw%2FycB6JrNzY3BW7uAbARKgUqSQVIC8KfCq8K8vhxq9wlntK4DvtJ07UgBfW6TU6FhvTwqN8FRyRyoHiYOjCoZTUEHH5FDC9Y%2FL6wuSZ9Ic2M3X0tzEfo6p%2FscL9B%2FLy8XVJNS8y3Yuo41aKz0%2BEkQrGwoWlO3N2zomVTDZV4l5n8s3Plq94oS%2BnTk%2FVZj27%2Bk5%2FnX%2FhsMNI893Wj2ht2thNVSEp8PGSlBK%2F%2BSf286nqOnWmqWcllexiSGQbg9QezKf2WGco13yhdaVMUT95A39zL0DDwPg%2BIZc3pPlzU5dStGa4IaeNgGZaAFWHJWoMOc5v5E1B7Wf6tcAoD%2B5PLb3jP0fYzo4xIYrZIo5UaOVQ6MKMrCoIPtidrZ29lAttaoI4UrxQdBU1OL5sCsO8%2FwD5e6V5708RXNINQgB%2Bp3oFStf2JAKc4m%2F4XOIWX5R%2FmVoOpummwIySAxNMssZhZG2q3Mqen80eeoKZqYq8l8h%2Fk%2FceW9Qt9Z1DU3W4gPJLS0JCEGvwTytT1U3%2Bx6arnWs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F1%2B%2F5s2bFXZs2bFXZs2bFXZs2bFXUzZs2KuzZs2KoXUjILG49E0k4EKetK43TYkhsoQp5EqGZvEnvgp1DKVbdW2I9jhDdaDqT%2FuLLWJbOzP8AulEVnAPVVkb4hiqB8wWUXmS%2BXTYWQi3ikZphuUlqOKmn7P8ANnOtRsiPW0TWUKqD9ofajYfZkQ%2B3%2FDLnYtH0Wy0W3aC0BJc8pJHPJ2J8ThV5u8tJrdoZrdQL6EH0z0Lj%2BQ%2F8a4bTbxXQPMGq%2Fl9r7mSs9jcUN3Cv2Zo%2B1xD4Sp%2FzZnaNYhtfNmgRaho7JcMwE1pKCASP246%2Fsn%2BZf58gsugWWtaPFp1xRL21qFkFCyP3U96YR%2BUfMt7%2BX%2BqvpmqEtpUsnGeOtQjE0FxD%2FwAzUxOy%2B5kHmGCOa1s7%2BVeEsFYpHI3SvwyBvDi647RtH1by3qEXmPT5VlgnWmo2C1Amj6rIrH4RMnVcCz3FvJ5x1pIqX2h30cVy3ouv2nQEeka9XZW5ZJNPult7dbZpTLasP9HlYUalP7uVf2JlH2v%2BEw891ZzY3tvqNtHdWz84pBUHoQe6sP2WX9rC7zJoEOu2Xp7LdRVa3lPY90b%2FACHwi0IahBqtdOo9hKf9LjY0Vf8ALU%2F78ybZFD591jS3R3gnRo5Ymp4MjA9snHkr8weRi0LzJII7pQEtdQc0SYdFWQ%2Fsy%2F5X7eH%2FAJw8uLqMDX9qg%2BtRL%2B8Uf7sQf8bLnJbuyjcNFKnND1U%2Fw8Dh5pfQo3Gc487eVFhMmq2KfuHNbmNR%2Fdsf92KP5G%2Fa%2FlyPeXPM%2Fmfy2Y4pmk1PRqfBBKpNwiDr6E3%2B7OH8j51%2B1ubXU7JLiKklvcJWjDqrDdWH%2FEsV5PntoFiuUuQOFxFvHKpKsPpWnLJZ5b8w65p1xEguXuIp3q8d07P1%2FZVm%2Bx%2Fkccbr%2Bhm2125sbPggX95AZq8FRhy3p%2FL8Srk181aDHqempqtvRLu2hDngPheMDmV%2F2P2ozjsrKLW5ju4Eni%2By4rQ9Qe4OL5D%2FACp5hgu7iOwkkUXFxD6yx9DWM8HNMmGJFFDRFRQioPUHIhrmgrAXubdK2z19WOleFepH%2BRkwymCkUIqD1BxBpWIaNq09o31WURrZoiem32ePEheCIB8VV%2BLJcGB3BBHtka1LQXVne0XnC9eUQ%2B0tevHxXA2lxazHfW620rx2atW4gkSqFOPCgdvjDClVwkA7hWYZswzZFXYnNBFPG0UyCSNvtKwqDimbFWE6voE1hIbu0Be3BrQVLIP8rxXJRo92b3T4Z2%2B1Ti3zG1cGkAih3B7ZSRpGvCNQqjsooN8NquzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Dv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxViPmbyo91cfpvQiINVT%2B%2Bh6RXSD9iXwl%2F33N%2FwWQzW9AXXo%2FXaFg7L%2B%2BhK0mjdBuafzACjrnYcDTWNrPKk8kYMsZDI42NR40w3tRW3z1p2l6ho%2BotLAfXVE5OgDVljA%2BLj%2FxZGv7OS2BbeaRbscpI5YuLQq3ETIfiQcv2ZVP90%2F8AsMk3mi1FjqBnt0CpcIHIUU%2BNT8RFP5tuWRDTFEulwPaP9YjVSfVjBIFGPM%2F7BvHCOSXqXlu6trnTI1t7Y2Zj%2BGW1YhmQ%2BJcfb5fzYcZBPKl1I7GRXHKGi3AY%2FajPRvdsnQNd8BFFDjnL%2FPWhJaXguIKRw33KngklPi%2F2Pxcs6jkY892Ul3onqwoZJLWRZeAHIlT8D7fJsAVBaLpUeueS9PtriYPcWykQXkfZ4yVDD%2FJP2WwX5X1NJ2NrQIGXkoXpzQ8JP65GPJfmOTR5G0zXLmGCzlYmzhZPSeE05ceP7UTjfliOhagkWs3CW0gkUXbPZjoZVkY8kQHr8OSHUJZD540vmYtVRBIAvoTo260JrGzU7cvhzaJ5jgm0t9O1u7giu%2FRdY%2BJ48oyCg%2Fd9QyfZ%2FwArJhPBFcwvbzqHikBV0PQg9sgt%2FwCSLpJy9pxniPRiQsgH8rfzYB5ql%2Fkq1hXU4ZigNwjsizftemU3Uf5Jzp%2BRXyloF%2Fpj3FzqYiR3YraxREsyx%2FzTOaL6j%2Fyp8CZKsSUOzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Hv%2BbNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxV2bNmxVg35iPrMEFld6XbR3CRM%2Fro1fUIIHwx%2Fs4U%2FlrqOkz3c1lYQmENFJI8DCgRzIDIg5b1JavTOiajZLf2cls1KsKofBh9k5ydpJPL%2FmzT9ZcBIWY2t5sFoD8Ls5C1%2FwCDkyQ5KyjWdLGi6ml3brSyvKxuo6I58P8AJPVclOiXZurPi5rLAfTf5fsn7sE3drBqFq9vLR4pV2I7dwy%2B%2BF2j6Xf2F5dS3EqNbyhViVa8iV%2Fbfag6%2FZXBdj3KnWURXLzYFYV5n8n3us6ut7btEITGsbc6hl418B8WFd75Ym8svHqVqPrQiCsJSPiikH2jQfsNnScayhwVYBlOxB3BGG1Sby7rf6YgZ5KCZftIBSmHeFllodlp95LeWqlDMKGIfYB7kDDPE%2BSuzZs2BXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F%2F0u%2F5s2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZFfM%2BipLW%2BSJZAf71CtaMPsygf8SyVZRAIIO4PbCDW6pP5YvDd6Wiu1Zbc%2Bi%2B9Tt9mv%2Bxw5xG3tbe1Vlt41jDHkwUUqfE4tgPNXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFXZs2bFX%2F9Pv%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV9%2F5s8AZsVff%2BbPAGbFX3%2FmzwBmxV%2F%2FZ');background-position:center center;border:1px solid #0a0}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css new file mode 100644 index 0000000..222342f --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css @@ -0,0 +1,27 @@ +.yui3-skin-night .yui3-dial-ring-vml, +.yui3-skin-night .yui3-dial-center-button-vml, +.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night v\:oval.yui3-dial-marker-max-min, +.yui3-skin-night .yui3-dial-marker-vml, +.yui3-skin-night .yui3-dial-handle-vml { + background: none; + opacity:1; +} + +div.base64-singlequotes { + width:100px; + height:100px; + background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QAAAAAAAD5Q7t%2FAAAACXBIWXMAAA3WAAAN1gGQb3mcAAAFrUlEQVRYw%2B2Xz28kRxXHP%2B9Vdc8vj2fG9uIkm2yUeFGEhNCKQwBpj1yRUBAnpJU4ceZP4MxfkBxy2GO45bQXuEGQohUKigQ%2BsBBE1sbYXv8Yz%2FRMd9fjUN09PV5nFZA4kZZa79W3quu9er%2FqNfy%2FPwJgZty%2Ffz%2FZ29vrpmmqhlWTgmFg1UpbfWhYhG6Yq2cFi%2FNrj9nJyWnx%2BPHjeafbMTEzPvjVB9%2B6d%2B%2FezweDwV1BfHubivkC3lZya%2F4m7Np8UZYXhweHH7733rvvC0Kyv7%2F%2F7p07d34qIjyvr63RNb4l4CbsRUrNrq6OfvfRRz%2FxDx486A%2F6g7vXhX9ZIf%2Bp4JomaToZj8d7Pk1SFRFXb1aWodq09l%2F9YZu%2FCWMVL9e%2FaVFVQVUREEG8r3VUEZ4cX%2FHL30%2B5shRtAhFq4wggNb6GrXgVa2K2jYtACIHv7Sz54TfHjWWagBOBy0Xgt%2BcjLtwQxVCpNwURQat1DdYaT7pwdwKDFA6ncHgFizJmSb3WLPDa7PMIVlb2daqZxdONUnAetEojEdBGiXXhTmAjhZ0%2B3N6AlzeEROH1TXiWGf%2BcwmkWZYnAfAkdx1pq%2BhUbT9z3IElUJlVhI4WsgCLUyggi4MQYd4VXNmCYRqXOspV7UoHbQ3hpEMeLAk5mkFYRYlWI%2BHZ6CTDwkKSQqrA7gFeHMF3C6VyYLmFZGiKCE6GrMFsaWb7yuVOh66N1FkUUpBJ3TyvFovToBl9XMbNY2bZ70BsKfW94hbyErosmXpQwy4VgkCjMizjvRRik0EtiLNwagBf465lwOqtkETEn60XT1%2BlTazrpKlR%2BKkooy3Xfb3Wj3wGWJRQhnni7B53q5FqZ4%2FUR7PYhGMxyuMwgWVqTxrYWAwZYQX78J5i8ie9txSAkoOqqQAqk3pBgKLDhlY5XVKPCi3w97YRoKSFaceCgF2hqSXRBPQAIOcXRH8hP%2F0y6%2BRpWLrEyg3SbS9tmzggzJQSLQZo4xoOE8UbCsJfQ7zi6iaIizZ5OBVfXDKPireWC%2BvAYWOBqeszl9Jg03afbH6OqGH%2FBSUrqbrFIXiHoiEDC%2FPySi2d9nnZHJE7opY7dcY%2FdcZej84zpPGfY9Uw2ErYGCf2O4mUVEzELWtqUxZKjf3zK2cURzicMRy%2BzvbuH8ylFPqXIPqNczClKY1mUZFcnSDKkv%2FUNuptbWG%2BLw%2FMh%2FzrYpKBHKV3ONOXzYxeV20z49qhs7gaMWIjqQQiBxVXB4irg05yz4u%2FMpieoJuTLjDJfUJYBzBAFUUHkhMvLvzFPuvQ2JvQ3duh0R%2FjuiDQdIn6MJdvkxTafZUPuaN6UaOo6UNtgNl9weboguwqoA5fCjEusNCzE8LJQFRuNrzpQD%2BrmZNM55%2F4A5z1J2iHtDEg6fZK0j0uHlDrh2N4i3Ptuc%2BH5tjp5HliWQmmOUAhlYe0rqUqWSEOhcZ05AvE1UdColSQJaHWlSUYgJy%2FO2fFfo%2F34piphFOZ4OrvNdL5EJZbcmE8OQzFxIJEGEgIeE1%2FhrjJLxZcOrIVpVC7TW00WmLWyAMDEs%2Bi9wVJDtG17Y21vVmNxLKqIOkQqqoq2qHORmgj9UQcza7mgFm4GmiDjO5C72DSoQ6uPVTW%2BzuFUcQ2teKd4pzhd8b6Nu6jg7vZsrb1rClEIxhu7Q37x47fIy3j%2Fi8iqqlUuEWTFN%2FOrMU3fEEuhUM8FIPDqZgcRIVhsAXxtjGDGS5M%2BP%2Fv%2Bm7yopVrRVsPabsW%2BYG1T%2Fy3KahqSg6cHRb5cTmt5ZXhxQ7nS6yZsVWOajDFbw2JSCSGEIsuyC%2F%2Fo0aPp%2Fv7%2Br9NO5%2F5gMOhJLNn%2FpQLrLfw6tkKKorCDg4NPP%2Fnkjx%2FLOz96h2enzyZvf%2BftH9za2fm6qLrnO9tGk2vY86f%2FMliWZRdPnjz5zcOHDz%2B%2B%2Fifimorzv31C9X718G%2FYrCYSNJa5LgAAACJ6VFh0U29mdHdhcmUAAHjaKy8v18vMyy5OTixI1csvSgcANtgGWBBTylwAAAAASUVORK5CYII%3D'); + background-position:center center; + border:1px solid #00aa00; +} + +div.otherdataurl { + background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kFBQ0WDWwqwjwAAANMSURBVEjHrdZbaFxVFAbgb2aSTG6GTi6mVIwxNxF9qFI0RQnFUqiYamutVutLa2t9EY0oPggFoYgPRR%2FaghYviA%2BiIAYvmBJKoYWiiBCigVTT1FisbUhrEtNkJpc5PuQkjGEmJqkLFmdz2Hv%2Fa%2F3rX3tvlm95oS%2FLokuZtIpbdvAs7KFtL22wjb3V1C41upy2ke1DXC2k%2FBjv1HHXDrbkEamg7lX2P8QTldQ2UtfOB8uiJsHNiB%2Fik0GmO%2BgZIxgnGA59nGCMoJPeQaYP047iBDXZEohkAYof4%2FNyKlZRdR%2F1ASZCnoOMhWkUheMz9F1laJSRZ3gEqVw1ipZQjcoBRrbT3Ez9OJLhZkHG5CD8l8Q47qXhMZp%2FYxhVFaxBLBtQejdtA%2FTtZPMIJnOknI2WSYzicTYN8OtTvICZbECxdr5Pkm6iPL0C3c%2BgkfIJgi%2F4LnP%2FudRKD3K4jf1VJGLEAiuz6VnA4AGam1h7gpNIzSFe66D3NurLKVhJNkHo07N9V9BE3XHOYmyeuirqG1l9mdHgOkDSGd8%2FGWtg9Roa56lrYdchDtRQPLlCkEywKVRScDfrurnwC2diiPTRe47iVtbnLZDxckGCkKYpPM%2FRr3kbyRhsYOtRDiQonFoBSHrBOI18rOeOPvr76YrCeUbf5fTvjOddJ0gQ1uMPku9z6hwjiEZhgOMn%2BaaUeHQJIOkMD7KMA5QQP01HP18hPbfvDTvZPETqb2YiS1BWrozM6jk9SPJJHkZZ5qFagtoaNnbyZg1FE4sUPRdlAQpwkdSjvDZAJ%2FoxNt%2Bw6NlGbQVFl5iKLKKsXCAwyFQZ8S3ciu65ho1lBJ5%2FkZk3OBGjpJWGmVCmsjTkQvA8JHCUU7s5eImevzg%2Fd7BGFhzCARIf8uVN3J5Heh1VM%2BHlko2y%2FHBxF0NJolfo38eDuJJxbf0ro%2FnMurh8hM%2FupH4tdT8zciOFsTC8SAgQoJfRxKzCuvfw0k%2F8MDx7xqUyez%2BS48ESIN7Ky6OUpfAtrxzhx03UR4m0c%2FZF7tnKW2mma4l9yuthTSIZIvxPi6EcpZW0PM0xtOzjo%2Bf4GPfv4r1qNqAUFYs9diJLBC1CIa7FZx8fUlwI22LuNv%2FfLbKMAOftH9TwRXg6%2FiCDAAAAAElFTkSuQmCC"); +} + +.yui-skin-sam .yui-h-slider { + background: url(bg-h.gif) no-repeat 5px 0; + height: 28px; + width: 228px; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css.min new file mode 100644 index 0000000..d919bca --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-base64-twourls.css.min @@ -0,0 +1 @@ +.yui3-skin-night .yui3-dial-ring-vml,.yui3-skin-night .yui3-dial-center-button-vml,.yui3-skin-night .yui3-dial-marker v\:oval.yui3-dial-marker-max-min,.yui3-skin-night v\:oval.yui3-dial-marker-max-min,.yui3-skin-night .yui3-dial-marker-vml,.yui3-skin-night .yui3-dial-handle-vml{background:0;opacity:1}div.base64-singlequotes{width:100px;height:100px;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QAAAAAAAD5Q7t%2FAAAACXBIWXMAAA3WAAAN1gGQb3mcAAAFrUlEQVRYw%2B2Xz28kRxXHP%2B9Vdc8vj2fG9uIkm2yUeFGEhNCKQwBpj1yRUBAnpJU4ceZP4MxfkBxy2GO45bQXuEGQohUKigQ%2BsBBE1sbYXv8Yz%2FRMd9fjUN09PV5nFZA4kZZa79W3quu9er%2FqNfy%2FPwJgZty%2Ffz%2FZ29vrpmmqhlWTgmFg1UpbfWhYhG6Yq2cFi%2FNrj9nJyWnx%2BPHjeafbMTEzPvjVB9%2B6d%2B%2FezweDwV1BfHubivkC3lZya%2F4m7Np8UZYXhweHH7733rvvC0Kyv7%2F%2F7p07d34qIjyvr63RNb4l4CbsRUrNrq6OfvfRRz%2FxDx486A%2F6g7vXhX9ZIf%2Bp4JomaToZj8d7Pk1SFRFXb1aWodq09l%2F9YZu%2FCWMVL9e%2FaVFVQVUREEG8r3VUEZ4cX%2FHL30%2B5shRtAhFq4wggNb6GrXgVa2K2jYtACIHv7Sz54TfHjWWagBOBy0Xgt%2BcjLtwQxVCpNwURQat1DdYaT7pwdwKDFA6ncHgFizJmSb3WLPDa7PMIVlb2daqZxdONUnAetEojEdBGiXXhTmAjhZ0%2B3N6AlzeEROH1TXiWGf%2BcwmkWZYnAfAkdx1pq%2BhUbT9z3IElUJlVhI4WsgCLUyggi4MQYd4VXNmCYRqXOspV7UoHbQ3hpEMeLAk5mkFYRYlWI%2BHZ6CTDwkKSQqrA7gFeHMF3C6VyYLmFZGiKCE6GrMFsaWb7yuVOh66N1FkUUpBJ3TyvFovToBl9XMbNY2bZ70BsKfW94hbyErosmXpQwy4VgkCjMizjvRRik0EtiLNwagBf465lwOqtkETEn60XT1%2BlTazrpKlR%2BKkooy3Xfb3Wj3wGWJRQhnni7B53q5FqZ4%2FUR7PYhGMxyuMwgWVqTxrYWAwZYQX78J5i8ie9txSAkoOqqQAqk3pBgKLDhlY5XVKPCi3w97YRoKSFaceCgF2hqSXRBPQAIOcXRH8hP%2F0y6%2BRpWLrEyg3SbS9tmzggzJQSLQZo4xoOE8UbCsJfQ7zi6iaIizZ5OBVfXDKPireWC%2BvAYWOBqeszl9Jg03afbH6OqGH%2FBSUrqbrFIXiHoiEDC%2FPySi2d9nnZHJE7opY7dcY%2FdcZej84zpPGfY9Uw2ErYGCf2O4mUVEzELWtqUxZKjf3zK2cURzicMRy%2BzvbuH8ylFPqXIPqNczClKY1mUZFcnSDKkv%2FUNuptbWG%2BLw%2FMh%2FzrYpKBHKV3ONOXzYxeV20z49qhs7gaMWIjqQQiBxVXB4irg05yz4u%2FMpieoJuTLjDJfUJYBzBAFUUHkhMvLvzFPuvQ2JvQ3duh0R%2FjuiDQdIn6MJdvkxTafZUPuaN6UaOo6UNtgNl9weboguwqoA5fCjEusNCzE8LJQFRuNrzpQD%2BrmZNM55%2F4A5z1J2iHtDEg6fZK0j0uHlDrh2N4i3Ptuc%2BH5tjp5HliWQmmOUAhlYe0rqUqWSEOhcZ05AvE1UdColSQJaHWlSUYgJy%2FO2fFfo%2F34piphFOZ4OrvNdL5EJZbcmE8OQzFxIJEGEgIeE1%2FhrjJLxZcOrIVpVC7TW00WmLWyAMDEs%2Bi9wVJDtG17Y21vVmNxLKqIOkQqqoq2qHORmgj9UQcza7mgFm4GmiDjO5C72DSoQ6uPVTW%2BzuFUcQ2teKd4pzhd8b6Nu6jg7vZsrb1rClEIxhu7Q37x47fIy3j%2Fi8iqqlUuEWTFN%2FOrMU3fEEuhUM8FIPDqZgcRIVhsAXxtjGDGS5M%2BP%2Fv%2Bm7yopVrRVsPabsW%2BYG1T%2Fy3KahqSg6cHRb5cTmt5ZXhxQ7nS6yZsVWOajDFbw2JSCSGEIsuyC%2F%2Fo0aPp%2Fv7%2Br9NO5%2F5gMOhJLNn%2FpQLrLfw6tkKKorCDg4NPP%2Fnkjx%2FLOz96h2enzyZvf%2BftH9za2fm6qLrnO9tGk2vY86f%2FMliWZRdPnjz5zcOHDz%2B%2B%2Fifimorzv31C9X718G%2FYrCYSNJa5LgAAACJ6VFh0U29mdHdhcmUAAHjaKy8v18vMyy5OTixI1csvSgcANtgGWBBTylwAAAAASUVORK5CYII%3D');background-position:center center;border:1px solid #0a0}div.otherdataurl{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kFBQ0WDWwqwjwAAANMSURBVEjHrdZbaFxVFAbgb2aSTG6GTi6mVIwxNxF9qFI0RQnFUqiYamutVutLa2t9EY0oPggFoYgPRR%2FaghYviA%2BiIAYvmBJKoYWiiBCigVTT1FisbUhrEtNkJpc5PuQkjGEmJqkLFmdz2Hv%2Fa%2F3rX3tvlm95oS%2FLokuZtIpbdvAs7KFtL22wjb3V1C41upy2ke1DXC2k%2FBjv1HHXDrbkEamg7lX2P8QTldQ2UtfOB8uiJsHNiB%2Fik0GmO%2BgZIxgnGA59nGCMoJPeQaYP047iBDXZEohkAYof4%2FNyKlZRdR%2F1ASZCnoOMhWkUheMz9F1laJSRZ3gEqVw1ipZQjcoBRrbT3Ez9OJLhZkHG5CD8l8Q47qXhMZp%2FYxhVFaxBLBtQejdtA%2FTtZPMIJnOknI2WSYzicTYN8OtTvICZbECxdr5Pkm6iPL0C3c%2BgkfIJgi%2F4LnP%2FudRKD3K4jf1VJGLEAiuz6VnA4AGam1h7gpNIzSFe66D3NurLKVhJNkHo07N9V9BE3XHOYmyeuirqG1l9mdHgOkDSGd8%2FGWtg9Roa56lrYdchDtRQPLlCkEywKVRScDfrurnwC2diiPTRe47iVtbnLZDxckGCkKYpPM%2FRr3kbyRhsYOtRDiQonFoBSHrBOI18rOeOPvr76YrCeUbf5fTvjOddJ0gQ1uMPku9z6hwjiEZhgOMn%2BaaUeHQJIOkMD7KMA5QQP01HP18hPbfvDTvZPETqb2YiS1BWrozM6jk9SPJJHkZZ5qFagtoaNnbyZg1FE4sUPRdlAQpwkdSjvDZAJ%2FoxNt%2Bw6NlGbQVFl5iKLKKsXCAwyFQZ8S3ciu65ho1lBJ5%2FkZk3OBGjpJWGmVCmsjTkQvA8JHCUU7s5eImevzg%2Fd7BGFhzCARIf8uVN3J5Heh1VM%2BHlko2y%2FHBxF0NJolfo38eDuJJxbf0ro%2FnMurh8hM%2FupH4tdT8zciOFsTC8SAgQoJfRxKzCuvfw0k%2F8MDx7xqUyez%2BS48ESIN7Ky6OUpfAtrxzhx03UR4m0c%2FZF7tnKW2mma4l9yuthTSIZIvxPi6EcpZW0PM0xtOzjo%2Bf4GPfv4r1qNqAUFYs9diJLBC1CIa7FZx8fUlwI22LuNv%2FfLbKMAOftH9TwRXg6%2FiCDAAAAAElFTkSuQmCC")}.yui-skin-sam .yui-h-slider{background:url(bg-h.gif) no-repeat 5px 0;height:28px;width:228px} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css new file mode 100644 index 0000000..f9799d7 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css @@ -0,0 +1,30 @@ +/*csslint fontfamily: true*/ + +/** + * Foo + */ + +.y-ff-1 { + font-family:"Foo Bar",Helvetica,Arial; + text-rendering: optimizeLegibility; +} + +.ua-op .y-ff-1 { + /* Some Comment */ + font-family:Helvetica,Arial; +} + +/* +Foo + +Bar +*/ + +@font-face { + font-family: "Foo Bar"; + src: url("data:font/truetype;base64,gRbIUFAIrsQNGditEWbAUKwAA") format("truetype"), + url("http://yuilibrary.com/fonts/foo-bar.svg#webfontse22fewwr") format("svg"); + font-weight: normal; + font-style: normal; +} + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css.min new file mode 100644 index 0000000..7c4c0ed --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-dbquote-font.css.min @@ -0,0 +1,5 @@ +.y-ff-1{font-family:"Foo Bar",Helvetica,Arial;text-rendering:optimizeLegibility}.ua-op .y-ff-1{font-family:Helvetica,Arial}@font-face{font-family:"Foo Bar";src:url("data:font/truetype;base64,gRbIUFAIrsQNGditEWbAUKwAA") format("truetype"),url("http://yuilibrary.com/fonts/foo-bar.svg#webfontse22fewwr") format("svg");font-weight:normal;font-style:normal} + + + + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css new file mode 100644 index 0000000..0d45c94 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css @@ -0,0 +1,13 @@ +div.nonbase64-doublequotes { + width:100px; + height:100px; + background-image:url( + "data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0C%00%00%00%0E%08%03%00%00%00%2Cc%0D%DE%00%00%00%A2PLTEQQQ%FA%FA%FA%FC%FC%FC%EE%EE%EE%A9%A9%A9%E9%E9%E9%0A%0A%0A%0D%0D%0D444PPP%CD%CD%CD%CC%CC%CC%F5%F5%F5UUU%D0%D0%D0'''%F9%F9%F9%A6%A6%A6%40%40%40FFF%A0%A0%A0%89%89%89%8D%8D%8D%20%20%20%14%14%14%DA%DA%DA%B6%B6%B6%02%02%02%87%87%87%81%81%81%AC%AC%AC%0E%0E%0E111%7D%7D%7D%92%92%92333%B9%B9%B9%BC%BC%BChhh)))%E1%E1%E1%03%03%03%CB%CB%CB%EB%EB%EB%FD%FD%FD%A3%A3%A3(((%04%04%04%CA%CA%CAttt%2C%2C%2C%F4%F4%F4%00%00%00%FF%FF%FF%D6%DE%02%C3%00%00%006tRNS%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%00%A1%8FN1%00%00%00iIDAT%08%D7E%C7E%16%02Q%10%C5%D0j%C3%DD%BDqw%5E%F6%BF5%06%D4%3Fd%94kx%BDf%DE6%FFIA%AB%C8qYj%1F%E3Xk%93%E0%C8JZ%10%90%9E%3A1%60%BBY%85%A8%AE%14%C0%5E%1A6%8E%C5w%02%60%99%C9%FA%9A%03%60%8C%EFz%8C%CE%0EnSu%3F%01%AD%B2%06%04%F0%3CT%FF%B8nk%3F%7C%01%C5z%1B%F9%26%2F%3Az%00%00%00%00IEND%AEB%60%82" + ); + border:1px solid #00aa00; +} + +span.othercss { + font-family:"Times New Roman"; + font-weight:inherit; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css.min new file mode 100644 index 0000000..1acc41d --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-doublequotes.css.min @@ -0,0 +1 @@ +div.nonbase64-doublequotes{width:100px;height:100px;background-image:url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0C%00%00%00%0E%08%03%00%00%00%2Cc%0D%DE%00%00%00%A2PLTEQQQ%FA%FA%FA%FC%FC%FC%EE%EE%EE%A9%A9%A9%E9%E9%E9%0A%0A%0A%0D%0D%0D444PPP%CD%CD%CD%CC%CC%CC%F5%F5%F5UUU%D0%D0%D0'''%F9%F9%F9%A6%A6%A6%40%40%40FFF%A0%A0%A0%89%89%89%8D%8D%8D%20%20%20%14%14%14%DA%DA%DA%B6%B6%B6%02%02%02%87%87%87%81%81%81%AC%AC%AC%0E%0E%0E111%7D%7D%7D%92%92%92333%B9%B9%B9%BC%BC%BChhh)))%E1%E1%E1%03%03%03%CB%CB%CB%EB%EB%EB%FD%FD%FD%A3%A3%A3(((%04%04%04%CA%CA%CAttt%2C%2C%2C%F4%F4%F4%00%00%00%FF%FF%FF%D6%DE%02%C3%00%00%006tRNS%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%00%A1%8FN1%00%00%00iIDAT%08%D7E%C7E%16%02Q%10%C5%D0j%C3%DD%BDqw%5E%F6%BF5%06%D4%3Fd%94kx%BDf%DE6%FFIA%AB%C8qYj%1F%E3Xk%93%E0%C8JZ%10%90%9E%3A1%60%BBY%85%A8%AE%14%C0%5E%1A6%8E%C5w%02%60%99%C9%FA%9A%03%60%8C%EFz%8C%CE%0EnSu%3F%01%AD%B2%06%04%F0%3CT%FF%B8nk%3F%7C%01%C5z%1B%F9%26%2F%3Az%00%00%00%00IEND%AEB%60%82");border:1px solid #0a0}span.othercss{font-family:"Times New Roman";font-weight:inherit} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css new file mode 100644 index 0000000..b4bc9b2 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css @@ -0,0 +1,11 @@ +div.nonbase64-noquotes { + width:100px; + height:100px; + background-image:url( data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0C%00%00%00%0E%08%03%00%00%00%2Cc%0D%DE%00%00%00%A2PLTEQQQ%FA%FA%FA%FC%FC%FC%EE%EE%EE%A9%A9%A9%E9%E9%E9%0A%0A%0A%0D%0D%0D444PPP%CD%CD%CD%CC%CC%CC%F5%F5%F5UUU%D0%D0%D0\'\'\'%F9%F9%F9%A6%A6%A6%40%40%40FFF%A0%A0%A0%89%89%89%8D%8D%8D%20%20%20%14%14%14%DA%DA%DA%B6%B6%B6%02%02%02%87%87%87%81%81%81%AC%AC%AC%0E%0E%0E111%7D%7D%7D%92%92%92333%B9%B9%B9%BC%BC%BChhh\)\)\)%E1%E1%E1%03%03%03%CB%CB%CB%EB%EB%EB%FD%FD%FD%A3%A3%A3\(\(\(%04%04%04%CA%CA%CAttt%2C%2C%2C%F4%F4%F4%00%00%00%FF%FF%FF%D6%DE%02%C3%00%00%006tRNS%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%00%A1%8FN1%00%00%00iIDAT%08%D7E%C7E%16%02Q%10%C5%D0j%C3%DD%BDqw%5E%F6%BF5%06%D4%3Fd%94kx%BDf%DE6%FFIA%AB%C8qYj%1F%E3Xk%93%E0%C8JZ%10%90%9E%3A1%60%BBY%85%A8%AE%14%C0%5E%1A6%8E%C5w%02%60%99%C9%FA%9A%03%60%8C%EFz%8C%CE%0EnSu%3F%01%AD%B2%06%04%F0%3CT%FF%B8nk%3F%7C%01%C5z%1B%F9%26%2F%3Az%00%00%00%00IEND%AEB%60%82 ); + border:1px solid red; +} + +span.othercss { + font-family:"Times New Roman"; + font-weight:inherit; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css.min new file mode 100644 index 0000000..8f4bf08 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-noquotes.css.min @@ -0,0 +1 @@ +div.nonbase64-noquotes{width:100px;height:100px;background-image:url(data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0C%00%00%00%0E%08%03%00%00%00%2Cc%0D%DE%00%00%00%A2PLTEQQQ%FA%FA%FA%FC%FC%FC%EE%EE%EE%A9%A9%A9%E9%E9%E9%0A%0A%0A%0D%0D%0D444PPP%CD%CD%CD%CC%CC%CC%F5%F5%F5UUU%D0%D0%D0\'\'\'%F9%F9%F9%A6%A6%A6%40%40%40FFF%A0%A0%A0%89%89%89%8D%8D%8D%20%20%20%14%14%14%DA%DA%DA%B6%B6%B6%02%02%02%87%87%87%81%81%81%AC%AC%AC%0E%0E%0E111%7D%7D%7D%92%92%92333%B9%B9%B9%BC%BC%BChhh\)\)\)%E1%E1%E1%03%03%03%CB%CB%CB%EB%EB%EB%FD%FD%FD%A3%A3%A3\(\(\(%04%04%04%CA%CA%CAttt%2C%2C%2C%F4%F4%F4%00%00%00%FF%FF%FF%D6%DE%02%C3%00%00%006tRNS%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%00%A1%8FN1%00%00%00iIDAT%08%D7E%C7E%16%02Q%10%C5%D0j%C3%DD%BDqw%5E%F6%BF5%06%D4%3Fd%94kx%BDf%DE6%FFIA%AB%C8qYj%1F%E3Xk%93%E0%C8JZ%10%90%9E%3A1%60%BBY%85%A8%AE%14%C0%5E%1A6%8E%C5w%02%60%99%C9%FA%9A%03%60%8C%EFz%8C%CE%0EnSu%3F%01%AD%B2%06%04%F0%3CT%FF%B8nk%3F%7C%01%C5z%1B%F9%26%2F%3Az%00%00%00%00IEND%AEB%60%82);border:1px solid red}span.othercss{font-family:"Times New Roman";font-weight:inherit} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css new file mode 100644 index 0000000..0488549 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css @@ -0,0 +1,15 @@ +/* Some Comment */ + +div.nonbase64-singlequotes { + width:100px; + height:100px; + background-image:url('data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0C%00%00%00%0E%08%03%00%00%00%2Cc%0D%DE%00%00%00%A2PLTEQQQ%FA%FA%FA%FC%FC%FC%EE%EE%EE%A9%A9%A9%E9%E9%E9%0A%0A%0A%0D%0D%0D444PPP%CD%CD%CD%CC%CC%CC%F5%F5%F5UUU%D0%D0%D0\'\'\'%F9%F9%F9%A6%A6%A6%40%40%40FFF%A0%A0%A0%89%89%89%8D%8D%8D%20%20%20%14%14%14%DA%DA%DA%B6%B6%B6%02%02%02%87%87%87%81%81%81%AC%AC%AC%0E%0E%0E111%7D%7D%7D%92%92%92333%B9%B9%B9%BC%BC%BChhh)))%E1%E1%E1%03%03%03%CB%CB%CB%EB%EB%EB%FD%FD%FD%A3%A3%A3(((%04%04%04%CA%CA%CAttt%2C%2C%2C%F4%F4%F4%00%00%00%FF%FF%FF%D6%DE%02%C3%00%00%006tRNS%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%00%A1%8FN1%00%00%00iIDAT%08%D7E%C7E%16%02Q%10%C5%D0j%C3%DD%BDqw%5E%F6%BF5%06%D4%3Fd%94kx%BDf%DE6%FFIA%AB%C8qYj%1F%E3Xk%93%E0%C8JZ%10%90%9E%3A1%60%BBY%85%A8%AE%14%C0%5E%1A6%8E%C5w%02%60%99%C9%FA%9A%03%60%8C%EFz%8C%CE%0EnSu%3F%01%AD%B2%06%04%F0%3CT%FF%B8nk%3F%7C%01%C5z%1B%F9%26%2F%3Az%00%00%00%00IEND%AEB%60%82'); + border:1px solid #0000aa; +} + +/* Some Other Comment */ + +span.othercss { + font-family:"Times New Roman"; + font-weight:inherit; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css.min new file mode 100644 index 0000000..badbf06 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-nonbase64-singlequotes.css.min @@ -0,0 +1,2 @@ +div.nonbase64-singlequotes{width:100px;height:100px;background-image:url('data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0C%00%00%00%0E%08%03%00%00%00%2Cc%0D%DE%00%00%00%A2PLTEQQQ%FA%FA%FA%FC%FC%FC%EE%EE%EE%A9%A9%A9%E9%E9%E9%0A%0A%0A%0D%0D%0D444PPP%CD%CD%CD%CC%CC%CC%F5%F5%F5UUU%D0%D0%D0\'\'\'%F9%F9%F9%A6%A6%A6%40%40%40FFF%A0%A0%A0%89%89%89%8D%8D%8D%20%20%20%14%14%14%DA%DA%DA%B6%B6%B6%02%02%02%87%87%87%81%81%81%AC%AC%AC%0E%0E%0E111%7D%7D%7D%92%92%92333%B9%B9%B9%BC%BC%BChhh)))%E1%E1%E1%03%03%03%CB%CB%CB%EB%EB%EB%FD%FD%FD%A3%A3%A3(((%04%04%04%CA%CA%CAttt%2C%2C%2C%F4%F4%F4%00%00%00%FF%FF%FF%D6%DE%02%C3%00%00%006tRNS%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%FF%00%A1%8FN1%00%00%00iIDAT%08%D7E%C7E%16%02Q%10%C5%D0j%C3%DD%BDqw%5E%F6%BF5%06%D4%3Fd%94kx%BDf%DE6%FFIA%AB%C8qYj%1F%E3Xk%93%E0%C8JZ%10%90%9E%3A1%60%BBY%85%A8%AE%14%C0%5E%1A6%8E%C5w%02%60%99%C9%FA%9A%03%60%8C%EFz%8C%CE%0EnSu%3F%01%AD%B2%06%04%F0%3CT%FF%B8nk%3F%7C%01%C5z%1B%F9%26%2F%3Az%00%00%00%00IEND%AEB%60%82');border:1px solid #00a}span.othercss{font-family:"Times New Roman";font-weight:inherit} + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css new file mode 100644 index 0000000..722c7ed --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css @@ -0,0 +1,31 @@ +/*csslint fontfamily: true*/ + +/** + * Foo + */ + +.y-ff-1 { + font-family:"Foo Bar",Helvetica,Arial; + text-rendering: optimizeLegibility; +} + +.ua-op .y-ff-1 { + /* Some Comment */ + font-family:Helvetica,Arial; +} + +/* +Foo + +Bar +*/ + +@font-face { + font-family: "Foo Bar"; + src: url( + data:font/truetype;base64,gRbIUFAIrsQNGditEWbAUKwAA) format("truetype"), + url("http://yuilibrary.com/fonts/foo-bar.svg#webfontse22fewwr") format("svg"); + font-weight: normal; + font-style: normal; +} + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css.min new file mode 100644 index 0000000..6b32e33 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-noquote-multiline-font.css.min @@ -0,0 +1,3 @@ +.y-ff-1{font-family:"Foo Bar",Helvetica,Arial;text-rendering:optimizeLegibility}.ua-op .y-ff-1{font-family:Helvetica,Arial}@font-face{font-family:"Foo Bar";src:url(data:font/truetype;base64,gRbIUFAIrsQNGditEWbAUKwAA) format("truetype"),url("http://yuilibrary.com/fonts/foo-bar.svg#webfontse22fewwr") format("svg");font-weight:normal;font-style:normal} + + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css new file mode 100644 index 0000000..e86097c --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css @@ -0,0 +1,90 @@ +.yui3-skin-sam .yui3-scrollview-scrollbar { + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate(0, 0); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-radius:3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg=="); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-bottom-right-radius:0; + border-bottom-left-radius:0; + + -webkit-border-bottom-right-radius:0; + -webkit-border-bottom-left-radius:0; + + -moz-border-radius-bottomright:0; + -moz-border-radius-bottomleft:0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-radius:0; + border-bottom-right-radius:3px; + border-bottom-left-radius:3px; + + -webkit-border-radius:0; + -webkit-border-bottom-right-radius:3px; + -webkit-border-bottom-left-radius:3px; + -webkit-transform: translate3d(0, 0, 0); + + -moz-border-radius:0; + -moz-border-radius-bottomright:3px; + -moz-border-radius-bottomleft:3px; + -moz-transform: translate(0, 0); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle { + border-radius:0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + + -webkit-transform: translate3d(0,0,0) scaleY(1); + -webkit-transform-origin-y: 0; + + -moz-transform: translate(0,0) scaleY(1); + -moz-transform-origin: 0 0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last { + border-top-right-radius: 0; + border-bottom-left-radius: 3px; + + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + + -moz-border-radius-topright: 0; + -moz-border-radius-bottomleft: 3px; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last { + border-bottom-left-radius: 0; + border-top-right-radius: 3px; + + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-right-radius: 3px; + + -moz-border-radius-bottomleft: 0; + -moz-border-radius-topright: 3px; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle { + -webkit-transform: translate3d(0,0,0) scaleX(1); + -webkit-transform-origin: 0 0; + + -moz-transform: translate(0,0) scaleX(1); + -moz-transform-origin: 0 0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child, +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child { + background-color: #aaa; + background-image: none; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css.min new file mode 100644 index 0000000..f9e7600 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-doublequotes.css.min @@ -0,0 +1 @@ +.yui3-skin-sam .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==")}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin-y:0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css new file mode 100644 index 0000000..ddf720e --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css @@ -0,0 +1,90 @@ +.yui3-skin-sam .yui3-scrollview-scrollbar { + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate(0, 0); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-radius:3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-bottom-right-radius:0; + border-bottom-left-radius:0; + + -webkit-border-bottom-right-radius:0; + -webkit-border-bottom-left-radius:0; + + -moz-border-radius-bottomright:0; + -moz-border-radius-bottomleft:0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-radius:0; + border-bottom-right-radius:3px; + border-bottom-left-radius:3px; + + -webkit-border-radius:0; + -webkit-border-bottom-right-radius:3px; + -webkit-border-bottom-left-radius:3px; + -webkit-transform: translate3d(0, 0, 0); + + -moz-border-radius:0; + -moz-border-radius-bottomright:3px; + -moz-border-radius-bottomleft:3px; + -moz-transform: translate(0, 0); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle { + border-radius:0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + + -webkit-transform: translate3d(0,0,0) scaleY(1); + -webkit-transform-origin-y: 0; + + -moz-transform: translate(0,0) scaleY(1); + -moz-transform-origin: 0 0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last { + border-top-right-radius: 0; + border-bottom-left-radius: 3px; + + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + + -moz-border-radius-topright: 0; + -moz-border-radius-bottomleft: 3px; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last { + border-bottom-left-radius: 0; + border-top-right-radius: 3px; + + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-right-radius: 3px; + + -moz-border-radius-bottomleft: 0; + -moz-border-radius-topright: 3px; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle { + -webkit-transform: translate3d(0,0,0) scaleX(1); + -webkit-transform-origin: 0 0; + + -moz-transform: translate(0,0) scaleX(1); + -moz-transform-origin: 0 0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child, +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child { + background-color: #aaa; + background-image: none; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css.min new file mode 100644 index 0000000..110f9fc --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-noquotes.css.min @@ -0,0 +1 @@ +.yui3-skin-sam .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin-y:0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css new file mode 100644 index 0000000..9d6ec7a --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css @@ -0,0 +1,90 @@ +.yui3-skin-sam .yui3-scrollview-scrollbar { + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate(0, 0); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-radius:3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg=='); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-bottom-right-radius:0; + border-bottom-left-radius:0; + + -webkit-border-bottom-right-radius:0; + -webkit-border-bottom-left-radius:0; + + -moz-border-radius-bottomright:0; + -moz-border-radius-bottomleft:0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last { + border-radius:0; + border-bottom-right-radius:3px; + border-bottom-left-radius:3px; + + -webkit-border-radius:0; + -webkit-border-bottom-right-radius:3px; + -webkit-border-bottom-left-radius:3px; + -webkit-transform: translate3d(0, 0, 0); + + -moz-border-radius:0; + -moz-border-radius-bottomright:3px; + -moz-border-radius-bottomleft:3px; + -moz-transform: translate(0, 0); +} + +.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle { + border-radius:0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + + -webkit-transform: translate3d(0,0,0) scaleY(1); + -webkit-transform-origin-y: 0; + + -moz-transform: translate(0,0) scaleY(1); + -moz-transform-origin: 0 0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first, +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last { + border-top-right-radius: 0; + border-bottom-left-radius: 3px; + + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + + -moz-border-radius-topright: 0; + -moz-border-radius-bottomleft: 3px; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last { + border-bottom-left-radius: 0; + border-top-right-radius: 3px; + + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-right-radius: 3px; + + -moz-border-radius-bottomleft: 0; + -moz-border-radius-topright: 3px; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle { + -webkit-transform: translate3d(0,0,0) scaleX(1); + -webkit-transform-origin: 0 0; + + -moz-transform: translate(0,0) scaleX(1); + -moz-transform-origin: 0 0; +} + +.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child, +.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child { + background-color: #aaa; + background-image: none; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css.min new file mode 100644 index 0000000..1a4e2c6 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-singlequotes.css.min @@ -0,0 +1 @@ +.yui3-skin-sam .yui3-scrollview-scrollbar{-webkit-transform:translate3d(0,0,0);-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==')}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-last{border-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-transform:translate3d(0,0,0);-moz-border-radius:0;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;-moz-transform:translate(0,0)}.yui3-skin-sam .yui3-scrollview-scrollbar .yui3-scrollview-middle{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;-webkit-transform:translate3d(0,0,0) scaleY(1);-webkit-transform-origin-y:0;-moz-transform:translate(0,0) scaleY(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-first,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-top-right-radius:0;border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-bottom-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomleft:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-last{border-bottom-left-radius:0;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:3px}.yui3-skin-sam .yui3-scrollview-scrollbar-horiz .yui3-scrollview-middle{-webkit-transform:translate3d(0,0,0) scaleX(1);-webkit-transform-origin:0 0;-moz-transform:translate(0,0) scaleX(1);-moz-transform-origin:0 0}.yui3-skin-sam .yui3-scrollview-scrollbar-vert-basic .yui3-scrollview-child,.yui3-skin-sam .yui3-scrollview-scrollbar-horiz-basic .yui3-scrollview-child{background-color:#aaa;background-image:none} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css new file mode 100644 index 0000000..78d615d --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css @@ -0,0 +1,106 @@ +html { + background: #fff; + color: #555; + height: 100%; +} + +#hd, #bd, #ft { + padding: 0 50px; +} + +#bd { + padding-bottom: 50px; + border-bottom: 1px solid #006e9c; +} + +#ft { + background: transparent no-repeat 0% 100%; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAeCAMAAAC/pnaKAAAAwFBMVEUkXIAoYYQoYYQoYYQyao02bpE6cpQ6cpREe51LgqNUiqtUiqtUiqtZj7BckrNlmrtlmrtlmrtroMB3qsp3qsp3qsp+sdCHudiHudiHudiHudiPwN+YyOaYyOaYyOaf0O2g0O6n1vOn1vOn1vOn1vOw3vu45f245f245f3B7f7K9f7K9f7K9f7X/v7X/v7p//7p//79//79//4AAABhAGMAbwBzAC4AcwB0AHIAaQBuAGcAcwABAAAAwIwmGwEAAABQQKFUAAAAQHRSTlP///////////////////////////////////////////////////////////////////8A////////////////0pfSbwAAAdtJREFUOI2NlNGqgzAMhv/ClDlQQcFdKOx4McFCKcH3f7eTtLWr07mFiUvbzz9Nk2LZGRH5937qZTiGyEx0Cr5xQpEd6xzNueCGc9SzUmAzP8cplO1zgRRutBAlM9EhZwknWj1LKXkwbOVojTqMEpKZOfeUD3OnR24VWeJf1OOBTnTgw8zZr3LyOlbdrWrdGlpG6Alz4Ni3RcT4Ldm8wHpOo9Yo5CPsdngM6D3HmLlESrgHD+YvrtEuUeLeMf7x7j23GJVgbJoHs0/cI3B7TNkfON5btsEUrvSdY694U0P9nXMp2mDsdbLmY14CN8XDjtzgo9CuqpYnGoMscDUmn08qsbOn/3Lte6rgP1eM7qQ1YMP+yPhiTmx2laDQspytgJI1MbIzZ7yHfj2/hYYtZ1xMM4dc3iTukjgJyKsrUBEH4uqFXNUh3aXxtWjbC3DpH8LRVPJ8MXLoA8fsz51ue73Q+1z7RkTEF0dWa1o5a8001C6ZbGuzh0bSTo9iS8X+C/NWbfTW5uZ9Vu4QaL20Xv3uhgyrZUXVtI2NfS3fbzgP75dNek/YbrL+k/EykecuZf6ZOzDJYsf9PCV3xhFHq7043mw+H1ylW+5Ab5jpADuPM2Z1P3POLWnUG/sHnIDsqkOjlqoAAAAASUVORK5CYII=); + /* image width: 55px */ + padding: 0 0 40px 0; + margin: 50px; +} + +#hd, #bd { + background: #f9f9f9; +} + +body { + margin: 0; + padding: 0; + font: 12px "Helvetica Nueue", Arial, sans-serif; +} + +#hd { + color: #fff; + padding-top: 50px; + margin: 0; +} + +#hd, h1, h2, p, .color { + margin: auto; +} + +h1, h2, a { + color: #006e9c; +} + +h1, h2 { + margin-top: 0; +} + +h4 .title { + font-weight: bold; + letter-spacing: -2px; + font-size: 47px; + text-shadow: 0 1px 0 #369; + background: #006e9d; + color: #fff; + padding: 0 10px; +} + +h4 { + display: block; + float: right; + margin: 0 0 0 20px; +} + +h4 .what { + display: block; + padding: 4px; + text-align: center; + font-weight: normal; +} + +h4 .version { + font-size: 11px; + color: #ccc; +} + +h2 { + font-size: 40px; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", + "Helvetica Neue", sans-serif; + font-weight: 300; +} + +h4, p { + padding: 6px 0 6px; +} + +#ft p.fine, #ft p.fine a { + color: #999; +} + +#ft p.intro { + font-size: 12px; +} + +#bd { + font-size: 14px; + color: #666; +} + +#ft p { + font-size: 11px; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css.min new file mode 100644 index 0000000..8d58663 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-realdata-yuiapp.css.min @@ -0,0 +1 @@ +html{background:#fff;color:#555;height:100%}#hd,#bd,#ft{padding:0 50px}#bd{padding-bottom:50px;border-bottom:1px solid #006e9c}#ft{background:transparent no-repeat 0 100%;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAeCAMAAAC/pnaKAAAAwFBMVEUkXIAoYYQoYYQoYYQyao02bpE6cpQ6cpREe51LgqNUiqtUiqtUiqtZj7BckrNlmrtlmrtlmrtroMB3qsp3qsp3qsp+sdCHudiHudiHudiHudiPwN+YyOaYyOaYyOaf0O2g0O6n1vOn1vOn1vOn1vOw3vu45f245f245f3B7f7K9f7K9f7K9f7X/v7X/v7p//7p//79//79//4AAABhAGMAbwBzAC4AcwB0AHIAaQBuAGcAcwABAAAAwIwmGwEAAABQQKFUAAAAQHRSTlP///////////////////////////////////////////////////////////////////8A////////////////0pfSbwAAAdtJREFUOI2NlNGqgzAMhv/ClDlQQcFdKOx4McFCKcH3f7eTtLWr07mFiUvbzz9Nk2LZGRH5937qZTiGyEx0Cr5xQpEd6xzNueCGc9SzUmAzP8cplO1zgRRutBAlM9EhZwknWj1LKXkwbOVojTqMEpKZOfeUD3OnR24VWeJf1OOBTnTgw8zZr3LyOlbdrWrdGlpG6Alz4Ni3RcT4Ldm8wHpOo9Yo5CPsdngM6D3HmLlESrgHD+YvrtEuUeLeMf7x7j23GJVgbJoHs0/cI3B7TNkfON5btsEUrvSdY694U0P9nXMp2mDsdbLmY14CN8XDjtzgo9CuqpYnGoMscDUmn08qsbOn/3Lte6rgP1eM7qQ1YMP+yPhiTmx2laDQspytgJI1MbIzZ7yHfj2/hYYtZ1xMM4dc3iTukjgJyKsrUBEH4uqFXNUh3aXxtWjbC3DpH8LRVPJ8MXLoA8fsz51ue73Q+1z7RkTEF0dWa1o5a8001C6ZbGuzh0bSTo9iS8X+C/NWbfTW5uZ9Vu4QaL20Xv3uhgyrZUXVtI2NfS3fbzgP75dNek/YbrL+k/EykecuZf6ZOzDJYsf9PCV3xhFHq7043mw+H1ylW+5Ab5jpADuPM2Z1P3POLWnUG/sHnIDsqkOjlqoAAAAASUVORK5CYII=);padding:0 0 40px 0;margin:50px}#hd,#bd{background:#f9f9f9}body{margin:0;padding:0;font:12px "Helvetica Nueue",Arial,sans-serif}#hd{color:#fff;padding-top:50px;margin:0}#hd,h1,h2,p,.color{margin:auto}h1,h2,a{color:#006e9c}h1,h2{margin-top:0}h4 .title{font-weight:bold;letter-spacing:-2px;font-size:47px;text-shadow:0 1px 0 #369;background:#006e9d;color:#fff;padding:0 10px}h4{display:block;float:right;margin:0 0 0 20px}h4 .what{display:block;padding:4px;text-align:center;font-weight:normal}h4 .version{font-size:11px;color:#ccc}h2{font-size:40px;font-family:"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",sans-serif;font-weight:300}h4,p{padding:6px 0 6px}#ft p.fine,#ft p.fine a{color:#999}#ft p.intro{font-size:12px}#bd{font-size:14px;color:#666}#ft p{font-size:11px} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css new file mode 100644 index 0000000..91bb3ed --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css @@ -0,0 +1,30 @@ +/*csslint fontfamily: true*/ + +/** + * Foo + */ + +.y-ff-1 { + font-family:"Foo Bar",Helvetica,Arial; + text-rendering: optimizeLegibility; +} + +.ua-op .y-ff-1 { + /* Some Comment */ + font-family:Helvetica,Arial; +} + +/* +Foo + +Bar +*/ + +@font-face { + font-family: "Foo Bar"; + src: url('data:font/truetype;base64,gRbIUFAIrsQNGditEWbAUKwAA') format("truetype"), + url("http://yuilibrary.com/fonts/foo-bar.svg#webfontse22fewwr") format("svg"); + font-weight: normal; + font-style: normal; +} + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css.min new file mode 100644 index 0000000..fd51d54 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dataurl-singlequote-font.css.min @@ -0,0 +1,3 @@ +.y-ff-1{font-family:"Foo Bar",Helvetica,Arial;text-rendering:optimizeLegibility}.ua-op .y-ff-1{font-family:Helvetica,Arial}@font-face{font-family:"Foo Bar";src:url('data:font/truetype;base64,gRbIUFAIrsQNGditEWbAUKwAA') format("truetype"),url("http://yuilibrary.com/fonts/foo-bar.svg#webfontse22fewwr") format("svg");font-weight:normal;font-style:normal} + + diff --git a/node_modules/less/node_modules/ycssmin/tests/files/decimals.css b/node_modules/less/node_modules/ycssmin/tests/files/decimals.css new file mode 100644 index 0000000..9593979 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/decimals.css @@ -0,0 +1,3 @@ +::selection { + margin: 0.6px 0.333pt 1.2em 8.8cm; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/decimals.css.min b/node_modules/less/node_modules/ycssmin/tests/files/decimals.css.min new file mode 100644 index 0000000..4dadedc --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/decimals.css.min @@ -0,0 +1 @@ +::selection{margin:.6px .333pt 1.2em 8.8cm} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css b/node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css new file mode 100644 index 0000000..43999c4 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css @@ -0,0 +1,7 @@ +/*! +$Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $ +*/ + +foo { + bar: baz +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css.min b/node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css.min new file mode 100644 index 0000000..9308100 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/dollar-header.css.min @@ -0,0 +1,3 @@ +/*! +$Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $ +*/foo{bar:baz} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/font-face.css b/node_modules/less/node_modules/ycssmin/tests/files/font-face.css new file mode 100644 index 0000000..4b6956c --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/font-face.css @@ -0,0 +1,6 @@ +@font-face { + font-family: 'gzipper'; + src: url(yanone.eot); + src: local('gzipper'), + url(yanone.ttf) format('truetype'); +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/font-face.css.min b/node_modules/less/node_modules/ycssmin/tests/files/font-face.css.min new file mode 100644 index 0000000..3a1077c --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/font-face.css.min @@ -0,0 +1 @@ +@font-face{font-family:'gzipper';src:url(yanone.eot);src:local('gzipper'),url(yanone.ttf) format('truetype')} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css b/node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css new file mode 100644 index 0000000..e4d5204 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css @@ -0,0 +1,5 @@ +/* Ignore the next rule in IE mac \*/ +.selector { + color: khaki; +} +/* Stop ignoring in IE mac */ diff --git a/node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css.min b/node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css.min new file mode 100644 index 0000000..f90df41 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/ie5mac.css.min @@ -0,0 +1 @@ +/*\*/.selector{color:khaki}/**/ \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css b/node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css new file mode 100644 index 0000000..d2f22d5 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css @@ -0,0 +1,16 @@ +/*! preserved */ +emptiness {} + +@import "another.css"; +/* I'm empty - delete me */ +empty { ;} + +@media print { + .noprint { display: none; } +} + +@media screen { + /* this rule should be removed, not simply minified.*/ + .breakme {} + .printonly { display: none; } +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css.min b/node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css.min new file mode 100644 index 0000000..0350c7f --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/media-empty-class.css.min @@ -0,0 +1 @@ +/*! preserved */@import "another.css";@media print{.noprint{display:none}}@media screen{.printonly{display:none}} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/media-multi.css b/node_modules/less/node_modules/ycssmin/tests/files/media-multi.css new file mode 100644 index 0000000..c589771 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/media-multi.css @@ -0,0 +1,3 @@ +@media only all and (max-width:50em), only all and (max-device-width:800px), only all and (max-width:780px) { + some-css : here +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/media-multi.css.min b/node_modules/less/node_modules/ycssmin/tests/files/media-multi.css.min new file mode 100644 index 0000000..57b52f7 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/media-multi.css.min @@ -0,0 +1 @@ +@media only all and (max-width:50em),only all and (max-device-width:800px),only all and (max-width:780px){some-css:here} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/media-test.css b/node_modules/less/node_modules/ycssmin/tests/files/media-test.css new file mode 100644 index 0000000..af118ff --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/media-test.css @@ -0,0 +1,3 @@ +@media screen and (-webkit-min-device-pixel-ratio:0) { + some-css : here +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/media-test.css.min b/node_modules/less/node_modules/ycssmin/tests/files/media-test.css.min new file mode 100644 index 0000000..0e7168e --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/media-test.css.min @@ -0,0 +1 @@ +@media screen and (-webkit-min-device-pixel-ratio:0){some-css:here} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css b/node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css new file mode 100644 index 0000000..60deca7 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css @@ -0,0 +1,14 @@ +/* example from https://developer.mozilla.org/en/CSS/opacity */ +pre { /* make the box translucent (80% opaque) */ + border: solid red; + opacity: 0.8; /* Firefox, Safari(WebKit), Opera */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */ + filter: PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */ + zoom: 1; /* set "zoom", "width" or "height" to trigger "hasLayout" in IE 7 and lower */ +} + +/** and again */ +code { + -ms-filter: "PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */ + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */ +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css.min b/node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css.min new file mode 100644 index 0000000..99b4fa8 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/opacity-filter.css.min @@ -0,0 +1 @@ +pre{border:solid red;opacity:.8;-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80);zoom:1}code{-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css b/node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css new file mode 100644 index 0000000..06818f0 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css @@ -0,0 +1,15 @@ +#AddAddressForm { + padding: 0; +} +#AddAddressForm .messageBoxNeutral { + padding: 0; +} +#FeedbackMailForm{ + padding: 0; +} +#FeedbackMailForm .classe{ + margin: 0; +} +.classes, #FeedBackMailForm { + margin: 0; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css.min b/node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css.min new file mode 100644 index 0000000..373bcbb --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/preserve-case.css.min @@ -0,0 +1 @@ +#AddAddressForm{padding:0}#AddAddressForm .messageBoxNeutral{padding:0}#FeedbackMailForm{padding:0}#FeedbackMailForm .classe{margin:0}.classes,#FeedBackMailForm{margin:0} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css b/node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css new file mode 100644 index 0000000..e1f0c92 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css @@ -0,0 +1,6 @@ +#sel-o { + content: "on\"ce upon \ +a time"; + content: 'once upon \ +a ti\'me'; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css.min b/node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css.min new file mode 100644 index 0000000..6ac20b6 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/preserve-new-line.css.min @@ -0,0 +1,3 @@ +#sel-o{content:"on\"ce upon \ +a time";content:'once upon \ +a ti\'me'} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css b/node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css new file mode 100644 index 0000000..9151373 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css @@ -0,0 +1,7 @@ +/* preserving strings */ +.sele { + content: "\"keep \" me"; + something: '\\\' . . '; + else: 'empty{}'; + content: "/* test */"; /* <---- this is not a comment, should be be kept */ +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css.min b/node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css.min new file mode 100644 index 0000000..3f1d010 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/preserve-strings.css.min @@ -0,0 +1 @@ +.sele{content:"\"keep \" me";something:'\\\' . . ';else:'empty{}';content:"/* test */"} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css b/node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css new file mode 100644 index 0000000..dbadef4 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css @@ -0,0 +1,16 @@ +/* +because of IE6 first-letter and first-line +must be followed by a space +http://reference.sitepoint.com/css/pseudoelement-firstletter +Thanks: P.Sorokin comment at http://www.phpied.com/cssmin-js/ +*/ +p:first-letter{ + buh: hum; +} +p:first-line{ + baa: 1; +} + +p:first-line,a,p:first-letter,b{ + color: red; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css.min b/node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css.min new file mode 100644 index 0000000..687117c --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/pseudo-first.css.min @@ -0,0 +1 @@ +p:first-letter {buh:hum}p:first-line {baa:1}p:first-line ,a,p:first-letter ,b{color:red} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/pseudo.css b/node_modules/less/node_modules/ycssmin/tests/files/pseudo.css new file mode 100644 index 0000000..a9a1bd9 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/pseudo.css @@ -0,0 +1,5 @@ +p :link , +div :link { + ba:zinga;;; + foo: bar;;; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/pseudo.css.min b/node_modules/less/node_modules/ycssmin/tests/files/pseudo.css.min new file mode 100644 index 0000000..a339ed2 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/pseudo.css.min @@ -0,0 +1 @@ +p :link,div :link{ba:zinga;foo:bar} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/special-comments.css b/node_modules/less/node_modules/ycssmin/tests/files/special-comments.css new file mode 100644 index 0000000..4e184ba --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/special-comments.css @@ -0,0 +1,13 @@ +/*!************88**** + Preserving comments + as they are + ******************** + Keep the initial ! + *******************/ +#yo { + ma: "ma"; +} +/*! +I said +pre- +serve! */ \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/special-comments.css.min b/node_modules/less/node_modules/ycssmin/tests/files/special-comments.css.min new file mode 100644 index 0000000..92ecbac --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/special-comments.css.min @@ -0,0 +1,9 @@ +/*!************88**** + Preserving comments + as they are + ******************** + Keep the initial ! + *******************/#yo{ma:"ma"}/*! +I said +pre- +serve! */ \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css b/node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css new file mode 100644 index 0000000..3295417 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css @@ -0,0 +1,118 @@ +/* + TODO will need to remove settings on HTML since we can't namespace it. + TODO with the prefix, should I group by selector or property for weight savings? +*/ +html{ + color:#000; + background:#FFF; +} +/* + TODO remove settings on BODY since we can't namespace it. +*/ +/* + TODO test putting a class on HEAD. + - Fails on FF. +*/ +body, +div, +dl, +dt, +dd, +ul, +ol, +li, +h1, +h2, +h3, +h4, +h5, +h6, +pre, +code, +form, +fieldset, +legend, +input, +textarea, +p, +blockquote, +th, +td { + margin:0; + padding:0; +} +table { + border-collapse:collapse; + border-spacing:0; +} +fieldset, +img { + border:0; +} +/* + TODO think about hanlding inheritence differently, maybe letting IE6 fail a bit... +*/ +address, +caption, +cite, +code, +dfn, +em, +strong, +th, +var { + font-style:normal; + font-weight:normal; +} + +ol, +ul { + list-style:none; +} + +caption, +th { + text-align:left; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-size:100%; + font-weight:normal; +} +q:before, +q:after { + content:''; +} +abbr, +acronym { + border:0; + font-variant:normal; +} +/* to preserve line-height and selector appearance */ +sup { + vertical-align:text-top; +} +sub { + vertical-align:text-bottom; +} +input, +textarea, +select { + font-family:inherit; + font-size:inherit; + font-weight:inherit; +} +/*to enable resizing for IE*/ +input, +textarea, +select { + *font-size:100%; +} +/*because legend doesn't inherit in IE */ +legend { + color:#000; +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css.min b/node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css.min new file mode 100644 index 0000000..c506602 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/special/linebreakpos.css.min @@ -0,0 +1,6 @@ +html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0} +table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal} +ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal} +q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal} +sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit} +input,textarea,select{*font-size:100%}legend{color:#000} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css b/node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css new file mode 100644 index 0000000..8b6e517 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css @@ -0,0 +1,5 @@ +#elementarr { + width: 1px; + *width: 3pt; + _width: 2em; +} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css.min b/node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css.min new file mode 100644 index 0000000..0a014c3 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/star-underscore-hacks.css.min @@ -0,0 +1 @@ +#elementarr{width:1px;*width:3pt;_width:2em} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css b/node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css new file mode 100644 index 0000000..d94d192 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css @@ -0,0 +1,8 @@ +/* te " st */ +a{a:1} +/*!"preserve" me*/ +b{content: "/**/"} +/* quite " quote ' \' \" */ +/* ie mac \*/ +c {c : 3} +/* end hiding */ \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css.min b/node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css.min new file mode 100644 index 0000000..7cdec2d --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/string-in-comment.css.min @@ -0,0 +1 @@ +a{a:1}/*!"preserve" me*/b{content:"/**/"}/*\*/c{c:3}/**/ \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css b/node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css new file mode 100644 index 0000000..83a50f2 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css @@ -0,0 +1,2 @@ +c {-webkit-transform-origin: 0 0;} +d {-MOZ-TRANSFORM-ORIGIN: 0 0 } \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css.min b/node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css.min new file mode 100644 index 0000000..b640ddf --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/webkit-transform.css.min @@ -0,0 +1 @@ +c{-webkit-transform-origin:0 0}d{-moz-transform-origin:0 0} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/files/zeros.css b/node_modules/less/node_modules/ycssmin/tests/files/zeros.css new file mode 100644 index 0000000..a5a4da2 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/zeros.css @@ -0,0 +1,6 @@ +a { + margin: 0px 0pt 0em 0%; + _padding-top: 0ex; + background-position: 0 0; + padding: 0in 0cm 0mm 0pc +} diff --git a/node_modules/less/node_modules/ycssmin/tests/files/zeros.css.min b/node_modules/less/node_modules/ycssmin/tests/files/zeros.css.min new file mode 100644 index 0000000..14ac7a9 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/files/zeros.css.min @@ -0,0 +1 @@ +a{margin:0;_padding-top:0;background-position:0 0;padding:0} \ No newline at end of file diff --git a/node_modules/less/node_modules/ycssmin/tests/tests.js b/node_modules/less/node_modules/ycssmin/tests/tests.js new file mode 100644 index 0000000..6178029 --- /dev/null +++ b/node_modules/less/node_modules/ycssmin/tests/tests.js @@ -0,0 +1,49 @@ +var vows = require('vows'), + assert = require('assert'), + path = require('path'), + fs = require('fs'), + exists = fs.existsSync || path.existsSync, + base = path.join(__dirname, './files'), + cssmin = require('../cssmin').cssmin, + files = fs.readdirSync(base), + tests = { + 'should be loaded': { + topic: function() { + return require('../cssmin').cssmin; + }, + 'should be a function': function(topic) { + assert.isFunction(topic); + } + } + }; + +files.forEach(function(file) { + if (path.extname(file) === '.css') { + var comp = path.join(base, file + '.min'); + if (exists(comp)) { + tests['should be loaded'][file] = (function(file) { + var expected = (fs.readFileSync(path.join(base, file + '.min'), 'utf8')).trim(), + str = (fs.readFileSync(path.join(base, file), 'utf8')).trim(); + return function(topic) { + var out = topic(str); + assert.equal(expected, out); + }; + }(file)); + } + } +}); + +//Line Break Test +(function() { + var file = 'linebreakpos.css'; + tests['should be loaded']['and should handle linebreak'] = (function(file) { + var expected = (fs.readFileSync(path.join(base, 'special', file + '.min'), 'utf8')).trim(), + str = (fs.readFileSync(path.join(base, 'special', file), 'utf8')).trim(); + return function(topic) { + var out = topic(str, 100); + assert.equal(expected, out); + }; + }(file)); +}()); + +vows.describe('cssmin tests').addBatch(tests).export(module); diff --git a/node_modules/less/package.json b/node_modules/less/package.json new file mode 100644 index 0000000..faf9faf --- /dev/null +++ b/node_modules/less/package.json @@ -0,0 +1,92 @@ +{ + "name": "less", + "version": "1.4.1", + "description": "Leaner CSS", + "homepage": "http://lesscss.org", + "author": { + "name": "Alexis Sellier", + "email": "self@cloudhead.net" + }, + "contributors": [ + { + "name": "The Core Less Team" + } + ], + "bugs": { + "url": "https://github.com/cloudhead/less.js/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/cloudhead/less.js.git" + }, + "bin": { + "lessc": "./bin/lessc" + }, + "main": "./lib/less/index", + "directories": { + "test": "./test" + }, + "jam": { + "main": "./dist/less-1.4.1.js" + }, + "engines": { + "node": ">=0.4.2" + }, + "scripts": { + "test": "make test" + }, + "optionalDependencies": { + "mime": "1.2.x", + "request": ">=2.12.0", + "mkdirp": "~0.3.4", + "ycssmin": ">=1.0.1" + }, + "devDependencies": { + "diff": "~1.0" + }, + "keywords": [ + "compile less", + "css nesting", + "css variable", + "css", + "gradients css", + "gradients css3", + "less compiler", + "less css", + "less mixins", + "less", + "less.js", + "lesscss", + "mixins", + "nested css", + "parser", + "preprocessor", + "bootstrap css", + "bootstrap less", + "style", + "styles", + "stylesheet", + "variables in css", + "css less" + ], + "licenses": [ + { + "type": "Apache v2", + "url": "https://github.com/cloudhead/less.js/blob/master/LICENSE" + } + ], + "readme": "less.js\n=======\n\nThe **dynamic** stylesheet language.\n\n\n\nabout\n-----\n\nThis is the JavaScript, and now official, stable version of LESS.\n\nFor more information on the language and usage visit [lesscss.org](http://lesscss.org). More information also available [in our wiki](https://github.com/cloudhead/less.js/wiki)\n\nlicense\n-------\n\nSee `LICENSE` file.\n\n> Copyright (c) 2009-2013 Alexis Sellier & The Core Less Team\n", + "readmeFilename": "README.md", + "_id": "less@1.4.1", + "dependencies": { + "mime": "1.2.x", + "request": ">=2.12.0", + "mkdirp": "~0.3.4", + "ycssmin": ">=1.0.1" + }, + "dist": { + "shasum": "ba08f323d2475fc68b8fde5ff56246245f3ee023" + }, + "_from": "less@", + "_resolved": "https://registry.npmjs.org/less/-/less-1.4.1.tgz" +} diff --git a/node_modules/less/test/browser-test-prepare.js b/node_modules/less/test/browser-test-prepare.js new file mode 100644 index 0000000..0272279 --- /dev/null +++ b/node_modules/less/test/browser-test-prepare.js @@ -0,0 +1,46 @@ +var path = require('path'), + fs = require('fs'), + sys = require('util'); + +var readDirFilesSync = function(dir, regex, callback) { + fs.readdirSync(dir).forEach(function (file) { + if (! regex.test(file)) { return; } + callback(file); + }); +} + +var createTestRunnerPage = function(dir, exclude, testSuiteName, dir2) { + var output = '\n'; + + readDirFilesSync(path.join("test", dir, 'less', dir2 || ""), /\.less$/, function (file) { + var name = path.basename(file, '.less'), + id = (dir ? dir + '-' : "") + 'less-' + (dir2 ? dir2 + "-" : "") + name; + + if (exclude && name.match(exclude)) { return; } + + output += '\n'; + output += '\n'; + }); + + output += String(fs.readFileSync(path.join('test/browser', 'template.htm'))).replace("{runner-name}", testSuiteName); + + fs.writeFileSync(path.join('test/browser', 'test-runner-'+testSuiteName+'.htm'), output); +}; + +var removeFiles = function(dir, regex) { + readDirFilesSync(dir, regex, function(file) { + fs.unlinkSync(path.join(dir, file), function() { + console.log("Failed to delete " + file); + }); + }); +} + +removeFiles("test/browser", /test-runner-[a-zA-Z-]*\.htm$/); +createTestRunnerPage("", /javascript|urls/, "main"); +createTestRunnerPage("", null, "legacy", "legacy"); +createTestRunnerPage("", /javascript/, "errors", "errors"); +createTestRunnerPage("browser", null, "browser"); +createTestRunnerPage("browser", null, "relative-urls", "relative-urls"); +createTestRunnerPage("browser", null, "rootpath", "rootpath"); +createTestRunnerPage("browser", null, "rootpath-relative", "rootpath-relative"); +createTestRunnerPage("browser", null, "production"); \ No newline at end of file diff --git a/node_modules/less/test/browser/common.js b/node_modules/less/test/browser/common.js new file mode 100644 index 0000000..74f12fe --- /dev/null +++ b/node_modules/less/test/browser/common.js @@ -0,0 +1,126 @@ +/*if not async then phantomjs fails to run the webserver and the test concurrently*/ +var less = { async: true, strictMath: true }; + +/* record log messages for testing */ +var logMessages = [], + realConsoleLog = console.log; +console.log = function(msg) { + logMessages.push(msg); + realConsoleLog.call(console, msg); +}; + +var testLessEqualsInDocument = function() { + testLessInDocument(testSheet); +}; + +var testLessErrorsInDocument = function() { + testLessInDocument(testErrorSheet); +}; + +var testLessInDocument = function(testFunc) { + var links = document.getElementsByTagName('link'), + typePattern = /^text\/(x-)?less$/; + + for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + testFunc(links[i]); + } + } +}; + +var testSheet = function(sheet) { + it(sheet.id + " should match the expected output", function() { + var lessOutputId = sheet.id.replace("original-", ""), + expectedOutputId = "expected-" + lessOutputId, + lessOutput = document.getElementById(lessOutputId).innerText, + expectedOutputHref = document.getElementById(expectedOutputId).href, + expectedOutput = loadFile(expectedOutputHref); + + waitsFor(function() { + return expectedOutput.loaded; + }, "failed to load expected outout", 10000); + + runs(function() { + // use sheet to do testing + expect(lessOutput).toEqual(expectedOutput.text); + }); + }); +}; + +var testErrorSheet = function(sheet) { + it(sheet.id + " should match an error", function() { + var lessHref = sheet.href, + id = sheet.id.replace(/^original-less:/, "less-error-message:"), + errorHref = lessHref.replace(/.less$/, ".txt"), + errorFile = loadFile(errorHref), + actualErrorElement = document.getElementById(id), + actualErrorMsg; + + describe("the error", function() { + expect(actualErrorElement).not.toBe(null); + }); + + actualErrorMsg = actualErrorElement.innerText + .replace(/\n\d+/g, function(lineNo) { return lineNo + " "; }) + .replace(/\n\s*in /g, " in ") + .replace("\n\n", "\n"); + + waitsFor(function() { + return errorFile.loaded; + }, "failed to load expected outout", 10000); + + runs(function() { + var errorTxt = errorFile.text + .replace("{path}", "") + .replace("{pathrel}", "") + .replace("{pathhref}", "http://localhost:8081/less/errors/") + .replace("{404status}", " (404)"); + expect(actualErrorMsg).toEqual(errorTxt); + if (errorTxt == actualErrorMsg) { + actualErrorElement.style.display = "none"; + } + }); + }); +}; + +var loadFile = function(href) { + var request = new XMLHttpRequest(), + response = { loaded: false, text: ""}; + request.open('GET', href, true); + request.onload = function(e) { + response.text = request.response.replace(/\r/g, ""); + response.loaded = true; + } + request.send(); + return response; +}; + +(function() { + var jasmineEnv = jasmine.getEnv(); + jasmineEnv.updateInterval = 1000; + + var htmlReporter = new jasmine.HtmlReporter(); + + jasmineEnv.addReporter(htmlReporter); + + jasmineEnv.specFilter = function(spec) { + return htmlReporter.specFilter(spec); + }; + + var currentWindowOnload = window.onload; + + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + execJasmine(); + }; + + function execJasmine() { + setTimeout(function() { + jasmineEnv.execute(); + }, 3000); + } + +})(); \ No newline at end of file diff --git a/node_modules/less/test/browser/css/relative-urls/urls.css b/node_modules/less/test/browser/css/relative-urls/urls.css new file mode 100644 index 0000000..d0da499 --- /dev/null +++ b/node_modules/less/test/browser/css/relative-urls/urls.css @@ -0,0 +1,36 @@ +@import "http://localhost:8081/browser/less/imports/modify-this.css"; + +@import "http://localhost:8081/browser/less/imports/modify-again.css"; +.modify { + my-url: url("http://localhost:8081/browser/less/imports/a.png"); +} +.modify { + my-url: url("http://localhost:8081/browser/less/imports/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(http://localhost:8081/browser/less/relative-urls/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(http://localhost:8081/browser/less/relative-urls/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(http://localhost:8081/browser/less/relative-urls/bg.jpg) no-repeat, url(http://localhost:8081/browser/less/relative-urls/bg.png) repeat-x top left, url(http://localhost:8081/browser/less/relative-urls/bg); +} +.values { + url: url('http://localhost:8081/browser/less/relative-urls/Trebuchet'); +} diff --git a/node_modules/less/test/browser/css/rootpath-relative/urls.css b/node_modules/less/test/browser/css/rootpath-relative/urls.css new file mode 100644 index 0000000..817d581 --- /dev/null +++ b/node_modules/less/test/browser/css/rootpath-relative/urls.css @@ -0,0 +1,36 @@ +@import "https://www.github.com/cloudhead/imports/modify-this.css"; + +@import "https://www.github.com/cloudhead/imports/modify-again.css"; +.modify { + my-url: url("https://www.github.com/cloudhead/imports/a.png"); +} +.modify { + my-url: url("https://www.github.com/cloudhead/imports/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(https://www.github.com/cloudhead/less.js/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(https://www.github.com/cloudhead/less.js/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(https://www.github.com/cloudhead/less.js/bg.jpg) no-repeat, url(https://www.github.com/cloudhead/less.js/bg.png) repeat-x top left, url(https://www.github.com/cloudhead/less.js/bg); +} +.values { + url: url('https://www.github.com/cloudhead/less.js/Trebuchet'); +} diff --git a/node_modules/less/test/browser/css/rootpath/urls.css b/node_modules/less/test/browser/css/rootpath/urls.css new file mode 100644 index 0000000..a3ef5d9 --- /dev/null +++ b/node_modules/less/test/browser/css/rootpath/urls.css @@ -0,0 +1,36 @@ +@import "https://www.github.com/modify-this.css"; + +@import "https://www.github.com/modify-again.css"; +.modify { + my-url: url("https://www.github.com/a.png"); +} +.modify { + my-url: url("https://www.github.com/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(https://www.github.com/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(https://www.github.com/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(https://www.github.com/bg.jpg) no-repeat, url(https://www.github.com/bg.png) repeat-x top left, url(https://www.github.com/bg); +} +.values { + url: url('https://www.github.com/Trebuchet'); +} diff --git a/node_modules/less/test/browser/css/urls.css b/node_modules/less/test/browser/css/urls.css new file mode 100644 index 0000000..19ba27e --- /dev/null +++ b/node_modules/less/test/browser/css/urls.css @@ -0,0 +1,49 @@ +@import "http://localhost:8081/browser/less/modify-this.css"; + +@import "http://localhost:8081/browser/less/modify-again.css"; +.modify { + my-url: url("http://localhost:8081/browser/less/a.png"); +} +.modify { + my-url: url("http://localhost:8081/browser/less/b.png"); +} +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(http://localhost:8081/browser/less/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(http://localhost:8081/browser/less/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(http://localhost:8081/browser/less/bg.jpg) no-repeat, url(http://localhost:8081/browser/less/bg.png) repeat-x top left, url(http://localhost:8081/browser/less/bg); +} +.values { + url: url('http://localhost:8081/browser/less/Trebuchet'); +} +#data-uri { + uri: url('http://localhost:8081/browser/less/../../data/image.jpg'); +} +#data-uri-guess { + uri: url('http://localhost:8081/browser/less/../../data/image.jpg'); +} +#data-uri-ascii { + uri-1: url('http://localhost:8081/browser/less/../../data/page.html'); + uri-2: url('http://localhost:8081/browser/less/../../data/page.html'); +} +#data-uri-toobig { + uri: url('http://localhost:8081/browser/less/../../data/data-uri-fail.png'); +} diff --git a/node_modules/less/test/browser/jasmine-html.js b/node_modules/less/test/browser/jasmine-html.js new file mode 100644 index 0000000..543d569 --- /dev/null +++ b/node_modules/less/test/browser/jasmine-html.js @@ -0,0 +1,681 @@ +jasmine.HtmlReporterHelpers = {}; + +jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { + var results = child.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + + return status; +}; + +jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { + var parentDiv = this.dom.summary; + var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; + var parent = child[parentSuite]; + + if (parent) { + if (typeof this.views.suites[parent.id] == 'undefined') { + this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); + } + parentDiv = this.views.suites[parent.id].element; + } + + parentDiv.appendChild(childElement); +}; + + +jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { + for(var fn in jasmine.HtmlReporterHelpers) { + ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; + } +}; + +jasmine.HtmlReporter = function(_doc) { + var self = this; + var doc = _doc || window.document; + + var reporterView; + + var dom = {}; + + // Jasmine Reporter Public Interface + self.logRunningSpecs = false; + + self.reportRunnerStarting = function(runner) { + var specs = runner.specs() || []; + + if (specs.length == 0) { + return; + } + + createReporterDom(runner.env.versionString()); + doc.body.appendChild(dom.reporter); + setExceptionHandling(); + + reporterView = new jasmine.HtmlReporter.ReporterView(dom); + reporterView.addSpecs(specs, self.specFilter); + }; + + self.reportRunnerResults = function(runner) { + reporterView && reporterView.complete(); + }; + + self.reportSuiteResults = function(suite) { + reporterView.suiteComplete(suite); + }; + + self.reportSpecStarting = function(spec) { + if (self.logRunningSpecs) { + self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } + }; + + self.reportSpecResults = function(spec) { + reporterView.specComplete(spec); + }; + + self.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } + }; + + self.specFilter = function(spec) { + if (!focusedSpecName()) { + return true; + } + + return spec.getFullName().indexOf(focusedSpecName()) === 0; + }; + + return self; + + function focusedSpecName() { + var specName; + + (function memoizeFocusedSpec() { + if (specName) { + return; + } + + var paramMap = []; + var params = jasmine.HtmlReporter.parameters(doc); + + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + specName = paramMap.spec; + })(); + + return specName; + } + + function createReporterDom(version) { + dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, + dom.banner = self.createDom('div', { className: 'banner' }, + self.createDom('span', { className: 'title' }, "Jasmine "), + self.createDom('span', { className: 'version' }, version)), + + dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), + dom.alert = self.createDom('div', {className: 'alert'}, + self.createDom('span', { className: 'exceptions' }, + self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'), + self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))), + dom.results = self.createDom('div', {className: 'results'}, + dom.summary = self.createDom('div', { className: 'summary' }), + dom.details = self.createDom('div', { id: 'details' })) + ); + } + + function noTryCatch() { + return window.location.search.match(/catch=false/); + } + + function searchWithCatch() { + var params = jasmine.HtmlReporter.parameters(window.document); + var removed = false; + var i = 0; + + while (!removed && i < params.length) { + if (params[i].match(/catch=/)) { + params.splice(i, 1); + removed = true; + } + i++; + } + if (jasmine.CATCH_EXCEPTIONS) { + params.push("catch=false"); + } + + return params.join("&"); + } + + function setExceptionHandling() { + var chxCatch = document.getElementById('no_try_catch'); + + if (noTryCatch()) { + chxCatch.setAttribute('checked', true); + jasmine.CATCH_EXCEPTIONS = false; + } + chxCatch.onclick = function() { + window.location.search = searchWithCatch(); + }; + } +}; +jasmine.HtmlReporter.parameters = function(doc) { + var paramStr = doc.location.search.substring(1); + var params = []; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + } + return params; +} +jasmine.HtmlReporter.sectionLink = function(sectionName) { + var link = '?'; + var params = []; + + if (sectionName) { + params.push('spec=' + encodeURIComponent(sectionName)); + } + if (!jasmine.CATCH_EXCEPTIONS) { + params.push("catch=false"); + } + if (params.length > 0) { + link += params.join("&"); + } + + return link; +}; +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter); +jasmine.HtmlReporter.ReporterView = function(dom) { + this.startedAt = new Date(); + this.runningSpecCount = 0; + this.completeSpecCount = 0; + this.passedCount = 0; + this.failedCount = 0; + this.skippedCount = 0; + + this.createResultsMenu = function() { + this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, + this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), + ' | ', + this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); + + this.summaryMenuItem.onclick = function() { + dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); + }; + + this.detailsMenuItem.onclick = function() { + showDetails(); + }; + }; + + this.addSpecs = function(specs, specFilter) { + this.totalSpecCount = specs.length; + + this.views = { + specs: {}, + suites: {} + }; + + for (var i = 0; i < specs.length; i++) { + var spec = specs[i]; + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); + if (specFilter(spec)) { + this.runningSpecCount++; + } + } + }; + + this.specComplete = function(spec) { + this.completeSpecCount++; + + if (isUndefined(this.views.specs[spec.id])) { + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); + } + + var specView = this.views.specs[spec.id]; + + switch (specView.status()) { + case 'passed': + this.passedCount++; + break; + + case 'failed': + this.failedCount++; + break; + + case 'skipped': + this.skippedCount++; + break; + } + + specView.refresh(); + this.refresh(); + }; + + this.suiteComplete = function(suite) { + var suiteView = this.views.suites[suite.id]; + if (isUndefined(suiteView)) { + return; + } + suiteView.refresh(); + }; + + this.refresh = function() { + + if (isUndefined(this.resultsMenu)) { + this.createResultsMenu(); + } + + // currently running UI + if (isUndefined(this.runningAlert)) { + this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" }); + dom.alert.appendChild(this.runningAlert); + } + this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); + + // skipped specs UI + if (isUndefined(this.skippedAlert)) { + this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" }); + } + + this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.skippedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.skippedAlert); + } + + // passing specs UI + if (isUndefined(this.passedAlert)) { + this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" }); + } + this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); + + // failing specs UI + if (isUndefined(this.failedAlert)) { + this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); + } + this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); + + if (this.failedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.failedAlert); + dom.alert.appendChild(this.resultsMenu); + } + + // summary info + this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); + this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; + }; + + this.complete = function() { + dom.alert.removeChild(this.runningAlert); + + this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.failedCount === 0) { + dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); + } else { + showDetails(); + } + + dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); + }; + + return this; + + function showDetails() { + if (dom.reporter.className.search(/showDetails/) === -1) { + dom.reporter.className += " showDetails"; + } + } + + function isUndefined(obj) { + return typeof obj === 'undefined'; + } + + function isDefined(obj) { + return !isUndefined(obj); + } + + function specPluralizedFor(count) { + var str = count + " spec"; + if (count > 1) { + str += "s" + } + return str; + } + +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); + + +jasmine.HtmlReporter.SpecView = function(spec, dom, views) { + this.spec = spec; + this.dom = dom; + this.views = views; + + this.symbol = this.createDom('li', { className: 'pending' }); + this.dom.symbolSummary.appendChild(this.symbol); + + this.summary = this.createDom('div', { className: 'specSummary' }, + this.createDom('a', { + className: 'description', + href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.description) + ); + + this.detail = this.createDom('div', { className: 'specDetail' }, + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.getFullName()) + ); +}; + +jasmine.HtmlReporter.SpecView.prototype.status = function() { + return this.getSpecStatus(this.spec); +}; + +jasmine.HtmlReporter.SpecView.prototype.refresh = function() { + this.symbol.className = this.status(); + + switch (this.status()) { + case 'skipped': + break; + + case 'passed': + this.appendSummaryToSuiteDiv(); + break; + + case 'failed': + this.appendSummaryToSuiteDiv(); + this.appendFailureDetail(); + break; + } +}; + +jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { + this.summary.className += ' ' + this.status(); + this.appendToSummary(this.spec, this.summary); +}; + +jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { + this.detail.className += ' ' + this.status(); + + var resultItems = this.spec.results().getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + this.detail.appendChild(messagesDiv); + this.dom.details.appendChild(this.detail); + } +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { + this.suite = suite; + this.dom = dom; + this.views = views; + + this.element = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description) + ); + + this.appendToSummary(this.suite, this.element); +}; + +jasmine.HtmlReporter.SuiteView.prototype.status = function() { + return this.getSpecStatus(this.suite); +}; + +jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { + this.element.className += " " + this.status(); +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); + +/* @deprecated Use jasmine.HtmlReporter instead + */ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/node_modules/less/test/browser/jasmine.css b/node_modules/less/test/browser/jasmine.css new file mode 100644 index 0000000..8c008dc --- /dev/null +++ b/node_modules/less/test/browser/jasmine.css @@ -0,0 +1,82 @@ +body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } + +#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +#HTMLReporter a { text-decoration: none; } +#HTMLReporter a:hover { text-decoration: underline; } +#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } +#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } +#HTMLReporter #jasmine_content { position: fixed; right: 100%; } +#HTMLReporter .version { color: #aaaaaa; } +#HTMLReporter .banner { margin-top: 14px; } +#HTMLReporter .duration { color: #aaaaaa; float: right; } +#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } +#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } +#HTMLReporter .symbolSummary li.passed { font-size: 14px; } +#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } +#HTMLReporter .symbolSummary li.failed { line-height: 9px; } +#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } +#HTMLReporter .symbolSummary li.skipped { font-size: 14px; } +#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } +#HTMLReporter .symbolSummary li.pending { line-height: 11px; } +#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } +#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +#HTMLReporter .runningAlert { background-color: #666666; } +#HTMLReporter .skippedAlert { background-color: #aaaaaa; } +#HTMLReporter .skippedAlert:first-child { background-color: #333333; } +#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } +#HTMLReporter .passingAlert { background-color: #a6b779; } +#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } +#HTMLReporter .failingAlert { background-color: #cf867e; } +#HTMLReporter .failingAlert:first-child { background-color: #b03911; } +#HTMLReporter .results { margin-top: 14px; } +#HTMLReporter #details { display: none; } +#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } +#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter.showDetails .summary { display: none; } +#HTMLReporter.showDetails #details { display: block; } +#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter .summary { margin-top: 14px; } +#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } +#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } +#HTMLReporter .summary .specSummary.failed a { color: #b03911; } +#HTMLReporter .description + .suite { margin-top: 0; } +#HTMLReporter .suite { margin-top: 14px; } +#HTMLReporter .suite a { color: #333333; } +#HTMLReporter #details .specDetail { margin-bottom: 28px; } +#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } +#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } +#HTMLReporter .resultMessage span.result { display: block; } +#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } + +#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } +#TrivialReporter a:visited, #TrivialReporter a { color: #303; } +#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } +#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } +#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } +#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } +#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } +#TrivialReporter .runner.running { background-color: yellow; } +#TrivialReporter .options { text-align: right; font-size: .8em; } +#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } +#TrivialReporter .suite .suite { margin: 5px; } +#TrivialReporter .suite.passed { background-color: #dfd; } +#TrivialReporter .suite.failed { background-color: #fdd; } +#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } +#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } +#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } +#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } +#TrivialReporter .spec.skipped { background-color: #bbb; } +#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } +#TrivialReporter .passed { background-color: #cfc; display: none; } +#TrivialReporter .failed { background-color: #fbb; } +#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } +#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } +#TrivialReporter .resultMessage .mismatch { color: black; } +#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } +#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } +#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } +#TrivialReporter #jasmine_content { position: fixed; right: 100%; } +#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } diff --git a/node_modules/less/test/browser/jasmine.js b/node_modules/less/test/browser/jasmine.js new file mode 100644 index 0000000..6b3459b --- /dev/null +++ b/node_modules/less/test/browser/jasmine.js @@ -0,0 +1,2600 @@ +var isCommonJS = typeof window == "undefined" && typeof exports == "object"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Maximum levels of nesting that will be included when an object is pretty-printed + */ +jasmine.MAX_PRETTY_PRINT_DEPTH = 40; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +/** + * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite. + * Set to false to let the exception bubble up in the browser. + * + */ +jasmine.CATCH_EXCEPTIONS = true; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the + * attributes on the object. + * + * @example + * // don't care about any other attributes than foo. + * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); + * + * @param sample {Object} sample + * @returns matchable object for the sample + */ +jasmine.objectContaining = function (sample) { + return new jasmine.Matchers.ObjectContaining(sample); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + * @return {jasmine.Matchers} + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.source != b.source) + mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/"); + + if (a.ignoreCase != b.ignoreCase) + mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.global != b.global) + mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.multiline != b.multiline) + mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier"); + + if (a.sticky != b.sticky) + mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier"); + + return (mismatchValues.length === 0); +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a.jasmineMatches) { + return a.jasmineMatches(b); + } + + if (b.jasmineMatches) { + return b.jasmineMatches(a); + } + + if (a instanceof jasmine.Matchers.ObjectContaining) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.ObjectContaining) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (a instanceof RegExp && b instanceof RegExp) { + return this.compareRegExps_(a, b, mismatchKeys, mismatchValues); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + if (!jasmine.CATCH_EXCEPTIONS) { + this.func.apply(this.spec); + } + else { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that compares the actual to NaN. + */ +jasmine.Matchers.prototype.toBeNaN = function() { + this.message = function() { + return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ]; + }; + + return (this.actual !== this.actual); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."; + var positiveMessage = ""; + if (this.actual.callCount === 0) { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called."; + } else { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '') + } + return [positiveMessage, invertedMessage]; + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision, as number of decimal places + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2); +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} [expected] + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineToString = function() { + return ''; +}; + +jasmine.Matchers.ObjectContaining = function (sample) { + this.sample = sample; +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var env = jasmine.getEnv(); + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { + return ""; +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!obj.hasOwnProperty(property)) continue; + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Array"); + return; + } + + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { + this.append("Object"); + return; + } + + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + + // parallel to blocks. each true value in this array means the block will + // get executed even if we abort + this.ensured = []; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.unshift(block); + this.ensured.unshift(ensure); +}; + +jasmine.Queue.prototype.add = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.push(block); + this.ensured.push(ensure); +}; + +jasmine.Queue.prototype.insertNext = function(block, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.ensured.splice((this.index + this.offset + 1), 0, ensure); + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this), true); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 3, + "build": 1, + "revision": 1354556913 +}; diff --git a/node_modules/less/test/browser/less/imports/urls.less b/node_modules/less/test/browser/less/imports/urls.less new file mode 100644 index 0000000..290e6b4 --- /dev/null +++ b/node_modules/less/test/browser/less/imports/urls.less @@ -0,0 +1,4 @@ +@import "modify-this.css"; +.modify { + my-url: url("a.png"); +} \ No newline at end of file diff --git a/node_modules/less/test/browser/less/imports/urls2.less b/node_modules/less/test/browser/less/imports/urls2.less new file mode 100644 index 0000000..b834bb9 --- /dev/null +++ b/node_modules/less/test/browser/less/imports/urls2.less @@ -0,0 +1,4 @@ +@import "modify-again.css"; +.modify { + my-url: url("b.png"); +} \ No newline at end of file diff --git a/node_modules/less/test/browser/less/relative-urls/urls.less b/node_modules/less/test/browser/less/relative-urls/urls.less new file mode 100644 index 0000000..7923d4c --- /dev/null +++ b/node_modules/less/test/browser/less/relative-urls/urls.less @@ -0,0 +1,33 @@ +@import ".././imports/urls.less"; +@import "http://localhost:8081/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} diff --git a/node_modules/less/test/browser/less/rootpath-relative/urls.less b/node_modules/less/test/browser/less/rootpath-relative/urls.less new file mode 100644 index 0000000..1c5ac88 --- /dev/null +++ b/node_modules/less/test/browser/less/rootpath-relative/urls.less @@ -0,0 +1,33 @@ +@import "../imports/urls.less"; +@import "http://localhost:8081/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} diff --git a/node_modules/less/test/browser/less/rootpath/urls.less b/node_modules/less/test/browser/less/rootpath/urls.less new file mode 100644 index 0000000..1c5ac88 --- /dev/null +++ b/node_modules/less/test/browser/less/rootpath/urls.less @@ -0,0 +1,33 @@ +@import "../imports/urls.less"; +@import "http://localhost:8081/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} diff --git a/node_modules/less/test/browser/less/urls.less b/node_modules/less/test/browser/less/urls.less new file mode 100644 index 0000000..1f39a92 --- /dev/null +++ b/node_modules/less/test/browser/less/urls.less @@ -0,0 +1,49 @@ +@import "imports/urls.less"; +@import "http://localhost:8081/browser/less/imports/urls2.less"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} +#data-uri { + uri: data-uri('image/jpeg;base64', '../../data/image.jpg'); +} + +#data-uri-guess { + uri: data-uri('../../data/image.jpg'); +} + +#data-uri-ascii { + uri-1: data-uri('text/html', '../../data/page.html'); + uri-2: data-uri('../../data/page.html'); +} + +#data-uri-toobig { + uri: data-uri('../../data/data-uri-fail.png'); +} diff --git a/node_modules/less/test/browser/phantom-runner.js b/node_modules/less/test/browser/phantom-runner.js new file mode 100644 index 0000000..0325ba5 --- /dev/null +++ b/node_modules/less/test/browser/phantom-runner.js @@ -0,0 +1,141 @@ +var webpage = require('webpage'); +var server = require('webserver').create(); +var system = require('system'); +var fs = require('fs'); +var host, port = 8081; + +var listening = server.listen(port, function (request, response) { + //console.log("Requested "+request.url); + + var filename = ("test/" + request.url.slice(1)).replace(/[\\\/]/g, fs.separator); + + if (!fs.exists(filename) || !fs.isFile(filename)) { + response.statusCode = 404; + response.write("

    File Not Found

    File:"+filename+"

    "); + response.close(); + return; + } + + // we set the headers here + response.statusCode = 200; + response.headers = {"Cache": "no-cache", "Content-Type": "text/html"}; + + response.write(fs.read(filename)); + + response.close(); +}); +if (!listening) { + console.log("could not create web server listening on port " + port); + phantom.exit(); +} + +/** + * Wait until the test condition is true or a timeout occurs. Useful for waiting + * on a server response or for a ui change (fadeIn, etc.) to occur. + * + * @param testFx javascript condition that evaluates to a boolean, + * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or + * as a callback function. + * @param onReady what to do when testFx condition is fulfilled, + * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or + * as a callback function. + * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. + * @param timeOutErrorMessage the error message if time out occurs + */ +function waitFor(testFx, onReady, timeOutMillis, timeOutErrorMessage) { + var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 10001, //< Default Max Timeout is 10s + start = new Date().getTime(), + condition = false, + interval = setInterval(function() { + if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { + // If not time-out yet and condition not yet fulfilled + condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code + } else { + if(!condition) { + // If condition still not fulfilled (timeout but condition is 'false') + console.log(timeOutErrorMessage || "'waitFor()' timeout"); + phantom.exit(1); + } else { + // Condition fulfilled (timeout and/or condition is 'true') + typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled + clearInterval(interval); //< Stop this interval + } + } + }, 100); //< repeat check every 100ms +}; + +function testPage(url) { + var page = webpage.create(); + page.open(url, function (status) { + if (status !== "success") { + console.log("Unable to access network - " + status); + phantom.exit(); + } else { + waitFor(function(){ + return page.evaluate(function(){ + return document.body && document.body.querySelector && + document.body.querySelector('.symbolSummary .pending') === null && + document.body.querySelector('.results') !== null; + }); + }, function(){ + page.onConsoleMessage = function (msg) { + console.log(msg); + }; + var exitCode = page.evaluate(function(){ + console.log(''); + console.log(document.body.querySelector('.description').innerText); + var list = document.body.querySelectorAll('.results > #details > .specDetail.failed'); + if (list && list.length > 0) { + console.log(''); + console.log(list.length + ' test(s) FAILED:'); + for (var i = 0; i < list.length; ++i) { + var el = list[i], + desc = el.querySelector('.description'), + msg = el.querySelector('.resultMessage.fail'); + console.log(''); + console.log(desc.innerText); + console.log(msg.innerText); + console.log(''); + } + return 1; + } else { + console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText); + return 0; + } + }); + testFinished(exitCode); + }, + 10000, // 10 second timeout + "Test failed waiting for jasmine results on page: " + url); + } + }); +} + +function scanDirectory(path, regex) { + var files = []; + fs.list(path).forEach(function (file) { + if (file.match(regex)) { + files.push(file); + } + }); + return files; +}; + +var totalTests = 0, + totalFailed = 0, + totalDone = 0; + +function testFinished(failed) { + if (failed) { totalFailed++; } + totalDone++; + if (totalDone === totalTests) { phantom.exit(totalFailed > 0 ? 1 : 0); } +} + +if (system.args.length != 2 && system.args[1] != "--no-tests") { + var files = scanDirectory("test/browser/", /^test-runner-.+\.htm$/); + totalTests = files.length; + console.log("found " + files.length + " tests"); + files.forEach(function(file) { + testPage("http://localhost:8081/browser/" + file); + }); +} \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-browser.js b/node_modules/less/test/browser/runner-browser.js new file mode 100644 index 0000000..79c5e1c --- /dev/null +++ b/node_modules/less/test/browser/runner-browser.js @@ -0,0 +1,7 @@ +describe("less.js browser behaviour", function() { + testLessEqualsInDocument(); + + it("has some log messages", function() { + expect(logMessages.length).toBeGreaterThan(0); + }); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-errors.js b/node_modules/less/test/browser/runner-errors.js new file mode 100644 index 0000000..93994a5 --- /dev/null +++ b/node_modules/less/test/browser/runner-errors.js @@ -0,0 +1,5 @@ +less.strictUnits = true; + +describe("less.js error tests", function() { + testLessErrorsInDocument(); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-legacy.js b/node_modules/less/test/browser/runner-legacy.js new file mode 100644 index 0000000..e60c84c --- /dev/null +++ b/node_modules/less/test/browser/runner-legacy.js @@ -0,0 +1,6 @@ +less.strictMath = false; +less.strictUnits = false; + +describe("less.js legacy tests", function() { + testLessEqualsInDocument(); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-main.js b/node_modules/less/test/browser/runner-main.js new file mode 100644 index 0000000..d9637c0 --- /dev/null +++ b/node_modules/less/test/browser/runner-main.js @@ -0,0 +1,15 @@ +less.functions = { + add: function (a, b) { + return new(less.tree.Dimension)(a.value + b.value); + }, + increment: function (a) { + return new(less.tree.Dimension)(a.value + 1); + }, + _color: function (str) { + if (str.value === "evil red") { return new(less.tree.Color)("600") } + } +}; + +describe("less.js main tests", function() { + testLessEqualsInDocument(); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-production.js b/node_modules/less/test/browser/runner-production.js new file mode 100644 index 0000000..94c0c8d --- /dev/null +++ b/node_modules/less/test/browser/runner-production.js @@ -0,0 +1,7 @@ +less.env = "production"; + +describe("less.js production behaviour", function() { + it("doesn't log any messages", function() { + expect(logMessages.length).toEqual(0); + }); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-relative-urls.js b/node_modules/less/test/browser/runner-relative-urls.js new file mode 100644 index 0000000..4e47f63 --- /dev/null +++ b/node_modules/less/test/browser/runner-relative-urls.js @@ -0,0 +1,4 @@ +less.relativeUrls = true; +describe("less.js browser test - relative url's", function() { + testLessEqualsInDocument(); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-rootpath-relative.js b/node_modules/less/test/browser/runner-rootpath-relative.js new file mode 100644 index 0000000..b318b42 --- /dev/null +++ b/node_modules/less/test/browser/runner-rootpath-relative.js @@ -0,0 +1,5 @@ +less.rootpath = "https://www.github.com/cloudhead/less.js/"; +less.relativeUrls = true; +describe("less.js browser test - rootpath and relative url's", function() { + testLessEqualsInDocument(); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/runner-rootpath.js b/node_modules/less/test/browser/runner-rootpath.js new file mode 100644 index 0000000..2c7edd7 --- /dev/null +++ b/node_modules/less/test/browser/runner-rootpath.js @@ -0,0 +1,4 @@ +less.rootpath = "https://www.github.com/"; +describe("less.js browser test - rootpath url's", function() { + testLessEqualsInDocument(); +}); \ No newline at end of file diff --git a/node_modules/less/test/browser/template.htm b/node_modules/less/test/browser/template.htm new file mode 100644 index 0000000..c000fdc --- /dev/null +++ b/node_modules/less/test/browser/template.htm @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/node_modules/less/test/css/charsets.css b/node_modules/less/test/css/charsets.css new file mode 100644 index 0000000..9f44090 --- /dev/null +++ b/node_modules/less/test/css/charsets.css @@ -0,0 +1 @@ +@charset "UTF-8"; diff --git a/node_modules/less/test/css/colors.css b/node_modules/less/test/css/colors.css new file mode 100644 index 0000000..1695677 --- /dev/null +++ b/node_modules/less/test/css/colors.css @@ -0,0 +1,80 @@ +#yelow #short { + color: #fea; +} +#yelow #long { + color: #ffeeaa; +} +#yelow #rgba { + color: rgba(255, 238, 170, 0.1); +} +#yelow #argb { + color: #1affeeaa; +} +#blue #short { + color: #00f; +} +#blue #long { + color: #0000ff; +} +#blue #rgba { + color: rgba(0, 0, 255, 0.1); +} +#blue #argb { + color: #1a0000ff; +} +#alpha #hsla { + color: rgba(61, 45, 41, 0.6); +} +#overflow .a { + color: #000000; +} +#overflow .b { + color: #ffffff; +} +#overflow .c { + color: #ffffff; +} +#overflow .d { + color: #00ff00; +} +#grey { + color: #c8c8c8; +} +#333333 { + color: #333333; +} +#808080 { + color: #808080; +} +#00ff00 { + color: #00ff00; +} +.lightenblue { + color: #3333ff; +} +.darkenblue { + color: #0000cc; +} +.unknowncolors { + color: blue2; + border: 2px solid superred; +} +.transparent { + color: transparent; + background-color: rgba(0, 0, 0, 0); +} +#alpha #fromvar { + opacity: 0.7; +} +#alpha #short { + opacity: 1; +} +#alpha #long { + opacity: 1; +} +#alpha #rgba { + opacity: 0.2; +} +#alpha #hsl { + opacity: 1; +} diff --git a/node_modules/less/test/css/comments.css b/node_modules/less/test/css/comments.css new file mode 100644 index 0000000..03e82de --- /dev/null +++ b/node_modules/less/test/css/comments.css @@ -0,0 +1,64 @@ +/******************\ +* * +* Comment Header * +* * +\******************/ +/* + + Comment + +*/ +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ +/* @group Variables +------------------- */ +#comments { + /**/ + color: red; + /* A C-style comment */ + /* A C-style comment */ + + background-color: orange; + font-size: 12px; + /* lost comment */ + content: "content"; + border: 1px solid black; + padding: 0; + margin: 2em; +} +/* commented out + #more-comments { + color: grey; + } +*/ +.selector, +.lots, +.comments { + color: #808080, /* blue */ #ffa500; + -webkit-border-radius: 2px /* webkit only */; + -moz-border-radius: 8px /* moz only with operation */; +} +.test { + color: 1px //put in @b - causes problems! --->; +} +#last { + color: #0000ff; +} +/* *//* { *//* *//* *//* */#div { + color: #A33; +} +/* } */ diff --git a/node_modules/less/test/css/compression/compression.css b/node_modules/less/test/css/compression/compression.css new file mode 100644 index 0000000..2f831a9 --- /dev/null +++ b/node_modules/less/test/css/compression/compression.css @@ -0,0 +1,2 @@ +#colours{color1:#fea;color2:#fea;color3:rgba(255,238,170,0.1);string:"#ffeeaa"} +dimensions{val:.1px;val:0;val:4cm;val:.2;val:5;angles-must-have-unit:0deg;width:auto\9} diff --git a/node_modules/less/test/css/css-3.css b/node_modules/less/test/css/css-3.css new file mode 100644 index 0000000..fb5c02b --- /dev/null +++ b/node_modules/less/test/css/css-3.css @@ -0,0 +1,114 @@ +.comma-delimited { + text-shadow: -1px -1px 1px #ff0000, 6px 5px 5px #ffff00; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; + -webkit-transform: rotate(-0.0000000001deg); +} +@font-face { + font-family: Headline; + unicode-range: U+??????, U+0???, U+0-7F, U+A5; +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); + transform: rotateX(45deg); +} +.item[data-cra_zy-attr1b-ut3=bold] { + font-weight: bold; +} +p:not([class*="lead"]) { + color: black; +} +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} +div#id.class[a=1][b=2].class:not(1) { + color: white; +} +ul.comma > li:not(:only-child)::after { + color: white; +} +ol.comma > li:nth-last-child(2)::after { + color: white; +} +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} +a[href^="http://"] { + color: black; +} +a[href$="http://"] { + color: black; +} +form[data-disabled] { + color: black; +} +p::before { + color: black; +} +#issue322 { + -webkit-animation: anim2 7s infinite ease-in-out; +} +@-webkit-keyframes frames { + 0% { + border: 1px; + } + 5.5% { + border: 2px; + } + 100% { + border: 3px; + } +} +@keyframes fontbulger1 { + to { + font-size: 15px; + } + from, + to { + font-size: 12px; + } + 0%, + 100% { + font-size: 12px; + } +} +.units { + font: 1.2rem/2rem; + font: 8vw/9vw; + font: 10vh/12vh; + font: 12vm/15vm; + font: 12vmin/15vmin; + font: 1.2ch/1.5ch; +} +@supports ( box-shadow: 2px 2px 2px black ) or + ( -moz-box-shadow: 2px 2px 2px black ) { + .outline { + box-shadow: 2px 2px 2px black; + -moz-box-shadow: 2px 2px 2px black; + } +} +@-x-document url-prefix(""github.com"") { + h1 { + color: red; + } +} +@viewport { + font-size: 10px; +} +@namespace foo url(http://www.example.com); +foo | h1 { + color: blue; +} +foo | * { + color: yellow; +} +| h1 { + color: red; +} +* | h1 { + color: green; +} +h1 { + color: green; +} diff --git a/node_modules/less/test/css/css-escapes.css b/node_modules/less/test/css/css-escapes.css new file mode 100644 index 0000000..4d343aa --- /dev/null +++ b/node_modules/less/test/css/css-escapes.css @@ -0,0 +1,24 @@ +.escape\|random\|char { + color: red; +} +.mixin\!tUp { + font-weight: bold; +} +.\34 04 { + background: red; +} +.\34 04 strong { + color: #ff00ff; + font-weight: bold; +} +.trailingTest\+ { + color: red; +} +/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ +\62\6c\6f \63 \6B \0071 \000075o\74 e { + color: silver; +} +[ng\:cloak], +ng\:form { + display: none; +} diff --git a/node_modules/less/test/css/css.css b/node_modules/less/test/css/css.css new file mode 100644 index 0000000..b011a7e --- /dev/null +++ b/node_modules/less/test/css/css.css @@ -0,0 +1,95 @@ +@charset "utf-8"; +div { + color: black; +} +div { + width: 99%; +} +* { + min-width: 45em; +} +h1, +h2 > a > p, +h3 { + color: none; +} +div.class { + color: blue; +} +div#id { + color: green; +} +.class#id { + color: purple; +} +.one.two.three { + color: grey; +} +@media print { + * { + font-size: 3em; + } +} +@media screen { + * { + font-size: 10px; + } +} +@font-face { + font-family: 'Garamond Pro'; +} +a:hover, +a:link { + color: #999; +} +p, +p:first-child { + text-transform: none; +} +q:lang(no) { + quotes: none; +} +p + h1 { + font-size: 2.2em; +} +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + font: 100%/16px Arial; + margin: 1px 0; + padding: 0 auto; +} +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small / 20px 'Trebuchet MS', Verdana, sans-serif; + font: 0/0 a; + border-radius: 5px / 10px; +} +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), to(#0000ff)); + margin: ; + filter: alpha(opacity=100); + width: auto\9; +} +.misc .nested-multiple { + multiple-semi-colons: yes; +} +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} +@font-face { + font-family: font-a; +} +@font-face { + font-family: font-b; +} +.æøå { + margin: 0; +} diff --git a/node_modules/less/test/css/debug/linenumbers-all.css b/node_modules/less/test/css/debug/linenumbers-all.css new file mode 100644 index 0000000..c6fb355 --- /dev/null +++ b/node_modules/less/test/css/debug/linenumbers-all.css @@ -0,0 +1,43 @@ +@charset "UTF-8"; +/* line 3, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000033}} +/* @charset "ISO-8859-1"; */ +/* line 23, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000323}} +.tst3 { + color: grey; +} +/* line 15, {path}linenumbers.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000315}} +.test1 { + color: black; +} +/* line 6, {path}linenumbers.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\000036}} +.test2 { + color: red; +} +@media all { + /* line 5, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000035}} + .tst { + color: black; + } +} +@media all and screen { + /* line 7, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000037}} + .tst { + color: red; + } + /* line 9, {pathimport}test.less */ + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000039}} + .tst .tst3 { + color: white; + } +} +/* line 18, {pathimport}test.less */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000318}} +.tst2 { + color: white; +} diff --git a/node_modules/less/test/css/debug/linenumbers-comments.css b/node_modules/less/test/css/debug/linenumbers-comments.css new file mode 100644 index 0000000..9c48baa --- /dev/null +++ b/node_modules/less/test/css/debug/linenumbers-comments.css @@ -0,0 +1,35 @@ +@charset "UTF-8"; +/* line 3, {pathimport}test.less */ +/* @charset "ISO-8859-1"; */ +/* line 23, {pathimport}test.less */ +.tst3 { + color: grey; +} +/* line 15, {path}linenumbers.less */ +.test1 { + color: black; +} +/* line 6, {path}linenumbers.less */ +.test2 { + color: red; +} +@media all { + /* line 5, {pathimport}test.less */ + .tst { + color: black; + } +} +@media all and screen { + /* line 7, {pathimport}test.less */ + .tst { + color: red; + } + /* line 9, {pathimport}test.less */ + .tst .tst3 { + color: white; + } +} +/* line 18, {pathimport}test.less */ +.tst2 { + color: white; +} diff --git a/node_modules/less/test/css/debug/linenumbers-mediaquery.css b/node_modules/less/test/css/debug/linenumbers-mediaquery.css new file mode 100644 index 0000000..3fdbbaf --- /dev/null +++ b/node_modules/less/test/css/debug/linenumbers-mediaquery.css @@ -0,0 +1,35 @@ +@charset "UTF-8"; +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000033}} +/* @charset "ISO-8859-1"; */ +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000323}} +.tst3 { + color: grey; +} +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000315}} +.test1 { + color: black; +} +@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\000036}} +.test2 { + color: red; +} +@media all { + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000035}} + .tst { + color: black; + } +} +@media all and screen { + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000037}} + .tst { + color: red; + } + @media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000039}} + .tst .tst3 { + color: white; + } +} +@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000318}} +.tst2 { + color: white; +} diff --git a/node_modules/less/test/css/extend-chaining.css b/node_modules/less/test/css/extend-chaining.css new file mode 100644 index 0000000..afde5ca --- /dev/null +++ b/node_modules/less/test/css/extend-chaining.css @@ -0,0 +1,72 @@ +.a, +.b, +.c { + color: black; +} +.f, +.e, +.d { + color: black; +} +.g.h, +.i.j.h, +.k.j.h { + color: black; +} +.i.j, +.k.j { + color: white; +} +.l, +.m, +.n, +.o, +.p, +.q, +.r, +.s, +.t { + color: black; +} +.u, +.v.u.v { + color: black; +} +.w, +.v.w.v { + color: black; +} +.x, +.y, +.z { + color: x; +} +.y, +.z, +.x { + color: y; +} +.z, +.x, +.y { + color: z; +} +@media tv { + .ma, + .mb, + .mc { + color: black; + } + .md, + .ma, + .mb, + .mc { + color: white; + } +} +@media tv and plasma { + .me, + .mf { + background: red; + } +} diff --git a/node_modules/less/test/css/extend-clearfix.css b/node_modules/less/test/css/extend-clearfix.css new file mode 100644 index 0000000..966892a --- /dev/null +++ b/node_modules/less/test/css/extend-clearfix.css @@ -0,0 +1,19 @@ +.clearfix, +.foo, +.bar { + *zoom: 1; +} +.clearfix:after, +.foo:after, +.bar:after { + content: ''; + display: block; + clear: both; + height: 0; +} +.foo { + color: red; +} +.bar { + color: blue; +} diff --git a/node_modules/less/test/css/extend-exact.css b/node_modules/less/test/css/extend-exact.css new file mode 100644 index 0000000..beff413 --- /dev/null +++ b/node_modules/less/test/css/extend-exact.css @@ -0,0 +1,37 @@ +.replace.replace .replace, +.c.replace + .replace .replace, +.replace.replace .c, +.c.replace + .replace .c, +.rep_ace { + prop: copy-paste-replace; +} +.a .b .c { + prop: not_effected; +} +.a, +.effected { + prop: is_effected; +} +.a .b { + prop: not_effected; +} +.a .b.c { + prop: not_effected; +} +.c .b .a, +.a .b .a, +.c .a .a, +.a .a .a, +.c .b .c, +.a .b .c, +.c .a .c, +.a .a .c { + prop: not_effected; +} +.e.e, +.dbl { + prop: extend-double; +} +.e.e:hover { + hover: not-extended; +} diff --git a/node_modules/less/test/css/extend-media.css b/node_modules/less/test/css/extend-media.css new file mode 100644 index 0000000..23bd7b8 --- /dev/null +++ b/node_modules/less/test/css/extend-media.css @@ -0,0 +1,24 @@ +.ext1 .ext2, +.all .ext2 { + background: black; +} +@media tv { + .ext1 .ext3, + .tv-lowres .ext3, + .all .ext3 { + color: white; + } + .tv-lowres { + background: blue; + } +} +@media tv and hires { + .ext1 .ext4, + .tv-hires .ext4, + .all .ext4 { + color: green; + } + .tv-hires { + background: red; + } +} diff --git a/node_modules/less/test/css/extend-nest.css b/node_modules/less/test/css/extend-nest.css new file mode 100644 index 0000000..2c3905d --- /dev/null +++ b/node_modules/less/test/css/extend-nest.css @@ -0,0 +1,57 @@ +.sidebar, +.sidebar2, +.type1 .sidebar3, +.type2.sidebar4 { + width: 300px; + background: red; +} +.sidebar .box, +.sidebar2 .box, +.type1 .sidebar3 .box, +.type2.sidebar4 .box { + background: #FFF; + border: 1px solid #000; + margin: 10px 0; +} +.sidebar2 { + background: blue; +} +.type1 .sidebar3 { + background: green; +} +.type2.sidebar4 { + background: red; +} +.button, +.submit { + color: black; +} +.button:hover, +.submit:hover { + color: white; +} +.button2 :hover { + nested: white; +} +.button2 :hover { + notnested: black; +} +.amp-test-h, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-a.amp-test-d.amp-test-b.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-a.amp-test-e.amp-test-g, +.amp-test-f.amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e + .amp-test-c .amp-test-b.amp-test-d.amp-test-b.amp-test-e.amp-test-g { + test: extended by masses of selectors; +} diff --git a/node_modules/less/test/css/extend-selector.css b/node_modules/less/test/css/extend-selector.css new file mode 100644 index 0000000..dc03d1c --- /dev/null +++ b/node_modules/less/test/css/extend-selector.css @@ -0,0 +1,72 @@ +.error, +.badError { + border: 1px #f00; + background: #fdd; +} +.error.intrusion, +.badError.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error, +.intrusion .badError { + display: none; +} +.badError { + border-width: 3px; +} +.foo .bar, +.foo .baz, +.ext1 .ext2 .bar, +.ext1 .ext2 .baz, +.ext3 .bar, +.ext3 .baz, +.ext4 .bar, +.ext4 .baz { + display: none; +} +div.ext5, +.ext6 > .ext5, +div.ext7, +.ext6 > .ext7 { + width: 100px; +} +.ext, +.a .c, +.b .c { + test: 1; +} +.a, +.b { + test: 2; +} +.a .c, +.b .c { + test: 3; +} +.a .c .d, +.b .c .d { + test: 4; +} +.replace.replace .replace, +.c.replace + .replace .replace, +.replace.replace .c, +.c.replace + .replace .c, +.rep_ace .rep_ace .rep_ace, +.c.rep_ace + .rep_ace .rep_ace, +.rep_ace .rep_ace .c, +.c.rep_ace + .rep_ace .c { + prop: copy-paste-replace; +} +.attributes [data="test"], +.attributes .attributes .attribute-test { + extend: attributes; +} +.attributes [data], +.attributes .attributes .attribute-test2 { + extend: attributes2; +} +.attributes [data="test3"], +.attributes .attributes .attribute-test { + extend: attributes2; +} diff --git a/node_modules/less/test/css/extend.css b/node_modules/less/test/css/extend.css new file mode 100644 index 0000000..2895641 --- /dev/null +++ b/node_modules/less/test/css/extend.css @@ -0,0 +1,76 @@ +.error, +.badError { + border: 1px #f00; + background: #fdd; +} +.error.intrusion, +.badError.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error, +.intrusion .badError { + display: none; +} +.badError { + border-width: 3px; +} +.foo .bar, +.foo .baz, +.ext1 .ext2 .bar, +.ext1 .ext2 .baz, +.ext3 .bar, +.ext3 .baz, +.foo .ext3, +.ext4 .bar, +.ext4 .baz, +.foo .ext4 { + display: none; +} +div.ext5, +.ext6 > .ext5, +div.ext7, +.ext6 > .ext7 { + width: 100px; +} +.ext8.ext9, +.fuu { + result: add-foo; +} +.ext8 .ext9, +.ext8 + .ext9, +.ext8 > .ext9, +.buu, +.zap, +.zoo { + result: bar-matched; +} +.ext8.nomatch { + result: none; +} +.ext8 .ext9, +.buu { + result: match-nested-bar; +} +.ext8.ext9, +.fuu { + result: match-nested-foo; +} +.aa, +.cc { + color: black; +} +.aa .dd, +.aa .ee { + background: red; +} +.bb, +.cc, +.ee, +.ff { + background: red; +} +.bb .bb, +.ff .ff { + color: black; +} diff --git a/node_modules/less/test/css/functions.css b/node_modules/less/test/css/functions.css new file mode 100644 index 0000000..eacebd8 --- /dev/null +++ b/node_modules/less/test/css/functions.css @@ -0,0 +1,128 @@ +#functions { + color: #660000; + width: 16; + height: undefined("self"); + border-width: 5; + variable: 11; + background: linear-gradient(#000000, #ffffff); +} +#built-in { + escaped: -Some::weird(#thing, y); + lighten: #ffcccc; + darken: #330000; + saturate: #203c31; + desaturate: #29332f; + greyscale: #2e2e2e; + hsl-clamp: #ffffff; + spin-p: #bf6a40; + spin-n: #bf4055; + luma-white: 100%; + luma-black: 0%; + luma-black-alpha: 0%; + luma-red: 21%; + luma-green: 72%; + luma-blue: 7%; + luma-yellow: 93%; + luma-cyan: 79%; + luma-white-alpha: 50%; + contrast-filter: contrast(30%); + contrast-white: #000000; + contrast-black: #ffffff; + contrast-red: #ffffff; + contrast-green: #000000; + contrast-blue: #ffffff; + contrast-yellow: #000000; + contrast-cyan: #000000; + contrast-light: #111111; + contrast-dark: #eeeeee; + contrast-wrongorder: #111111; + contrast-light-thresh: #111111; + contrast-dark-thresh: #eeeeee; + contrast-high-thresh: #eeeeee; + contrast-low-thresh: #111111; + contrast-light-thresh-per: #111111; + contrast-dark-thresh-per: #eeeeee; + contrast-high-thresh-per: #eeeeee; + contrast-low-thresh-per: #111111; + format: "rgb(32, 128, 64)"; + format-string: "hello world"; + format-multiple: "hello earth 2"; + format-url-encode: "red is %23ff0000"; + eformat: rgb(32, 128, 64); + unitless: 12; + unit: 14em; + hue: 98; + saturation: 12%; + lightness: 95%; + hsvhue: 98; + hsvsaturation: 12%; + hsvvalue: 95%; + red: 255; + green: 255; + blue: 255; + rounded: 11; + rounded-two: 10.67; + roundedpx: 3px; + roundedpx-three: 3.333px; + rounded-percentage: 10%; + ceil: 11px; + floor: 12px; + sqrt: 5px; + pi: 3.141592653589793; + mod: 2m; + abs: 4%; + tan: 0.9004040442978399; + sin: 0.17364817766693033; + cos: 0.8438539587324921; + atan: 0.1rad; + atan: 34.00000000000001deg; + atan: 45.00000000000001deg; + pow: 64px; + pow: 64; + pow: 27; + percentage: 20%; + color: #ff0011; + tint: #898989; + tint-full: #ffffff; + tint-percent: #898989; + shade: #686868; + shade-full: #000000; + shade-percent: #686868; + fade-out: rgba(255, 0, 0, 0.95); + fade-in: rgba(255, 0, 0, 0.9500000000000001); + hsv: #4d2926; + hsva: rgba(77, 40, 38, 0.2); + mix: #ff3300; + mix-0: #ffff00; + mix-100: #ff0000; + mix-weightless: #ff8000; +} +#built-in .is-a { + color: true; + color1: true; + color2: true; + keyword: true; + number: true; + string: true; + pixel: true; + percent: true; + em: true; + cat: true; +} +#alpha { + alpha: rgba(153, 94, 51, 0.6); +} +#blendmodes { + multiply: #ed0000; + screen: #f600f6; + overlay: #ed0000; + softlight: #ff0000; + hardlight: #0000ed; + difference: #f600f6; + exclusion: #f600f6; + average: #7b007b; + negation: #d73131; +} +#extract { + result: 3 2 1 C B A; +} diff --git a/node_modules/less/test/css/ie-filters.css b/node_modules/less/test/css/ie-filters.css new file mode 100644 index 0000000..007aa53 --- /dev/null +++ b/node_modules/less/test/css/ie-filters.css @@ -0,0 +1,9 @@ +.nav { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=20); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr="#000000", GradientType=0); +} +.evalTest1 { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=30); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=5); +} diff --git a/node_modules/less/test/css/import-interpolation.css b/node_modules/less/test/css/import-interpolation.css new file mode 100644 index 0000000..16b7a15 --- /dev/null +++ b/node_modules/less/test/css/import-interpolation.css @@ -0,0 +1,6 @@ +body { + width: 100%; +} +.a { + var: test; +} diff --git a/node_modules/less/test/css/import-once.css b/node_modules/less/test/css/import-once.css new file mode 100644 index 0000000..b2a15d3 --- /dev/null +++ b/node_modules/less/test/css/import-once.css @@ -0,0 +1,3 @@ +#import { + color: #ff0000; +} diff --git a/node_modules/less/test/css/import.css b/node_modules/less/test/css/import.css new file mode 100644 index 0000000..616657a --- /dev/null +++ b/node_modules/less/test/css/import.css @@ -0,0 +1,38 @@ +@import url(http://fonts.googleapis.com/css?family=Open+Sans); + +@import url(/absolute/something.css) screen and (color) and (max-width: 600px); + +@import url("//ha.com/file.css") (min-width: 100px); +#import-test { + height: 10px; + color: #ff0000; + width: 10px; + height: 30%; +} +@media screen and (max-width: 600px) { + body { + width: 100%; + } +} +#import { + color: #ff0000; +} +.mixin { + height: 10px; + color: #ff0000; +} +@media screen and (max-width: 601px) { + #css { + color: yellow; + } +} +@media screen and (max-width: 602px) { + body { + width: 100%; + } +} +@media screen and (max-width: 603px) { + #css { + color: yellow; + } +} diff --git a/node_modules/less/test/css/javascript.css b/node_modules/less/test/css/javascript.css new file mode 100644 index 0000000..8268ab3 --- /dev/null +++ b/node_modules/less/test/css/javascript.css @@ -0,0 +1,23 @@ +.eval { + js: 42; + js: 2; + js: "hello world"; + js: 1, 2, 3; + title: "string"; + ternary: true; + multiline: 2; +} +.scope { + var: 42; + escaped: 7px; +} +.vars { + width: 8; +} +.escape-interpol { + width: hello world; +} +.arrays { + ary: "1, 2, 3"; + ary1: "1, 2, 3"; +} diff --git a/node_modules/less/test/css/lazy-eval.css b/node_modules/less/test/css/lazy-eval.css new file mode 100644 index 0000000..1adfb8f --- /dev/null +++ b/node_modules/less/test/css/lazy-eval.css @@ -0,0 +1,3 @@ +.lazy-eval { + width: 100%; +} diff --git a/node_modules/less/test/css/legacy/legacy.css b/node_modules/less/test/css/legacy/legacy.css new file mode 100644 index 0000000..2f9bb80 --- /dev/null +++ b/node_modules/less/test/css/legacy/legacy.css @@ -0,0 +1,7 @@ +@media (-o-min-device-pixel-ratio: 2/1) { + .test-math-and-units { + font: ignores 0/0 rules; + test-division: 7em; + simple: 2px; + } +} diff --git a/node_modules/less/test/css/media.css b/node_modules/less/test/css/media.css new file mode 100644 index 0000000..5aa1d4e --- /dev/null +++ b/node_modules/less/test/css/media.css @@ -0,0 +1,203 @@ +@media print { + .class { + color: blue; + } + .class .sub { + width: 42; + } + .top, + header > h1 { + color: #444444; + } +} +@media screen { + body { + max-width: 480; + } +} +@media all and (device-aspect-ratio: 16 / 9) { + body { + max-width: 800px; + } +} +@media all and (orientation: portrait) { + aside { + float: none; + } +} +@media handheld and (min-width: 42), screen and (min-width: 20em) { + body { + max-width: 480px; + } +} +@media print { + body { + padding: 20px; + } + body header { + background-color: red; + } +} +@media print and (orientation: landscape) { + body { + margin-left: 20px; + } +} +@media screen { + .sidebar { + width: 300px; + } +} +@media screen and (orientation: landscape) { + .sidebar { + width: 500px; + } +} +@media a { + +} +@media a and b { + .first .second .third { + width: 300px; + } + .first .second .fourth { + width: 3; + } +} +@media a and b and c { + .first .second .third { + width: 500px; + } +} +@media a, b and c { + body { + width: 95%; + } +} +@media a and x, b and c and x, a and y, b and c and y { + body { + width: 100%; + } +} +.a { + background: black; +} +@media handheld { + .a { + background: white; + } +} +@media handheld and (max-width: 100px) { + .a { + background: red; + } +} +.b { + background: black; +} +@media handheld { + .b { + background: white; + } +} +@media handheld and (max-width: 200px) { + .b { + background: red; + } +} +@media only screen and (max-width: 200px) { + width: 480px; +} +@media print { + @page :left { + margin: 0.5cm; + } + @page :right { + margin: 0.5cm; + } + @page Test:first { + margin: 1cm; + } + @page :first { + size: 8.5in 11in;@top-left { + margin: 1cm; + } + @top-left-corner { + margin: 1cm; + } + @top-center { + margin: 1cm; + } + @top-right { + margin: 1cm; + } + @top-right-corner { + margin: 1cm; + } + @bottom-left { + margin: 1cm; + } + @bottom-left-corner { + margin: 1cm; + } + @bottom-center { + margin: 1cm; + } + @bottom-right { + margin: 1cm; + } + @bottom-right-corner { + margin: 1cm; + } + @left-top { + margin: 1cm; + } + @left-middle { + margin: 1cm; + } + @left-bottom { + margin: 1cm; + } + @right-top { + margin: 1cm; + } + @right-middle { + content: "Page " counter(page); + } + @right-bottom { + margin: 1cm; + } + } +} +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { + .b { + background: red; + } +} +body { + background: red; +} +@media (max-width: 500px) { + body { + background: green; + } +} +@media (max-width: 1000px) { + body { + background: red; + background: blue; + } +} +@media (max-width: 1000px) and (max-width: 500px) { + body { + background: green; + } +} +@media (max-width: 1200px) { + /* a comment */ +} +@media (max-width: 1200px) and (max-width: 900px) { + body { + font-size: 11px; + } +} diff --git a/node_modules/less/test/css/mixins-args.css b/node_modules/less/test/css/mixins-args.css new file mode 100644 index 0000000..2b6c5c9 --- /dev/null +++ b/node_modules/less/test/css/mixins-args.css @@ -0,0 +1,113 @@ +#hidden { + color: transparent; +} +#hidden1 { + color: transparent; +} +.two-args { + color: blue; + width: 10px; + height: 99%; + border: 2px dotted #000000; +} +.one-arg { + width: 15px; + height: 49%; +} +.no-parens { + width: 5px; + height: 49%; +} +.no-args { + width: 5px; + height: 49%; +} +.var-args { + width: 45; + height: 17%; +} +.multi-mix { + width: 10px; + height: 29%; + margin: 4; + padding: 5; +} +body { + padding: 30px; + color: #ff0000; +} +.scope-mix { + width: 8; +} +.content { + width: 600px; +} +.content .column { + margin: 600px; +} +#same-var-name { + radius: 5px; +} +#var-inside { + width: 10px; +} +.arguments { + border: 1px solid #000000; + width: 1px; +} +.arguments2 { + border: 0px; + width: 0px; +} +.arguments3 { + border: 0px; + width: 0px; +} +.arguments4 { + border: 0 1 2 3 4; + rest: 1 2 3 4; + width: 0; +} +.edge-case { + border: "{"; + width: "{"; +} +.slash-vs-math { + border-radius: 2px/5px; + border-radius: 5px/10px; + border-radius: 6px; +} +.comma-vs-semi-colon { + one: a; + two: b, c; + one: d, e; + two: f; + one: g; + one: h; + one: i; + one: j; + one: k; + two: l; + one: m, n; + one: o, p; + two: q; + one: r, s; + two: t; +} +#named-conflict { + four: a, 11, 12, 13; + four: a, 21, 22, 23; +} +.test-mixin-default-arg { + defaults: 1px 1px 1px; + defaults: 2px 2px 2px; +} +.selector { + margin: 2, 2, 2, 2; +} +.selector2 { + margin: 2, 2, 2, 2; +} +.selector3 { + margin: 4; +} diff --git a/node_modules/less/test/css/mixins-closure.css b/node_modules/less/test/css/mixins-closure.css new file mode 100644 index 0000000..b1021b6 --- /dev/null +++ b/node_modules/less/test/css/mixins-closure.css @@ -0,0 +1,9 @@ +.class { + width: 99px; +} +.overwrite { + width: 99px; +} +.nested .class { + width: 5px; +} diff --git a/node_modules/less/test/css/mixins-guards.css b/node_modules/less/test/css/mixins-guards.css new file mode 100644 index 0000000..847aef1 --- /dev/null +++ b/node_modules/less/test/css/mixins-guards.css @@ -0,0 +1,76 @@ +.light1 { + color: white; + margin: 1px; +} +.light2 { + color: black; + margin: 1px; +} +.max1 { + width: 6; +} +.max2 { + width: 8; +} +.glob1 { + margin: auto auto; +} +.ops1 { + height: gt-or-eq; + height: lt-or-eq; +} +.ops2 { + height: gt-or-eq; + height: not-eq; +} +.ops3 { + height: lt-or-eq; + height: not-eq; +} +.default1 { + content: default; +} +.test1 { + content: "true."; +} +.test2 { + content: "false."; +} +.test3 { + content: "false."; +} +.test4 { + content: "false."; +} +.test5 { + content: "false."; +} +.bool1 { + content: true and true; + content: true; + content: false, true; + content: false and true and true, true; + content: false, true and true; + content: false, false, true; + content: false, true and true and true, false; + content: not false; + content: not false and false, not false; +} +.equality-units { + test: pass; +} +.colorguardtest { + content: is #ff0000; + content: is not #0000ff its #ff0000; + content: is not #0000ff its #800080; +} +.stringguardtest { + content: is theme1; + content: is not theme2; + content: is theme1 no quotes; +} +#tryNumberPx { + catch: all; + declare: 4; + declare: 4px; +} diff --git a/node_modules/less/test/css/mixins-important.css b/node_modules/less/test/css/mixins-important.css new file mode 100644 index 0000000..535726b --- /dev/null +++ b/node_modules/less/test/css/mixins-important.css @@ -0,0 +1,38 @@ +.class { + border: 1; + boxer: 1; + border: 2 !important; + boxer: 2 !important; + border: 3; + boxer: 3; + border: 4 !important; + boxer: 4 !important; + border: 5; + boxer: 5; + border: 0 !important; + boxer: 0 !important; + border: 9 !important; + border: 9; + boxer: 9; +} +.class .inner { + test: 1; +} +.class .inner { + test: 2 !important; +} +.class .inner { + test: 3; +} +.class .inner { + test: 4 !important; +} +.class .inner { + test: 5; +} +.class .inner { + test: 0 !important; +} +.class .inner { + test: 9; +} diff --git a/node_modules/less/test/css/mixins-named-args.css b/node_modules/less/test/css/mixins-named-args.css new file mode 100644 index 0000000..e460aa1 --- /dev/null +++ b/node_modules/less/test/css/mixins-named-args.css @@ -0,0 +1,27 @@ +.named-arg { + color: blue; + width: 5px; + height: 99%; + args: 1px 100%; + text-align: center; +} +.class { + width: 5px; + height: 19%; + args: 1px 20%; +} +.all-args-wrong-args { + width: 10px; + height: 9%; + args: 2px 10%; +} +.named-args2 { + width: 15px; + height: 49%; + color: #646464; +} +.named-args3 { + width: 5px; + height: 29%; + color: #123456; +} diff --git a/node_modules/less/test/css/mixins-nested.css b/node_modules/less/test/css/mixins-nested.css new file mode 100644 index 0000000..6378c47 --- /dev/null +++ b/node_modules/less/test/css/mixins-nested.css @@ -0,0 +1,14 @@ +.class .inner { + height: 300; +} +.class .inner .innest { + width: 30; + border-width: 60; +} +.class2 .inner { + height: 600; +} +.class2 .inner .innest { + width: 60; + border-width: 120; +} diff --git a/node_modules/less/test/css/mixins-pattern.css b/node_modules/less/test/css/mixins-pattern.css new file mode 100644 index 0000000..8b82833 --- /dev/null +++ b/node_modules/less/test/css/mixins-pattern.css @@ -0,0 +1,47 @@ +.zero { + variadic: true; + zero: 0; + one: 1; + two: 2; + three: 3; +} +.one { + variadic: true; + one: 1; + one-req: 1; + two: 2; + three: 3; +} +.two { + variadic: true; + two: 2; + three: 3; +} +.three { + variadic: true; + three-req: 3; + three: 3; +} +.left { + left: 1; +} +.right { + right: 1; +} +.border-right { + color: black; + border-right: 4px; +} +.border-left { + color: black; + border-left: 4px; +} +.only-right { + right: 33; +} +.only-left { + left: 33; +} +.left-right { + both: 330; +} diff --git a/node_modules/less/test/css/mixins.css b/node_modules/less/test/css/mixins.css new file mode 100644 index 0000000..62939e1 --- /dev/null +++ b/node_modules/less/test/css/mixins.css @@ -0,0 +1,121 @@ +.mixin { + border: 1px solid black; +} +.mixout { + border-color: orange; +} +.borders { + border-style: dashed; +} +#namespace .borders { + border-style: dotted; +} +#namespace .biohazard { + content: "death"; +} +#namespace .biohazard .man { + color: transparent; +} +#theme > .mixin { + background-color: grey; +} +#container { + color: black; + border: 1px solid black; + border-color: orange; + background-color: grey; +} +#header .milk { + color: white; + border: 1px solid black; + background-color: grey; +} +#header #cookie { + border-style: dashed; +} +#header #cookie .chips { + border-style: dotted; +} +#header #cookie .chips .calories { + color: black; + border: 1px solid black; + border-color: orange; + background-color: grey; +} +.secure-zone { + color: transparent; +} +.direct { + border-style: dotted; +} +.bo, +.bar { + width: 100%; +} +.bo { + border: 1px; +} +.ar.bo.ca { + color: black; +} +.jo.ki { + background: none; +} +.amp.support { + color: orange; +} +.extended { + width: 100%; + border: 1px; + background: none; + color: orange; +} +.foo .bar { + width: 100%; +} +.underParents { + color: red; +} +.parent .underParents { + color: red; +} +* + h1 { + margin-top: 25px; +} +legend + h1 { + margin-top: 0; +} +h1 + * { + margin-top: 10px; +} +* + h2 { + margin-top: 20px; +} +legend + h2 { + margin-top: 0; +} +h2 + * { + margin-top: 8px; +} +* + h3 { + margin-top: 15px; +} +legend + h3 { + margin-top: 0; +} +h3 + * { + margin-top: 5px; +} +.error { + background-image: "/a.png"; + background-position: center center; +} +.test-rec .recursion { + color: black; +} +.button { + padding-left: 44px; +} +.button.large { + padding-left: 40em; +} diff --git a/node_modules/less/test/css/operations.css b/node_modules/less/test/css/operations.css new file mode 100644 index 0000000..fb9e0af --- /dev/null +++ b/node_modules/less/test/css/operations.css @@ -0,0 +1,49 @@ +#operations { + color: #111111; + height: 9px; + width: 3em; + substraction: 0; + division: 1; +} +#operations .spacing { + height: 9px; + width: 3em; +} +.with-variables { + height: 16em; + width: 24em; + size: 1cm; +} +.with-functions { + color: #646464; + color: #ff8080; + color: #c94a4a; +} +.negative { + height: 0px; + width: 4px; +} +.shorthands { + padding: -1px 2px 0 -4px; +} +.rem-dimensions { + font-size: 5.5rem; +} +.colors { + color: #123; + border-color: #334455; + background-color: #000000; +} +.colors .other { + color: #222222; + border-color: #222222; +} +.negations { + variable: -4px; + variable1: 0px; + variable2: 0px; + variable3: 8px; + variable4: 0px; + paren: -4px; + paren2: 16px; +} diff --git a/node_modules/less/test/css/parens.css b/node_modules/less/test/css/parens.css new file mode 100644 index 0000000..412823f --- /dev/null +++ b/node_modules/less/test/css/parens.css @@ -0,0 +1,33 @@ +.parens { + border: 2px solid #000000; + margin: 1px 3px 16 3; + width: 36; + padding: 2px 36px; +} +.more-parens { + padding: 8 4 4 4px; + width-all: 96; + width-first: 16 * 6; + width-keep: (4 * 4) * 6; + height-keep: (7 * 7) + (8 * 8); + height-all: 113; + height-parts: 49 + 64; + margin-keep: (4 * (5 + 5) / 2) - (4 * 2); + margin-parts: 20 - 8; + margin-all: 12; + border-radius-keep: 4px * (1 + 1) / 4 + 3px; + border-radius-parts: 8px / 7px; + border-radius-all: 5px; +} +.negative { + neg-var: -1; + neg-var-paren: -(1); +} +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1; +} +.mixed-units { + margin: 2px 4em 1 5pc; + padding: 6px 1em 2px 2; +} diff --git a/node_modules/less/test/css/rulesets.css b/node_modules/less/test/css/rulesets.css new file mode 100644 index 0000000..408c76a --- /dev/null +++ b/node_modules/less/test/css/rulesets.css @@ -0,0 +1,33 @@ +#first > .one { + font-size: 2em; +} +#first > .one > #second .two > #deux { + width: 50%; +} +#first > .one > #second .two > #deux #third { + height: 100%; +} +#first > .one > #second .two > #deux #third:focus { + color: black; +} +#first > .one > #second .two > #deux #third:focus #fifth > #sixth .seventh #eighth + #ninth { + color: purple; +} +#first > .one > #second .two > #deux #fourth, +#first > .one > #second .two > #deux #five, +#first > .one > #second .two > #deux #six { + color: #110000; +} +#first > .one > #second .two > #deux #fourth .seven, +#first > .one > #second .two > #deux #five .seven, +#first > .one > #second .two > #deux #six .seven, +#first > .one > #second .two > #deux #fourth .eight > #nine, +#first > .one > #second .two > #deux #five .eight > #nine, +#first > .one > #second .two > #deux #six .eight > #nine { + border: 1px solid black; +} +#first > .one > #second .two > #deux #fourth #ten, +#first > .one > #second .two > #deux #five #ten, +#first > .one > #second .two > #deux #six #ten { + color: red; +} diff --git a/node_modules/less/test/css/scope.css b/node_modules/less/test/css/scope.css new file mode 100644 index 0000000..baa0552 --- /dev/null +++ b/node_modules/less/test/css/scope.css @@ -0,0 +1,35 @@ +.tiny-scope { + color: #998899; +} +.scope1 { + color: #0000ff; + border-color: #000000; +} +.scope1 .scope2 { + color: #0000ff; +} +.scope1 .scope2 .scope3 { + color: #ff0000; + border-color: #000000; + background-color: #ffffff; +} +.scope { + scoped-val: #008000; +} +.heightIsSet { + height: 1024px; +} +.useHeightInMixinCall { + mixin-height: 1024px; +} +.imported { + exists: true; +} +.testImported { + exists: true; +} +#allAreUsedHere { + default: 'top level'; + scope: 'top level'; + sub-scope-only: 'inside'; +} diff --git a/node_modules/less/test/css/selectors.css b/node_modules/less/test/css/selectors.css new file mode 100644 index 0000000..69865c0 --- /dev/null +++ b/node_modules/less/test/css/selectors.css @@ -0,0 +1,141 @@ +h1 a:hover, +h2 a:hover, +h3 a:hover, +h1 p:hover, +h2 p:hover, +h3 p:hover { + color: red; +} +#all { + color: blue; +} +#the { + color: blue; +} +#same { + color: blue; +} +ul, +li, +div, +q, +blockquote, +textarea { + margin: 0; +} +td { + margin: 0; + padding: 0; +} +td, +input { + line-height: 1em; +} +a { + color: red; +} +a:hover { + color: blue; +} +div a { + color: green; +} +p a span { + color: yellow; +} +.foo .bar .qux, +.foo .baz .qux { + display: block; +} +.qux .foo .bar, +.qux .foo .baz { + display: inline; +} +.qux.foo .bar, +.qux.foo .baz { + display: inline-block; +} +.qux .foo .bar .biz, +.qux .foo .baz .biz { + display: none; +} +.a.b.c { + color: red; +} +.c .b.a { + color: red; +} +.foo .p.bar { + color: red; +} +.foo.p.bar { + color: red; +} +.foo + .foo { + background: amber; +} +.foo + .foo { + background: amber; +} +.foo + .foo, +.foo + .bar, +.bar + .foo, +.bar + .bar { + background: amber; +} +.foo a > .foo a, +.foo a > .bar a, +.foo a > .foo b, +.foo a > .bar b, +.bar a > .foo a, +.bar a > .bar a, +.bar a > .foo b, +.bar a > .bar b, +.foo b > .foo a, +.foo b > .bar a, +.foo b > .foo b, +.foo b > .bar b, +.bar b > .foo a, +.bar b > .bar a, +.bar b > .foo b, +.bar b > .bar b { + background: amber; +} +.other ::fnord { + color: #ff0000; +} +.other::fnord { + color: #ff0000; +} +.other ::bnord { + color: #ff0000; +} +.other::bnord { + color: #ff0000; +} +.blood { + color: red; +} +.bloodred { + color: green; +} +#blood.blood.red.black { + color: black; +} +:nth-child(3) { + selector: interpolated; +} +.test:nth-child(odd):not(:nth-child(3)) { + color: #ff0000; +} +[prop], +[prop="value3"], +[prop*="val3"], +[|prop~="val3"], +[*|prop$="val3"], +[ns|prop^="val3"], +[3^="val3"], +[3=3], +[3] { + attributes: yes; +} diff --git a/node_modules/less/test/css/static-urls/urls.css b/node_modules/less/test/css/static-urls/urls.css new file mode 100644 index 0000000..b5a690e --- /dev/null +++ b/node_modules/less/test/css/static-urls/urls.css @@ -0,0 +1,42 @@ +@import "folder (1)/../css/background.css"; + +@import "folder (1)/import-test-d.css"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(folder\ \(1\)/fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(folder\ \(1\)/images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(folder\ \(1\)/bg.jpg) no-repeat, url(folder\ \(1\)/bg.png) repeat-x top left, url(folder\ \(1\)/bg); +} +.values { + url: url('folder (1)/Trebuchet'); +} +#logo { + width: 100px; + height: 100px; + background: url('folder (1)/../assets/logo.png'); +} +@font-face { + font-family: xecret; + src: url('folder (1)/../assets/xecret.ttf'); +} +#secret { + font-family: xecret, sans-serif; +} diff --git a/node_modules/less/test/css/strings.css b/node_modules/less/test/css/strings.css new file mode 100644 index 0000000..522bae5 --- /dev/null +++ b/node_modules/less/test/css/strings.css @@ -0,0 +1,40 @@ +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; + escapes: "\"hello\" \\world"; + escapes2: "\"llo"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; + semi-colon: ';'; +} +#escaped { + filter: DX.Transform.MS.BS.filter(opacity=50); +} +#one-line { + image: url(http://tooks.com); +} +#crazy { + image: url(http://), "}", url("http://}"); +} +#interpolation { + url: "http://lesscss.org/dev/image.jpg"; + url2: "http://lesscss.org/image-256.jpg"; + url3: "http://lesscss.org#445566"; + url4: "http://lesscss.org/hello"; + url5: "http://lesscss.org/54.4px"; +} +.mix-mul-class { + color: #0000ff; + color: #ff0000; + color: #000000; + color: #ffa500; +} diff --git a/node_modules/less/test/css/urls.css b/node_modules/less/test/css/urls.css new file mode 100644 index 0000000..f736962 --- /dev/null +++ b/node_modules/less/test/css/urls.css @@ -0,0 +1,59 @@ +@import "import/../css/background.css"; + +@import "import/import-test-d.css"; + +@import "file.css"; +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; + background: url("img.jpg") center / 100px; + background: #ffffff url(image.png) center / 1px 100px repeat-x scroll content-box padding-box; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + url: url('Trebuchet'); +} +#logo { + width: 100px; + height: 100px; + background: url('import/imports/../assets/logo.png'); +} +@font-face { + font-family: xecret; + src: url('import/imports/../assets/xecret.ttf'); +} +#secret { + font-family: xecret, sans-serif; +} +#data-uri { + uri: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg=='); +} +#data-uri-guess { + uri: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg=='); +} +#data-uri-ascii { + uri-1: url('data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A'); + uri-2: url('data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A'); +} +#data-uri-toobig { + uri: url('../data/data-uri-fail.png'); +} diff --git a/node_modules/less/test/css/variables.css b/node_modules/less/test/css/variables.css new file mode 100644 index 0000000..f8d8518 --- /dev/null +++ b/node_modules/less/test/css/variables.css @@ -0,0 +1,45 @@ +.variables { + width: 14cm; +} +.variables { + height: 24px; + color: #888888; + font-family: "Trebuchet MS", Verdana, sans-serif; + quotes: "~" "~"; +} +.redef { + zero: 0; +} +.redef .inition { + three: 3; +} +.values { + minus-one: -1; + font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; + color: #888888 !important; + multi: something 'A', B, C, 'Trebuchet'; +} +.variable-names { + name: 'hello'; +} +.alpha { + filter: alpha(opacity=42); +} +.testPollution { + a: 'no-pollution'; +} +.units { + width: 1px; + same-unit-as-previously: 1px; + square-pixel-divided: 1px; + odd-unit: 2; + percentage: 500%; + pixels: 500px; + conversion-metric-a: 30mm; + conversion-metric-b: 3cm; + conversion-imperial: 3in; + custom-unit: 420octocats; + custom-unit-cancelling: 18dogs; + mix-units: 2px; + invalid-units: 1px; +} diff --git a/node_modules/less/test/css/whitespace.css b/node_modules/less/test/css/whitespace.css new file mode 100644 index 0000000..74c9b65 --- /dev/null +++ b/node_modules/less/test/css/whitespace.css @@ -0,0 +1,42 @@ +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white; +} +.whitespace { + color: white ; +} +.white, +.space, +.mania { + color: white; +} +.no-semi-column { + color: #ffffff; +} +.no-semi-column { + color: white; + white-space: pre; +} +.no-semi-column { + border: 2px solid #ffffff; +} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.sel .newline_ws .tab_ws { + color: white; + background-position: 45 -23; +} diff --git a/node_modules/less/test/data/data-uri-fail.png b/node_modules/less/test/data/data-uri-fail.png new file mode 100644 index 0000000000000000000000000000000000000000..f91b59fb314c105c5d290775cd5395bc6140caf7 GIT binary patch literal 52420 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
    {q9NrvoS|g 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 zbiv&This page is 100% Awesome. diff --git a/node_modules/less/test/less-test.js b/node_modules/less/test/less-test.js new file mode 100644 index 0000000..3bddf33 --- /dev/null +++ b/node_modules/less/test/less-test.js @@ -0,0 +1,214 @@ +var path = require('path'), + fs = require('fs'), + sys = require('util'); + +var less = require('../lib/less'); +var stylize = require('../lib/less/lessc_helper').stylize; + +var globals = Object.keys(global); + +var oneTestOnly = process.argv[2]; + +var totalTests = 0, + failedTests = 0, + passedTests = 0; + +less.tree.functions.add = function (a, b) { + return new(less.tree.Dimension)(a.value + b.value); +}; +less.tree.functions.increment = function (a) { + return new(less.tree.Dimension)(a.value + 1); +}; +less.tree.functions._color = function (str) { + if (str.value === "evil red") { return new(less.tree.Color)("600") } +}; + +sys.puts("\n" + stylize("LESS", 'underline') + "\n"); + +runTestSet({strictMath: true, relativeUrls: true, silent: true}); + +runTestSet({strictMath: true, strictUnits: true}, "errors/", function(name, err, compiledLess, doReplacements) { + fs.readFile(path.join('test/less/', name) + '.txt', 'utf8', function (e, expectedErr) { + sys.print("- " + name + ": "); + expectedErr = doReplacements(expectedErr, 'test/less/errors/'); + if (!err) { + if (compiledLess) { + fail("No Error", 'red'); + } else { + fail("No Error, No Output"); + } + } else { + var errMessage = less.formatError(err); + if (errMessage === expectedErr) { + ok('OK'); + } else { + difference("FAIL", expectedErr, errMessage); + } + } + sys.puts(""); + });}, null, function(input, directory) { + return input.replace( + "{path}", path.join(process.cwd(), "/test/less/errors/")) + .replace("{pathrel}", path.join("test", "less", "errors/")) + .replace("{pathhref}", "") + .replace("{404status}", "") + .replace(/\r\n/g, '\n'); + }); + +runTestSet({strictMath: true, dumpLineNumbers: 'comments'}, "debug/", null, + function(name) { return name + '-comments'; }); +runTestSet({strictMath: true, dumpLineNumbers: 'mediaquery'}, "debug/", null, + function(name) { return name + '-mediaquery'; }); +runTestSet({strictMath: true, dumpLineNumbers: 'all'}, "debug/", null, + function(name) { return name + '-all'; }); +runTestSet({strictMath: true, relativeUrls: false, rootpath: "folder (1)/"}, "static-urls/"); +runTestSet({strictMath: true, compress: true}, "compression/"); +runTestSet({strictMath: false}, "legacy/"); +testNoOptions(); + +function globalReplacements(input, directory) { + var p = path.join(process.cwd(), directory), + pathimport = path.join(process.cwd(), directory + "import/"), + pathesc = p.replace(/[.:/\\]/g, function(a) { return '\\' + (a=='\\' ? '\/' : a); }), + pathimportesc = pathimport.replace(/[.:/\\]/g, function(a) { return '\\' + (a=='\\' ? '\/' : a); }); + + return input.replace(/\{path\}/g, p) + .replace(/\{pathesc\}/g, pathesc) + .replace(/\{pathimport\}/g, pathimport) + .replace(/\{pathimportesc\}/g, pathimportesc) + .replace(/\r\n/g, '\n'); +} + +function checkGlobalLeaks() { + return Object.keys(global).filter(function(v) { + return globals.indexOf(v) < 0; + }); +} + +function runTestSet(options, foldername, verifyFunction, nameModifier, doReplacements) { + foldername = foldername || ""; + + if(!doReplacements) + doReplacements = globalReplacements; + + fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) { + if (! /\.less/.test(file)) { return } + + var name = foldername + path.basename(file, '.less'); + + if (oneTestOnly && name !== oneTestOnly) { return; } + + totalTests++; + + toCSS(options, path.join('test/less/', foldername + file), function (err, less) { + + if (verifyFunction) { + return verifyFunction(name, err, less, doReplacements); + } + var css_name = name; + if(nameModifier) css_name=nameModifier(name); + fs.readFile(path.join('test/css', css_name) + '.css', 'utf8', function (e, css) { + sys.print("- " + css_name + ": ") + + css = css && doReplacements(css, 'test/less/' + foldername); + if (less === css) { ok('OK'); } + else if (err) { + fail("ERROR: " + (err && err.message)); + } else { + difference("FAIL", css, less); + } + sys.puts(""); + }); + }); + }); +} + +function diff(left, right) { + sys.puts(""); + require('diff').diffLines(left, right).forEach(function(item) { + if(item.added || item.removed) { + sys.print(stylize(item.value, item.added ? 'green' : 'red')); + } else { + sys.print(item.value); + } + }); +} + +function fail(msg) { + sys.print(stylize(msg, 'red')); + failedTests++; + endTest(); +} + +function difference(msg, left, right) { + sys.print(stylize(msg, 'yellow')); + failedTests++; + + diff(left, right); + endTest(); +} + +function ok(msg) { + sys.print(stylize(msg, 'green')); + passedTests++; + endTest(); +} + +function endTest() { + var leaked = checkGlobalLeaks(); + if (failedTests + passedTests === totalTests) { + sys.puts(""); + sys.puts(""); + if (failedTests > 0) { + sys.print(failedTests); + sys.print(stylize(" Failed", "red")); + sys.print(", " + passedTests + " passed"); + } else { + sys.print(stylize("All Passed ", "green")); + sys.print(passedTests + " run"); + } + if (leaked.length > 0) { + sys.puts(""); + sys.puts(""); + sys.print(stylize("Global leak detected: ", "red") + leaked.join(', ')); + sys.print("\n"); + } + } +} + +function toCSS(options, path, callback) { + var tree, css; + options = options || {}; + fs.readFile(path, 'utf8', function (e, str) { + if (e) { return callback(e) } + + options.paths = [require('path').dirname(path)]; + options.filename = require('path').resolve(process.cwd(), path); + options.optimization = options.optimization || 0; + + new(less.Parser)(options).parse(str, function (err, tree) { + if (err) { + callback(err); + } else { + try { + css = tree.toCSS(options); + callback(null, css); + } catch (e) { + callback(e); + } + } + }); + }); +} + +function testNoOptions() { + totalTests++; + try { + sys.print("- Integration - creating parser without options: "); + new(less.Parser); + } catch(e) { + fail(stylize("FAIL\n", "red")); + return; + } + ok(stylize("OK\n", "green")); +} diff --git a/node_modules/less/test/less/charsets.less b/node_modules/less/test/less/charsets.less new file mode 100644 index 0000000..550d40e --- /dev/null +++ b/node_modules/less/test/less/charsets.less @@ -0,0 +1,3 @@ +@charset "UTF-8"; + +@import "import/import-charset-test"; \ No newline at end of file diff --git a/node_modules/less/test/less/colors.less b/node_modules/less/test/less/colors.less new file mode 100644 index 0000000..656ca63 --- /dev/null +++ b/node_modules/less/test/less/colors.less @@ -0,0 +1,92 @@ +#yelow { + #short { + color: #fea; + } + #long { + color: #ffeeaa; + } + #rgba { + color: rgba(255, 238, 170, 0.1); + } + #argb { + color: argb(rgba(255, 238, 170, 0.1)); + } +} + +#blue { + #short { + color: #00f; + } + #long { + color: #0000ff; + } + #rgba { + color: rgba(0, 0, 255, 0.1); + } + #argb { + color: argb(rgba(0, 0, 255, 0.1)); + } +} + +#alpha #hsla { + color: hsla(11, 20%, 20%, 0.6); +} + +#overflow { + .a { color: (#111111 - #444444); } // #000000 + .b { color: (#eee + #fff); } // #ffffff + .c { color: (#aaa * 3); } // #ffffff + .d { color: (#00ee00 + #009900); } // #00ff00 +} + +#grey { + color: rgb(200, 200, 200); +} + +#333333 { + color: rgb(20%, 20%, 20%); +} + +#808080 { + color: hsl(50, 0%, 50%); +} + +#00ff00 { + color: hsl(120, 100%, 50%); +} + +.lightenblue { + color: lighten(blue, 10%); +} + +.darkenblue { + color: darken(blue, 10%); +} + +.unknowncolors { + color: blue2; + border: 2px solid superred; +} + +.transparent { + color: transparent; + background-color: rgba(0, 0, 0, 0); +} +#alpha { + @colorvar: rgba(150, 200, 150, 0.7); + #fromvar { + opacity: alpha(@colorvar); + } + #short { + opacity: alpha(#aaa); + } + #long { + opacity: alpha(#bababa); + } + #rgba { + opacity: alpha(rgba(50, 120, 95, 0.2)); + } + #hsl { + opacity: alpha(hsl(120, 100%, 50%)); + } +} diff --git a/node_modules/less/test/less/comments.less b/node_modules/less/test/less/comments.less new file mode 100644 index 0000000..b803ff7 --- /dev/null +++ b/node_modules/less/test/less/comments.less @@ -0,0 +1,77 @@ +/******************\ +* * +* Comment Header * +* * +\******************/ + +/* + + Comment + +*/ + +/* + * Comment Test + * + * - cloudhead (http://cloudhead.net) + * + */ + +//////////////// +@var: "content"; +//////////////// + +/* Colors + * ------ + * #EDF8FC (background blue) + * #166C89 (darkest blue) + * + * Text: + * #333 (standard text) // A comment within a comment! + * #1F9EC9 (standard link) + * + */ + +/* @group Variables +------------------- */ +#comments /* boo */ { + /**/ // An empty comment + color: red; /* A C-style comment */ /* A C-style comment */ + background-color: orange; // A little comment + font-size: 12px; + + /* lost comment */ content: @var; + + border: 1px solid black; + + // padding & margin // + padding: 0; // }{ '" + margin: 2em; +} // + +/* commented out + #more-comments { + color: grey; + } +*/ + +.selector /* .with */, .lots, /* of */ .comments { + color: grey, /* blue */ orange; + -webkit-border-radius: 2px /* webkit only */; + -moz-border-radius: (2px * 4) /* moz only with operation */; +} + +.mixin_def_with_colors(@a: white, // in + @b: 1px //put in @b - causes problems! ---> + ) // the + when (@a = white) { + .test { + color: @b; + } +} +.mixin_def_with_colors(); + +#last { color: blue } +// + +/* *//* { *//* *//* *//* */#div { color:#A33; }/* } */ diff --git a/node_modules/less/test/less/compression/compression.less b/node_modules/less/test/less/compression/compression.less new file mode 100644 index 0000000..c1a10e0 --- /dev/null +++ b/node_modules/less/test/less/compression/compression.less @@ -0,0 +1,16 @@ +#colours { + color1: #fea; + color2: #ffeeaa; + color3: rgba(255, 238, 170, 0.1); + @color1: #fea; + string: "@{color1}"; +} +dimensions { + val: 0.1px; + val: 0em; + val: 4cm; + val: 0.2; + val: 5; + angles-must-have-unit: 0deg; + width: auto\9; +} \ No newline at end of file diff --git a/node_modules/less/test/less/css-3.less b/node_modules/less/test/less/css-3.less new file mode 100644 index 0000000..6e5a195 --- /dev/null +++ b/node_modules/less/test/less/css-3.less @@ -0,0 +1,114 @@ +.comma-delimited { + text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; + -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, + 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; + -webkit-transform: rotate(-0.0000000001deg); +} +@font-face { + font-family: Headline; + unicode-range: U+??????, U+0???, U+0-7F, U+A5; +} +.other { + -moz-transform: translate(0, 11em) rotate(-90deg); + transform: rotateX(45deg); +} +.item[data-cra_zy-attr1b-ut3=bold] { + font-weight: bold; +} +p:not([class*="lead"]) { + color: black; +} + +input[type="text"].class#id[attr=32]:not(1) { + color: white; +} + +div#id.class[a=1][b=2].class:not(1) { + color: white; +} + +ul.comma > li:not(:only-child)::after { + color: white; +} + +ol.comma > li:nth-last-child(2)::after { + color: white; +} + +li:nth-child(4n+1), +li:nth-child(-5n), +li:nth-child(-n+2) { + color: white; +} + +a[href^="http://"] { + color: black; +} + +a[href$="http://"] { + color: black; +} + +form[data-disabled] { + color: black; +} + +p::before { + color: black; +} + +#issue322 { + -webkit-animation: anim2 7s infinite ease-in-out; +} + +@-webkit-keyframes frames { + 0% { border: 1px } + 5.5% { border: 2px } + 100% { border: 3px } +} + +@keyframes fontbulger1 { + to { + font-size: 15px; + } + from,to { + font-size: 12px; + } + 0%,100% { + font-size: 12px; + } +} + +.units { + font: 1.2rem/2rem; + font: 8vw/9vw; + font: 10vh/12vh; + font: 12vm/15vm; + font: 12vmin/15vmin; + font: 1.2ch/1.5ch; +} + +@supports ( box-shadow: 2px 2px 2px black ) or + ( -moz-box-shadow: 2px 2px 2px black ) { + .outline { + box-shadow: 2px 2px 2px black; + -moz-box-shadow: 2px 2px 2px black; + } +} + +@-x-document url-prefix(""github.com"") { + h1 { + color: red; + } +} + +@viewport { + font-size: 10px; +} +@namespace foo url(http://www.example.com); + +foo|h1 { color: blue; } +foo|* { color: yellow; } +|h1 { color: red; } +*|h1 { color: green; } +h1 { color: green; } \ No newline at end of file diff --git a/node_modules/less/test/less/css-escapes.less b/node_modules/less/test/less/css-escapes.less new file mode 100644 index 0000000..6a4b283 --- /dev/null +++ b/node_modules/less/test/less/css-escapes.less @@ -0,0 +1,33 @@ +@ugly: fuchsia; + +.escape\|random\|char { + color: red; +} + +.mixin\!tUp { + font-weight: bold; +} + +// class="404" +.\34 04 { + background: red; + + strong { + color: @ugly; + .mixin\!tUp; + } +} + +.trailingTest\+ { + color: red; +} + +/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ +\62\6c\6f \63 \6B \0071 \000075o\74 e { + color: silver; +} + +[ng\:cloak], +ng\:form { + display: none; +} diff --git a/node_modules/less/test/less/css.less b/node_modules/less/test/less/css.less new file mode 100644 index 0000000..766bdd4 --- /dev/null +++ b/node_modules/less/test/less/css.less @@ -0,0 +1,108 @@ +@charset "utf-8"; +div { color: black; } +div { width: 99%; } + +* { + min-width: 45em; +} + +h1, h2 > a > p, h3 { + color: none; +} + +div.class { + color: blue; +} + +div#id { + color: green; +} + +.class#id { + color: purple; +} + +.one.two.three { + color: grey; +} + +@media print { + * { + font-size: 3em; + } +} + +@media screen { + * { + font-size: 10px; + } +} + +@font-face { + font-family: 'Garamond Pro'; +} + +a:hover, a:link { + color: #999; +} + +p, p:first-child { + text-transform: none; +} + +q:lang(no) { + quotes: none; +} + +p + h1 { + font-size: +2.2em; +} + +#shorthands { + border: 1px solid #000; + font: 12px/16px Arial; + font: 100%/16px Arial; + margin: 1px 0; + padding: 0 auto; +} + +#more-shorthands { + margin: 0; + padding: 1px 0 2px 0; + font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; + font: 0/0 a; + border-radius: 5px / 10px; +} + +.misc { + -moz-border-radius: 2px; + display: -moz-inline-stack; + width: .1em; + background-color: #009998; + background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); + margin: ; + .nested-multiple { + multiple-semi-colons: yes;;;;;; + }; + filter: alpha(opacity=100); + width: auto\9; +} + +#important { + color: red !important; + width: 100%!important; + height: 20px ! important; +} + +.def-font(@name) { + @font-face { + font-family: @name + } +} + +.def-font(font-a); +.def-font(font-b); + +.æøå { + margin: 0; +} diff --git a/node_modules/less/test/less/debug/import/test.less b/node_modules/less/test/less/debug/import/test.less new file mode 100644 index 0000000..795082f --- /dev/null +++ b/node_modules/less/test/less/debug/import/test.less @@ -0,0 +1,25 @@ +@charset "ISO-8859-1"; + +.mixin_import1() { + @media all { + .tst { + color: black; + @media screen { + color: red; + .tst3 { + color: white; + } + } + } + } +} + +.mixin_import2() { + .tst2 { + color: white; + } +} + +.tst3 { + color: grey; +} \ No newline at end of file diff --git a/node_modules/less/test/less/debug/linenumbers.less b/node_modules/less/test/less/debug/linenumbers.less new file mode 100644 index 0000000..172ba02 --- /dev/null +++ b/node_modules/less/test/less/debug/linenumbers.less @@ -0,0 +1,23 @@ +@charset "UTF-8"; + +@import "import/test.less"; + +.start() { + .test2 { + color: red; + } +} + +.mix() { + color: black; +} + +.test1 { + .mix(); +} + +.start(); + +.mixin_import1(); + +.mixin_import2(); \ No newline at end of file diff --git a/node_modules/less/test/less/errors/add-mixed-units.less b/node_modules/less/test/less/errors/add-mixed-units.less new file mode 100644 index 0000000..9b708de --- /dev/null +++ b/node_modules/less/test/less/errors/add-mixed-units.less @@ -0,0 +1,3 @@ +.a { + error: (1px + 3em); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/add-mixed-units.txt b/node_modules/less/test/less/errors/add-mixed-units.txt new file mode 100644 index 0000000..b555361 --- /dev/null +++ b/node_modules/less/test/less/errors/add-mixed-units.txt @@ -0,0 +1,2 @@ +SyntaxError: Incompatible units. Change the units or use the unit function. Bad units: 'px' and 'em'. in {path}add-mixed-units.less on line null, column 0: +1 error: (1px + 3em); diff --git a/node_modules/less/test/less/errors/add-mixed-units2.less b/node_modules/less/test/less/errors/add-mixed-units2.less new file mode 100644 index 0000000..2663116 --- /dev/null +++ b/node_modules/less/test/less/errors/add-mixed-units2.less @@ -0,0 +1,3 @@ +.a { + error: ((1px * 2px) + (3em * 3px)); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/add-mixed-units2.txt b/node_modules/less/test/less/errors/add-mixed-units2.txt new file mode 100644 index 0000000..cc65a76 --- /dev/null +++ b/node_modules/less/test/less/errors/add-mixed-units2.txt @@ -0,0 +1,2 @@ +SyntaxError: Incompatible units. Change the units or use the unit function. Bad units: 'px*px' and 'em*px'. in {path}add-mixed-units2.less on line null, column 0: +1 error: ((1px * 2px) + (3em * 3px)); diff --git a/node_modules/less/test/less/errors/bad-variable-declaration1.less b/node_modules/less/test/less/errors/bad-variable-declaration1.less new file mode 100644 index 0000000..c2dc6ac --- /dev/null +++ b/node_modules/less/test/less/errors/bad-variable-declaration1.less @@ -0,0 +1 @@ +@@demo: "hi"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/bad-variable-declaration1.txt b/node_modules/less/test/less/errors/bad-variable-declaration1.txt new file mode 100644 index 0000000..5ae9d4a --- /dev/null +++ b/node_modules/less/test/less/errors/bad-variable-declaration1.txt @@ -0,0 +1,2 @@ +ParseError: Unrecognised input in {path}bad-variable-declaration1.less on line 1, column 1: +1 @@demo: "hi"; diff --git a/node_modules/less/test/less/errors/color-operation-error.less b/node_modules/less/test/less/errors/color-operation-error.less new file mode 100644 index 0000000..7c60c00 --- /dev/null +++ b/node_modules/less/test/less/errors/color-operation-error.less @@ -0,0 +1,3 @@ +.a { + prop: (3 / #fff); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/color-operation-error.txt b/node_modules/less/test/less/errors/color-operation-error.txt new file mode 100644 index 0000000..1b3f889 --- /dev/null +++ b/node_modules/less/test/less/errors/color-operation-error.txt @@ -0,0 +1,2 @@ +OperationError: Can't substract or divide a color from a number in {path}color-operation-error.less on line null, column 0: +1 prop: (3 / #fff); diff --git a/node_modules/less/test/less/errors/comment-in-selector.less b/node_modules/less/test/less/errors/comment-in-selector.less new file mode 100644 index 0000000..a7d2639 --- /dev/null +++ b/node_modules/less/test/less/errors/comment-in-selector.less @@ -0,0 +1 @@ +#gaga /* Comment */ span { color: red } \ No newline at end of file diff --git a/node_modules/less/test/less/errors/comment-in-selector.txt b/node_modules/less/test/less/errors/comment-in-selector.txt new file mode 100644 index 0000000..e48f878 --- /dev/null +++ b/node_modules/less/test/less/errors/comment-in-selector.txt @@ -0,0 +1,2 @@ +ParseError: Unrecognised input in {path}comment-in-selector.less on line 1, column 21: +1 #gaga /* Comment */ span { color: red } diff --git a/node_modules/less/test/less/errors/divide-mixed-units.less b/node_modules/less/test/less/errors/divide-mixed-units.less new file mode 100644 index 0000000..d228b7c --- /dev/null +++ b/node_modules/less/test/less/errors/divide-mixed-units.less @@ -0,0 +1,3 @@ +.a { + error: (1px / 3em); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/divide-mixed-units.txt b/node_modules/less/test/less/errors/divide-mixed-units.txt new file mode 100644 index 0000000..c189d2a --- /dev/null +++ b/node_modules/less/test/less/errors/divide-mixed-units.txt @@ -0,0 +1,4 @@ +SyntaxError: Multiple units in dimension. Correct the units or use the unit function. Bad unit: px/em in {path}divide-mixed-units.less on line 2, column 3: +1 .a { +2 error: (1px / 3em); +3 } diff --git a/node_modules/less/test/less/errors/extend-no-selector.less b/node_modules/less/test/less/errors/extend-no-selector.less new file mode 100644 index 0000000..84689ef --- /dev/null +++ b/node_modules/less/test/less/errors/extend-no-selector.less @@ -0,0 +1,3 @@ +:extend(.a all) { + property: red; +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/extend-no-selector.txt b/node_modules/less/test/less/errors/extend-no-selector.txt new file mode 100644 index 0000000..bd2e3cd --- /dev/null +++ b/node_modules/less/test/less/errors/extend-no-selector.txt @@ -0,0 +1,3 @@ +SyntaxError: Extend must be used to extend a selector, it cannot be used on its own in {path}extend-no-selector.less on line 1, column 17: +1 :extend(.a all) { +2 property: red; diff --git a/node_modules/less/test/less/errors/extend-not-at-end.less b/node_modules/less/test/less/errors/extend-not-at-end.less new file mode 100644 index 0000000..90ee512 --- /dev/null +++ b/node_modules/less/test/less/errors/extend-not-at-end.less @@ -0,0 +1,3 @@ +.a:extend(.b all).c { + property: red; +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/extend-not-at-end.txt b/node_modules/less/test/less/errors/extend-not-at-end.txt new file mode 100644 index 0000000..32ebedf --- /dev/null +++ b/node_modules/less/test/less/errors/extend-not-at-end.txt @@ -0,0 +1,3 @@ +SyntaxError: Extend can only be used at the end of selector in {path}extend-not-at-end.less on line 1, column 21: +1 .a:extend(.b all).c { +2 property: red; diff --git a/node_modules/less/test/less/errors/import-missing.less b/node_modules/less/test/less/errors/import-missing.less new file mode 100644 index 0000000..5ce8e4d --- /dev/null +++ b/node_modules/less/test/less/errors/import-missing.less @@ -0,0 +1,6 @@ +.a { + color: green; + // tests line number for import reference is correct +} + +@import "file-does-not-exist.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/import-missing.txt b/node_modules/less/test/less/errors/import-missing.txt new file mode 100644 index 0000000..488d154 --- /dev/null +++ b/node_modules/less/test/less/errors/import-missing.txt @@ -0,0 +1,3 @@ +FileError: '{pathhref}file-does-not-exist.less' wasn't found{404status} in {path}import-missing.less on line 6, column 1: +5 +6 @import "file-does-not-exist.less"; diff --git a/node_modules/less/test/less/errors/import-no-semi.less b/node_modules/less/test/less/errors/import-no-semi.less new file mode 100644 index 0000000..bf2c7f6 --- /dev/null +++ b/node_modules/less/test/less/errors/import-no-semi.less @@ -0,0 +1 @@ +@import "this-statement-is-invalid.less" \ No newline at end of file diff --git a/node_modules/less/test/less/errors/import-no-semi.txt b/node_modules/less/test/less/errors/import-no-semi.txt new file mode 100644 index 0000000..8b3f795 --- /dev/null +++ b/node_modules/less/test/less/errors/import-no-semi.txt @@ -0,0 +1,2 @@ +ParseError: Unrecognised input in {path}import-no-semi.less on line 1, column 1: +1 @import "this-statement-is-invalid.less" diff --git a/node_modules/less/test/less/errors/import-subfolder1.less b/node_modules/less/test/less/errors/import-subfolder1.less new file mode 100644 index 0000000..4280673 --- /dev/null +++ b/node_modules/less/test/less/errors/import-subfolder1.less @@ -0,0 +1 @@ +@import "imports/import-subfolder1.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/import-subfolder1.txt b/node_modules/less/test/less/errors/import-subfolder1.txt new file mode 100644 index 0000000..9762927 --- /dev/null +++ b/node_modules/less/test/less/errors/import-subfolder1.txt @@ -0,0 +1,3 @@ +NameError: .mixin-not-defined is undefined in {path}mixin-not-defined.less on line 11, column 1: +10 +11 .mixin-not-defined(); diff --git a/node_modules/less/test/less/errors/import-subfolder2.less b/node_modules/less/test/less/errors/import-subfolder2.less new file mode 100644 index 0000000..a6b9b9c --- /dev/null +++ b/node_modules/less/test/less/errors/import-subfolder2.less @@ -0,0 +1 @@ +@import "imports/import-subfolder2.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/import-subfolder2.txt b/node_modules/less/test/less/errors/import-subfolder2.txt new file mode 100644 index 0000000..7d514ef --- /dev/null +++ b/node_modules/less/test/less/errors/import-subfolder2.txt @@ -0,0 +1,2 @@ +ParseError: missing opening `{` in {path}parse-error-curly-bracket.less on line 1, column 2: +1 }} diff --git a/node_modules/less/test/less/errors/imports/import-subfolder1.less b/node_modules/less/test/less/errors/imports/import-subfolder1.less new file mode 100644 index 0000000..24ec053 --- /dev/null +++ b/node_modules/less/test/less/errors/imports/import-subfolder1.less @@ -0,0 +1 @@ +@import "subfolder/mixin-not-defined.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/imports/import-subfolder2.less b/node_modules/less/test/less/errors/imports/import-subfolder2.less new file mode 100644 index 0000000..6058ad1 --- /dev/null +++ b/node_modules/less/test/less/errors/imports/import-subfolder2.less @@ -0,0 +1 @@ +@import "subfolder/parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/imports/import-test.less b/node_modules/less/test/less/errors/imports/import-test.less new file mode 100644 index 0000000..a91ae05 --- /dev/null +++ b/node_modules/less/test/less/errors/imports/import-test.less @@ -0,0 +1,4 @@ +.someclass +{ + font-weight: bold; +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less b/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less new file mode 100644 index 0000000..2bb2d09 --- /dev/null +++ b/node_modules/less/test/less/errors/imports/subfolder/mixin-not-defined.less @@ -0,0 +1 @@ +@import "../../mixin-not-defined.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less b/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less new file mode 100644 index 0000000..f37fa9d --- /dev/null +++ b/node_modules/less/test/less/errors/imports/subfolder/parse-error-curly-bracket.less @@ -0,0 +1 @@ +@import "../../parse-error-curly-bracket.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/javascript-error.less b/node_modules/less/test/less/errors/javascript-error.less new file mode 100644 index 0000000..9cffb9f --- /dev/null +++ b/node_modules/less/test/less/errors/javascript-error.less @@ -0,0 +1,3 @@ +.scope { + var: `this.foo.toJS()`; +} diff --git a/node_modules/less/test/less/errors/javascript-error.txt b/node_modules/less/test/less/errors/javascript-error.txt new file mode 100644 index 0000000..3c83a96 --- /dev/null +++ b/node_modules/less/test/less/errors/javascript-error.txt @@ -0,0 +1,4 @@ +SyntaxError: JavaScript evaluation error: 'TypeError: Cannot call method 'toJS' of undefined' in {path}javascript-error.less on line 2, column 27: +1 .scope { +2 var: `this.foo.toJS()`; +3 } diff --git a/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less b/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less new file mode 100644 index 0000000..9b0e23a --- /dev/null +++ b/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.less @@ -0,0 +1,6 @@ +.mixin(@a : 4, @b : 3, @c: 2) { + will: fail; +} +.mixin-test { + .mixin(@a: 5; @b: 6, @c: 7); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt b/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt new file mode 100644 index 0000000..a07f5e9 --- /dev/null +++ b/node_modules/less/test/less/errors/mixed-mixin-definition-args-1.txt @@ -0,0 +1,4 @@ +SyntaxError: Cannot mix ; and , as delimiter types in {path}mixed-mixin-definition-args-1.less on line 5, column 30: +4 .mixin-test { +5 .mixin(@a: 5; @b: 6, @c: 7); +6 } diff --git a/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less b/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less new file mode 100644 index 0000000..c970942 --- /dev/null +++ b/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.less @@ -0,0 +1,6 @@ +.mixin(@a : 4, @b : 3, @c: 2) { + will: fail; +} +.mixin-test { + .mixin(@a: 5, @b: 6; @c: 7); +} diff --git a/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt b/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt new file mode 100644 index 0000000..fa00183 --- /dev/null +++ b/node_modules/less/test/less/errors/mixed-mixin-definition-args-2.txt @@ -0,0 +1,4 @@ +SyntaxError: Cannot mix ; and , as delimiter types in {path}mixed-mixin-definition-args-2.less on line 5, column 26: +4 .mixin-test { +5 .mixin(@a: 5, @b: 6; @c: 7); +6 } diff --git a/node_modules/less/test/less/errors/mixin-not-defined.less b/node_modules/less/test/less/errors/mixin-not-defined.less new file mode 100644 index 0000000..e2dad5c --- /dev/null +++ b/node_modules/less/test/less/errors/mixin-not-defined.less @@ -0,0 +1,11 @@ + +.error-is-further-on() { +} + +.pad-here-to-reproduce-error-in() { +} + +.the-import-subfolder-test() { +} + +.mixin-not-defined(); \ No newline at end of file diff --git a/node_modules/less/test/less/errors/mixin-not-defined.txt b/node_modules/less/test/less/errors/mixin-not-defined.txt new file mode 100644 index 0000000..9762927 --- /dev/null +++ b/node_modules/less/test/less/errors/mixin-not-defined.txt @@ -0,0 +1,3 @@ +NameError: .mixin-not-defined is undefined in {path}mixin-not-defined.less on line 11, column 1: +10 +11 .mixin-not-defined(); diff --git a/node_modules/less/test/less/errors/mixin-not-matched.less b/node_modules/less/test/less/errors/mixin-not-matched.less new file mode 100644 index 0000000..be0d6b1 --- /dev/null +++ b/node_modules/less/test/less/errors/mixin-not-matched.less @@ -0,0 +1,6 @@ +@saxofon:trumpete; + +.mixin(saxofon) { +} + +.mixin(@saxofon); \ No newline at end of file diff --git a/node_modules/less/test/less/errors/mixin-not-matched.txt b/node_modules/less/test/less/errors/mixin-not-matched.txt new file mode 100644 index 0000000..57df977 --- /dev/null +++ b/node_modules/less/test/less/errors/mixin-not-matched.txt @@ -0,0 +1,3 @@ +RuntimeError: No matching definition was found for `.mixin(trumpete)` in {path}mixin-not-matched.less on line 6, column 1: +5 +6 .mixin(@saxofon); diff --git a/node_modules/less/test/less/errors/mixin-not-matched2.less b/node_modules/less/test/less/errors/mixin-not-matched2.less new file mode 100644 index 0000000..14f44bf --- /dev/null +++ b/node_modules/less/test/less/errors/mixin-not-matched2.less @@ -0,0 +1,6 @@ +@saxofon:trumpete; + +.mixin(@a, @b) { +} + +.mixin(@a: @saxofon); \ No newline at end of file diff --git a/node_modules/less/test/less/errors/mixin-not-matched2.txt b/node_modules/less/test/less/errors/mixin-not-matched2.txt new file mode 100644 index 0000000..dceedaf --- /dev/null +++ b/node_modules/less/test/less/errors/mixin-not-matched2.txt @@ -0,0 +1,3 @@ +RuntimeError: No matching definition was found for `.mixin(@a:trumpete)` in {path}mixin-not-matched2.less on line 6, column 1: +5 +6 .mixin(@a: @saxofon); diff --git a/node_modules/less/test/less/errors/multiply-mixed-units.less b/node_modules/less/test/less/errors/multiply-mixed-units.less new file mode 100644 index 0000000..ff983a8 --- /dev/null +++ b/node_modules/less/test/less/errors/multiply-mixed-units.less @@ -0,0 +1,7 @@ +/* Test */ +#blah { + // blah +} +.a { + error: (1px * 1em); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/multiply-mixed-units.txt b/node_modules/less/test/less/errors/multiply-mixed-units.txt new file mode 100644 index 0000000..9ed834f --- /dev/null +++ b/node_modules/less/test/less/errors/multiply-mixed-units.txt @@ -0,0 +1,4 @@ +SyntaxError: Multiple units in dimension. Correct the units or use the unit function. Bad unit: em*px in {path}multiply-mixed-units.less on line 6, column 3: +5 .a { +6 error: (1px * 1em); +7 } diff --git a/node_modules/less/test/less/errors/parens-error-1.less b/node_modules/less/test/less/errors/parens-error-1.less new file mode 100644 index 0000000..7c8ec10 --- /dev/null +++ b/node_modules/less/test/less/errors/parens-error-1.less @@ -0,0 +1,3 @@ +.a { + something: (12 (13 + 5 -23) + 5); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/parens-error-1.txt b/node_modules/less/test/less/errors/parens-error-1.txt new file mode 100644 index 0000000..6fc40ac --- /dev/null +++ b/node_modules/less/test/less/errors/parens-error-1.txt @@ -0,0 +1,4 @@ +SyntaxError: expected ')' got '(' in {path}parens-error-1.less on line 2, column 18: +1 .a { +2 something: (12 (13 + 5 -23) + 5); +3 } diff --git a/node_modules/less/test/less/errors/parens-error-2.less b/node_modules/less/test/less/errors/parens-error-2.less new file mode 100644 index 0000000..4a392b8 --- /dev/null +++ b/node_modules/less/test/less/errors/parens-error-2.less @@ -0,0 +1,3 @@ +.a { + something: (12 * (13 + 5 -23)); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/parens-error-2.txt b/node_modules/less/test/less/errors/parens-error-2.txt new file mode 100644 index 0000000..cee5c52 --- /dev/null +++ b/node_modules/less/test/less/errors/parens-error-2.txt @@ -0,0 +1,4 @@ +SyntaxError: expected ')' got '-' in {path}parens-error-2.less on line 2, column 28: +1 .a { +2 something: (12 * (13 + 5 -23)); +3 } diff --git a/node_modules/less/test/less/errors/parens-error-3.less b/node_modules/less/test/less/errors/parens-error-3.less new file mode 100644 index 0000000..9e6d540 --- /dev/null +++ b/node_modules/less/test/less/errors/parens-error-3.less @@ -0,0 +1,3 @@ +.a { + something: (12 + (13 + 10 -23)); +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/parens-error-3.txt b/node_modules/less/test/less/errors/parens-error-3.txt new file mode 100644 index 0000000..3280ef0 --- /dev/null +++ b/node_modules/less/test/less/errors/parens-error-3.txt @@ -0,0 +1,4 @@ +SyntaxError: expected ')' got '-' in {path}parens-error-3.less on line 2, column 29: +1 .a { +2 something: (12 + (13 + 10 -23)); +3 } diff --git a/node_modules/less/test/less/errors/parse-error-curly-bracket.less b/node_modules/less/test/less/errors/parse-error-curly-bracket.less new file mode 100644 index 0000000..a2950a1 --- /dev/null +++ b/node_modules/less/test/less/errors/parse-error-curly-bracket.less @@ -0,0 +1 @@ +}} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/parse-error-curly-bracket.txt b/node_modules/less/test/less/errors/parse-error-curly-bracket.txt new file mode 100644 index 0000000..7d514ef --- /dev/null +++ b/node_modules/less/test/less/errors/parse-error-curly-bracket.txt @@ -0,0 +1,2 @@ +ParseError: missing opening `{` in {path}parse-error-curly-bracket.less on line 1, column 2: +1 }} diff --git a/node_modules/less/test/less/errors/parse-error-missing-bracket.less b/node_modules/less/test/less/errors/parse-error-missing-bracket.less new file mode 100644 index 0000000..144a6ed --- /dev/null +++ b/node_modules/less/test/less/errors/parse-error-missing-bracket.less @@ -0,0 +1,2 @@ +body { + background-color: #fff; diff --git a/node_modules/less/test/less/errors/parse-error-missing-bracket.txt b/node_modules/less/test/less/errors/parse-error-missing-bracket.txt new file mode 100644 index 0000000..0005f46 --- /dev/null +++ b/node_modules/less/test/less/errors/parse-error-missing-bracket.txt @@ -0,0 +1,3 @@ +ParseError: missing closing `}` in {path}parse-error-missing-bracket.less on line 3, column 1: +2 background-color: #fff; +3 diff --git a/node_modules/less/test/less/errors/parse-error-with-import.less b/node_modules/less/test/less/errors/parse-error-with-import.less new file mode 100644 index 0000000..6be3de8 --- /dev/null +++ b/node_modules/less/test/less/errors/parse-error-with-import.less @@ -0,0 +1,13 @@ +@import 'import/import-test.less'; + +body +{ + font-family: arial, sans-serif; +} + +nonsense; + +.clickable +{ + cursor: pointer; +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/parse-error-with-import.txt b/node_modules/less/test/less/errors/parse-error-with-import.txt new file mode 100644 index 0000000..07732c9 --- /dev/null +++ b/node_modules/less/test/less/errors/parse-error-with-import.txt @@ -0,0 +1,4 @@ +ParseError: Unrecognised input in {path}parse-error-with-import.less on line 8, column 9: +7 +8 nonsense; +9 diff --git a/node_modules/less/test/less/errors/property-ie5-hack.less b/node_modules/less/test/less/errors/property-ie5-hack.less new file mode 100644 index 0000000..51bf6e3 --- /dev/null +++ b/node_modules/less/test/less/errors/property-ie5-hack.less @@ -0,0 +1,3 @@ +.test { + display/*/: block; /*sorry for IE5*/ +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/property-ie5-hack.txt b/node_modules/less/test/less/errors/property-ie5-hack.txt new file mode 100644 index 0000000..e42ef90 --- /dev/null +++ b/node_modules/less/test/less/errors/property-ie5-hack.txt @@ -0,0 +1,4 @@ +ParseError: Unrecognised input in {path}property-ie5-hack.less on line 2, column 3: +1 .test { +2 display/*/: block; /*sorry for IE5*/ +3 } diff --git a/node_modules/less/test/less/errors/property-in-root.less b/node_modules/less/test/less/errors/property-in-root.less new file mode 100644 index 0000000..8fed4be --- /dev/null +++ b/node_modules/less/test/less/errors/property-in-root.less @@ -0,0 +1,4 @@ +.a() { + prop:1; +} +.a(); \ No newline at end of file diff --git a/node_modules/less/test/less/errors/property-in-root.txt b/node_modules/less/test/less/errors/property-in-root.txt new file mode 100644 index 0000000..04b2776 --- /dev/null +++ b/node_modules/less/test/less/errors/property-in-root.txt @@ -0,0 +1,4 @@ +SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root.less on line 2, column 3: +1 .a() { +2 prop:1; +3 } diff --git a/node_modules/less/test/less/errors/property-in-root2.less b/node_modules/less/test/less/errors/property-in-root2.less new file mode 100644 index 0000000..ce8656d --- /dev/null +++ b/node_modules/less/test/less/errors/property-in-root2.less @@ -0,0 +1 @@ +@import "property-in-root"; \ No newline at end of file diff --git a/node_modules/less/test/less/errors/property-in-root2.txt b/node_modules/less/test/less/errors/property-in-root2.txt new file mode 100644 index 0000000..04b2776 --- /dev/null +++ b/node_modules/less/test/less/errors/property-in-root2.txt @@ -0,0 +1,4 @@ +SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root.less on line 2, column 3: +1 .a() { +2 prop:1; +3 } diff --git a/node_modules/less/test/less/errors/property-in-root3.less b/node_modules/less/test/less/errors/property-in-root3.less new file mode 100644 index 0000000..056c2f7 --- /dev/null +++ b/node_modules/less/test/less/errors/property-in-root3.less @@ -0,0 +1,4 @@ +prop:1; +.a { + prop:1; +} \ No newline at end of file diff --git a/node_modules/less/test/less/errors/property-in-root3.txt b/node_modules/less/test/less/errors/property-in-root3.txt new file mode 100644 index 0000000..68ef945 --- /dev/null +++ b/node_modules/less/test/less/errors/property-in-root3.txt @@ -0,0 +1,3 @@ +SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root3.less on line 1, column 1: +1 prop:1; +2 .a { diff --git a/node_modules/less/test/less/errors/recursive-variable.less b/node_modules/less/test/less/errors/recursive-variable.less new file mode 100644 index 0000000..c1ca75f --- /dev/null +++ b/node_modules/less/test/less/errors/recursive-variable.less @@ -0,0 +1 @@ +@bodyColor: darken(@bodyColor, 30%); \ No newline at end of file diff --git a/node_modules/less/test/less/errors/recursive-variable.txt b/node_modules/less/test/less/errors/recursive-variable.txt new file mode 100644 index 0000000..eb616e7 --- /dev/null +++ b/node_modules/less/test/less/errors/recursive-variable.txt @@ -0,0 +1,2 @@ +NameError: Recursive variable definition for @bodyColor in {path}recursive-variable.less on line 1, column 20: +1 @bodyColor: darken(@bodyColor, 30%); diff --git a/node_modules/less/test/less/extend-chaining.less b/node_modules/less/test/less/extend-chaining.less new file mode 100644 index 0000000..8ffc48a --- /dev/null +++ b/node_modules/less/test/less/extend-chaining.less @@ -0,0 +1,79 @@ +//very simple chaining +.a { + color: black; +} +.b:extend(.a) {} +.c:extend(.b) {} + +//very simple chaining, ordering not important + +.d:extend(.e) {} +.e:extend(.f) {} +.f { + color: black; +} + +//extend with all + +.g.h { + color: black; +} +.i.j:extend(.g all) { + color: white; +} +.k:extend(.i all) {} + +//extend multi-chaining + +.l { + color: black; +} +.m:extend(.l){} +.n:extend(.m){} +.o:extend(.n){} +.p:extend(.o){} +.q:extend(.p){} +.r:extend(.q){} +.s:extend(.r){} +.t:extend(.s){} + +// self referencing is ignored + +.u {color: black;} +.v.u.v:extend(.u all){} + +// circular reference because the new extend product will match the existing extend + +.w:extend(.w) {color: black;} +.v.w.v:extend(.w all){} + +// classic circular references + +.x:extend(.z) { + color: x; +} +.y:extend(.x) { + color: y; +} +.z:extend(.y) { + color: z; +} + +// media queries - dont extend outside, do extend inside + +@media tv { + .ma:extend(.a,.b,.c,.d,.e,.f,.g,.h,.i,.j,.k,.l,.m,.n,.o,.p,.q,.r,.s,.t,.u,.v,.w,.x,.y,.z,.md) { + color: black; + } + .md { + color: white; + } + @media plasma { + .me, .mf { + &:extend(.mb,.md); + background: red; + } + } +} +.mb:extend(.ma) {}; +.mc:extend(.mb) {}; \ No newline at end of file diff --git a/node_modules/less/test/less/extend-clearfix.less b/node_modules/less/test/less/extend-clearfix.less new file mode 100644 index 0000000..82445df --- /dev/null +++ b/node_modules/less/test/less/extend-clearfix.less @@ -0,0 +1,19 @@ +.clearfix { + *zoom: 1; + &:after { + content: ''; + display: block; + clear: both; + height: 0; + } +} + +.foo { + &:extend(.clearfix all); + color: red; +} + +.bar { + &:extend(.clearfix all); + color: blue; +} diff --git a/node_modules/less/test/less/extend-exact.less b/node_modules/less/test/less/extend-exact.less new file mode 100644 index 0000000..41dc413 --- /dev/null +++ b/node_modules/less/test/less/extend-exact.less @@ -0,0 +1,46 @@ +.replace.replace, +.c.replace + .replace { + .replace, + .c { + prop: copy-paste-replace; + } +} +.rep_ace:extend(.replace.replace .replace) {} + +.a .b .c { + prop: not_effected; +} + +.a { + prop: is_effected; + .b { + prop: not_effected; + } + .b.c { + prop: not_effected; + } +} + +.c, .a { + .b, .a { + .a, .c { + prop: not_effected; + } + } +} + +.effected { + &:extend(.a); + &:extend(.b); + &:extend(.c); +} + +.e { + && { + prop: extend-double; + &:hover { + hover: not-extended; + } + } +} +.dbl:extend(.e.e) {} diff --git a/node_modules/less/test/less/extend-media.less b/node_modules/less/test/less/extend-media.less new file mode 100644 index 0000000..1b22c3f --- /dev/null +++ b/node_modules/less/test/less/extend-media.less @@ -0,0 +1,24 @@ +.ext1 .ext2 { + background: black; +} + +@media tv { + .ext1 .ext3 { + color: white; + } + .tv-lowres :extend(.ext1 all) { + background: blue; + } + @media hires { + .ext1 .ext4 { + color: green; + } + .tv-hires :extend(.ext1 all) { + background: red; + } + } +} + +.all:extend(.ext1 all) { + +} \ No newline at end of file diff --git a/node_modules/less/test/less/extend-nest.less b/node_modules/less/test/less/extend-nest.less new file mode 100644 index 0000000..9d4d27b --- /dev/null +++ b/node_modules/less/test/less/extend-nest.less @@ -0,0 +1,65 @@ +.sidebar { + width: 300px; + background: red; + + .box { + background: #FFF; + border: 1px solid #000; + margin: 10px 0; + } +} + +.sidebar2 { + &:extend(.sidebar all); + background: blue; +} + +.type1 { + .sidebar3 { + &:extend(.sidebar all); + background: green; + } +} + +.type2 { + &.sidebar4 { + &:extend(.sidebar all); + background: red; + } +} + +.button { + color: black; + &:hover { + color: white; + } +} +.submit { + &:extend(.button); + &:hover:extend(.button:hover) {} +} + +.nomatch { + &:hover:extend(.button :hover) {} +} + +.button2 { + :hover { + nested: white; + } +} +.button2 :hover { + notnested: black; +} + +.nomatch :extend(.button2:hover) {} + +.amp-test-a, +.amp-test-b { + .amp-test-c &.amp-test-d&.amp-test-e { + .amp-test-f&+&.amp-test-g:extend(.amp-test-h) {} + } +} +.amp-test-h { + test: extended by masses of selectors; +} \ No newline at end of file diff --git a/node_modules/less/test/less/extend-selector.less b/node_modules/less/test/less/extend-selector.less new file mode 100644 index 0000000..7d6f044 --- /dev/null +++ b/node_modules/less/test/less/extend-selector.less @@ -0,0 +1,84 @@ +.error { + border: 1px #f00; + background: #fdd; +} +.error.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error { + display: none; +} +.badError:extend(.error all) { + border-width: 3px; +} + +.foo .bar, .foo .baz { + display: none; +} + +.ext1 .ext2 + :extend(.foo all) { +} + +.ext3:extend(.foo all), +.ext4:extend(.foo all) { +} + +div.ext5, +.ext6 > .ext5 { + width: 100px; +} + +.should-not-exist-in-output, +.ext7:extend(.ext5 all) { +} + +.ext { + test: 1; +} +// same as +// .a .c:extend(.ext all) +// .b .c:extend(.ext all) +// .a .c .d +// .b .c .d +.a, .b { + test: 2; + .c:extend(.ext all) { + test: 3; + .d { + test: 4; + } + } +} + +.replace.replace, +.c.replace + .replace { + .replace, + .c { + prop: copy-paste-replace; + } +} +.rep_ace:extend(.replace all) {} + +.attributes { + [data="test"] { + extend: attributes; + } + .attribute-test { + &:extend([data="test"] all); + } + [data] { + extend: attributes2; + } + .attribute-test2 { + &:extend([data] all); //you could argue it should match [data="test"]... not for now though... + } + @attr-data: "test3"; + [data=@{attr-data}] { + extend: attributes2; + } + .attribute-test { + &:extend([data="test3"] all); + } +} \ No newline at end of file diff --git a/node_modules/less/test/less/extend.less b/node_modules/less/test/less/extend.less new file mode 100644 index 0000000..1db5d43 --- /dev/null +++ b/node_modules/less/test/less/extend.less @@ -0,0 +1,81 @@ +.error { + border: 1px #f00; + background: #fdd; +} +.error.intrusion { + font-size: 1.3em; + font-weight: bold; +} +.intrusion .error { + display: none; +} +.badError { + &:extend(.error all); + border-width: 3px; +} + +.foo .bar, .foo .baz { + display: none; +} + +.ext1 .ext2 { + &:extend(.foo all); +} + +.ext3, +.ext4 { + &:extend(.foo all); + &:extend(.bar all); +} + +div.ext5, +.ext6 > .ext5 { + width: 100px; +} + +.ext7 { + &:extend(.ext5 all); +} + +.ext8.ext9 { + result: add-foo; +} +.ext8 .ext9, +.ext8 + .ext9, +.ext8 > .ext9 { + result: bar-matched; +} +.ext8.nomatch { + result: none; +} +.ext8 { + .ext9 { + result: match-nested-bar; + } +} +.ext8 { + &.ext9 { + result: match-nested-foo; + } +} + +.fuu:extend(.ext8.ext9 all) {} +.buu:extend(.ext8 .ext9 all) {} +.zap:extend(.ext8 + .ext9 all) {} +.zoo:extend(.ext8 > .ext9 all) {} + +.aa { + color: black; + .dd { + background: red; + } +} +.bb { + background: red; + .bb { + color: black; + } +} +.cc:extend(.aa,.bb) {} +.ee:extend(.dd all,.bb) {} +.ff:extend(.dd,.bb all) {} \ No newline at end of file diff --git a/node_modules/less/test/less/functions.less b/node_modules/less/test/less/functions.less new file mode 100644 index 0000000..f60dab4 --- /dev/null +++ b/node_modules/less/test/less/functions.less @@ -0,0 +1,142 @@ +#functions { + @var: 10; + @colors: #000, #fff; + color: _color("evil red"); // #660000 + width: increment(15); + height: undefined("self"); + border-width: add(2, 3); + variable: increment(@var); + background: linear-gradient(@colors); +} + +#built-in { + @r: 32; + escaped: e("-Some::weird(#thing, y)"); + lighten: lighten(#ff0000, 40%); + darken: darken(#ff0000, 40%); + saturate: saturate(#29332f, 20%); + desaturate: desaturate(#203c31, 20%); + greyscale: greyscale(#203c31); + hsl-clamp: hsl(380, 150%, 150%); + spin-p: spin(hsl(340, 50%, 50%), 40); + spin-n: spin(hsl(30, 50%, 50%), -40); + luma-white: luma(#fff); + luma-black: luma(#000); + luma-black-alpha: luma(rgba(0,0,0,0.5)); + luma-red: luma(#ff0000); + luma-green: luma(#00ff00); + luma-blue: luma(#0000ff); + luma-yellow: luma(#ffff00); + luma-cyan: luma(#00ffff); + luma-white-alpha: luma(rgba(255,255,255,0.5)); + contrast-filter: contrast(30%); + contrast-white: contrast(#fff); + contrast-black: contrast(#000); + contrast-red: contrast(#ff0000); + contrast-green: contrast(#00ff00); + contrast-blue: contrast(#0000ff); + contrast-yellow: contrast(#ffff00); + contrast-cyan: contrast(#00ffff); + contrast-light: contrast(#fff, #111111, #eeeeee); + contrast-dark: contrast(#000, #111111, #eeeeee); + contrast-wrongorder: contrast(#fff, #eeeeee, #111111, 0.5); + contrast-light-thresh: contrast(#fff, #111111, #eeeeee, 0.5); + contrast-dark-thresh: contrast(#000, #111111, #eeeeee, 0.5); + contrast-high-thresh: contrast(#555, #111111, #eeeeee, 0.6); + contrast-low-thresh: contrast(#555, #111111, #eeeeee, 0.1); + contrast-light-thresh-per: contrast(#fff, #111111, #eeeeee, 50%); + contrast-dark-thresh-per: contrast(#000, #111111, #eeeeee, 50%); + contrast-high-thresh-per: contrast(#555, #111111, #eeeeee, 60%); + contrast-low-thresh-per: contrast(#555, #111111, #eeeeee, 10%); + format: %("rgb(%d, %d, %d)", @r, 128, 64); + format-string: %("hello %s", "world"); + format-multiple: %("hello %s %d", "earth", 2); + format-url-encode: %('red is %A', #ff0000); + eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); + + unitless: unit(12px); + unit: unit((13px + 1px), em); + + hue: hue(hsl(98, 12%, 95%)); + saturation: saturation(hsl(98, 12%, 95%)); + lightness: lightness(hsl(98, 12%, 95%)); + hsvhue: hsvhue(hsv(98, 12%, 95%)); + hsvsaturation: hsvsaturation(hsv(98, 12%, 95%)); + hsvvalue: hsvvalue(hsv(98, 12%, 95%)); + red: red(#f00); + green: green(#0f0); + blue: blue(#00f); + rounded: round((@r/3)); + rounded-two: round((@r/3), 2); + roundedpx: round((10px / 3)); + roundedpx-three: round((10px / 3), 3); + rounded-percentage: round(10.2%); + ceil: ceil(10.1px); + floor: floor(12.9px); + sqrt: sqrt(25px); + pi: pi(); + mod: mod(13m, 11cm); // could take into account units, doesn't at the moment + abs: abs(-4%); + tan: tan(42deg); + sin: sin(10deg); + cos: cos(12); + atan: atan(tan(0.1rad)); + atan: convert(acos(cos(34deg)), deg); + atan: convert(acos(cos(50grad)), deg); + pow: pow(8px, 2); + pow: pow(4, 3); + pow: pow(3, 3em); + percentage: percentage((10px / 50)); + color: color("#ff0011"); + tint: tint(#777777, 13); + tint-full: tint(#777777, 100); + tint-percent: tint(#777777, 13%); + shade: shade(#777777, 13); + shade-full: shade(#777777, 100); + shade-percent: shade(#777777, 13%); + + fade-out: fadeOut(red, 5%); // support fadeOut and fadeout + fade-in: fadein(fadeout(red, 10%), 5%); + + hsv: hsv(5, 50%, 30%); + hsva: hsva(3, 50%, 30%, 0.2); + + mix: mix(#ff0000, #ffff00, 80); + mix-0: mix(#ff0000, #ffff00, 0); + mix-100: mix(#ff0000, #ffff00, 100); + mix-weightless: mix(#ff0000, #ffff00); + + .is-a { + color: iscolor(#ddd); + color1: iscolor(red); + color2: iscolor(rgb(0, 0, 0)); + keyword: iskeyword(hello); + number: isnumber(32); + string: isstring("hello"); + pixel: ispixel(32px); + percent: ispercentage(32%); + em: isem(32em); + cat: isunit(32cat, cat); + } +} + +#alpha { + alpha: darken(hsla(25, 50%, 50%, 0.6), 10%); +} + +#blendmodes { + multiply: multiply(#f60000, #f60000); + screen: screen(#f60000, #0000f6); + overlay: overlay(#f60000, #0000f6); + softlight: softlight(#f60000, #ffffff); + hardlight: hardlight(#f60000, #0000f6); + difference: difference(#f60000, #0000f6); + exclusion: exclusion(#f60000, #0000f6); + average: average(#f60000, #0000f6); + negation: negation(#f60000, #313131); +} + +#extract { + @anon: A B C 1 2 3; + result: extract(@anon, 6) extract(@anon, 5) extract(@anon, 4) extract(@anon, 3) extract(@anon, 2) extract(@anon, 1); +} diff --git a/node_modules/less/test/less/ie-filters.less b/node_modules/less/test/less/ie-filters.less new file mode 100644 index 0000000..3350b65 --- /dev/null +++ b/node_modules/less/test/less/ie-filters.less @@ -0,0 +1,15 @@ +@fat: 0; +@cloudhead: "#000000"; + +.nav { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat); +} +.evalTest(@arg) { + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@arg); +} +.evalTest1 { + .evalTest(30); + .evalTest(5); +} \ No newline at end of file diff --git a/node_modules/less/test/less/import-interpolation.less b/node_modules/less/test/less/import-interpolation.less new file mode 100644 index 0000000..21cfe08 --- /dev/null +++ b/node_modules/less/test/less/import-interpolation.less @@ -0,0 +1,8 @@ +@my_theme: "test"; + +@import "import/import-@{my_theme}-e.less"; + +@import "import/import-@{in}@{terpolation}.less"; + +@in: "in"; +@terpolation: "terpolation"; \ No newline at end of file diff --git a/node_modules/less/test/less/import-once.less b/node_modules/less/test/less/import-once.less new file mode 100644 index 0000000..a7abe26 --- /dev/null +++ b/node_modules/less/test/less/import-once.less @@ -0,0 +1,4 @@ +@import "import/import-once-test-c"; +@import "import/import-once-test-c"; +@import "import/import-once-test-c.less"; +@import "import/deeper/import-once-test-a"; diff --git a/node_modules/less/test/less/import.less b/node_modules/less/test/less/import.less new file mode 100644 index 0000000..0168940 --- /dev/null +++ b/node_modules/less/test/less/import.less @@ -0,0 +1,21 @@ +@import url(http://fonts.googleapis.com/css?family=Open+Sans); + +@import url(/absolute/something.css) screen and (color) and (max-width: 600px); + +@var: 100px; +@import url("//ha.com/file.css") (min-width:@var); + +#import-test { + .mixin; + width: 10px; + height: (@a + 10%); +} +@import "import/import-test-e" screen and (max-width: 600px); + +@import url("import/import-test-a.less"); + +@import (less, multiple) "import/import-test-d.css" screen and (max-width: 601px); + +@import (multiple) "import/import-test-e" screen and (max-width: 602px); + +@import (less, multiple) url("import/import-test-d.css") screen and (max-width: 603px); \ No newline at end of file diff --git a/node_modules/less/test/less/import/deeper/import-once-test-a.less b/node_modules/less/test/less/import/deeper/import-once-test-a.less new file mode 100644 index 0000000..8a747fc --- /dev/null +++ b/node_modules/less/test/less/import/deeper/import-once-test-a.less @@ -0,0 +1 @@ +@import "../import-once-test-c"; \ No newline at end of file diff --git a/node_modules/less/test/less/import/import-and-relative-paths-test.less b/node_modules/less/test/less/import/import-and-relative-paths-test.less new file mode 100644 index 0000000..da69998 --- /dev/null +++ b/node_modules/less/test/less/import/import-and-relative-paths-test.less @@ -0,0 +1,6 @@ +@import "../css/background.css"; +@import "import-test-d.css"; + +@import "imports/logo"; +@import "imports/font"; + diff --git a/node_modules/less/test/less/import/import-charset-test.less b/node_modules/less/test/less/import/import-charset-test.less new file mode 100644 index 0000000..07a66e1 --- /dev/null +++ b/node_modules/less/test/less/import/import-charset-test.less @@ -0,0 +1 @@ +@charset "ISO-8859-1"; \ No newline at end of file diff --git a/node_modules/less/test/less/import/import-interpolation.less b/node_modules/less/test/less/import/import-interpolation.less new file mode 100644 index 0000000..aa49a70 --- /dev/null +++ b/node_modules/less/test/less/import/import-interpolation.less @@ -0,0 +1 @@ +@import "import-@{in}@{terpolation}2.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/import/import-interpolation2.less b/node_modules/less/test/less/import/import-interpolation2.less new file mode 100644 index 0000000..12bfb4e --- /dev/null +++ b/node_modules/less/test/less/import/import-interpolation2.less @@ -0,0 +1,5 @@ +.a { + var: test; +} + +@in: "redefined-does-nothing"; \ No newline at end of file diff --git a/node_modules/less/test/less/import/import-once-test-c.less b/node_modules/less/test/less/import/import-once-test-c.less new file mode 100644 index 0000000..686747a --- /dev/null +++ b/node_modules/less/test/less/import/import-once-test-c.less @@ -0,0 +1,6 @@ + +@c: red; + +#import { + color: @c; +} diff --git a/node_modules/less/test/less/import/import-test-a.less b/node_modules/less/test/less/import/import-test-a.less new file mode 100644 index 0000000..b3b3b8f --- /dev/null +++ b/node_modules/less/test/less/import/import-test-a.less @@ -0,0 +1,3 @@ +@import "import-test-b.less"; +@a: 20%; +@import "urls.less"; \ No newline at end of file diff --git a/node_modules/less/test/less/import/import-test-b.less b/node_modules/less/test/less/import/import-test-b.less new file mode 100644 index 0000000..ce2d35a --- /dev/null +++ b/node_modules/less/test/less/import/import-test-b.less @@ -0,0 +1,8 @@ +@import "import-test-c"; + +@b: 100%; + +.mixin { + height: 10px; + color: @c; +} diff --git a/node_modules/less/test/less/import/import-test-c.less b/node_modules/less/test/less/import/import-test-c.less new file mode 100644 index 0000000..686747a --- /dev/null +++ b/node_modules/less/test/less/import/import-test-c.less @@ -0,0 +1,6 @@ + +@c: red; + +#import { + color: @c; +} diff --git a/node_modules/less/test/less/import/import-test-d.css b/node_modules/less/test/less/import/import-test-d.css new file mode 100644 index 0000000..30575f0 --- /dev/null +++ b/node_modules/less/test/less/import/import-test-d.css @@ -0,0 +1 @@ +#css { color: yellow; } diff --git a/node_modules/less/test/less/import/import-test-e.less b/node_modules/less/test/less/import/import-test-e.less new file mode 100644 index 0000000..98b84b0 --- /dev/null +++ b/node_modules/less/test/less/import/import-test-e.less @@ -0,0 +1,2 @@ + +body { width: 100% } diff --git a/node_modules/less/test/less/import/imports/font.less b/node_modules/less/test/less/import/imports/font.less new file mode 100644 index 0000000..5abb7e7 --- /dev/null +++ b/node_modules/less/test/less/import/imports/font.less @@ -0,0 +1,8 @@ +@font-face { + font-family: xecret; + src: url('../assets/xecret.ttf'); +} + +#secret { + font-family: xecret, sans-serif; +} diff --git a/node_modules/less/test/less/import/imports/logo.less b/node_modules/less/test/less/import/imports/logo.less new file mode 100644 index 0000000..22893a2 --- /dev/null +++ b/node_modules/less/test/less/import/imports/logo.less @@ -0,0 +1,5 @@ +#logo { + width: 100px; + height: 100px; + background: url('../assets/logo.png'); +} diff --git a/node_modules/less/test/less/import/urls.less b/node_modules/less/test/less/import/urls.less new file mode 100644 index 0000000..bb48f77 --- /dev/null +++ b/node_modules/less/test/less/import/urls.less @@ -0,0 +1 @@ +// empty file showing that it loads from the relative path first diff --git a/node_modules/less/test/less/javascript.less b/node_modules/less/test/less/javascript.less new file mode 100644 index 0000000..b826a78 --- /dev/null +++ b/node_modules/less/test/less/javascript.less @@ -0,0 +1,29 @@ +.eval { + js: `42`; + js: `1 + 1`; + js: `"hello world"`; + js: `[1, 2, 3]`; + title: `typeof process.title`; + ternary: `(1 + 1 == 2 ? true : false)`; + multiline: `(function(){var x = 1 + 1; + return x})()`; +} +.scope { + @foo: 42; + var: `parseInt(this.foo.toJS())`; + escaped: ~`2 + 5 + 'px'`; +} +.vars { + @var: `4 + 4`; + width: @var; +} +.escape-interpol { + @world: "world"; + width: ~`"hello" + " " + @{world}`; +} +.arrays { + @ary: 1, 2, 3; + @ary2: 1 2 3; + ary: `@{ary}.join(', ')`; + ary1: `@{ary2}.join(', ')`; +} diff --git a/node_modules/less/test/less/lazy-eval.less b/node_modules/less/test/less/lazy-eval.less new file mode 100644 index 0000000..72b3fd4 --- /dev/null +++ b/node_modules/less/test/less/lazy-eval.less @@ -0,0 +1,6 @@ +@var: @a; +@a: 100%; + +.lazy-eval { + width: @var; +} diff --git a/node_modules/less/test/less/legacy/legacy.less b/node_modules/less/test/less/legacy/legacy.less new file mode 100644 index 0000000..92d0008 --- /dev/null +++ b/node_modules/less/test/less/legacy/legacy.less @@ -0,0 +1,7 @@ +@media (-o-min-device-pixel-ratio: 2/1) { + .test-math-and-units { + font: ignores 0/0 rules; + test-division: 4 / 2 + 5em; + simple: 1px + 1px; + } +} \ No newline at end of file diff --git a/node_modules/less/test/less/media.less b/node_modules/less/test/less/media.less new file mode 100644 index 0000000..3d55d31 --- /dev/null +++ b/node_modules/less/test/less/media.less @@ -0,0 +1,210 @@ + +// For now, variables can't be declared inside @media blocks. + +@var: 42; + +@media print { + .class { + color: blue; + .sub { + width: @var; + } + } + .top, header > h1 { + color: (#222 * 2); + } +} + +@media screen { + @base: 8; + body { max-width: (@base * 60); } +} + +@ratio_large: 16; +@ratio_small: 9; + +@media all and (device-aspect-ratio: @ratio_large / @ratio_small) { + body { max-width: 800px; } +} + +@media all and (orientation:portrait) { + aside { float: none; } +} + +@media handheld and (min-width: @var), screen and (min-width: 20em) { + body { + max-width: 480px; + } +} + +body { + @media print { + padding: 20px; + + header { + background-color: red; + } + + @media (orientation:landscape) { + margin-left: 20px; + } + } +} + +@media screen { + .sidebar { + width: 300px; + @media (orientation: landscape) { + width: 500px; + } + } +} + +@media a { + .first { + @media b { + .second { + .third { + width: 300px; + @media c { + width: 500px; + } + } + .fourth { + width: 3; + } + } + } + } +} + +body { + @media a, b and c { + width: 95%; + + @media x, y { + width: 100%; + } + } +} + +.mediaMixin(@fallback: 200px) { + background: black; + + @media handheld { + background: white; + + @media (max-width: @fallback) { + background: red; + } + } +} + +.a { + .mediaMixin(100px); +} + +.b { + .mediaMixin(); +} +@smartphone: ~"only screen and (max-width: 200px)"; +@media @smartphone { + width: 480px; +} + +@media print { + @page :left { + margin: 0.5cm; + } + @page :right { + margin: 0.5cm; + } + @page Test:first { + margin: 1cm; + } + @page :first { + size: 8.5in 11in; + @top-left { + margin: 1cm; + } + @top-left-corner { + margin: 1cm; + } + @top-center { + margin: 1cm; + } + @top-right { + margin: 1cm; + } + @top-right-corner { + margin: 1cm; + } + @bottom-left { + margin: 1cm; + } + @bottom-left-corner { + margin: 1cm; + } + @bottom-center { + margin: 1cm; + } + @bottom-right { + margin: 1cm; + } + @bottom-right-corner { + margin: 1cm; + } + @left-top { + margin: 1cm; + } + @left-middle { + margin: 1cm; + } + @left-bottom { + margin: 1cm; + } + @right-top { + margin: 1cm; + } + @right-middle { + content: "Page " counter(page); + } + @right-bottom { + margin: 1cm; + } + } +} + +@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-resolution: 2dppx), (min-resolution: 128dpcm) { + .b { + background: red; + } +} + +.bg() { + background: red; + + @media (max-width: 500px) { + background: green; + } +} + +body { + .bg(); +} + +@bpMedium: 1000px; +@media (max-width: @bpMedium) { + body { + .bg(); + background: blue; + } +} + +@media (max-width: 1200px) { + /* a comment */ + + @media (max-width: 900px) { + body { font-size: 11px; } + } +} diff --git a/node_modules/less/test/less/mixins-args.less b/node_modules/less/test/less/mixins-args.less new file mode 100644 index 0000000..e7fd38b --- /dev/null +++ b/node_modules/less/test/less/mixins-args.less @@ -0,0 +1,205 @@ +.mixin (@a: 1px, @b: 50%) { + width: (@a * 5); + height: (@b - 1%); +} + +.mixina (@style, @width, @color: black) { + border: @width @style @color; +} + +.mixiny +(@a: 0, @b: 0) { + margin: @a; + padding: @b; +} + +.hidden() { + color: transparent; // asd +} + +#hidden { + .hidden; +} + +#hidden1 { + .hidden(); +} + +.two-args { + color: blue; + .mixin(2px, 100%); + .mixina(dotted, 2px); +} + +.one-arg { + .mixin(3px); +} + +.no-parens { + .mixin; +} + +.no-args { + .mixin(); +} + +.var-args { + @var: 9; + .mixin(@var, (@var * 2)); +} + +.multi-mix { + .mixin(2px, 30%); + .mixiny(4, 5); +} + +.maxa(@arg1: 10, @arg2: #f00) { + padding: (@arg1 * 2px); + color: @arg2; +} + +body { + .maxa(15); +} + +@glob: 5; +.global-mixin(@a:2) { + width: (@glob + @a); +} + +.scope-mix { + .global-mixin(3); +} + +.nested-ruleset (@width: 200px) { + width: @width; + .column { margin: @width; } +} +.content { + .nested-ruleset(600px); +} + +// + +.same-var-name2(@radius) { + radius: @radius; +} +.same-var-name(@radius) { + .same-var-name2(@radius); +} +#same-var-name { + .same-var-name(5px); +} + +// + +.var-inside () { + @var: 10px; + width: @var; +} +#var-inside { .var-inside; } + +.mixin-arguments (@width: 0px, ...) { + border: @arguments; + width: @width; +} + +.arguments { + .mixin-arguments(1px, solid, black); +} +.arguments2 { + .mixin-arguments(); +} +.arguments3 { + .mixin-arguments; +} + +.mixin-arguments2 (@width, @rest...) { + border: @arguments; + rest: @rest; + width: @width; +} +.arguments4 { + .mixin-arguments2(0, 1, 2, 3, 4); +} + +// Edge cases + +.edge-case { + .mixin-arguments("{"); +} + +// Division vs. Literal Slash +.border-radius(@r: 2px/5px) { + border-radius: @r; +} +.slash-vs-math { + .border-radius(); + .border-radius(5px/10px); + .border-radius((3px * 2)); +} +// semi-colon vs comma for delimiting + +.mixin-takes-one(@a) { + one: @a; +} + +.mixin-takes-two(@a; @b) { + one: @a; + two: @b; +} + +.comma-vs-semi-colon { + .mixin-takes-two(@a : a; @b : b, c); + .mixin-takes-two(@a : d, e; @b : f); + .mixin-takes-one(@a: g); + .mixin-takes-one(@a : h;); + .mixin-takes-one(i); + .mixin-takes-one(j;); + .mixin-takes-two(k, l); + .mixin-takes-one(m, n;); + .mixin-takes-two(o, p; q); + .mixin-takes-two(r, s; t;); +} + +.mixin-conflict(@a:defA, @b:defB, @c:defC) { + three: @a, @b, @c; +} + +.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) { + four: @a, @b, @c, @d; +} + +#named-conflict { + .mixin-conflict(11, 12, 13, @a:a); + .mixin-conflict(@a:a, 21, 22, 23); +} +@a: 3px; +.mixin-default-arg(@a: 1px, @b: @a, @c: @b) { + defaults: 1px 1px 1px; + defaults: 2px 2px 2px; +} + +.test-mixin-default-arg { + .mixin-default-arg(); + .mixin-default-arg(2px); +} + +.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) { + margin: @margin; +} +.selector { + .mixin-comma-default1(#33acfe; 4); +} +.mixin-comma-default2(@margin: 2, 2, 2, 2;) { + margin: @margin; +} +.selector2 { + .mixin-comma-default2(); +} +.mixin-comma-default3(@margin: 2, 2, 2, 2) { + margin: @margin; +} +.selector3 { + .mixin-comma-default3(4,2,2,2); +} \ No newline at end of file diff --git a/node_modules/less/test/less/mixins-closure.less b/node_modules/less/test/less/mixins-closure.less new file mode 100644 index 0000000..01251d2 --- /dev/null +++ b/node_modules/less/test/less/mixins-closure.less @@ -0,0 +1,26 @@ +.scope { + @var: 99px; + .mixin () { + width: @var; + } +} + +.class { + .scope > .mixin; +} + +.overwrite { + @var: 0px; + .scope > .mixin; +} + +.nested { + @var: 5px; + .mixin () { + width: @var; + } + .class { + @var: 10px; + .mixin; + } +} diff --git a/node_modules/less/test/less/mixins-guards.less b/node_modules/less/test/less/mixins-guards.less new file mode 100644 index 0000000..4e35401 --- /dev/null +++ b/node_modules/less/test/less/mixins-guards.less @@ -0,0 +1,137 @@ + +// Stacking, functions.. + +.light (@a) when (lightness(@a) > 50%) { + color: white; +} +.light (@a) when (lightness(@a) < 50%) { + color: black; +} +.light (@a) { + margin: 1px; +} + +.light1 { .light(#ddd) } +.light2 { .light(#444) } + +// Arguments against each other + +.max (@a, @b) when (@a > @b) { + width: @a; +} +.max (@a, @b) when (@a < @b) { + width: @b; +} + +.max1 { .max(3, 6) } +.max2 { .max(8, 1) } + +// Globals inside guards + +@g: auto; + +.glob (@a) when (@a = @g) { + margin: @a @g; +} +.glob1 { .glob(auto) } + +// Other operators + +.ops (@a) when (@a >= 0) { + height: gt-or-eq; +} +.ops (@a) when (@a =< 0) { + height: lt-or-eq; +} +.ops (@a) when not(@a = 0) { + height: not-eq; +} +.ops1 { .ops(0) } +.ops2 { .ops(1) } +.ops3 { .ops(-1) } + +// Scope and default values + +@a: auto; + +.default (@a: inherit) when (@a = inherit) { + content: default; +} +.default1 { .default } + +// true & false keywords +.test (@a) when (@a) { + content: "true."; +} +.test (@a) when not (@a) { + content: "false."; +} + +.test1 { .test(true) } +.test2 { .test(false) } +.test3 { .test(1) } +.test4 { .test(boo) } +.test5 { .test("true") } + +// Boolean expressions + +.bool () when (true) and (false) { content: true and false } // FALSE +.bool () when (true) and (true) { content: true and true } // TRUE +.bool () when (true) { content: true } // TRUE +.bool () when (false) and (false) { content: true } // FALSE +.bool () when (false), (true) { content: false, true } // TRUE +.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE +.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE +.bool () when (false), (true) and (true) { content: false, true and true } // TRUE +.bool () when (false), (false), (true) { content: false, false, true } // TRUE +.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE +.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE +.bool () when not (false) { content: not false } +.bool () when not (true) and not (false) { content: not true and not false } +.bool () when not (true) and not (true) { content: not true and not true } +.bool () when not (false) and (false), not (false) { content: not false and false, not false } + +.bool1 { .bool } + +.equality-unit-test(@num) when (@num = 1%) { + test: fail; +} +.equality-unit-test(@num) when (@num = 2) { + test: pass; +} +.equality-units { + .equality-unit-test(1px); + .equality-unit-test(2px); +} + +.colorguard(@col) when (@col = red) { content: is @col; } +.colorguard(@col) when not (blue = @col) { content: is not blue its @col; } +.colorguard(@col) {} +.colorguardtest { + .colorguard(red); + .colorguard(blue); + .colorguard(purple); +} + +.stringguard(@str) when (@str = "theme1") { content: is theme1; } +.stringguard(@str) when not ("theme2" = @str) { content: is not theme2; } +.stringguard(@str) when (~"theme1" = @str) { content: is theme1 no quotes; } +.stringguard(@str) {} +.stringguardtest { + .stringguard("theme1"); + .stringguard("theme2"); + .stringguard(theme1); +} + +.mixin(...) { + catch:all; +} +.mixin(@var) when (@var=4) { + declare: 4; +} +.mixin(@var) when (@var=4px) { + declare: 4px; +} +#tryNumberPx { + .mixin(4px); +} \ No newline at end of file diff --git a/node_modules/less/test/less/mixins-important.less b/node_modules/less/test/less/mixins-important.less new file mode 100644 index 0000000..df1fd71 --- /dev/null +++ b/node_modules/less/test/less/mixins-important.less @@ -0,0 +1,22 @@ + +.mixin (9) { + border: 9 !important; +} +.mixin (@a: 0) { + border: @a; + boxer: @a; + .inner { + test: @a; + } + // comment +} + +.class { + .mixin(1); + .mixin(2) !important; + .mixin(3); + .mixin(4) !important; + .mixin(5); + .mixin !important; + .mixin(9); +} diff --git a/node_modules/less/test/less/mixins-named-args.less b/node_modules/less/test/less/mixins-named-args.less new file mode 100644 index 0000000..d79e0f4 --- /dev/null +++ b/node_modules/less/test/less/mixins-named-args.less @@ -0,0 +1,36 @@ +.mixin (@a: 1px, @b: 50%) { + width: (@a * 5); + height: (@b - 1%); + args: @arguments; +} +.mixin (@a: 1px, @b: 50%) when (@b > 75%){ + text-align: center; +} + +.named-arg { + color: blue; + .mixin(@b: 100%); +} + +.class { + @var: 20%; + .mixin(@b: @var); +} + +.all-args-wrong-args { + .mixin(@b: 10%, @a: 2px); +} + +.mixin2 (@a: 1px, @b: 50%, @c: 50) { + width: (@a * 5); + height: (@b - 1%); + color: (#000000 + @c); +} + +.named-args2 { + .mixin2(3px, @c: 100); +} + +.named-args3 { + .mixin2(@b: 30%, @c: #123456); +} \ No newline at end of file diff --git a/node_modules/less/test/less/mixins-nested.less b/node_modules/less/test/less/mixins-nested.less new file mode 100644 index 0000000..43443de --- /dev/null +++ b/node_modules/less/test/less/mixins-nested.less @@ -0,0 +1,22 @@ +.mix-inner (@var) { + border-width: @var; +} + +.mix (@a: 10) { + .inner { + height: (@a * 10); + + .innest { + width: @a; + .mix-inner((@a * 2)); + } + } +} + +.class { + .mix(30); +} + +.class2 { + .mix(60); +} diff --git a/node_modules/less/test/less/mixins-pattern.less b/node_modules/less/test/less/mixins-pattern.less new file mode 100644 index 0000000..f6a12ec --- /dev/null +++ b/node_modules/less/test/less/mixins-pattern.less @@ -0,0 +1,99 @@ +.mixin (...) { + variadic: true; +} +.mixin () { + zero: 0; +} +.mixin (@a: 1px) { + one: 1; +} +.mixin (@a) { + one-req: 1; +} +.mixin (@a: 1px, @b: 2px) { + two: 2; +} + +.mixin (@a, @b, @c) { + three-req: 3; +} + +.mixin (@a: 1px, @b: 2px, @c: 3px) { + three: 3; +} + +.zero { + .mixin(); +} + +.one { + .mixin(1); +} + +.two { + .mixin(1, 2); +} + +.three { + .mixin(1, 2, 3); +} + +// + +.mixout ('left') { + left: 1; +} + +.mixout ('right') { + right: 1; +} + +.left { + .mixout('left'); +} +.right { + .mixout('right'); +} + +// + +.border (@side, @width) { + color: black; + .border-side(@side, @width); +} +.border-side (left, @w) { + border-left: @w; +} +.border-side (right, @w) { + border-right: @w; +} + +.border-right { + .border(right, 4px); +} +.border-left { + .border(left, 4px); +} + +// + + +.border-radius (@r) { + both: (@r * 10); +} +.border-radius (@r, left) { + left: @r; +} +.border-radius (@r, right) { + right: @r; +} + +.only-right { + .border-radius(33, right); +} +.only-left { + .border-radius(33, left); +} +.left-right { + .border-radius(33); +} diff --git a/node_modules/less/test/less/mixins.less b/node_modules/less/test/less/mixins.less new file mode 100644 index 0000000..f1ef474 --- /dev/null +++ b/node_modules/less/test/less/mixins.less @@ -0,0 +1,114 @@ +.mixin { border: 1px solid black; } +.mixout { border-color: orange; } +.borders { border-style: dashed; } + +#namespace { + .borders { + border-style: dotted; + } + .biohazard { + content: "death"; + .man { + color: transparent; + } + } +} +#theme { + > .mixin { + background-color: grey; + } +} +#container { + color: black; + .mixin; + .mixout; + #theme > .mixin; +} + +#header { + .milk { + color: white; + .mixin; + #theme > .mixin; + } + #cookie { + .chips { + #namespace .borders; + .calories { + #container; + } + } + .borders; + } +} +.secure-zone { #namespace .biohazard .man; } +.direct { + #namespace > .borders; +} + +.bo, .bar { + width: 100%; +} +.bo { + border: 1px; +} +.ar.bo.ca { + color: black; +} +.jo.ki { + background: none; +} +.amp { + &.support { + color: orange; + } +} +.extended { + .bo; + .jo.ki; + .amp.support; +} +.foo .bar { + .bar; +} +.has_parents() { + & .underParents { + color: red; + } +} +.has_parents(); +.parent { + .has_parents(); +} +.margin_between(@above, @below) { + * + & { margin-top: @above; } + legend + & { margin-top: 0; } + & + * { margin-top: @below; } +} +h1 { .margin_between(25px, 10px); } +h2 { .margin_between(20px, 8px); } +h3 { .margin_between(15px, 5px); } + +.mixin_def(@url, @position){ + background-image: @url; + background-position: @position; +} +.error{ + @s: "/"; + .mixin_def( "@{s}a.png", center center); +} +.recursion() { + color: black; +} +.test-rec { + .recursion { + .recursion(); + } +} +.paddingFloat(@padding) { padding-left: @padding; } + +.button { + .paddingFloat(((10px + 12) * 2)); + + &.large { .paddingFloat(((10em * 2) * 2)); } +} diff --git a/node_modules/less/test/less/operations.less b/node_modules/less/test/less/operations.less new file mode 100644 index 0000000..3e483c8 --- /dev/null +++ b/node_modules/less/test/less/operations.less @@ -0,0 +1,62 @@ +#operations { + color: (#110000 + #000011 + #001100); // #111111 + height: (10px / 2px + 6px - 1px * 2); // 9px + width: (2 * 4 - 5em); // 3em + .spacing { + height: (10px / 2px+6px-1px*2); + width: (2 * 4-5em); + } + substraction: (20 - 10 - 5 - 5); // 0 + division: (20 / 5 / 4); // 1 +} + +@x: 4; +@y: 12em; + +.with-variables { + height: (@x + @y); // 16em + width: (12 + @y); // 24em + size: (5cm - @x); // 1cm +} + +.with-functions { + color: (rgb(200, 200, 200) / 2); + color: (2 * hsl(0, 50%, 50%)); + color: (rgb(10, 10, 10) + hsl(0, 50%, 50%)); +} + +@z: -2; + +.negative { + height: (2px + @z); // 0px + width: (2px - @z); // 4px +} + +.shorthands { + padding: -1px 2px 0 -4px; // +} + +.rem-dimensions { + font-size: (20rem / 5 + 1.5rem); // 5.5rem +} + +.colors { + color: #123; // #112233 + border-color: (#234 + #111111); // #334455 + background-color: (#222222 - #fff); // #000000 + .other { + color: (2 * #111); // #222222 + border-color: (#333333 / 3 + #111); // #222222 + } +} + +.negations { + @var: 4px; + variable: (-@var); // 4 + variable1: (-@var + @var); // 0 + variable2: (@var + -@var); // 0 + variable3: (@var - -@var); // 8 + variable4: (-@var - -@var); // 0 + paren: (-(@var)); // -4px + paren2: (-(2 + 2) * -@var); // 16 +} diff --git a/node_modules/less/test/less/parens.less b/node_modules/less/test/less/parens.less new file mode 100644 index 0000000..deb4139 --- /dev/null +++ b/node_modules/less/test/less/parens.less @@ -0,0 +1,41 @@ +.parens { + @var: 1px; + border: (@var * 2) solid black; + margin: (@var * 1) (@var + 2) (4 * 4) 3; + width: (6 * 6); + padding: 2px (6 * 6px); +} + +.more-parens { + @var: (2 * 2); + padding: (2 * @var) 4 4 (@var * 1px); + width-all: ((@var * @var) * 6); + width-first: ((@var * @var)) * 6; + width-keep: (@var * @var) * 6; + height-keep: (7 * 7) + (8 * 8); + height-all: ((7 * 7) + (8 * 8)); + height-parts: ((7 * 7)) + ((8 * 8)); + margin-keep: (4 * (5 + 5) / 2) - (@var * 2); + margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2)); + margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2))); + border-radius-keep: 4px * (1 + 1) / @var + 3px; + border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px)); + border-radius-all: (4px * (1 + 1) / @var + 3px); + //margin: (6 * 6)px; +} + +.negative { + @var: 1; + neg-var: -@var; // -1 ? + neg-var-paren: -(@var); // -(1) ? +} + +.nested-parens { + width: 2 * (4 * (2 + (1 + 6))) - 1; + height: ((2 + 3) * (2 + 3) / (9 - 4)) + 1; +} + +.mixed-units { + margin: 2px 4em 1 5pc; + padding: (2px + 4px) 1em 2px 2; +} diff --git a/node_modules/less/test/less/rulesets.less b/node_modules/less/test/less/rulesets.less new file mode 100644 index 0000000..e81192d --- /dev/null +++ b/node_modules/less/test/less/rulesets.less @@ -0,0 +1,30 @@ +#first > .one { + > #second .two > #deux { + width: 50%; + #third { + &:focus { + color: black; + #fifth { + > #sixth { + .seventh #eighth { + + #ninth { + color: purple; + } + } + } + } + } + height: 100%; + } + #fourth, #five, #six { + color: #110000; + .seven, .eight > #nine { + border: 1px solid black; + } + #ten { + color: red; + } + } + } + font-size: 2em; +} diff --git a/node_modules/less/test/less/scope.less b/node_modules/less/test/less/scope.less new file mode 100644 index 0000000..36d3706 --- /dev/null +++ b/node_modules/less/test/less/scope.less @@ -0,0 +1,79 @@ +@x: red; +@x: blue; +@z: transparent; +@mix: none; + +.mixin { + @mix: #989; +} +@mix: blue; +.tiny-scope { + color: @mix; // #989 + .mixin; +} + +.scope1 { + @y: orange; + @z: black; + color: @x; // blue + border-color: @z; // black + .hidden { + @x: #131313; + } + .scope2 { + @y: red; + color: @x; // blue + .scope3 { + @local: white; + color: @y; // red + border-color: @z; // black + background-color: @local; // white + } + } +} + +#namespace { + .scoped_mixin() { + @local-will-be-made-global: green; + .scope { + scoped-val: @local-will-be-made-global; + } + } +} + +#namespace > .scoped_mixin(); + +.setHeight(@h) { @height: 1024px; } +.useHeightInMixinCall(@h) { .useHeightInMixinCall { mixin-height: @h; } } +@mainHeight: 50%; +.setHeight(@mainHeight); +.heightIsSet { height: @height; } +.useHeightInMixinCall(@height); + +.importRuleset() { + .imported { + exists: true; + } +} +.importRuleset(); +.testImported { + .imported; +} + +@parameterDefault: 'top level'; +@anotherVariable: 'top level'; +//mixin uses top-level variables +.mixinNoParam(@parameter: @parameterDefault) when (@parameter = 'top level') { + default: @parameter; + scope: @anotherVariable; + sub-scope-only: @subScopeOnly; +} + +#allAreUsedHere { + //redefine top-level variables in different scope + @parameterDefault: 'inside'; + @anotherVariable: 'inside'; + @subScopeOnly: 'inside'; + //use the mixin + .mixinNoParam(); +} \ No newline at end of file diff --git a/node_modules/less/test/less/selectors.less b/node_modules/less/test/less/selectors.less new file mode 100644 index 0000000..f92fd81 --- /dev/null +++ b/node_modules/less/test/less/selectors.less @@ -0,0 +1,143 @@ +h1, h2, h3 { + a, p { + &:hover { + color: red; + } + } +} + +#all { color: blue; } +#the { color: blue; } +#same { color: blue; } + +ul, li, div, q, blockquote, textarea { + margin: 0; +} + +td { + margin: 0; + padding: 0; +} + +td, input { + line-height: 1em; +} + +a { + color: red; + + &:hover { color: blue; } + + div & { color: green; } + + p & span { color: yellow; } +} + +.foo { + .bar, .baz { + & .qux { + display: block; + } + .qux & { + display: inline; + } + .qux& { + display: inline-block; + } + .qux & .biz { + display: none; + } + } +} + +.b { + &.c { + .a& { + color: red; + } + } +} + +.b { + .c & { + &.a { + color: red; + } + } +} + +.p { + .foo &.bar { + color: red; + } +} + +.p { + .foo&.bar { + color: red; + } +} + +.foo { + .foo + & { + background: amber; + } + & + & { + background: amber; + } +} + +.foo, .bar { + & + & { + background: amber; + } +} + +.foo, .bar { + a, b { + & > & { + background: amber; + } + } +} + +.other ::fnord { color: red } +.other::fnord { color: red } +.other { + ::bnord {color: red } + &::bnord {color: red } +} +// selector interpolation +@theme: blood; +@selector: ~".@{theme}"; +@{selector} { + color:red; +} +@{selector}red { + color: green; +} +.red { + #@{theme}.@{theme}&.black { + color:black; + } +} +@num: 3; +:nth-child(@{num}) { + selector: interpolated; +} +.test { + &:nth-child(odd):not(:nth-child(3)) { + color: #ff0000; + } +} +[prop], +[prop="value@{num}"], +[prop*="val@{num}"], +[|prop~="val@{num}"], +[*|prop$="val@{num}"], +[ns|prop^="val@{num}"], +[@{num}^="val@{num}"], +[@{num}=@{num}], +[@{num}] { + attributes: yes; +} \ No newline at end of file diff --git a/node_modules/less/test/less/static-urls/urls.less b/node_modules/less/test/less/static-urls/urls.less new file mode 100644 index 0000000..b0c7de0 --- /dev/null +++ b/node_modules/less/test/less/static-urls/urls.less @@ -0,0 +1,33 @@ +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} + +@import "../import/import-and-relative-paths-test"; diff --git a/node_modules/less/test/less/strings.less b/node_modules/less/test/less/strings.less new file mode 100644 index 0000000..32fad72 --- /dev/null +++ b/node_modules/less/test/less/strings.less @@ -0,0 +1,51 @@ +#strings { + background-image: url("http://son-of-a-banana.com"); + quotes: "~" "~"; + content: "#*%:&^,)!.(~*})"; + empty: ""; + brackets: "{" "}"; + escapes: "\"hello\" \\world"; + escapes2: "\"llo"; +} +#comments { + content: "/* hello */ // not-so-secret"; +} +#single-quote { + quotes: "'" "'"; + content: '""#!&""'; + empty: ''; + semi-colon: ';'; +} +#escaped { + filter: ~"DX.Transform.MS.BS.filter(opacity=50)"; +} +#one-line { image: url(http://tooks.com) } +#crazy { image: url(http://), "}", url("http://}") } +#interpolation { + @var: '/dev'; + url: "http://lesscss.org@{var}/image.jpg"; + + @var2: 256; + url2: "http://lesscss.org/image-@{var2}.jpg"; + + @var3: #456; + url3: "http://lesscss.org@{var3}"; + + @var4: hello; + url4: "http://lesscss.org/@{var4}"; + + @var5: 54.4px; + url5: "http://lesscss.org/@{var5}"; +} + +// multiple calls with string interpolation + +.mix-mul (@a: green) { + color: ~"@{a}"; +} +.mix-mul-class { + .mix-mul(blue); + .mix-mul(red); + .mix-mul(black); + .mix-mul(orange); +} diff --git a/node_modules/less/test/less/urls.less b/node_modules/less/test/less/urls.less new file mode 100644 index 0000000..82f2df0 --- /dev/null +++ b/node_modules/less/test/less/urls.less @@ -0,0 +1,57 @@ +@font-face { + src: url("/fonts/garamond-pro.ttf"); + src: local(Futura-Medium), + url(fonts.svg#MyGeometricModern) format("svg"); +} +#shorthands { + background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; + background: url("img.jpg") center / 100px; + background: #fff url(image.png) center / 1px 100px repeat-x scroll content-box padding-box; +} +#misc { + background-image: url(images/image.jpg); +} +#data-uri { + background: url(data:image/png;charset=utf-8;base64, + kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ + k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U + kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); + background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); + background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700); +} + +#svg-data-uri { + background: transparent url('data:image/svg+xml, '); +} + +.comma-delimited { + background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); +} +.values { + @a: 'Trebuchet'; + url: url(@a); +} + +@import "import/import-and-relative-paths-test"; + +#data-uri { + uri: data-uri('image/jpeg;base64', '../data/image.jpg'); +} + +#data-uri-guess { + uri: data-uri('../data/image.jpg'); +} + +#data-uri-ascii { + uri-1: data-uri('text/html', '../data/page.html'); + uri-2: data-uri('../data/page.html'); +} + +#data-uri-toobig { + uri: data-uri('../data/data-uri-fail.png'); +} +.add_an_import(@file_to_import) { +@import "@{file_to_import}"; +} + +.add_an_import("file.css"); diff --git a/node_modules/less/test/less/variables.less b/node_modules/less/test/less/variables.less new file mode 100644 index 0000000..e896f40 --- /dev/null +++ b/node_modules/less/test/less/variables.less @@ -0,0 +1,83 @@ +@a: 2; +@x: (@a * @a); +@y: (@x + 1); +@z: (@x * 2 + @y); +@var: -1; + +.variables { + width: (@z + 1cm); // 14cm +} + +@b: @a * 10; +@c: #888; + +@fonts: "Trebuchet MS", Verdana, sans-serif; +@f: @fonts; + +@quotes: "~" "~"; +@q: @quotes; +@onePixel: 1px; + +.variables { + height: (@b + @x + 0px); // 24px + color: @c; + font-family: @f; + quotes: @q; +} + +.redef { + @var: 0; + .inition { + @var: 4; + @var: 2; + three: @var; + @var: 3; + } + zero: @var; +} + +.values { + minus-one: @var; + @a: 'Trebuchet'; + @multi: 'A', B, C; + font-family: @a, @a, @a; + color: @c !important; + multi: something @multi, @a; +} + +.variable-names { + @var: 'hello'; + @name: 'var'; + name: @@name; +} + +.alpha { + @var: 42; + filter: alpha(opacity=@var); +} + +.polluteMixin() { + @a: 'pollution'; +} +.testPollution { + @a: 'no-pollution'; + a: @a; + .polluteMixin(); + a: @a; +} + +.units { + width: @onePixel; + same-unit-as-previously: (@onePixel / @onePixel); + square-pixel-divided: (@onePixel * @onePixel / @onePixel); + odd-unit: unit((@onePixel * 4em / 2cm)); + percentage: (10 * 50%); + pixels: (50px * 10); + conversion-metric-a: (20mm + 1cm); + conversion-metric-b: (1cm + 20mm); + conversion-imperial: (1in + 72pt + 6pc); + custom-unit: (42octocats * 10); + custom-unit-cancelling: (8cats * 9dogs / 4cats); + mix-units: (1px + 1em); + invalid-units: (1px * 1px); +} diff --git a/node_modules/less/test/less/whitespace.less b/node_modules/less/test/less/whitespace.less new file mode 100644 index 0000000..ab4804d --- /dev/null +++ b/node_modules/less/test/less/whitespace.less @@ -0,0 +1,44 @@ + + +.whitespace + { color: white; } + +.whitespace +{ + color: white; +} + .whitespace +{ color: white; } + +.whitespace{color:white;} +.whitespace { color : white ; } + +.white, +.space, +.mania +{ color: white; } + +.no-semi-column { color: white } +.no-semi-column { + color: white; + white-space: pre +} +.no-semi-column {border: 2px solid white} +.newlines { + background: the, + great, + wall; + border: 2px + solid + black; +} +.empty { + +} +.sel +.newline_ws .tab_ws { +color: +white; +background-position: 45 +-23; +} diff --git a/node_modules/log4node/.npmignore b/node_modules/log4node/.npmignore new file mode 100644 index 0000000..2392abe --- /dev/null +++ b/node_modules/log4node/.npmignore @@ -0,0 +1,4 @@ +node_modules +npm-debug.log +test/test.log* +test/process.pid diff --git a/node_modules/log4node/CHANGELOG b/node_modules/log4node/CHANGELOG new file mode 100644 index 0000000..28f39a7 --- /dev/null +++ b/node_modules/log4node/CHANGELOG @@ -0,0 +1,6 @@ +CHANGELOG + +0.1.2 + +* feature : getter on log level, thx to @dax +* feature : specify prefix as function, thx to @dax \ No newline at end of file diff --git a/node_modules/log4node/Readme.markdown b/node_modules/log4node/Readme.markdown new file mode 100644 index 0000000..96a0e74 --- /dev/null +++ b/node_modules/log4node/Readme.markdown @@ -0,0 +1,132 @@ +# Overview + +This module is designed to be used with Node Cluster in production: +* one log file for all workers +* compatible with logrotate: an USR2 signal reopen the log file + +This module is compatible with node 0.8.x. For the node 0.6.x, please use version 0.0.1 of this module. + +This module is inspired from [this module](https://github.com/visionmedia/log.js). + +# How to use it + +## Installation + + npm install log4node + +## Usage + +Default logger: +```js +var log = require('log4node'); + +log.error("this is a log"); +``` +Will output to console. + +Note: you can reconfigure default logger by calling + + log.reconfigure({level: 'info', file: 'toto.log'}); + +Will now write into `toto.log` + +Your custom logger: +```js +var log4node = require('log4node'); + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.error("this is a log"); +log.debug("this is a debug log"); +``` + +Note : you can use the syntax accepted by [`utils.format`](http://nodejs.org/api/util.html#util_util_format_format). + +## Log level + +Log level can be adjusted for each logger: + + log.setLogLevel('info'); + +Log level for default logger is 'info'. + +Available log levels are: + +* emergency +* alert +* critical +* error +* warning +* notice +* info +* debug + +## Prefix + +Prefix of log lines can be changed: + +```js +log.setPrefix("%d - %p "); +``` + +You can use following field in prefix: +* `%d`: current date +* `%p`: current process id +* `%l`: log level + +Default prefix is: `[%d] %l ` + +## Cluster mode + +Workers processes will send logs to the cluster master for writing to file. + +Setup is fully transparent for developper. + +A full example can be found [here](https://github.com/bpaquet/log4node/blob/master/test/cluster/test1.js). + +## Reopen log file + +Just send USR2 signal to node process, or, in cluster mode, to master node process: + + kill -USR2 pid + +Example of logrotate file: + + /var/log/node.log { + rotate 5 + weekly + postrotate + kill -USR2 `cat process.pid` + endscript + } + +## Create a specialized logger +This feature is provided to specialize a logger for a sub-component. +You can create a new logger with its own level and prefix for a sub-component. +The logs will be send to the same files with a prefix. + +```js +log = new log4node.Log4Node('warning', 'test.log'); +sublogger1 = log.clone({prefix:'SUBMODULE - ', level:'error'); +``` + +or with the default logger + +```js +sublogger1 = log4node.clone(prefix:'SUBMODULE - ', level:'error'); +``` + +# License + +Copyright 2012 Bertrand Paquet + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/node_modules/log4node/lib/log4node.js b/node_modules/log4node/lib/log4node.js new file mode 100644 index 0000000..5e8a4d3 --- /dev/null +++ b/node_modules/log4node/lib/log4node.js @@ -0,0 +1,175 @@ +// Copyright 2012 Bertrand Paquet +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var fs = require('fs'), + util = require('util'), + cluster = require('cluster'), + events = require('events'); + +var + loggers = {}, + // levels are accessible through the exports object in uppercase + // eg: exports.EMERGENCY === 0 + // all levels are also available as function helpers + // eg: logger.alert('message') + levels = { + 'emergency': 0, + 'alert': 1, + 'critical': 2, + 'error': 3, + 'warning': 4, + 'notice': 5, + 'info': 6, + 'debug': 7 +} + +var sig_listener = new events.EventEmitter(); +sig_listener.setMaxListeners(0); + +process.on('SIGUSR2', function() { + sig_listener.emit('SIGUSR2'); +}); + +cluster.on('online', function(worker) { + worker.on('message', function(msg) { + if (msg.log && msg.logger_id && loggers[msg.logger_id]) { + loggers[msg.logger_id].write(msg.log); + } + }) +}); + +function computePrefix(prefix, level) { + if (typeof prefix === 'function') { + return prefix(level); + } + else { + return prefix + .replace(/%d/, new Date().toUTCString()) + .replace(/%l/, level.toUpperCase()) + .replace(/%p/, process.pid); + } +} + +function Log4Node(config) { + config = config || {}; + if (config.parent) { + this.parent = config.parent; + this.setLogLevel(config.level || this.parent.level); + var child_prefix = config.prefix || ''; + this.prefix = function(level) { + return computePrefix(this.parent.prefix, level) + computePrefix(child_prefix, level); + }.bind(this); + this.id = this.parent.id; + } + else { + this.setLogLevel(config.level); + this.prefix = config.prefix || "[%d] %l "; + this.id = config.file || 'stdout'; + loggers[this.id] = this; + if (cluster.isMaster) { + if (config.file === undefined) { + this.stream = process.stdout; + } + else { + this.file = config.file; + this.reopen(); + sig_listener.on('SIGUSR2', function() { + this.reopen(); + }.bind(this)); + this.stream.on('error', function(err) { + console.warn('Unable to write into file : ' + this.file + ' ' + err); + }.bind(this)); + } + } + } +} + +Log4Node.prototype.clone = function(config) { + config = config || {}; + config.parent = this; + return new Log4Node(config); +} + +Log4Node.prototype.reopen = function() { + if (this.stream) { + this.stream.end(); + } + this.stream = fs.createWriteStream(this.file, {flags: 'a', encoding: 'utf-8'}); +} + +Log4Node.prototype.setPrefix = function(prefix) { + this.prefix = prefix; +} + +Log4Node.prototype.setLogLevel = function(level) { + if (typeof level === 'string') level = levels[level]; + this.level = level === undefined ? levels.info : level; +} + +Log4Node.prototype.getLogLevel = function(level) { + return this.level; +} + +Log4Node.prototype.write = function(msg) { + if (this.parent) { + this.parent.write(msg); + } + else { + this.stream.write(msg + '\n'); + } +} + +Log4Node.prototype.log = function(level, args) { + if (levels[level] <= this.level) { + var i = 1; + var msg = computePrefix(this.prefix, level); + msg += util.format.apply(this, args); + if (cluster.isMaster) { + this.write(msg); + } + else { + // do no try to send a message to master if disconnected + // because in this case node will emit an error event + if (process.connected) { + process.send({log: msg, logger_id: this.id}); + } + } + } +} + +// exports +exports.Log4Node = Log4Node; + +Object.keys(levels).forEach(function(level) { + // Log4Node.INFO|DEBUG.. + exports[level.toUpperCase()] = levels[level]; + + // Log4Node.prototype.info|debug.. + Log4Node.prototype[level] = function() { + this.log(level, arguments); + } +}); + +// set easy defaultLogger +// allows require('Log4Node').info('')|debug('').. +var defaultLogger = new Log4Node(); + +Object.keys(Log4Node.prototype).forEach(function(method) { + exports[method] = function() { + return defaultLogger[method].apply(defaultLogger, arguments); + } +}); + +exports.reconfigure = function(config) { + return defaultLogger = new Log4Node(config); +} diff --git a/node_modules/log4node/license.txt b/node_modules/log4node/license.txt new file mode 100644 index 0000000..12605f3 --- /dev/null +++ b/node_modules/log4node/license.txt @@ -0,0 +1,13 @@ +Copyright 2012 Bertrand Paquet + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/node_modules/log4node/package.json b/node_modules/log4node/package.json new file mode 100644 index 0000000..547f0f8 --- /dev/null +++ b/node_modules/log4node/package.json @@ -0,0 +1,45 @@ +{ + "name": "log4node", + "description": "Logger for node cluster, compatible with logrotate", + "version": "0.1.2", + "author": { + "name": "Bertrand Paquet", + "email": "bertrand.paquet@gmail.com" + }, + "keywords": [ + "log", + "logger", + "cluster", + "logrotate" + ], + "main": "./lib/log4node.js", + "homepage": "https://github.com/bpaquet/log4node", + "repository": { + "type": "git", + "url": "git://github.com/bpaquet/log4node.git" + }, + "licenses": [ + { + "type": "Apache2", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], + "devDependencies": { + "vows": "0.6.x", + "whereis": "0.0.2" + }, + "scripts": { + "test": "./test-runner.sh" + }, + "engines": { + "node": ">= 0.6.0" + }, + "readme": "# Overview\n\nThis module is designed to be used with Node Cluster in production:\n* one log file for all workers\n* compatible with logrotate: an USR2 signal reopen the log file\n\nThis module is compatible with node 0.8.x. For the node 0.6.x, please use version 0.0.1 of this module.\n\nThis module is inspired from [this module](https://github.com/visionmedia/log.js).\n\n# How to use it\n\n## Installation\n\n npm install log4node\n\n## Usage\n\nDefault logger:\n```js\nvar log = require('log4node');\n\nlog.error(\"this is a log\");\n```\nWill output to console.\n\nNote: you can reconfigure default logger by calling\n\n log.reconfigure({level: 'info', file: 'toto.log'});\n\nWill now write into `toto.log`\n\nYour custom logger:\n```js\nvar log4node = require('log4node');\n log = new log4node.Log4Node({level: 'warning', file: 'test.log'});\n\nlog.error(\"this is a log\");\nlog.debug(\"this is a debug log\");\n```\n\nNote : you can use the syntax accepted by [`utils.format`](http://nodejs.org/api/util.html#util_util_format_format).\n\n## Log level\n\nLog level can be adjusted for each logger:\n\n log.setLogLevel('info');\n\nLog level for default logger is 'info'.\n\nAvailable log levels are:\n\n* emergency\n* alert\n* critical\n* error\n* warning\n* notice\n* info\n* debug\n\n## Prefix\n\nPrefix of log lines can be changed:\n\n```js\nlog.setPrefix(\"%d - %p \");\n```\n\nYou can use following field in prefix:\n* `%d`: current date\n* `%p`: current process id\n* `%l`: log level\n\nDefault prefix is: `[%d] %l `\n\n## Cluster mode\n\nWorkers processes will send logs to the cluster master for writing to file.\n\nSetup is fully transparent for developper.\n\nA full example can be found [here](https://github.com/bpaquet/log4node/blob/master/test/cluster/test1.js).\n\n## Reopen log file\n\nJust send USR2 signal to node process, or, in cluster mode, to master node process:\n\n kill -USR2 pid\n\nExample of logrotate file:\n\n /var/log/node.log {\n rotate 5\n weekly\n postrotate\n kill -USR2 `cat process.pid`\n endscript\n }\n\n## Create a specialized logger\nThis feature is provided to specialize a logger for a sub-component.\nYou can create a new logger with its own level and prefix for a sub-component.\nThe logs will be send to the same files with a prefix.\n\n```js\nlog = new log4node.Log4Node('warning', 'test.log');\nsublogger1 = log.clone({prefix:'SUBMODULE - ', level:'error');\n```\n\nor with the default logger\n\n```js\nsublogger1 = log4node.clone(prefix:'SUBMODULE - ', level:'error');\n```\n\n# License\n\nCopyright 2012 Bertrand Paquet\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", + "readmeFilename": "Readme.markdown", + "_id": "log4node@0.1.2", + "dist": { + "shasum": "5648004b539af4738cd96c868eaa1f127d874819" + }, + "_from": "log4node@", + "_resolved": "https://registry.npmjs.org/log4node/-/log4node-0.1.2.tgz" +} diff --git a/node_modules/log4node/test-runner.sh b/node_modules/log4node/test-runner.sh new file mode 100755 index 0000000..448e133 --- /dev/null +++ b/node_modules/log4node/test-runner.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +cd test + +if [ "$TEST" = "" ]; then + TEST=`ls test*.js` +fi + +for test in $TEST; do + echo "Launching test : $test" + NODE_PATH=../lib vows $test --spec + echo "" +done diff --git a/node_modules/log4node/test/cluster-logger-after-fork/output1 b/node_modules/log4node/test/cluster-logger-after-fork/output1 new file mode 100644 index 0000000..443fa47 --- /dev/null +++ b/node_modules/log4node/test/cluster-logger-after-fork/output1 @@ -0,0 +1,4 @@ +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker diff --git a/node_modules/log4node/test/cluster-logger-after-fork/test1.js b/node_modules/log4node/test/cluster-logger-after-fork/test1.js new file mode 100644 index 0000000..9a23c91 --- /dev/null +++ b/node_modules/log4node/test/cluster-logger-after-fork/test1.js @@ -0,0 +1,16 @@ +var cluster = require('cluster'), + log4node = require('log4node'); + +if (cluster.isMaster) { + for (var i = 0; i < 4; i++) { + cluster.fork(); + } + var log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); +} else { + var log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + log.setPrefix("%l %p : "); + log.error("Hello, I'm a worker"); + setTimeout(function() { + process.exit(); + }, 100); +} diff --git a/node_modules/log4node/test/cluster-logrotate/logrotate.conf b/node_modules/log4node/test/cluster-logrotate/logrotate.conf new file mode 100644 index 0000000..79dc0ea --- /dev/null +++ b/node_modules/log4node/test/cluster-logrotate/logrotate.conf @@ -0,0 +1,7 @@ +"test.log" { + rotate 5 + weekly + postrotate + kill -USR2 `cat process.pid` + endscript +} diff --git a/node_modules/log4node/test/cluster-logrotate/output1 b/node_modules/log4node/test/cluster-logrotate/output1 new file mode 100644 index 0000000..5deb79c --- /dev/null +++ b/node_modules/log4node/test/cluster-logrotate/output1 @@ -0,0 +1,5 @@ +ERROR \d+ : Master started +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker diff --git a/node_modules/log4node/test/cluster-logrotate/output2 b/node_modules/log4node/test/cluster-logrotate/output2 new file mode 100644 index 0000000..0f189b6 --- /dev/null +++ b/node_modules/log4node/test/cluster-logrotate/output2 @@ -0,0 +1,4 @@ +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died diff --git a/node_modules/log4node/test/cluster-logrotate/test1.js b/node_modules/log4node/test/cluster-logrotate/test1.js new file mode 100644 index 0000000..add2947 --- /dev/null +++ b/node_modules/log4node/test/cluster-logrotate/test1.js @@ -0,0 +1,22 @@ +var cluster = require('cluster'), + log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("%l %p : "); + +if (cluster.isMaster) { + for (var i = 0; i < 4; i++) { + cluster.fork(); + } + + log.error("Master started"); + + cluster.on('exit', function(worker) { + log.error('Worker ' + worker.process.pid + ' died'); + }); +} else { + log.error("Hello, I'm a worker"); + setTimeout(function() { + process.exit(); + }, 2000); +} diff --git a/node_modules/log4node/test/cluster-stdout-sig/output1 b/node_modules/log4node/test/cluster-stdout-sig/output1 new file mode 100644 index 0000000..1f11478 --- /dev/null +++ b/node_modules/log4node/test/cluster-stdout-sig/output1 @@ -0,0 +1,9 @@ +ERROR \d+ : Master started +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died diff --git a/node_modules/log4node/test/cluster-stdout-sig/test1.js b/node_modules/log4node/test/cluster-stdout-sig/test1.js new file mode 100644 index 0000000..23eee2a --- /dev/null +++ b/node_modules/log4node/test/cluster-stdout-sig/test1.js @@ -0,0 +1,22 @@ +var cluster = require('cluster'), + log = require('log4node'); + +log.setPrefix("%l %p : "); + +if (cluster.isMaster) { + for (var i = 0; i < 4; i++) { + cluster.fork(); + } + + log.error("Master started"); + + cluster.on('exit', function(worker) { + log.error('Worker ' + worker.process.pid + ' died'); + }); + +} else { + log.error("Hello, I'm a worker"); + setTimeout(function() { + process.exit(); + }, 100); +} diff --git a/node_modules/log4node/test/cluster-sub-logger-logrotate/logrotate.conf b/node_modules/log4node/test/cluster-sub-logger-logrotate/logrotate.conf new file mode 100644 index 0000000..79dc0ea --- /dev/null +++ b/node_modules/log4node/test/cluster-sub-logger-logrotate/logrotate.conf @@ -0,0 +1,7 @@ +"test.log" { + rotate 5 + weekly + postrotate + kill -USR2 `cat process.pid` + endscript +} diff --git a/node_modules/log4node/test/cluster-sub-logger-logrotate/output1 b/node_modules/log4node/test/cluster-sub-logger-logrotate/output1 new file mode 100644 index 0000000..5deb79c --- /dev/null +++ b/node_modules/log4node/test/cluster-sub-logger-logrotate/output1 @@ -0,0 +1,5 @@ +ERROR \d+ : Master started +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker diff --git a/node_modules/log4node/test/cluster-sub-logger-logrotate/output2 b/node_modules/log4node/test/cluster-sub-logger-logrotate/output2 new file mode 100644 index 0000000..0f189b6 --- /dev/null +++ b/node_modules/log4node/test/cluster-sub-logger-logrotate/output2 @@ -0,0 +1,4 @@ +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died diff --git a/node_modules/log4node/test/cluster-sub-logger-logrotate/test1.js b/node_modules/log4node/test/cluster-sub-logger-logrotate/test1.js new file mode 100644 index 0000000..0211ab9 --- /dev/null +++ b/node_modules/log4node/test/cluster-sub-logger-logrotate/test1.js @@ -0,0 +1,24 @@ +var cluster = require('cluster'), + log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("%l %p : "); + +var sublog = log.clone(); + +if (cluster.isMaster) { + for (var i = 0; i < 4; i++) { + cluster.fork(); + } + + sublog.error("Master started"); + + cluster.on('exit', function(worker) { + sublog.error('Worker ' + worker.process.pid + ' died'); + }); +} else { + sublog.error("Hello, I'm a worker"); + setTimeout(function() { + process.exit(); + }, 2000); +} diff --git a/node_modules/log4node/test/cluster-sub-logger/output1 b/node_modules/log4node/test/cluster-sub-logger/output1 new file mode 100644 index 0000000..441c7db --- /dev/null +++ b/node_modules/log4node/test/cluster-sub-logger/output1 @@ -0,0 +1,9 @@ +ERROR \d+ : Master started +ERROR \d+ : WORKER - Hello, I'm a worker +ERROR \d+ : WORKER - Hello, I'm a worker +ERROR \d+ : WORKER - Hello, I'm a worker +ERROR \d+ : WORKER - Hello, I'm a worker +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died diff --git a/node_modules/log4node/test/cluster-sub-logger/test1.js b/node_modules/log4node/test/cluster-sub-logger/test1.js new file mode 100644 index 0000000..ddcc2e5 --- /dev/null +++ b/node_modules/log4node/test/cluster-sub-logger/test1.js @@ -0,0 +1,25 @@ +var cluster = require('cluster'), + log4node = require('log4node'), + log = new log4node.Log4Node({prefix:'warning', file:'test.log'}); + +log.setPrefix("%l %p : "); + +if (cluster.isMaster) { + for (var i = 0; i < 4; i++) { + cluster.fork(); + } + + log.error("Master started"); + + cluster.on('exit', function(worker) { + log.error('Worker ' + worker.process.pid + ' died'); + }); + +} else { + var workerLog = log.clone({prefix: "WORKER - "}); + + workerLog.error("Hello, I'm a worker"); + setTimeout(function() { + process.exit(); + }, 100); +} diff --git a/node_modules/log4node/test/cluster/output1 b/node_modules/log4node/test/cluster/output1 new file mode 100644 index 0000000..1f11478 --- /dev/null +++ b/node_modules/log4node/test/cluster/output1 @@ -0,0 +1,9 @@ +ERROR \d+ : Master started +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Hello, I'm a worker +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died +ERROR \d+ : Worker \d+ died diff --git a/node_modules/log4node/test/cluster/test1.js b/node_modules/log4node/test/cluster/test1.js new file mode 100644 index 0000000..0dfb3c2 --- /dev/null +++ b/node_modules/log4node/test/cluster/test1.js @@ -0,0 +1,23 @@ +var cluster = require('cluster'), + log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("%l %p : "); + +if (cluster.isMaster) { + for (var i = 0; i < 4; i++) { + cluster.fork(); + } + + log.error("Master started"); + + cluster.on('exit', function(worker) { + log.error('Worker ' + worker.process.pid + ' died'); + }); + +} else { + log.error("Hello, I'm a worker"); + setTimeout(function() { + process.exit(); + }, 100); +} diff --git a/node_modules/log4node/test/helper.js b/node_modules/log4node/test/helper.js new file mode 100644 index 0000000..36ef5b6 --- /dev/null +++ b/node_modules/log4node/test/helper.js @@ -0,0 +1,123 @@ +var fs = require('fs'), + vows = require('vows'), + assert = require('assert'), + spawn = require('child_process').spawn, + whereis = require('whereis'); + +function launch(command, args, pid_file, callback) { + var child = spawn(command, args); + var stdout = ''; + + if (pid_file) { + fs.writeFile(pid_file, child.pid, function(err) { + if (err) { + return console.warn(err); + } + }); + } + + child.stdout.on('data', function (data) { + console.log('child stdout [' + command + ']: ' + data); + stdout += data; + }); + + child.stderr.on('data', function (data) { + console.log('child stderr [' + command + ']: ' + data); + }); + + child.on('exit', function(code) { + callback(code, stdout) + }); +}; + +function remove_test_files() { + fs.readdirSync('.').forEach(function(i) { + if (i.match(/^test.log.*$/) || i.match(/^process.*/)) { + fs.unlinkSync(i); + } + }); + if (fs.existsSync('/tmp/s')) { + fs.unlinkSync('/tmp/s'); + } +} + +function check_content(content, file) { + regexp = fs.readFileSync(file, 'utf-8'); + if (!content.match(new RegExp("^" + regexp + "$"))) { + console.log("Content"); + console.log(content); + console.log("Regexp"); + console.log(regexp); + assert.fail("File not match"); + } +} + +function check_file(file, target_file) { + target_file = target_file || 'test.log'; + content = fs.readFileSync(target_file, 'utf-8'); + check_content(content, file); +} + +function check_file_content(file, expected_content) { + content = fs.readFileSync(file, 'utf-8'); + assert.equal(content, expected_content); +} + +function create_test(name, file_to_launch, final_file, topic_callback, check_callback, test_callback) { + test_name = file_to_launch.match(/\/([^\/]+)\.js$/)[1] + test = {} + test[test_name] = { + topic: function () { + remove_test_files(); + test_callback = test_callback || function(f, callback) { + launch('node', [f], 'process.pid', function(code, stdout) { + callback(null, code, stdout); + }); + if (topic_callback) { + topic_callback(); + } + }; + test_callback(file_to_launch, this.callback); + }, + + 'check_code': function(code) { + assert.equal(code, 0); + }, + + 'check content': function () { + if (final_file) { + check_file(final_file); + } + }, + + } + if (check_callback) { + test[test_name]['specific_check'] = function(err, code, stdout) { + check_callback(stdout); + } + } + test[test_name]['remove test files'] = function() { + remove_test_files(); + } + return vows.describe(name).addBatch(test); +} + +function logrotate(callback) { + whereis('logrotate', function(err, res) { + if(err) { + console.log("You must have logrotate in your path to run all tests."); + return process.exit(1); + } + callback(res); + }); +} + +module.exports = { + launch: launch, + remove_test_files: remove_test_files, + check_file: check_file, + check_content: check_content, + check_file_content: check_file_content, + create_test: create_test, + logrotate: logrotate, +}; \ No newline at end of file diff --git a/node_modules/log4node/test/multiple-appender/logrotate.conf b/node_modules/log4node/test/multiple-appender/logrotate.conf new file mode 100644 index 0000000..2fb8d32 --- /dev/null +++ b/node_modules/log4node/test/multiple-appender/logrotate.conf @@ -0,0 +1,7 @@ +"test.log" { + rotate 5 + weekly + postrotate + kill -USR2 `cat process1.pid` && kill -USR2 `cat process2.pid` + endscript +} diff --git a/node_modules/log4node/test/multiple-appender/output1 b/node_modules/log4node/test/multiple-appender/output1 new file mode 100644 index 0000000..dbf1f7a --- /dev/null +++ b/node_modules/log4node/test/multiple-appender/output1 @@ -0,0 +1,2 @@ +p1 titi1 +p2 titi1 diff --git a/node_modules/log4node/test/multiple-appender/output2 b/node_modules/log4node/test/multiple-appender/output2 new file mode 100644 index 0000000..2f095c4 --- /dev/null +++ b/node_modules/log4node/test/multiple-appender/output2 @@ -0,0 +1,2 @@ +p1 titi2 +p2 titi2 diff --git a/node_modules/log4node/test/multiple-appender/test1.js b/node_modules/log4node/test/multiple-appender/test1.js new file mode 100644 index 0000000..7d00cc7 --- /dev/null +++ b/node_modules/log4node/test/multiple-appender/test1.js @@ -0,0 +1,10 @@ +var log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix(process.argv[2] + " "); + +log.warning("titi1"); + +setTimeout(function() { + log.warning("titi2") +}, 500); diff --git a/node_modules/log4node/test/no-cluster-append/output1 b/node_modules/log4node/test/no-cluster-append/output1 new file mode 100644 index 0000000..be9973f --- /dev/null +++ b/node_modules/log4node/test/no-cluster-append/output1 @@ -0,0 +1 @@ +WARNING - titi1 diff --git a/node_modules/log4node/test/no-cluster-append/output2 b/node_modules/log4node/test/no-cluster-append/output2 new file mode 100644 index 0000000..79512e5 --- /dev/null +++ b/node_modules/log4node/test/no-cluster-append/output2 @@ -0,0 +1,2 @@ +WARNING - titi1 +WARNING - titi1 diff --git a/node_modules/log4node/test/no-cluster-append/test1.js b/node_modules/log4node/test/no-cluster-append/test1.js new file mode 100644 index 0000000..508958f --- /dev/null +++ b/node_modules/log4node/test/no-cluster-append/test1.js @@ -0,0 +1,7 @@ +var log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("%l - "); + +log.warning("titi1"); + diff --git a/node_modules/log4node/test/no-cluster-logrotate/logrotate.conf b/node_modules/log4node/test/no-cluster-logrotate/logrotate.conf new file mode 100644 index 0000000..79dc0ea --- /dev/null +++ b/node_modules/log4node/test/no-cluster-logrotate/logrotate.conf @@ -0,0 +1,7 @@ +"test.log" { + rotate 5 + weekly + postrotate + kill -USR2 `cat process.pid` + endscript +} diff --git a/node_modules/log4node/test/no-cluster-logrotate/output1 b/node_modules/log4node/test/no-cluster-logrotate/output1 new file mode 100644 index 0000000..2e2301c --- /dev/null +++ b/node_modules/log4node/test/no-cluster-logrotate/output1 @@ -0,0 +1 @@ +\[WARNING - toto\] titi1 diff --git a/node_modules/log4node/test/no-cluster-logrotate/output2 b/node_modules/log4node/test/no-cluster-logrotate/output2 new file mode 100644 index 0000000..d06e772 --- /dev/null +++ b/node_modules/log4node/test/no-cluster-logrotate/output2 @@ -0,0 +1 @@ +\[ERROR - toto\] titi2 diff --git a/node_modules/log4node/test/no-cluster-logrotate/test1.js b/node_modules/log4node/test/no-cluster-logrotate/test1.js new file mode 100644 index 0000000..dff0810 --- /dev/null +++ b/node_modules/log4node/test/no-cluster-logrotate/test1.js @@ -0,0 +1,12 @@ +var log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("[%l - toto] "); + +log.warning("titi1"); + +setTimeout(function() { + log.error("titi2") +}, 2000); + + diff --git a/node_modules/log4node/test/no-cluster-sig/output1 b/node_modules/log4node/test/no-cluster-sig/output1 new file mode 100644 index 0000000..2e2301c --- /dev/null +++ b/node_modules/log4node/test/no-cluster-sig/output1 @@ -0,0 +1 @@ +\[WARNING - toto\] titi1 diff --git a/node_modules/log4node/test/no-cluster-sig/output2 b/node_modules/log4node/test/no-cluster-sig/output2 new file mode 100644 index 0000000..23b74ef --- /dev/null +++ b/node_modules/log4node/test/no-cluster-sig/output2 @@ -0,0 +1,2 @@ +\[WARNING - toto\] titi1 +\[ERROR - toto\] titi2 diff --git a/node_modules/log4node/test/no-cluster-sig/test1.js b/node_modules/log4node/test/no-cluster-sig/test1.js new file mode 100644 index 0000000..dff0810 --- /dev/null +++ b/node_modules/log4node/test/no-cluster-sig/test1.js @@ -0,0 +1,12 @@ +var log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("[%l - toto] "); + +log.warning("titi1"); + +setTimeout(function() { + log.error("titi2") +}, 2000); + + diff --git a/node_modules/log4node/test/no-cluster-stdout-sig/output1 b/node_modules/log4node/test/no-cluster-stdout-sig/output1 new file mode 100644 index 0000000..23b74ef --- /dev/null +++ b/node_modules/log4node/test/no-cluster-stdout-sig/output1 @@ -0,0 +1,2 @@ +\[WARNING - toto\] titi1 +\[ERROR - toto\] titi2 diff --git a/node_modules/log4node/test/no-cluster-stdout-sig/test1.js b/node_modules/log4node/test/no-cluster-stdout-sig/test1.js new file mode 100644 index 0000000..0498372 --- /dev/null +++ b/node_modules/log4node/test/no-cluster-stdout-sig/test1.js @@ -0,0 +1,11 @@ +var log4node = require('log4node'); + +log4node.setPrefix("[%l - toto] "); + +log4node.warning("titi1"); + +setTimeout(function() { + log4node.error("titi2") +}, 2000); + + diff --git a/node_modules/log4node/test/no-cluster/output1 b/node_modules/log4node/test/no-cluster/output1 new file mode 100644 index 0000000..d09197f --- /dev/null +++ b/node_modules/log4node/test/no-cluster/output1 @@ -0,0 +1,2 @@ +\[WARNING - toto\] titi1 +\[WARNING - toto\] titi3 diff --git a/node_modules/log4node/test/no-cluster/output2 b/node_modules/log4node/test/no-cluster/output2 new file mode 100644 index 0000000..7167cd7 --- /dev/null +++ b/node_modules/log4node/test/no-cluster/output2 @@ -0,0 +1,3 @@ +\[WARNING - toto\] titi1 +\[WARNING - toto\] titi3 +\[ERROR - toto\] titi2 diff --git a/node_modules/log4node/test/no-cluster/test1.js b/node_modules/log4node/test/no-cluster/test1.js new file mode 100644 index 0000000..f3ea65c --- /dev/null +++ b/node_modules/log4node/test/no-cluster/test1.js @@ -0,0 +1,13 @@ +var log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("[%l - toto] "); + +log.warning("titi1"); + +setTimeout(function() { + log.error("titi2") +}, 500); + +log.warning("titi3"); + diff --git a/node_modules/log4node/test/sub-logger-default/output1 b/node_modules/log4node/test/sub-logger-default/output1 new file mode 100644 index 0000000..556b384 --- /dev/null +++ b/node_modules/log4node/test/sub-logger-default/output1 @@ -0,0 +1,2 @@ +WARNING \d+ : SUB1 - titi1 +WARNING \d+ : SUB1 - titi4 diff --git a/node_modules/log4node/test/sub-logger-default/output2 b/node_modules/log4node/test/sub-logger-default/output2 new file mode 100644 index 0000000..bd25765 --- /dev/null +++ b/node_modules/log4node/test/sub-logger-default/output2 @@ -0,0 +1,3 @@ +WARNING \d+ : SUB1 - titi1 +WARNING \d+ : SUB1 - titi4 +CRITICAL \d+ : SUB2 - titi2 diff --git a/node_modules/log4node/test/sub-logger-default/test1.js b/node_modules/log4node/test/sub-logger-default/test1.js new file mode 100644 index 0000000..9d1dc5f --- /dev/null +++ b/node_modules/log4node/test/sub-logger-default/test1.js @@ -0,0 +1,15 @@ +var log = require('log4node'); + +log.reconfigure({level: 'warning', file: 'test.log', prefix: "%l %p : "}); + +var sublogger1 = log.clone({prefix: "SUB1 - "}); +var sublogger2 = log.clone({prefix: "SUB2 - ", level: 'error'}); + +sublogger1.warning("titi1"); + +setTimeout(function() { + sublogger2.critical("titi2"); + sublogger2.warning("titi3"); +}, 500); + +sublogger1.warning("titi4"); diff --git a/node_modules/log4node/test/sub-logger/output1 b/node_modules/log4node/test/sub-logger/output1 new file mode 100644 index 0000000..556b384 --- /dev/null +++ b/node_modules/log4node/test/sub-logger/output1 @@ -0,0 +1,2 @@ +WARNING \d+ : SUB1 - titi1 +WARNING \d+ : SUB1 - titi4 diff --git a/node_modules/log4node/test/sub-logger/output2 b/node_modules/log4node/test/sub-logger/output2 new file mode 100644 index 0000000..bd25765 --- /dev/null +++ b/node_modules/log4node/test/sub-logger/output2 @@ -0,0 +1,3 @@ +WARNING \d+ : SUB1 - titi1 +WARNING \d+ : SUB1 - titi4 +CRITICAL \d+ : SUB2 - titi2 diff --git a/node_modules/log4node/test/sub-logger/test1.js b/node_modules/log4node/test/sub-logger/test1.js new file mode 100644 index 0000000..97f8276 --- /dev/null +++ b/node_modules/log4node/test/sub-logger/test1.js @@ -0,0 +1,16 @@ +var log4node = require('log4node'), + log = new log4node.Log4Node({level: 'warning', file: 'test.log'}); + +log.setPrefix("%l %p : "); + +var sublogger1 = log.clone({prefix: "SUB1 - "}); +var sublogger2 = log.clone({prefix: "SUB2 - ", level: 'error'}); + +sublogger1.warning("titi1"); + +setTimeout(function() { + sublogger2.critical("titi2"); + sublogger2.warning("titi3"); +}, 500); + +sublogger1.warning("titi4"); diff --git a/node_modules/log4node/test/test-cluster-logger-after-fork.js b/node_modules/log4node/test/test-cluster-logger-after-fork.js new file mode 100644 index 0000000..778f67d --- /dev/null +++ b/node_modules/log4node/test/test-cluster-logger-after-fork.js @@ -0,0 +1,3 @@ +var helper = require('./helper.js'); + +helper.create_test('cluster-logger-after-fork', 'cluster-logger-after-fork/test1.js', 'cluster-logger-after-fork/output1').export(module); diff --git a/node_modules/log4node/test/test-cluster-logrotate.js b/node_modules/log4node/test/test-cluster-logrotate.js new file mode 100644 index 0000000..011c45d --- /dev/null +++ b/node_modules/log4node/test/test-cluster-logrotate.js @@ -0,0 +1,12 @@ +var helper = require('./helper.js'); + +helper.create_test('cluster-logrotate', 'cluster-logrotate/test1.js', 'cluster-logrotate/output2', function() { + helper.logrotate(function(logrotate) { + setTimeout(function() { + helper.check_file("cluster-logrotate/output1"); + helper.launch(logrotate, ['-f', 'cluster-logrotate/logrotate.conf', '-s', '/tmp/s'], null, function(code) {}); + }, 500); + }); +}, function() { + helper.check_file("cluster-logrotate/output1", "test.log.1"); +}).export(module); diff --git a/node_modules/log4node/test/test-cluster-stdout-sig.js b/node_modules/log4node/test/test-cluster-stdout-sig.js new file mode 100644 index 0000000..6c3898e --- /dev/null +++ b/node_modules/log4node/test/test-cluster-stdout-sig.js @@ -0,0 +1,14 @@ +var helper = require('./helper.js'), + fs = require('fs'); + +helper.create_test('cluster-stdout-sig', 'cluster-stdout-sig/test1.js', null, function() { + helper.logrotate(function(logrotate) { + setTimeout(function() { + helper.launch("kill", ['-USR2', fs.readFileSync('process.pid')], null, function(code) { + assert.equal(code, 0); + }); + }, 500); + }); +}, function(stdout) { + helper.check_content(stdout, 'cluster-stdout-sig/output1'); +}).export(module); diff --git a/node_modules/log4node/test/test-cluster-sub-logger-logrotate.js b/node_modules/log4node/test/test-cluster-sub-logger-logrotate.js new file mode 100644 index 0000000..d5f5ae2 --- /dev/null +++ b/node_modules/log4node/test/test-cluster-sub-logger-logrotate.js @@ -0,0 +1,12 @@ +var helper = require('./helper.js'); + +helper.create_test('cluster-sub-logger-logrotate', 'cluster-sub-logger-logrotate/test1.js', 'cluster-sub-logger-logrotate/output2', function() { + helper.logrotate(function(logrotate) { + setTimeout(function() { + helper.check_file("cluster-sub-logger-logrotate/output1"); + helper.launch(logrotate, ['-f', 'cluster-sub-logger-logrotate/logrotate.conf', '-s', '/tmp/s'], null, function(code) {}); + }, 500); + }); +}, function() { + helper.check_file("cluster-sub-logger-logrotate/output1", "test.log.1"); +}).export(module); diff --git a/node_modules/log4node/test/test-cluster-sub-logger.js b/node_modules/log4node/test/test-cluster-sub-logger.js new file mode 100644 index 0000000..438fd10 --- /dev/null +++ b/node_modules/log4node/test/test-cluster-sub-logger.js @@ -0,0 +1,3 @@ +var helper = require('./helper.js'); + +helper.create_test('cluster', 'cluster-sub-logger/test1.js', 'cluster-sub-logger/output1', function() {}).export(module); diff --git a/node_modules/log4node/test/test-cluster.js b/node_modules/log4node/test/test-cluster.js new file mode 100644 index 0000000..45beb40 --- /dev/null +++ b/node_modules/log4node/test/test-cluster.js @@ -0,0 +1,15 @@ +var helper = require('./helper.js'); + +helper.create_test('cluster-logrotate', 'cluster-logrotate/test1.js', 'cluster-logrotate/output2', function() { + helper.logrotate(function(logrotate) { + setTimeout(function() { + helper.check_file("cluster-logrotate/output1"); + helper.launch(logrotate, ['-f', 'cluster-logrotate/logrotate.conf', '-s', '/tmp/s'], null, function(code) {}); + }, 500); + }); +}, function() { + helper.check_file("cluster-logrotate/output1", "test.log.1"); +}).export(module); +var helper = require('./helper.js'); + +helper.create_test('cluster', 'cluster/test1.js', 'cluster/output1', function() {}).export(module); diff --git a/node_modules/log4node/test/test-multiple-appender.js b/node_modules/log4node/test/test-multiple-appender.js new file mode 100644 index 0000000..2a131f9 --- /dev/null +++ b/node_modules/log4node/test/test-multiple-appender.js @@ -0,0 +1,29 @@ +var helper = require('./helper.js'), + assert = require('assert'); + +helper.create_test('multiple-appender', 'multiple-appender/test1.js', 'multiple-appender/output2', null, function() { + helper.check_file('test.log.1', 'multiple-appender/output1'); +}, function(f, callback) { + var process1_ok = false; + var process2_ok = false; + helper.launch('node', [f, 'p1'], 'process1.pid', function(code) { + assert.equal(code, 0); + process2_ok = true; + }); + setTimeout(function() { + helper.launch('node', [f, 'p2'], 'process2.pid', function(code) { + assert.equal(code, 0); + process1_ok = true; + }); + }, 20); + helper.logrotate(function(logrotate) { + setTimeout(function() { + helper.launch(logrotate, ['-f', 'multiple-appender/logrotate.conf', '-s', '/tmp/s'], null, function(code) {}); + }, 200); + }); + setTimeout(function() { + assert(process1_ok); + assert(process2_ok); + callback(undefined, 0); + }, 1000); +}).export(module); diff --git a/node_modules/log4node/test/test-no-cluster-append.js b/node_modules/log4node/test/test-no-cluster-append.js new file mode 100644 index 0000000..b798a98 --- /dev/null +++ b/node_modules/log4node/test/test-no-cluster-append.js @@ -0,0 +1,12 @@ +var helper = require('./helper.js'), + assert = require('assert'); + +helper.create_test('no-cluster-append', 'no-cluster-append/test1.js', 'no-cluster-append/output2', null, null, function(f, callback) { + helper.launch('node', [f], null, function(code) { + assert.equal(code, 0); + helper.check_file('no-cluster-append/output1'); + helper.launch('node', [f], null, function(code) { + callback(null, code); + }); + }); +}).export(module); diff --git a/node_modules/log4node/test/test-no-cluster-logrotate.js b/node_modules/log4node/test/test-no-cluster-logrotate.js new file mode 100644 index 0000000..ab75921 --- /dev/null +++ b/node_modules/log4node/test/test-no-cluster-logrotate.js @@ -0,0 +1,12 @@ +var helper = require('./helper.js'); + +helper.create_test('no-cluster-logrotate', 'no-cluster-logrotate/test1.js', 'no-cluster-logrotate/output2', function() { + helper.logrotate(function(logrotate) { + setTimeout(function() { + helper.check_file("no-cluster-logrotate/output1"); + helper.launch(logrotate, ['-f', 'no-cluster-logrotate/logrotate.conf', '-s', '/tmp/s'], null, function(code) {}); + }, 200); + }); +}, function() { + helper.check_file("no-cluster-logrotate/output1", "test.log.1"); +}).export(module); diff --git a/node_modules/log4node/test/test-no-cluster-sig.js b/node_modules/log4node/test/test-no-cluster-sig.js new file mode 100644 index 0000000..4ecdc74 --- /dev/null +++ b/node_modules/log4node/test/test-no-cluster-sig.js @@ -0,0 +1,12 @@ +var helper = require('./helper.js'), + assert = require('assert'), + fs = require('fs'); + +helper.create_test('no-cluster-sig', 'no-cluster-sig/test1.js', 'no-cluster-sig/output2', function() { + setTimeout(function() { + helper.check_file("no-cluster-sig/output1"); + helper.launch("kill", ['-USR2', fs.readFileSync('process.pid')], null, function(code) { + assert.equal(code, 0); + }); + }, 200); +}).export(module); diff --git a/node_modules/log4node/test/test-no-cluster-stdout-sig.js b/node_modules/log4node/test/test-no-cluster-stdout-sig.js new file mode 100644 index 0000000..f89fcc5 --- /dev/null +++ b/node_modules/log4node/test/test-no-cluster-stdout-sig.js @@ -0,0 +1,13 @@ +var helper = require('./helper.js'), + assert = require('assert'), + fs = require('fs'); + +helper.create_test('no-cluster-stdout-sig', 'no-cluster-stdout-sig/test1.js', null, function() { + setTimeout(function() { + helper.launch("kill", ['-USR2', fs.readFileSync('process.pid')], null, function(code) { + assert.equal(code, 0); + }); + }, 200); +}, function(stdout) { + helper.check_content(stdout, 'no-cluster-stdout-sig/output1'); +}).export(module); diff --git a/node_modules/log4node/test/test-no-cluster.js b/node_modules/log4node/test/test-no-cluster.js new file mode 100644 index 0000000..fc65e35 --- /dev/null +++ b/node_modules/log4node/test/test-no-cluster.js @@ -0,0 +1,7 @@ +var helper = require('./helper.js'); + +helper.create_test('no-cluster', 'no-cluster/test1.js', 'no-cluster/output2', function() { + setTimeout(function() { + helper.check_file("no-cluster/output1"); + }, 200); +}).export(module); diff --git a/node_modules/log4node/test/test-not-reopening-file.js b/node_modules/log4node/test/test-not-reopening-file.js new file mode 100644 index 0000000..dd9cefd --- /dev/null +++ b/node_modules/log4node/test/test-not-reopening-file.js @@ -0,0 +1,33 @@ +var cluster = require('cluster'), + vows = require('vows'), + assert = require('assert'), + log4node = require('log4node'); + +vows.describe('Test not reopening file').addBatch({ + 'is not called when a worker process is disconnected': { + 'topic': function() { + // setup process as a worker process + cluster.isMaster = false; + var calls = 0; + process.send = function(args) { + calls ++; + }; + + process.connected = true; + + log4node.info('log me baby'); + log4node.info('log me baby 2 times'); + + // when disconnected (ie, master dies) + process.connected = false; + + log4node.info('log me baby'); + + return calls; + }, + 'check': function(calls) { + assert.equal(calls, 2); + } + } +}).export(module); + diff --git a/node_modules/log4node/test/test-send-master.js b/node_modules/log4node/test/test-send-master.js new file mode 100644 index 0000000..0d57628 --- /dev/null +++ b/node_modules/log4node/test/test-send-master.js @@ -0,0 +1,33 @@ +var cluster = require('cluster'), + vows = require('vows'), + assert = require('assert'), + log4node = require('log4node'); + +vows.describe('Test process.send').addBatch({ + 'is not called when a worker process is disconnected': { + 'topic': function() { + // setup process as a worker process + cluster.isMaster = false; + var calls = 0; + process.send = function(args) { + calls ++; + }; + + process.connected = true; + + log4node.info('log me baby'); + log4node.info('log me baby 2 times'); + + // when disconnected (ie, master dies) + process.connected = false; + + log4node.info('log me baby'); + + return calls; + }, + 'check': function(calls) { + assert.equal(calls, 2); + } + } +}).export(module); + diff --git a/node_modules/log4node/test/test-set-loglevel.js b/node_modules/log4node/test/test-set-loglevel.js new file mode 100644 index 0000000..a46c80e --- /dev/null +++ b/node_modules/log4node/test/test-set-loglevel.js @@ -0,0 +1,30 @@ +var helper = require('./helper.js'), + vows = require('vows'), + assert = require('assert'), + log4node = require('log4node'); + +vows.describe('Test ').addBatch({ + 'set log level': { + 'topic': function() { + var logger = new log4node.Log4Node({level: 'info', file: 'test.log'}); + logger.setPrefix(''); + + logger.debug('start_debug'); + logger.info('start'); + logger.setLogLevel('critical'); + logger.info('stop'); + logger.critical('stop_critical') + + var callback = this.callback; + setTimeout(function() { + callback(null); + }, 200); + }, + 'check': function(err) { + assert.ifError(err); + helper.check_file_content('test.log', 'start\nstop_critical\n'); + helper.remove_test_files(); + } + } +}).export(module); + diff --git a/node_modules/log4node/test/test-set-prefix.js b/node_modules/log4node/test/test-set-prefix.js new file mode 100644 index 0000000..320165a --- /dev/null +++ b/node_modules/log4node/test/test-set-prefix.js @@ -0,0 +1,162 @@ +var helper = require('./helper.js'), + vows = require('vows'), + assert = require('assert'), + log4node = require('log4node'), + util = require('util'); + +vows.describe('Test ').addBatch({ + 'set string prefix': { + topic: function() { + var logger = new log4node.Log4Node({ + level: 'info', + file: 'test.log', + prefix: '%l ' + }); + + logger.info('start'); + + var callback = this.callback; + setTimeout(function() { + callback(null); + }, 200); + }, + + check: function(err) { + assert.ifError(err); + helper.check_file_content('test.log', 'INFO start\n'); + helper.remove_test_files(); + } + }, +}).addBatch({ + 'set string prefix inheritance': { + topic: function() { + var parent_logger = new log4node.Log4Node({ + level: 'info', + file: 'test.log', + prefix: '%l ' + }); + + var logger = new log4node.Log4Node({parent: parent_logger, prefix: 'sub '}); + + logger.info('start'); + + var callback = this.callback; + setTimeout(function() { + callback(null); + }, 200); + }, + + check: function(err) { + assert.ifError(err); + helper.check_file_content('test.log', 'INFO sub start\n'); + helper.remove_test_files(); + } + }, +}).addBatch({ + 'set string prefix inheritance with no prefix value': { + topic: function() { + var parent_logger = new log4node.Log4Node({ + level: 'info', + file: 'test.log', + prefix: '%l ' + }); + + var logger = new log4node.Log4Node({parent: parent_logger}); + + logger.info('start'); + + var callback = this.callback; + setTimeout(function() { + callback(null); + }, 200); + }, + + check: function(err) { + assert.ifError(err); + helper.check_file_content('test.log', 'INFO start\n'); + helper.remove_test_files(); + } + }, +}).addBatch({ + 'set function prefix': { + topic: function() { + var v = Math.random(); + var logger = new log4node.Log4Node({ + level: 'info', + file: 'test.log', + prefix: function(level) { + return util.format('[ %d ] %s ', v, level.toUpperCase()); + } + }); + + logger.info('start'); + + var callback = this.callback; + setTimeout(function() { + callback(null, v); + }, 200); + }, + + check: function(err, v) { + assert.ifError(err); + helper.check_file_content('test.log', '[ ' + v + ' ] INFO start\n'); + helper.remove_test_files(); + } + }, +}).addBatch({ + 'set function prefix inheritance default value': { + topic: function() { + var v = Math.random(); + var parent_logger = new log4node.Log4Node({ + level: 'info', + file: 'test.log', + prefix: function(level) { + return util.format('[ %d ] %s ', v, level.toUpperCase()); + } + }); + + var logger = new log4node.Log4Node({parent: parent_logger}); + + logger.info('start'); + + var callback = this.callback; + setTimeout(function() { + callback(null, v); + }, 200); + }, + + check: function(err, v) { + assert.ifError(err); + helper.check_file_content('test.log', '[ ' + v + ' ] INFO start\n'); + helper.remove_test_files(); + } + }, +}).addBatch({ + 'set function prefix inheritance with function': { + topic: function() { + var v = Math.random(); + var parent_logger = new log4node.Log4Node({ + level: 'info', + file: 'test.log', + prefix: function(level) { + return util.format('[ %d ] %s ', v, level.toUpperCase()); + } + }); + + var logger = new log4node.Log4Node({parent: parent_logger, prefix: function() {return 'tata ';}}); + + logger.info('start'); + + var callback = this.callback; + setTimeout(function() { + callback(null, v); + }, 200); + }, + + check: function(err, v) { + assert.ifError(err); + helper.check_file_content('test.log', '[ ' + v + ' ] INFO tata start\n'); + helper.remove_test_files(); + } + }, +}).export(module); diff --git a/node_modules/log4node/test/test-strange-params.js b/node_modules/log4node/test/test-strange-params.js new file mode 100644 index 0000000..fd02867 --- /dev/null +++ b/node_modules/log4node/test/test-strange-params.js @@ -0,0 +1,28 @@ +var helper = require('./helper.js'), + vows = require('vows'), + assert = require('assert'), + log4node = require('log4node'); + +vows.describe('Test strange params').addBatch({ + 'when calling log.info': { + 'topic': function() { + var logger = new log4node.Log4Node({level: 'info', file: 'test.log'}); + logger.setPrefix(''); + + logger.info('log me baby', 2, 5); + logger.info(undefined); + logger.info(null); + + var callback = this.callback; + setTimeout(function() { + callback(null); + }, 200); + }, + 'check': function(err) { + assert.ifError(err); + helper.check_file_content('test.log', 'log me baby 2 5\nundefined\nnull\n'); + helper.remove_test_files(); + } + } +}).export(module); + diff --git a/node_modules/log4node/test/test-sub-logger-default.js b/node_modules/log4node/test/test-sub-logger-default.js new file mode 100644 index 0000000..20fa041 --- /dev/null +++ b/node_modules/log4node/test/test-sub-logger-default.js @@ -0,0 +1,9 @@ +var helper = require('./helper.js'); + +helper.create_test('sub-logger-default', 'sub-logger-default/test1.js', 'sub-logger-default/output2', function() { + setTimeout(function() { + helper.check_file("sub-logger-default/output1"); + }, 200); +}).export(module); + + diff --git a/node_modules/log4node/test/test-sub-logger.js b/node_modules/log4node/test/test-sub-logger.js new file mode 100644 index 0000000..d420711 --- /dev/null +++ b/node_modules/log4node/test/test-sub-logger.js @@ -0,0 +1,9 @@ +var helper = require('./helper.js'); + +helper.create_test('sub-logger', 'sub-logger/test1.js', 'sub-logger/output2', function() { + setTimeout(function() { + helper.check_file("sub-logger/output1"); + }, 200); +}).export(module); + + diff --git a/node_modules/moment/.npmignore b/node_modules/moment/.npmignore new file mode 100644 index 0000000..12ac647 --- /dev/null +++ b/node_modules/moment/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +.DS_Store \ No newline at end of file diff --git a/node_modules/moment/.travis.yml b/node_modules/moment/.travis.yml new file mode 100644 index 0000000..b30fcb7 --- /dev/null +++ b/node_modules/moment/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 +before_script: + - npm install -g grunt-cli diff --git a/node_modules/moment/CONTRIBUTING.md b/node_modules/moment/CONTRIBUTING.md new file mode 100644 index 0000000..bf61ee6 --- /dev/null +++ b/node_modules/moment/CONTRIBUTING.md @@ -0,0 +1,45 @@ +All pull requests to the `master` branch will be closed. +======================================================== + +Please submit all pull requests to the `develop` branch. + +Language translations will not be merged without unit tests. +============================================================ + +See [the english unit tests](https://github.com/timrwood/moment/blob/develop/test/lang/en.js) for an example. + +Submitting Issues +================= + +If you are submitting a bug, please create a [jsfiddle](http://jsfiddle.net/) demonstrating the issue. + +Contributing +============ + +To contribute, fork the library and install grunt. + + npm install grunt -g + +You can add tests to the files in `/test/moment` or add a new test file if you are adding a new feature. + +To run the tests, do `grunt` to run all tests. + +To check the filesize, you can use `grunt size`. + +To minify all the files, use `grunt release`. + +If your code passes the unit tests (including the ones you wrote), submit a pull request. + +Submitting pull requests +======================== + +Moment.js now uses [git-flow](https://github.com/nvie/gitflow). If you're not familiar with git-flow, please read up on it, you'll be glad you did. + +When submitting new features, please create a new feature branch using `git flow feature start ` and submit the pull request to the `develop` branch. + +Pull requests for enhancements for features should be submitted to the `develop` branch as well. + +When submitting a bugfix, please check if there is an existing bugfix branch. If the latest stable version is `1.5.0`, the bugfix branch would be `hotfix/1.5.1`. All pull requests for bug fixes should be on a `hotfix` branch, unless the bug fix depends on a new feature. + +The `master` branch should always have the latest stable version. When bugfix or minor releases are needed, the develop/hotfix branch will be merged into master and released. + diff --git a/node_modules/moment/Gruntfile.js b/node_modules/moment/Gruntfile.js new file mode 100644 index 0000000..bffdeae --- /dev/null +++ b/node_modules/moment/Gruntfile.js @@ -0,0 +1,124 @@ +var fs = require('fs'); + +module.exports = function (grunt) { + + var minifiedFiles = { + 'min/langs.min.js' : ['min/langs.js'], + 'min/moment.min.js' : ['moment.js'] + }, + minLangs = { + langs: { + src: ['min/langs.js'], + dest: 'min/langs.min.js' + } + }; + + // all the lang files need to be added manually + fs.readdirSync('./lang').forEach(function (path) { + if (path.indexOf('.js') > -1) { + var dest = 'min/lang/' + path, + src = ['lang/' + path]; + + minifiedFiles[dest] = src; + minLangs[path] = {src: src, dest: dest}; + } + }); + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + concat : { + langs: { + src: ['lang/*.js'], + dest: 'min/langs.js' + } + }, + concatlang : { + langs: { + src: ['lang/*.js'], + dest: 'min/langs.js' + } + }, + minlang : minLangs, + minwithcomments : { + moment: { + src: ['moment.js'], + dest: 'min/moment.min.js' + } + }, + uglify : { + my_target: { + files: minifiedFiles + }, + options: { + fromString: true, + mangle: true, + compress: { + dead_code: false + }, + output: { + ascii_only: true + } + } + }, + nodeunit : { + all : ["test/**/*.js"] + }, + jshint: { + all: ["Gruntfile.js", "moment.js", "lang/**/*.js"], + options: { + "node" : true, + "browser" : true, + "boss" : false, + "curly" : true, + "debug" : false, + "devel" : false, + "eqeqeq" : true, + "eqnull" : true, + "evil" : false, + "forin" : false, + "immed" : false, + "laxbreak" : false, + "newcap" : true, + "noarg" : true, + "noempty" : false, + "nonew" : false, + "onevar" : true, + "plusplus" : false, + "regexp" : false, + "undef" : true, + "sub" : true, + "strict" : false, + "white" : true + } + }, + watch : { + test : { + files : [ + 'moment.js', + 'lang/*.js', + 'test/**/*.js' + ], + tasks: ['nodeunit'] + }, + jshint : { + files : '<%= jshint.all %>', + tasks: ['jshint'] + } + } + }); + + grunt.loadTasks("tasks"); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-watch'); + + // Default task. + grunt.registerTask('default', ['jshint', 'nodeunit']); + + // Task to be run when releasing a new version + grunt.registerTask('release', ['jshint', 'nodeunit', 'minwithcomments', 'concatlang', 'minlang']); +}; diff --git a/node_modules/moment/LICENSE b/node_modules/moment/LICENSE new file mode 100644 index 0000000..8beeefc --- /dev/null +++ b/node_modules/moment/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011-2012 Tim Wood + +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. \ No newline at end of file diff --git a/node_modules/moment/component.json b/node_modules/moment/component.json new file mode 100644 index 0000000..659a961 --- /dev/null +++ b/node_modules/moment/component.json @@ -0,0 +1,19 @@ +{ + "name": "moment", + "version": "2.1.0", + "scripts": ["moment.js"], + "main": "moment.js", + "description": "Parse, validate, manipulate, and display dates in javascript.", + "ignore": [ + ".gitignore", + ".travis.yml", + "composer.json", + "CONTRIBUTING.md", + "ender.js", + "Gruntfile.js", + "package.js", + "package.json", + "test", + "tasks" + ] +} diff --git a/node_modules/moment/composer.json b/node_modules/moment/composer.json new file mode 100644 index 0000000..8381de8 --- /dev/null +++ b/node_modules/moment/composer.json @@ -0,0 +1,18 @@ +{ + "name": "timrwood/moment", + "description": "Parse, validate, manipulate, and display dates in javascript.", + "keywords": [ + "moment", + "date", + "time", + "parse", + "format", + "validate", + "i18n", + "l10n", + "ender" + ], + "homepage": "http://github.com/timrwood/moment/", + "author": "Tim Wood (http://timwoodcreates.com/)", + "license": "MIT" +} diff --git a/node_modules/moment/ender.js b/node_modules/moment/ender.js new file mode 100644 index 0000000..71462a7 --- /dev/null +++ b/node_modules/moment/ender.js @@ -0,0 +1 @@ +$.ender({ moment: require('moment') }) diff --git a/node_modules/moment/lang/ar-ma.js b/node_modules/moment/lang/ar-ma.js new file mode 100644 index 0000000..bdb472c --- /dev/null +++ b/node_modules/moment/lang/ar-ma.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : Moroccan Arabic (ar-ma) +// author : ElFadili Yassine : https://github.com/ElFadiliY +// author : Abdel Said : https://github.com/abdelsaid + +require('../moment').lang('ar-ma', { + months : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"), + monthsShort : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"), + weekdays : "الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"), + weekdaysShort : "احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"), + weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[اليوم على الساعة] LT", + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : "في %s", + past : "منذ %s", + s : "ثوان", + m : "دقيقة", + mm : "%d دقائق", + h : "ساعة", + hh : "%d ساعات", + d : "يوم", + dd : "%d أيام", + M : "شهر", + MM : "%d أشهر", + y : "سنة", + yy : "%d سنوات" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/ar.js b/node_modules/moment/lang/ar.js new file mode 100644 index 0000000..197d96a --- /dev/null +++ b/node_modules/moment/lang/ar.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : Arabic (ar) +// author : Abdel Said : https://github.com/abdelsaid +// changes in months, weekdays : Ahmed Elkhatib + +require('../moment').lang('ar', { + months : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"), + monthsShort : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"), + weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"), + weekdaysShort : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"), + weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[اليوم على الساعة] LT", + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : "في %s", + past : "منذ %s", + s : "ثوان", + m : "دقيقة", + mm : "%d دقائق", + h : "ساعة", + hh : "%d ساعات", + d : "يوم", + dd : "%d أيام", + M : "شهر", + MM : "%d أشهر", + y : "سنة", + yy : "%d سنوات" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/bg.js b/node_modules/moment/lang/bg.js new file mode 100644 index 0000000..c5b4785 --- /dev/null +++ b/node_modules/moment/lang/bg.js @@ -0,0 +1,76 @@ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz + +require('../moment').lang('bg', { + months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"), + monthsShort : "янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"), + weekdays : "неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"), + weekdaysShort : "нед_пон_вто_сря_чет_пет_съб".split("_"), + weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "h:mm", + L : "D.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : "след %s", + past : "преди %s", + s : "няколко секунди", + m : "минута", + mm : "%d минути", + h : "час", + hh : "%d часа", + d : "ден", + dd : "%d дни", + M : "месец", + MM : "%d месеца", + y : "година", + yy : "%d години" + }, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/br.js b/node_modules/moment/lang/br.js new file mode 100644 index 0000000..deaee6c --- /dev/null +++ b/node_modules/moment/lang/br.js @@ -0,0 +1,97 @@ +// moment.js language configuration +// language : breton (br) +// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + +function relativeTimeWithMutation(number, withoutSuffix, key) { + var format = { + 'mm': "munutenn", + 'MM': "miz", + 'dd': "devezh" + }; + return number + ' ' + mutation(format[key], number); +} + +function specialMutationForYears(number) { + switch (lastNumber(number)) { + case 1: + case 3: + case 4: + case 5: + case 9: + return number + ' bloaz'; + default: + return number + ' vloaz'; + } +} + +function lastNumber(number) { + if (number > 9) { + return lastNumber(number % 10); + } + return number; +} + +function mutation(text, number) { + if (number === 2) { + return softMutation(text); + } + return text; +} + +function softMutation(text) { + var mutationTable = { + 'm': 'v', + 'b': 'v', + 'd': 'z' + }; + if (mutationTable[text.charAt(0)] === undefined) { + return text; + } + return mutationTable[text.charAt(0)] + text.substring(1); +} + +require('../moment').lang('br', { + months : "Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"), + monthsShort : "Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"), + weekdays : "Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"), + weekdaysShort : "Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"), + weekdaysMin : "Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"), + longDateFormat : { + LT : "h[e]mm A", + L : "DD/MM/YYYY", + LL : "D [a viz] MMMM YYYY", + LLL : "D [a viz] MMMM YYYY LT", + LLLL : "dddd, D [a viz] MMMM YYYY LT" + }, + calendar : { + sameDay : '[Hiziv da] LT', + nextDay : '[Warc\'hoazh da] LT', + nextWeek : 'dddd [da] LT', + lastDay : '[Dec\'h da] LT', + lastWeek : 'dddd [paset da] LT', + sameElse : 'L' + }, + relativeTime : { + future : "a-benn %s", + past : "%s 'zo", + s : "un nebeud segondennoù", + m : "ur vunutenn", + mm : relativeTimeWithMutation, + h : "un eur", + hh : "%d eur", + d : "un devezh", + dd : relativeTimeWithMutation, + M : "ur miz", + MM : relativeTimeWithMutation, + y : "ur bloaz", + yy : specialMutationForYears + }, + ordinal : function (number) { + var output = (number === 1) ? 'añ' : 'vet'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/ca.js b/node_modules/moment/lang/ca.js new file mode 100644 index 0000000..9bbe963 --- /dev/null +++ b/node_modules/moment/lang/ca.js @@ -0,0 +1,56 @@ +// moment.js language configuration +// language : catalan (ca) +// author : Juan G. Hurtado : https://github.com/juanghurtado + +require('../moment').lang('ca', { + months : "Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"), + monthsShort : "Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"), + weekdays : "Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"), + weekdaysShort : "Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"), + weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "fa %s", + s : "uns segons", + m : "un minut", + mm : "%d minuts", + h : "una hora", + hh : "%d hores", + d : "un dia", + dd : "%d dies", + M : "un mes", + MM : "%d mesos", + y : "un any", + yy : "%d anys" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/cs.js b/node_modules/moment/lang/cs.js new file mode 100644 index 0000000..cb98b2e --- /dev/null +++ b/node_modules/moment/lang/cs.js @@ -0,0 +1,145 @@ +// moment.js language configuration +// language : czech (cs) +// author : petrbela : https://github.com/petrbela + +var months = "leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"), + monthsShort = "led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"); + +function plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); +} + +function translate(number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár vteřin' : 'pár vteřinami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minuty' : 'minut'); + } else { + return result + 'minutami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodin'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'den' : 'dnem'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dny' : 'dní'); + } else { + return result + 'dny'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'měsíce' : 'měsíců'); + } else { + return result + 'měsíci'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } +} + +require('../moment').lang('cs', { + months : months, + monthsShort : monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(months, monthsShort)), + weekdays : "neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"), + weekdaysShort : "ne_po_út_st_čt_pá_so".split("_"), + weekdaysMin : "ne_po_út_st_čt_pá_so".split("_"), + longDateFormat : { + LT: "H:mm", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[dnes v] LT", + nextDay: '[zítra v] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v neděli v] LT'; + case 1: + case 2: + return '[v] dddd [v] LT'; + case 3: + return '[ve středu v] LT'; + case 4: + return '[ve čtvrtek v] LT'; + case 5: + return '[v pátek v] LT'; + case 6: + return '[v sobotu v] LT'; + } + }, + lastDay: '[včera v] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulou neděli v] LT'; + case 1: + case 2: + return '[minulé] dddd [v] LT'; + case 3: + return '[minulou středu v] LT'; + case 4: + case 5: + return '[minulý] dddd [v] LT'; + case 6: + return '[minulou sobotu v] LT'; + } + }, + sameElse: "L" + }, + relativeTime : { + future : "za %s", + past : "před %s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/cv.js b/node_modules/moment/lang/cv.js new file mode 100644 index 0000000..6e4b178 --- /dev/null +++ b/node_modules/moment/lang/cv.js @@ -0,0 +1,50 @@ +// moment.js language configuration +// language : chuvash (cv) +// author : Anatoly Mironov : https://github.com/mirontoli + + +require('../moment').lang('cv', { + months : "кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"), + monthsShort : "кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"), + weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"), + weekdaysShort : "выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"), + weekdaysMin : "вр_тн_ыт_юн_кç_эр_шм".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]", + LLL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT", + LLLL : "dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT" + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ĕнер] LT [сехетре]', + nextWeek: '[Çитес] dddd LT [сехетре]', + lastWeek: '[Иртнĕ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : function (output) { + var affix = /сехет$/i.exec(output) ? "рен" : /çул$/i.exec(output) ? "тан" : "ран"; + return output + affix; + }, + past : "%s каялла", + s : "пĕр-ик çеккунт", + m : "пĕр минут", + mm : "%d минут", + h : "пĕр сехет", + hh : "%d сехет", + d : "пĕр кун", + dd : "%d кун", + M : "пĕр уйăх", + MM : "%d уйăх", + y : "пĕр çул", + yy : "%d çул" + }, + ordinal : '%d-мĕш', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/da.js b/node_modules/moment/lang/da.js new file mode 100644 index 0000000..3f4c459 --- /dev/null +++ b/node_modules/moment/lang/da.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : danish (da) +// author : Ulrik Nielsen : https://github.com/mrbase + +require('../moment').lang('da', { + months : "Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"), + weekdays : "Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"), + weekdaysShort : "Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"), + weekdaysMin : "Sø_Ma_Ti_On_To_Fr_Lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D. MMMM, YYYY LT" + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : "om %s", + past : "%s siden", + s : "få sekunder", + m : "et minut", + mm : "%d minutter", + h : "en time", + hh : "%d timer", + d : "en dag", + dd : "%d dage", + M : "en måned", + MM : "%d måneder", + y : "et år", + yy : "%d år" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/de.js b/node_modules/moment/lang/de.js new file mode 100644 index 0000000..e809ba2 --- /dev/null +++ b/node_modules/moment/lang/de.js @@ -0,0 +1,61 @@ +// moment.js language configuration +// language : german (de) +// author : lluchs : https://github.com/lluchs +// author: Menelion Elensúle: https://github.com/Oire + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; +} + +require('../moment').lang('de', { + months : "Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"), + monthsShort : "Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"), + weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"), + weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"), + weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"), + longDateFormat : { + LT: "H:mm [Uhr]", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[Heute um] LT", + sameElse: "L", + nextDay: '[Morgen um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gestern um] LT', + lastWeek: '[letzten] dddd [um] LT' + }, + relativeTime : { + future : "in %s", + past : "vor %s", + s : "ein paar Sekunden", + m : processRelativeTime, + mm : "%d Minuten", + h : processRelativeTime, + hh : "%d Stunden", + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/el.js b/node_modules/moment/lang/el.js new file mode 100644 index 0000000..962ef00 --- /dev/null +++ b/node_modules/moment/lang/el.js @@ -0,0 +1,69 @@ +// moment.js language configuration +// language : modern greek (el) +// author : Aggelos Karalias : https://github.com/mehiel + +require('../moment').lang('el', { + monthsNominativeEl : "Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"), + monthsGenitiveEl : "Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"), + months : function (momentToFormat, format) { + if (/D/.test(format.substring(0, format.indexOf("MMMM")))) { // if there is a day number before 'MMMM' + return this._monthsGenitiveEl[momentToFormat.month()]; + } else { + return this._monthsNominativeEl[momentToFormat.month()]; + } + }, + monthsShort : "Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"), + weekdays : "Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"), + weekdaysShort : "Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"), + weekdaysMin : "Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"), + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'μμ' : 'ΜΜ'; + } else { + return isLower ? 'πμ' : 'ΠΜ'; + } + }, + longDateFormat : { + LT : "h:mm A", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendarEl : { + sameDay : '[Σήμερα {}] LT', + nextDay : '[Αύριο {}] LT', + nextWeek : 'dddd [{}] LT', + lastDay : '[Χθες {}] LT', + lastWeek : '[την προηγούμενη] dddd [{}] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + + return output.replace("{}", (hours % 12 === 1 ? "στη" : "στις")); + }, + relativeTime : { + future : "σε %s", + past : "%s πριν", + s : "δευτερόλεπτα", + m : "ένα λεπτό", + mm : "%d λεπτά", + h : "μία ώρα", + hh : "%d ώρες", + d : "μία μέρα", + dd : "%d μέρες", + M : "ένας μήνας", + MM : "%d μήνες", + y : "ένας χρόνος", + yy : "%d χρόνια" + }, + ordinal : function (number) { + return number + 'η'; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/en-ca.js b/node_modules/moment/lang/en-ca.js new file mode 100644 index 0000000..51bb2b9 --- /dev/null +++ b/node_modules/moment/lang/en-ca.js @@ -0,0 +1,49 @@ +// moment.js language configuration +// language : canadian english (en-ca) +// author : Jonathan Abourbih : https://github.com/jonbca + +require('../moment').lang('en-ca', { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "YYYY-MM-DD", + LL : "D MMMM, YYYY", + LLL : "D MMMM, YYYY LT", + LLLL : "dddd, D MMMM, YYYY LT" + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } +}); diff --git a/node_modules/moment/lang/en-gb.js b/node_modules/moment/lang/en-gb.js new file mode 100644 index 0000000..ce225eb --- /dev/null +++ b/node_modules/moment/lang/en-gb.js @@ -0,0 +1,53 @@ +// moment.js language configuration +// language : great britain english (en-gb) +// author : Chris Gedrim : https://github.com/chrisgedrim + +require('../moment').lang('en-gb', { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/eo.js b/node_modules/moment/lang/eo.js new file mode 100644 index 0000000..0e08cad --- /dev/null +++ b/node_modules/moment/lang/eo.js @@ -0,0 +1,55 @@ +// moment.js language configuration +// language : esperanto (eo) +// author : Colin Dean : https://github.com/colindean +// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. +// Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! + +require('../moment').lang('eo', { + months : "januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"), + monthsShort : "jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"), + weekdays : "Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"), + weekdaysShort : "Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D[-an de] MMMM, YYYY", + LLL : "D[-an de] MMMM, YYYY LT", + LLLL : "dddd, [la] D[-an de] MMMM, YYYY LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'p.t.m.' : 'P.T.M.'; + } else { + return isLower ? 'a.t.m.' : 'A.T.M.'; + } + }, + calendar : { + sameDay : '[Hodiaŭ je] LT', + nextDay : '[Morgaŭ je] LT', + nextWeek : 'dddd [je] LT', + lastDay : '[Hieraŭ je] LT', + lastWeek : '[pasinta] dddd [je] LT', + sameElse : 'L' + }, + relativeTime : { + future : "je %s", + past : "antaŭ %s", + s : "sekundoj", + m : "minuto", + mm : "%d minutoj", + h : "horo", + hh : "%d horoj", + d : "tago",//ne 'diurno', ĉar estas uzita por proksimumo + dd : "%d tagoj", + M : "monato", + MM : "%d monatoj", + y : "jaro", + yy : "%d jaroj" + }, + ordinal : "%da", + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/es.js b/node_modules/moment/lang/es.js new file mode 100644 index 0000000..0a690b7 --- /dev/null +++ b/node_modules/moment/lang/es.js @@ -0,0 +1,56 @@ +// moment.js language configuration +// language : spanish (es) +// author : Julio Napurí : https://github.com/julionc + +require('../moment').lang('es', { + months : "enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"), + monthsShort : "ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"), + weekdays : "domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"), + weekdaysShort : "dom._lun._mar._mié._jue._vie._sáb.".split("_"), + weekdaysMin : "Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D [de] MMMM [de] YYYY", + LLL : "D [de] MMMM [de] YYYY LT", + LLLL : "dddd, D [de] MMMM [de] YYYY LT" + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "hace %s", + s : "unos segundos", + m : "un minuto", + mm : "%d minutos", + h : "una hora", + hh : "%d horas", + d : "un día", + dd : "%d días", + M : "un mes", + MM : "%d meses", + y : "un año", + yy : "%d años" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/et.js b/node_modules/moment/lang/et.js new file mode 100644 index 0000000..5e07802 --- /dev/null +++ b/node_modules/moment/lang/et.js @@ -0,0 +1,50 @@ +// moment.js language configuration +// language : estonian (et) +// author : Henry Kehlmann : https://github.com/madhenry + +function translateSeconds(number, withoutSuffix, key, isFuture) { + return (isFuture || withoutSuffix) ? 'paari sekundi' : 'paar sekundit'; +} + +require('../moment').lang('et', { + months : "jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"), + monthsShort : "jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"), + weekdays : "pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"), + weekdaysShort : "P_E_T_K_N_R_L".split("_"), + weekdaysMin : "P_E_T_K_N_R_L".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay : '[Täna,] LT', + nextDay : '[Homme,] LT', + nextWeek : '[Järgmine] dddd LT', + lastDay : '[Eile,] LT', + lastWeek : '[Eelmine] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s pärast", + past : "%s tagasi", + s : translateSeconds, + m : "minut", + mm : "%d minutit", + h : "tund", + hh : "%d tundi", + d : "päev", + dd : "%d päeva", + M : "kuu", + MM : "%d kuud", + y : "aasta", + yy : "%d aastat" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/eu.js b/node_modules/moment/lang/eu.js new file mode 100644 index 0000000..6be894a --- /dev/null +++ b/node_modules/moment/lang/eu.js @@ -0,0 +1,50 @@ +// moment.js language configuration +// language : euskara (eu) +// author : Eneko Illarramendi : https://github.com/eillarra + +require('../moment').lang('eu', { + months : "urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"), + monthsShort : "urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"), + weekdays : "igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"), + weekdaysShort : "ig._al._ar._az._og._ol._lr.".split("_"), + weekdaysMin : "ig_al_ar_az_og_ol_lr".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "YYYY[ko] MMMM[ren] D[a]", + LLL : "YYYY[ko] MMMM[ren] D[a] LT", + LLLL : "dddd, YYYY[ko] MMMM[ren] D[a] LT", + l : "YYYY-M-D", + ll : "YYYY[ko] MMM D[a]", + lll : "YYYY[ko] MMM D[a] LT", + llll : "ddd, YYYY[ko] MMM D[a] LT" + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : "%s barru", + past : "duela %s", + s : "segundo batzuk", + m : "minutu bat", + mm : "%d minutu", + h : "ordu bat", + hh : "%d ordu", + d : "egun bat", + dd : "%d egun", + M : "hilabete bat", + MM : "%d hilabete", + y : "urte bat", + yy : "%d urte" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/fa.js b/node_modules/moment/lang/fa.js new file mode 100755 index 0000000..8369784 --- /dev/null +++ b/node_modules/moment/lang/fa.js @@ -0,0 +1,86 @@ +// moment.js language configuration +// language : Persian Language +// author : Ebrahim Byagowi : https://github.com/ebraminio +var symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' +}, numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' +}; + +require('../moment').lang('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + longDateFormat : { + LT : 'HH:mm', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "قبل از ظهر"; + } else { + return "بعد از ظهر"; + } + }, + calendar : { + sameDay : '[امروز ساعت] LT', + nextDay : '[فردا ساعت] LT', + nextWeek : 'dddd [ساعت] LT', + lastDay : '[دیروز ساعت] LT', + lastWeek : 'dddd [پیش] [ساعت] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'در %s', + past : '%s پیش', + s : 'چندین ثانیه', + m : 'یک دقیقه', + mm : '%d دقیقه', + h : 'یک ساعت', + hh : '%d ساعت', + d : 'یک روز', + dd : '%d روز', + M : 'یک ماه', + MM : '%d ماه', + y : 'یک سال', + yy : '%d سال' + }, + preparse: function (string) { + return string.replace(/[۰-۹]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinal : '%dم', + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/fi.js b/node_modules/moment/lang/fi.js new file mode 100644 index 0000000..717497a --- /dev/null +++ b/node_modules/moment/lang/fi.js @@ -0,0 +1,93 @@ +// moment.js language configuration +// language : finnish (fi) +// author : Tarmo Aidantausta : https://github.com/bleadof + +var numbers_past = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbers_future = ['nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbers_past[7], numbers_past[8], numbers_past[9]]; + +function translate(number, withoutSuffix, key, isFuture) { + var result = ""; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbal_number(number, isFuture) + " " + result; + return result; +} + +function verbal_number(number, isFuture) { + return number < 10 ? (isFuture ? numbers_future[number] : numbers_past[number]) : number; +} + +require('../moment').lang('fi', { + months : "tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"), + monthsShort : "tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"), + weekdays : "sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"), + weekdaysShort : "su_ma_ti_ke_to_pe_la".split("_"), + weekdaysMin : "su_ma_ti_ke_to_pe_la".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD.MM.YYYY", + LL : "Do MMMM[ta] YYYY", + LLL : "Do MMMM[ta] YYYY, [klo] LT", + LLLL : "dddd, Do MMMM[ta] YYYY, [klo] LT", + l : "D.M.YYYY", + ll : "Do MMM YYYY", + lll : "Do MMM YYYY, [klo] LT", + llll : "ddd, Do MMM YYYY, [klo] LT" + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s päästä", + past : "%s sitten", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : "%d.", + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/fr-ca.js b/node_modules/moment/lang/fr-ca.js new file mode 100644 index 0000000..c79a631 --- /dev/null +++ b/node_modules/moment/lang/fr-ca.js @@ -0,0 +1,44 @@ +// moment.js language configuration +// language : canadian french (fr-ca) +// author : Jonathan Abourbih : https://github.com/jonbca + +require('../moment').lang('fr-ca', { + months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"), + monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"), + weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), + weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[Aujourd'hui à] LT", + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dans %s", + past : "il y a %s", + s : "quelques secondes", + m : "une minute", + mm : "%d minutes", + h : "une heure", + hh : "%d heures", + d : "un jour", + dd : "%d jours", + M : "un mois", + MM : "%d mois", + y : "un an", + yy : "%d ans" + }, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + } +}); diff --git a/node_modules/moment/lang/fr.js b/node_modules/moment/lang/fr.js new file mode 100644 index 0000000..eddb9ee --- /dev/null +++ b/node_modules/moment/lang/fr.js @@ -0,0 +1,48 @@ +// moment.js language configuration +// language : french (fr) +// author : John Fischer : https://github.com/jfroffice + +require('../moment').lang('fr', { + months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"), + monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"), + weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), + weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[Aujourd'hui à] LT", + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dans %s", + past : "il y a %s", + s : "quelques secondes", + m : "une minute", + mm : "%d minutes", + h : "une heure", + hh : "%d heures", + d : "un jour", + dd : "%d jours", + M : "un mois", + MM : "%d mois", + y : "un an", + yy : "%d ans" + }, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/gl.js b/node_modules/moment/lang/gl.js new file mode 100644 index 0000000..fff421b --- /dev/null +++ b/node_modules/moment/lang/gl.js @@ -0,0 +1,61 @@ +// moment.js language configuration +// language : galician (gl) +// author : Juan G. Hurtado : https://github.com/juanghurtado + +require('../moment').lang('gl', { + months : "Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"), + monthsShort : "Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"), + weekdays : "Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"), + weekdaysShort : "Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"), + weekdaysMin : "Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : function (str) { + if (str === "uns segundos") { + return "nuns segundos"; + } + return "en " + str; + }, + past : "hai %s", + s : "uns segundos", + m : "un minuto", + mm : "%d minutos", + h : "unha hora", + hh : "%d horas", + d : "un día", + dd : "%d días", + M : "un mes", + MM : "%d meses", + y : "un ano", + yy : "%d anos" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/he.js b/node_modules/moment/lang/he.js new file mode 100644 index 0000000..5495f40 --- /dev/null +++ b/node_modules/moment/lang/he.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : Hebrew (he) +// author : Tomer Cohen : https://github.com/tomer +// author : Moshe Simantov : https://github.com/DevelopmentIL + +require('../moment').lang('he', { + months : "ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"), + monthsShort : "ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"), + weekdays : "ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"), + weekdaysShort : "א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"), + weekdaysMin : "א_ב_ג_ד_ה_ו_ש".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D [ב]MMMM YYYY", + LLL : "D [ב]MMMM YYYY LT", + LLLL : "dddd, D [ב]MMMM YYYY LT", + l : "D/M/YYYY", + ll : "D MMM YYYY", + lll : "D MMM YYYY LT", + llll : "ddd, D MMM YYYY LT" + }, + calendar : { + sameDay : '[היום ב־]LT', + nextDay : '[מחר ב־]LT', + nextWeek : 'dddd [בשעה] LT', + lastDay : '[אתמול ב־]LT', + lastWeek : '[ביום] dddd [האחרון בשעה] LT', + sameElse : 'L' + }, + relativeTime : { + future : "בעוד %s", + past : "לפני %s", + s : "מספר שניות", + m : "דקה", + mm : "%d דקות", + h : "שעה", + hh : "%d שעות", + d : "יום", + dd : "%d ימים", + M : "חודש", + MM : "%d חודשים", + y : "שנה", + yy : "%d שנים" + } +}); diff --git a/node_modules/moment/lang/hi.js b/node_modules/moment/lang/hi.js new file mode 100644 index 0000000..c3de1ea --- /dev/null +++ b/node_modules/moment/lang/hi.js @@ -0,0 +1,95 @@ +// moment.js language configuration +// language : hindi (hi) +// author : Mayank Singhal : https://github.com/mayanksinghal + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +require('../moment').lang('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split("_"), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split("_"), + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split("_"), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"), + longDateFormat : { + LT : "A h:mm बजे", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY, LT", + LLLL : "dddd, D MMMM YYYY, LT" + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[कल] LT', + nextWeek : 'dddd, LT', + lastDay : '[कल] LT', + lastWeek : '[पिछले] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s में", + past : "%s पहले", + s : "कुछ ही क्षण", + m : "एक मिनट", + mm : "%d मिनट", + h : "एक घंटा", + hh : "%d घंटे", + d : "एक दिन", + dd : "%d दिन", + M : "एक महीने", + MM : "%d महीने", + y : "एक वर्ष", + yy : "%d वर्ष" + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // Hindi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return "रात"; + } else if (hour < 10) { + return "सुबह"; + } else if (hour < 17) { + return "दोपहर"; + } else if (hour < 20) { + return "शाम"; + } else { + return "रात"; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/hu.js b/node_modules/moment/lang/hu.js new file mode 100644 index 0000000..2f6cbb6 --- /dev/null +++ b/node_modules/moment/lang/hu.js @@ -0,0 +1,87 @@ +// moment.js language configuration +// language : hungarian (hu) +// author : Adam Brunner : https://github.com/adambrunner + +var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); + +function translate(number, withoutSuffix, key, isFuture) { + var num = number, + suffix; + + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + case 'm': + return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'h': + return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'd': + return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'M': + return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'y': + return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + } + + return ''; +} + +function week(isFuture) { + return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; +} + +require('../moment').lang('hu', { + months : "január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"), + monthsShort : "jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"), + weekdays : "vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"), + weekdaysShort : "v_h_k_sze_cs_p_szo".split("_"), + longDateFormat : { + LT : "H:mm", + L : "YYYY.MM.DD.", + LL : "YYYY. MMMM D.", + LLL : "YYYY. MMMM D., LT", + LLLL : "YYYY. MMMM D., dddd LT" + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function () { + return week.call(this, true); + }, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function () { + return week.call(this, false); + }, + sameElse : 'L' + }, + relativeTime : { + future : "%s múlva", + past : "%s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/id.js b/node_modules/moment/lang/id.js new file mode 100644 index 0000000..1a27adb --- /dev/null +++ b/node_modules/moment/lang/id.js @@ -0,0 +1,57 @@ +// moment.js language configuration +// language : Bahasa Indonesia (id) +// author : Mohammad Satrio Utomo : https://github.com/tyok +// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + +require('../moment').lang('id', { + months : "Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"), + weekdays : "Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"), + weekdaysShort : "Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"), + weekdaysMin : "Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY [pukul] LT", + LLLL : "dddd, D MMMM YYYY [pukul] LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'siang'; + } else if (hours < 19) { + return 'sore'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Besok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kemarin pukul] LT', + lastWeek : 'dddd [lalu pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : "dalam %s", + past : "%s yang lalu", + s : "beberapa detik", + m : "semenit", + mm : "%d menit", + h : "sejam", + hh : "%d jam", + d : "sehari", + dd : "%d hari", + M : "sebulan", + MM : "%d bulan", + y : "setahun", + yy : "%d tahun" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/is.js b/node_modules/moment/lang/is.js new file mode 100644 index 0000000..ec594e3 --- /dev/null +++ b/node_modules/moment/lang/is.js @@ -0,0 +1,114 @@ +// moment.js language configuration +// language : icelandic (is) +// author : Hinrik Örn Sigurðsson : https://github.com/hinrik + +function plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; +} + +function translate(number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } + return result + 'mínútu'; + case 'hh': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (plural(number)) { + if (withoutSuffix) { + return result + 'dagar'; + } + return result + (isFuture ? 'daga' : 'dögum'); + } else if (withoutSuffix) { + return result + 'dagur'; + } + return result + (isFuture ? 'dag' : 'degi'); + case 'M': + if (withoutSuffix) { + return 'mánuður'; + } + return isFuture ? 'mánuð' : 'mánuði'; + case 'MM': + if (plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir'; + } + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } else if (withoutSuffix) { + return result + 'mánuður'; + } + return result + (isFuture ? 'mánuð' : 'mánuði'); + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } +} + +require('../moment').lang('is', { + months : "janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"), + monthsShort : "jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"), + weekdays : "sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"), + weekdaysShort : "sun_mán_þri_mið_fim_fös_lau".split("_"), + weekdaysMin : "Su_Má_Þr_Mi_Fi_Fö_La".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY [kl.] LT", + LLLL : "dddd, D. MMMM YYYY [kl.] LT" + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : "eftir %s", + past : "fyrir %s síðan", + s : translate, + m : translate, + mm : translate, + h : "klukkustund", + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/it.js b/node_modules/moment/lang/it.js new file mode 100644 index 0000000..c9df924 --- /dev/null +++ b/node_modules/moment/lang/it.js @@ -0,0 +1,49 @@ +// moment.js language configuration +// language : italian (it) +// author : Lorenzo : https://github.com/aliem +// author: Mattia Larentis: https://github.com/nostalgiaz + +require('../moment').lang('it', { + months : "Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"), + monthsShort : "Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"), + weekdays : "Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"), + weekdaysShort : "Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"), + weekdaysMin : "D_L_Ma_Me_G_V_S".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: '[lo scorso] dddd [alle] LT', + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? "tra" : "in") + " " + s; + }, + past : "%s fa", + s : "secondi", + m : "un minuto", + mm : "%d minuti", + h : "un'ora", + hh : "%d ore", + d : "un giorno", + dd : "%d giorni", + M : "un mese", + MM : "%d mesi", + y : "un anno", + yy : "%d anni" + }, + ordinal: '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/ja.js b/node_modules/moment/lang/ja.js new file mode 100644 index 0000000..84ce6e8 --- /dev/null +++ b/node_modules/moment/lang/ja.js @@ -0,0 +1,48 @@ +// moment.js language configuration +// language : japanese (ja) +// author : LI Long : https://github.com/baryon + +require('../moment').lang('ja', { + months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"), + weekdaysShort : "日_月_火_水_木_金_土".split("_"), + weekdaysMin : "日_月_火_水_木_金_土".split("_"), + longDateFormat : { + LT : "Ah時m分", + L : "YYYY/MM/DD", + LL : "YYYY年M月D日", + LLL : "YYYY年M月D日LT", + LLLL : "YYYY年M月D日LT dddd" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "午前"; + } else { + return "午後"; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s後", + past : "%s前", + s : "数秒", + m : "1分", + mm : "%d分", + h : "1時間", + hh : "%d時間", + d : "1日", + dd : "%d日", + M : "1ヶ月", + MM : "%dヶ月", + y : "1年", + yy : "%d年" + } +}); diff --git a/node_modules/moment/lang/ka.js b/node_modules/moment/lang/ka.js new file mode 100644 index 0000000..10252f6 --- /dev/null +++ b/node_modules/moment/lang/ka.js @@ -0,0 +1,97 @@ +// moment.js language configuration +// language : Georgian (ka) +// author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + 'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + + nounCase = (/D[oD] *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; +} + +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + 'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_') + }, + + nounCase = (/(წინა|შემდეგ)/).test(format) ? + 'accusative' : + 'nominative'; + + return weekdays[nounCase][m.day()]; +} + +require('../moment').lang('ka', { + months : monthsCaseReplace, + monthsShort : "იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"), + weekdaysMin : "კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[დღეს] LT[-ზე]', + nextDay : '[ხვალ] LT[-ზე]', + lastDay : '[გუშინ] LT[-ზე]', + nextWeek : '[შემდეგ] dddd LT[-ზე]', + lastWeek : '[წინა] dddd LT-ზე', + sameElse : 'L' + }, + relativeTime : { + future : function (s) { + return (/(წამი|წუთი|საათი|წელი)/).test(s) ? + s.replace(/ი$/, "ში") : + s + "ში"; + }, + past : function (s) { + if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { + return s.replace(/(ი|ე)$/, "ის წინ"); + } + if ((/წელი/).test(s)) { + return s.replace(/წელი$/, "წლის წინ"); + } + }, + s : "რამდენიმე წამი", + m : "წუთი", + mm : "%d წუთი", + h : "საათი", + hh : "%d საათი", + d : "დღე", + dd : "%d დღე", + M : "თვე", + MM : "%d თვე", + y : "წელი", + yy : "%d წელი" + }, + ordinal : function (number) { + if (number === 0) { + return number; + } + + if (number === 1) { + return number + "-ლი"; + } + + if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { + return "მე-" + number; + } + + return number + "-ე"; + }, + week : { + dow : 1, + doy : 7 + } +}); diff --git a/node_modules/moment/lang/ko.js b/node_modules/moment/lang/ko.js new file mode 100644 index 0000000..7a59cb7 --- /dev/null +++ b/node_modules/moment/lang/ko.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : korean (ko) +// author : Kyungwook, Park : https://github.com/kyungw00k + +require('../moment').lang('ko', { + months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"), + weekdaysShort : "일_월_화_수_목_금_토".split("_"), + weekdaysMin : "일_월_화_수_목_금_토".split("_"), + longDateFormat : { + LT : "A h시 mm분", + L : "YYYY.MM.DD", + LL : "YYYY년 MMMM D일", + LLL : "YYYY년 MMMM D일 LT", + LLLL : "YYYY년 MMMM D일 dddd LT" + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s 후", + past : "%s 전", + s : "몇초", + ss : "%d초", + m : "일분", + mm : "%d분", + h : "한시간", + hh : "%d시간", + d : "하루", + dd : "%d일", + M : "한달", + MM : "%d달", + y : "일년", + yy : "%d년" + }, + ordinal : '%d일' +}); diff --git a/node_modules/moment/lang/lv.js b/node_modules/moment/lang/lv.js new file mode 100644 index 0000000..7a721ac --- /dev/null +++ b/node_modules/moment/lang/lv.js @@ -0,0 +1,67 @@ +// moment.js language configuration +// language : latvian (lv) +// author : Kristaps Karlsons : https://github.com/skakri + +var units = { + 'mm': 'minūti_minūtes_minūte_minūtes', + 'hh': 'stundu_stundas_stunda_stundas', + 'dd': 'dienu_dienas_diena_dienas', + 'MM': 'mēnesi_mēnešus_mēnesis_mēneši', + 'yy': 'gadu_gadus_gads_gadi' +}; + +function format(word, number, withoutSuffix) { + var forms = word.split('_'); + if (withoutSuffix) { + return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; + } else { + return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; + } +} + +function relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(units[key], number, withoutSuffix); +} + +require('../moment').lang('lv', { + months : "janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"), + weekdays : "svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"), + weekdaysShort : "Sv_P_O_T_C_Pk_S".split("_"), + weekdaysMin : "Sv_P_O_T_C_Pk_S".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "YYYY. [gada] D. MMMM", + LLL : "YYYY. [gada] D. MMMM, LT", + LLLL : "YYYY. [gada] D. MMMM, dddd, LT" + }, + calendar : { + sameDay : '[Šodien pulksten] LT', + nextDay : '[Rīt pulksten] LT', + nextWeek : 'dddd [pulksten] LT', + lastDay : '[Vakar pulksten] LT', + lastWeek : '[Pagājušā] dddd [pulksten] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s vēlāk", + past : "%s agrāk", + s : "dažas sekundes", + m : "minūti", + mm : relativeTimeWithPlural, + h : "stundu", + hh : relativeTimeWithPlural, + d : "dienu", + dd : relativeTimeWithPlural, + M : "mēnesi", + MM : relativeTimeWithPlural, + y : "gadu", + yy : relativeTimeWithPlural + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/ms-my.js b/node_modules/moment/lang/ms-my.js new file mode 100644 index 0000000..fae7160 --- /dev/null +++ b/node_modules/moment/lang/ms-my.js @@ -0,0 +1,56 @@ +// moment.js language configuration +// language : Bahasa Malaysia (ms-MY) +// author : Weldan Jamili : https://github.com/weldan + +require('../moment').lang('ms-my', { + months : "Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"), + monthsShort : "Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"), + weekdays : "Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"), + weekdaysShort : "Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"), + weekdaysMin : "Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY [pukul] LT", + LLLL : "dddd, D MMMM YYYY [pukul] LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : "dalam %s", + past : "%s yang lepas", + s : "beberapa saat", + m : "seminit", + mm : "%d minit", + h : "sejam", + hh : "%d jam", + d : "sehari", + dd : "%d hari", + M : "sebulan", + MM : "%d bulan", + y : "setahun", + yy : "%d tahun" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/nb.js b/node_modules/moment/lang/nb.js new file mode 100644 index 0000000..a39f8f5 --- /dev/null +++ b/node_modules/moment/lang/nb.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : norwegian bokmål (nb) +// author : Espen Hovlandsdal : https://github.com/rexxars + +require('../moment').lang('nb', { + months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"), + weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"), + weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"), + weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[I dag klokken] LT', + nextDay: '[I morgen klokken] LT', + nextWeek: 'dddd [klokken] LT', + lastDay: '[I går klokken] LT', + lastWeek: '[Forrige] dddd [klokken] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "for %s siden", + s : "noen sekunder", + m : "ett minutt", + mm : "%d minutter", + h : "en time", + hh : "%d timer", + d : "en dag", + dd : "%d dager", + M : "en måned", + MM : "%d måneder", + y : "ett år", + yy : "%d år" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/ne.js b/node_modules/moment/lang/ne.js new file mode 100644 index 0000000..6df9a9c --- /dev/null +++ b/node_modules/moment/lang/ne.js @@ -0,0 +1,95 @@ +// moment.js language configuration +// language : nepali/nepalese +// author : suvash : https://github.com/suvash + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +require('../moment').lang('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split("_"), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split("_"), + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split("_"), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split("_"), + weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split("_"), + longDateFormat : { + LT : "Aको h:mm बजे", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY, LT", + LLLL : "dddd, D MMMM YYYY, LT" + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 3) { + return "राती"; + } else if (hour < 10) { + return "बिहान"; + } else if (hour < 15) { + return "दिउँसो"; + } else if (hour < 18) { + return "बेलुका"; + } else if (hour < 20) { + return "साँझ"; + } else { + return "राती"; + } + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[भोली] LT', + nextWeek : '[आउँदो] dddd[,] LT', + lastDay : '[हिजो] LT', + lastWeek : '[गएको] dddd[,] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%sमा", + past : "%s अगाडी", + s : "केही समय", + m : "एक मिनेट", + mm : "%d मिनेट", + h : "एक घण्टा", + hh : "%d घण्टा", + d : "एक दिन", + dd : "%d दिन", + M : "एक महिना", + MM : "%d महिना", + y : "एक बर्ष", + yy : "%d बर्ष" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/nl.js b/node_modules/moment/lang/nl.js new file mode 100644 index 0000000..018990b --- /dev/null +++ b/node_modules/moment/lang/nl.js @@ -0,0 +1,57 @@ +// moment.js language configuration +// language : dutch (nl) +// author : Joris Röling : https://github.com/jjupiter + +var monthsShortWithDots = "jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"), + monthsShortWithoutDots = "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"); + +require('../moment').lang('nl', { + months : "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + weekdays : "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"), + weekdaysShort : "zo._ma._di._wo._do._vr._za.".split("_"), + weekdaysMin : "Zo_Ma_Di_Wo_Do_Vr_Za".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Vandaag om] LT', + nextDay: '[Morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[Gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : "over %s", + past : "%s geleden", + s : "een paar seconden", + m : "één minuut", + mm : "%d minuten", + h : "één uur", + hh : "%d uur", + d : "één dag", + dd : "%d dagen", + M : "één maand", + MM : "%d maanden", + y : "één jaar", + yy : "%d jaar" + }, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/nn.js b/node_modules/moment/lang/nn.js new file mode 100644 index 0000000..b57a58f --- /dev/null +++ b/node_modules/moment/lang/nn.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : norwegian nynorsk (nn) +// author : https://github.com/mechuwind + +require('../moment').lang('nn', { + months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"), + weekdays : "sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"), + weekdaysShort : "sun_mån_tys_ons_tor_fre_lau".split("_"), + weekdaysMin : "su_må_ty_on_to_fr_lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[I dag klokka] LT', + nextDay: '[I morgon klokka] LT', + nextWeek: 'dddd [klokka] LT', + lastDay: '[I går klokka] LT', + lastWeek: '[Føregående] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "for %s siden", + s : "noen sekund", + m : "ett minutt", + mm : "%d minutt", + h : "en time", + hh : "%d timar", + d : "en dag", + dd : "%d dagar", + M : "en månad", + MM : "%d månader", + y : "ett år", + yy : "%d år" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/pl.js b/node_modules/moment/lang/pl.js new file mode 100644 index 0000000..9e511f7 --- /dev/null +++ b/node_modules/moment/lang/pl.js @@ -0,0 +1,88 @@ +// moment.js language configuration +// language : polish (pl) +// author : Rafal Hirsz : https://github.com/evoL + +var monthsNominative = "styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"), + monthsSubjective = "stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"); + +function plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && (~~(n / 10) !== 1); +} + +function translate(number, withoutSuffix, key) { + var result = number + " "; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (plural(number) ? 'lata' : 'lat'); + } +} + +require('../moment').lang('pl', { + months : function (momentToFormat, format) { + if (/D MMMM/.test(format)) { + return monthsSubjective[momentToFormat.month()]; + } else { + return monthsNominative[momentToFormat.month()]; + } + }, + monthsShort : "sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"), + weekdays : "niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"), + weekdaysShort : "nie_pon_wt_śr_czw_pt_sb".split("_"), + weekdaysMin : "N_Pn_Wt_Śr_Cz_Pt_So".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[W zeszłą niedzielę o] LT'; + case 3: + return '[W zeszłą środę o] LT'; + case 6: + return '[W zeszłą sobotę o] LT'; + default: + return '[W zeszły] dddd [o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : "za %s", + past : "%s temu", + s : "kilka sekund", + m : translate, + mm : translate, + h : translate, + hh : translate, + d : "1 dzień", + dd : '%d dni', + M : "miesiąc", + MM : translate, + y : "rok", + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/pt-br.js b/node_modules/moment/lang/pt-br.js new file mode 100644 index 0000000..bdb441d --- /dev/null +++ b/node_modules/moment/lang/pt-br.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : brazilian portuguese (pt-br) +// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + +require('../moment').lang('pt-br', { + months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"), + monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"), + weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"), + weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"), + weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D [de] MMMM [de] YYYY", + LLL : "D [de] MMMM [de] YYYY LT", + LLLL : "dddd, D [de] MMMM [de] YYYY LT" + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : "em %s", + past : "%s atrás", + s : "segundos", + m : "um minuto", + mm : "%d minutos", + h : "uma hora", + hh : "%d horas", + d : "um dia", + dd : "%d dias", + M : "um mês", + MM : "%d meses", + y : "um ano", + yy : "%d anos" + }, + ordinal : '%dº' +}); diff --git a/node_modules/moment/lang/pt.js b/node_modules/moment/lang/pt.js new file mode 100644 index 0000000..01a5f08 --- /dev/null +++ b/node_modules/moment/lang/pt.js @@ -0,0 +1,50 @@ +// moment.js language configuration +// language : portuguese (pt) +// author : Jefferson : https://github.com/jalex79 + +require('../moment').lang('pt', { + months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"), + monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"), + weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"), + weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"), + weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D [de] MMMM [de] YYYY", + LLL : "D [de] MMMM [de] YYYY LT", + LLLL : "dddd, D [de] MMMM [de] YYYY LT" + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : "em %s", + past : "%s atrás", + s : "segundos", + m : "um minuto", + mm : "%d minutos", + h : "uma hora", + hh : "%d horas", + d : "um dia", + dd : "%d dias", + M : "um mês", + MM : "%d meses", + y : "um ano", + yy : "%d anos" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/readme.md b/node_modules/moment/lang/readme.md new file mode 100644 index 0000000..f8c0f61 --- /dev/null +++ b/node_modules/moment/lang/readme.md @@ -0,0 +1,5 @@ +# Using language files in the browser + +The files in this directory are optimized for use with Node.js, hence the `require('../moment')` calls at the beginning of each file. + +If you are looking to use these files in the browser, the minified version of these files in `/min/lang/` are a better fit. We do some trickery to make each language file work with or without requirejs. If you are interested in the details, check out `/tasks/minify-lang.js`. diff --git a/node_modules/moment/lang/ro.js b/node_modules/moment/lang/ro.js new file mode 100644 index 0000000..036c85b --- /dev/null +++ b/node_modules/moment/lang/ro.js @@ -0,0 +1,46 @@ +// moment.js language configuration +// language : romanian (ro) +// author : Vlad Gurdiga : https://github.com/gurdiga +// author : Valentin Agachi : https://github.com/avaly + +require('../moment').lang('ro', { + months : "Ianuarie_Februarie_Martie_Aprilie_Mai_Iunie_Iulie_August_Septembrie_Octombrie_Noiembrie_Decembrie".split("_"), + monthsShort : "Ian_Feb_Mar_Apr_Mai_Iun_Iul_Aug_Sep_Oct_Noi_Dec".split("_"), + weekdays : "Duminică_Luni_Marţi_Miercuri_Joi_Vineri_Sâmbătă".split("_"), + weekdaysShort : "Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"), + weekdaysMin : "Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY H:mm", + LLLL : "dddd, D MMMM YYYY H:mm" + }, + calendar : { + sameDay: "[azi la] LT", + nextDay: '[mâine la] LT', + nextWeek: 'dddd [la] LT', + lastDay: '[ieri la] LT', + lastWeek: '[fosta] dddd [la] LT', + sameElse: 'L' + }, + relativeTime : { + future : "peste %s", + past : "%s în urmă", + s : "câteva secunde", + m : "un minut", + mm : "%d minute", + h : "o oră", + hh : "%d ore", + d : "o zi", + dd : "%d zile", + M : "o lună", + MM : "%d luni", + y : "un an", + yy : "%d ani" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/ru.js b/node_modules/moment/lang/ru.js new file mode 100644 index 0000000..069f675 --- /dev/null +++ b/node_modules/moment/lang/ru.js @@ -0,0 +1,125 @@ +// moment.js language configuration +// language : russian (ru) +// author : Viktorminator : https://github.com/Viktorminator +// Author : Menelion Elensúle : https://github.com/Oire + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} + +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'минута_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, + + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; +} + +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') + }, + + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + + return weekdays[nounCase][m.day()]; +} + +require('../moment').lang('ru', { + months : monthsCaseReplace, + monthsShort : "янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "вск_пнд_втр_срд_чтв_птн_сбт".split("_"), + weekdaysMin : "вс_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY г.", + LLL : "D MMMM YYYY г., LT", + LLLL : "dddd, D MMMM YYYY г., LT" + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function () { + return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : "через %s", + past : "%s назад", + s : "несколько секунд", + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : "час", + hh : relativeTimeWithPlural, + d : "день", + dd : relativeTimeWithPlural, + M : "месяц", + MM : relativeTimeWithPlural, + y : "год", + yy : relativeTimeWithPlural + }, + + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + return number + '-й'; + case 'D': + return number + '-го'; + case 'w': + case 'W': + return number + '-я'; + default: + return number; + } + }, + + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/sk.js b/node_modules/moment/lang/sk.js new file mode 100644 index 0000000..41c1189 --- /dev/null +++ b/node_modules/moment/lang/sk.js @@ -0,0 +1,146 @@ +// moment.js language configuration +// language : slovak (sk) +// author : Martin Minka : https://github.com/k2s +// based on work of petrbela : https://github.com/petrbela + +var months = "január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"), + monthsShort = "jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_"); + +function plural(n) { + return (n > 1) && (n < 5); +} + +function translate(number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minúty' : 'minút'); + } else { + return result + 'minútami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodín'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dni' : 'dní'); + } else { + return result + 'dňami'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'mesiace' : 'mesiacov'); + } else { + return result + 'mesiacmi'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } +} + +require('../moment').lang('sk', { + months : months, + monthsShort : monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(months, monthsShort)), + weekdays : "nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"), + weekdaysShort : "ne_po_ut_st_št_pi_so".split("_"), + weekdaysMin : "ne_po_ut_st_št_pi_so".split("_"), + longDateFormat : { + LT: "H:mm", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[dnes o] LT", + nextDay: '[zajtra o] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v nedeľu o] LT'; + case 1: + case 2: + return '[v] dddd [o] LT'; + case 3: + return '[v stredu o] LT'; + case 4: + return '[vo štvrtok o] LT'; + case 5: + return '[v piatok o] LT'; + case 6: + return '[v sobotu o] LT'; + } + }, + lastDay: '[včera o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulú nedeľu o] LT'; + case 1: + case 2: + return '[minulý] dddd [o] LT'; + case 3: + return '[minulú stredu o] LT'; + case 4: + case 5: + return '[minulý] dddd [o] LT'; + case 6: + return '[minulú sobotu o] LT'; + } + }, + sameElse: "L" + }, + relativeTime : { + future : "za %s", + past : "pred %s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/sl.js b/node_modules/moment/lang/sl.js new file mode 100644 index 0000000..a284f06 --- /dev/null +++ b/node_modules/moment/lang/sl.js @@ -0,0 +1,134 @@ +// moment.js language configuration +// language : slovenian (sl) +// author : Robert Sedovšek : https://github.com/sedovsek + +function translate(number, withoutSuffix, key) { + var result = number + " "; + switch (key) { + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2) { + result += 'minuti'; + } else if (number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minut'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += 'ura'; + } else if (number === 2) { + result += 'uri'; + } else if (number === 3 || number === 4) { + result += 'ure'; + } else { + result += 'ur'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dni'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mesec'; + } else if (number === 2) { + result += 'meseca'; + } else if (number === 3 || number === 4) { + result += 'mesece'; + } else { + result += 'mesecev'; + } + return result; + case 'yy': + if (number === 1) { + result += 'leto'; + } else if (number === 2) { + result += 'leti'; + } else if (number === 3 || number === 4) { + result += 'leta'; + } else { + result += 'let'; + } + return result; + } +} + +require('../moment').lang('sl', { + months : "januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"), + monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"), + weekdays : "nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"), + weekdaysShort : "ned._pon._tor._sre._čet._pet._sob.".split("_"), + weekdaysMin : "ne_po_to_sr_če_pe_so".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD. MM. YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay : '[danes ob] LT', + nextDay : '[jutri ob] LT', + + nextWeek : function () { + switch (this.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + }, + lastDay : '[včeraj ob] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[prejšnja] dddd [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : "čez %s", + past : "%s nazaj", + s : "nekaj sekund", + m : translate, + mm : translate, + h : translate, + hh : translate, + d : "en dan", + dd : translate, + M : "en mesec", + MM : translate, + y : "eno leto", + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/sq.js b/node_modules/moment/lang/sq.js new file mode 100644 index 0000000..833fe3e --- /dev/null +++ b/node_modules/moment/lang/sq.js @@ -0,0 +1,47 @@ +// moment.js language configuration +// language : Albanian (sq) +// author : Flakërim Ismani : https://github.com/flakerimi +// author: Menelion Elensúle: https://github.com/Oire (tests) + +require('../moment').lang('sq', { + months : "Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"), + monthsShort : "Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"), + weekdays : "E Diel_E Hënë_E Marte_E Mërkure_E Enjte_E Premte_E Shtunë".split("_"), + weekdaysShort : "Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"), + weekdaysMin : "D_H_Ma_Më_E_P_Sh".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Sot në] LT', + nextDay : '[Neser në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : "në %s", + past : "%s me parë", + s : "disa seconda", + m : "një minut", + mm : "%d minutea", + h : "një orë", + hh : "%d orë", + d : "një ditë", + dd : "%d ditë", + M : "një muaj", + MM : "%d muaj", + y : "një vit", + yy : "%d vite" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/sv.js b/node_modules/moment/lang/sv.js new file mode 100644 index 0000000..e3ea627 --- /dev/null +++ b/node_modules/moment/lang/sv.js @@ -0,0 +1,53 @@ +// moment.js language configuration +// language : swedish (sv) +// author : Jens Alm : https://github.com/ulmus + +require('../moment').lang('sv', { + months : "januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"), + monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"), + weekdays : "söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"), + weekdaysShort : "sön_mån_tis_ons_tor_fre_lör".split("_"), + weekdaysMin : "sö_må_ti_on_to_fr_lö".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Idag] LT', + nextDay: '[Imorgon] LT', + lastDay: '[Igår] LT', + nextWeek: 'dddd LT', + lastWeek: '[Förra] dddd[en] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "för %s sedan", + s : "några sekunder", + m : "en minut", + mm : "%d minuter", + h : "en timme", + hh : "%d timmar", + d : "en dag", + dd : "%d dagar", + M : "en månad", + MM : "%d månader", + y : "ett år", + yy : "%d år" + }, + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/th.js b/node_modules/moment/lang/th.js new file mode 100644 index 0000000..d2699cd --- /dev/null +++ b/node_modules/moment/lang/th.js @@ -0,0 +1,48 @@ +// moment.js language configuration +// language : thai (th) +// author : Kridsada Thanabulpong : https://github.com/sirn + +require('../moment').lang('th', { + months : "มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"), + monthsShort : "มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"), + weekdays : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"), + weekdaysShort : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"), // yes, three characters difference + weekdaysMin : "อา._จ._อ._พ._พฤ._ศ._ส.".split("_"), + longDateFormat : { + LT : "H นาฬิกา m นาที", + L : "YYYY/MM/DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY เวลา LT", + LLLL : "วันddddที่ D MMMM YYYY เวลา LT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "ก่อนเที่ยง"; + } else { + return "หลังเที่ยง"; + } + }, + calendar : { + sameDay : '[วันนี้ เวลา] LT', + nextDay : '[พรุ่งนี้ เวลา] LT', + nextWeek : 'dddd[หน้า เวลา] LT', + lastDay : '[เมื่อวานนี้ เวลา] LT', + lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', + sameElse : 'L' + }, + relativeTime : { + future : "อีก %s", + past : "%sที่แล้ว", + s : "ไม่กี่วินาที", + m : "1 นาที", + mm : "%d นาที", + h : "1 ชั่วโมง", + hh : "%d ชั่วโมง", + d : "1 วัน", + dd : "%d วัน", + M : "1 เดือน", + MM : "%d เดือน", + y : "1 ปี", + yy : "%d ปี" + } +}); diff --git a/node_modules/moment/lang/tr.js b/node_modules/moment/lang/tr.js new file mode 100644 index 0000000..731bfff --- /dev/null +++ b/node_modules/moment/lang/tr.js @@ -0,0 +1,82 @@ +// moment.js language configuration +// language : turkish (tr) +// authors : Erhan Gundogan : https://github.com/erhangundogan, +// Burak Yiğit Kaya: https://github.com/BYK + +var suffixes = { + 1: "'inci", + 5: "'inci", + 8: "'inci", + 70: "'inci", + 80: "'inci", + + 2: "'nci", + 7: "'nci", + 20: "'nci", + 50: "'nci", + + 3: "'üncü", + 4: "'üncü", + 100: "'üncü", + + 6: "'ncı", + + 9: "'uncu", + 10: "'uncu", + 30: "'uncu", + + 60: "'ıncı", + 90: "'ıncı" +}; + +require('../moment').lang('tr', { + months : "Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"), + monthsShort : "Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"), + weekdays : "Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"), + weekdaysShort : "Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"), + weekdaysMin : "Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s sonra", + past : "%s önce", + s : "birkaç saniye", + m : "bir dakika", + mm : "%d dakika", + h : "bir saat", + hh : "%d saat", + d : "bir gün", + dd : "%d gün", + M : "bir ay", + MM : "%d ay", + y : "bir yıl", + yy : "%d yıl" + }, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + "'ıncı"; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + + return number + (suffixes[a] || suffixes[b] || suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/tzm-la.js b/node_modules/moment/lang/tzm-la.js new file mode 100644 index 0000000..870947e --- /dev/null +++ b/node_modules/moment/lang/tzm-la.js @@ -0,0 +1,45 @@ +// moment.js language configuration +// language : Morocco Central Atlas Tamaziɣt in Latin (tzm-la) +// author : Abdel Said : https://github.com/abdelsaid + +require('../moment').lang('tzm-la', { + months : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"), + monthsShort : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"), + weekdays : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"), + weekdaysShort : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"), + weekdaysMin : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[asdkh g] LT", + nextDay: '[aska g] LT', + nextWeek: 'dddd [g] LT', + lastDay: '[assant g] LT', + lastWeek: 'dddd [g] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dadkh s yan %s", + past : "yan %s", + s : "imik", + m : "minuḍ", + mm : "%d minuḍ", + h : "saɛa", + hh : "%d tassaɛin", + d : "ass", + dd : "%d ossan", + M : "ayowr", + MM : "%d iyyirn", + y : "asgas", + yy : "%d isgasn" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/tzm.js b/node_modules/moment/lang/tzm.js new file mode 100644 index 0000000..cffb946 --- /dev/null +++ b/node_modules/moment/lang/tzm.js @@ -0,0 +1,45 @@ +// moment.js language configuration +// language : Morocco Central Atlas Tamaziɣt (tzm) +// author : Abdel Said : https://github.com/abdelsaid + +require('../moment').lang('tzm', { + months : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"), + monthsShort : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"), + weekdays : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"), + weekdaysShort : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"), + weekdaysMin : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[ⴰⵙⴷⵅ ⴴ] LT", + nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', + nextWeek: 'dddd [ⴴ] LT', + lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', + lastWeek: 'dddd [ⴴ] LT', + sameElse: 'L' + }, + relativeTime : { + future : "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s", + past : "ⵢⴰⵏ %s", + s : "ⵉⵎⵉⴽ", + m : "ⵎⵉⵏⵓⴺ", + mm : "%d ⵎⵉⵏⵓⴺ", + h : "ⵙⴰⵄⴰ", + hh : "%d ⵜⴰⵙⵙⴰⵄⵉⵏ", + d : "ⴰⵙⵙ", + dd : "%d oⵙⵙⴰⵏ", + M : "ⴰⵢoⵓⵔ", + MM : "%d ⵉⵢⵢⵉⵔⵏ", + y : "ⴰⵙⴳⴰⵙ", + yy : "%d ⵉⵙⴳⴰⵙⵏ" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/uk.js b/node_modules/moment/lang/uk.js new file mode 100644 index 0000000..6275411 --- /dev/null +++ b/node_modules/moment/lang/uk.js @@ -0,0 +1,132 @@ +// moment.js language configuration +// language : ukrainian (uk) +// author : zemlanin : https://github.com/zemlanin +// Author : Menelion Elensúle : https://github.com/Oire + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} + +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'хвилина_хвилини_хвилин', + 'hh': 'година_години_годин', + 'dd': 'день_дні_днів', + 'MM': 'місяць_місяці_місяців', + 'yy': 'рік_роки_років' + }; + if (key === 'm') { + return withoutSuffix ? 'хвилина' : 'хвилину'; + } + else if (key === 'h') { + return withoutSuffix ? 'година' : 'годину'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), + 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') + }, + + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; +} + +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), + 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), + 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') + }, + + nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? + 'accusative' : + ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? + 'genitive' : + 'nominative'); + + return weekdays[nounCase][m.day()]; +} + +function processHoursFunction(str) { + return function () { + return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; + }; +} + +require('../moment').lang('uk', { + months : monthsCaseReplace, + monthsShort : "січ_лют_бер_кві_тра_чер_лип_сер_вер_жов_лис_гру".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "нед_пон_вів_срд_чет_птн_суб".split("_"), + weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY р.", + LLL : "D MMMM YYYY р., LT", + LLLL : "dddd, D MMMM YYYY р., LT" + }, + calendar : { + sameDay: processHoursFunction('[Сьогодні '), + nextDay: processHoursFunction('[Завтра '), + lastDay: processHoursFunction('[Вчора '), + nextWeek: processHoursFunction('[У] dddd ['), + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return processHoursFunction('[Минулої] dddd [').call(this); + case 1: + case 2: + case 4: + return processHoursFunction('[Минулого] dddd [').call(this); + } + }, + sameElse: 'L' + }, + relativeTime : { + future : "за %s", + past : "%s тому", + s : "декілька секунд", + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : "годину", + hh : relativeTimeWithPlural, + d : "день", + dd : relativeTimeWithPlural, + M : "місяць", + MM : relativeTimeWithPlural, + y : "рік", + yy : relativeTimeWithPlural + }, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return number + '-й'; + case 'D': + return number + '-го'; + default: + return number; + } + }, + + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); diff --git a/node_modules/moment/lang/zh-cn.js b/node_modules/moment/lang/zh-cn.js new file mode 100644 index 0000000..e755416 --- /dev/null +++ b/node_modules/moment/lang/zh-cn.js @@ -0,0 +1,73 @@ +// moment.js language configuration +// language : chinese +// author : suupic : https://github.com/suupic + +require('../moment').lang('zh-cn', { + months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"), + weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"), + weekdaysMin : "日_一_二_三_四_五_六".split("_"), + longDateFormat : { + LT : "Ah点mm", + L : "YYYY年MMMD日", + LL : "YYYY年MMMD日", + LLL : "YYYY年MMMD日LT", + LLLL : "YYYY年MMMD日ddddLT", + l : "YYYY年MMMD日", + ll : "YYYY年MMMD日", + lll : "YYYY年MMMD日LT", + llll : "YYYY年MMMD日ddddLT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 9) { + return "早上"; + } else if (hour < 11 && minute < 30) { + return "上午"; + } else if (hour < 13 && minute < 30) { + return "中午"; + } else if (hour < 18) { + return "下午"; + } else { + return "晚上"; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinal : function (number, period) { + switch (period) { + case "d" : + case "D" : + case "DDD" : + return number + "日"; + case "M" : + return number + "月"; + case "w" : + case "W" : + return number + "周"; + default : + return number; + } + }, + relativeTime : { + future : "%s内", + past : "%s前", + s : "几秒", + m : "1分钟", + mm : "%d分钟", + h : "1小时", + hh : "%d小时", + d : "1天", + dd : "%d天", + M : "1个月", + MM : "%d个月", + y : "1年", + yy : "%d年" + } +}); diff --git a/node_modules/moment/lang/zh-tw.js b/node_modules/moment/lang/zh-tw.js new file mode 100644 index 0000000..ee9b87b --- /dev/null +++ b/node_modules/moment/lang/zh-tw.js @@ -0,0 +1,73 @@ +// moment.js language configuration +// language : traditional chinese (zh-tw) +// author : Ben : https://github.com/ben-lin + +require('../moment').lang('zh-tw', { + months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"), + weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"), + weekdaysMin : "日_一_二_三_四_五_六".split("_"), + longDateFormat : { + LT : "Ah點mm", + L : "YYYY年MMMD日", + LL : "YYYY年MMMD日", + LLL : "YYYY年MMMD日LT", + LLLL : "YYYY年MMMD日ddddLT", + l : "YYYY年MMMD日", + ll : "YYYY年MMMD日", + lll : "YYYY年MMMD日LT", + llll : "YYYY年MMMD日ddddLT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 9) { + return "早上"; + } else if (hour < 11 && minute < 30) { + return "上午"; + } else if (hour < 13 && minute < 30) { + return "中午"; + } else if (hour < 18) { + return "下午"; + } else { + return "晚上"; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinal : function (number, period) { + switch (period) { + case "d" : + case "D" : + case "DDD" : + return number + "日"; + case "M" : + return number + "月"; + case "w" : + case "W" : + return number + "週"; + default : + return number; + } + }, + relativeTime : { + future : "%s內", + past : "%s前", + s : "幾秒", + m : "一分鐘", + mm : "%d分鐘", + h : "一小時", + hh : "%d小時", + d : "一天", + dd : "%d天", + M : "一個月", + MM : "%d個月", + y : "一年", + yy : "%d年" + } +}); diff --git a/node_modules/moment/min/lang/ar-ma.js b/node_modules/moment/min/lang/ar-ma.js new file mode 100644 index 0000000..5be502c --- /dev/null +++ b/node_modules/moment/min/lang/ar-ma.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : Moroccan Arabic (ar-ma) +// author : ElFadili Yassine : https://github.com/ElFadiliY +// author : Abdel Said : https://github.com/abdelsaid +!function(){function e(e){e.lang("ar-ma",{months:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062a\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u062d\u062f_\u0627\u062a\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:6,doy:12}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ar.js b/node_modules/moment/min/lang/ar.js new file mode 100644 index 0000000..90308eb --- /dev/null +++ b/node_modules/moment/min/lang/ar.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : Arabic (ar) +// author : Abdel Said : https://github.com/abdelsaid +// changes in months, weekdays : Ahmed Elkhatib +!function(){function e(e){e.lang("ar",{months:"\u064a\u0646\u0627\u064a\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u0641\u0628\u0631\u0627\u064a\u0631/ \u0634\u0628\u0627\u0637_\u0645\u0627\u0631\u0633/ \u0622\u0630\u0627\u0631_\u0623\u0628\u0631\u064a\u0644/ \u0646\u064a\u0633\u0627\u0646_\u0645\u0627\u064a\u0648/ \u0623\u064a\u0627\u0631_\u064a\u0648\u0646\u064a\u0648/ \u062d\u0632\u064a\u0631\u0627\u0646_\u064a\u0648\u0644\u064a\u0648/ \u062a\u0645\u0648\u0632_\u0623\u063a\u0633\u0637\u0633/ \u0622\u0628_\u0633\u0628\u062a\u0645\u0628\u0631/ \u0623\u064a\u0644\u0648\u0644_\u0623\u0643\u062a\u0648\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644_\u0646\u0648\u0641\u0645\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u062f\u064a\u0633\u0645\u0628\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u0641\u0628\u0631\u0627\u064a\u0631/ \u0634\u0628\u0627\u0637_\u0645\u0627\u0631\u0633/ \u0622\u0630\u0627\u0631_\u0623\u0628\u0631\u064a\u0644/ \u0646\u064a\u0633\u0627\u0646_\u0645\u0627\u064a\u0648/ \u0623\u064a\u0627\u0631_\u064a\u0648\u0646\u064a\u0648/ \u062d\u0632\u064a\u0631\u0627\u0646_\u064a\u0648\u0644\u064a\u0648/ \u062a\u0645\u0648\u0632_\u0623\u063a\u0633\u0637\u0633/ \u0622\u0628_\u0633\u0628\u062a\u0645\u0628\u0631/ \u0623\u064a\u0644\u0648\u0644_\u0623\u0643\u062a\u0648\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644_\u0646\u0648\u0641\u0645\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u062f\u064a\u0633\u0645\u0628\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:6,doy:12}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/bg.js b/node_modules/moment/min/lang/bg.js new file mode 100644 index 0000000..e1ae41d --- /dev/null +++ b/node_modules/moment/min/lang/bg.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz +!function(){function e(e){e.lang("bg",{months:"\u044f\u043d\u0443\u0430\u0440\u0438_\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0438\u043b_\u043c\u0430\u0439_\u044e\u043d\u0438_\u044e\u043b\u0438_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438_\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438_\u043d\u043e\u0435\u043c\u0432\u0440\u0438_\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438".split("_"),monthsShort:"\u044f\u043d\u0440_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u044e\u043d\u0438_\u044e\u043b\u0438_\u0430\u0432\u0433_\u0441\u0435\u043f_\u043e\u043a\u0442_\u043d\u043e\u0435_\u0434\u0435\u043a".split("_"),weekdays:"\u043d\u0435\u0434\u0435\u043b\u044f_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u044f\u0434\u0430_\u0447\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a_\u043f\u0435\u0442\u044a\u043a_\u0441\u044a\u0431\u043e\u0442\u0430".split("_"),weekdaysShort:"\u043d\u0435\u0434_\u043f\u043e\u043d_\u0432\u0442\u043e_\u0441\u0440\u044f_\u0447\u0435\u0442_\u043f\u0435\u0442_\u0441\u044a\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"h:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[\u0414\u043d\u0435\u0441 \u0432] LT",nextDay:"[\u0423\u0442\u0440\u0435 \u0432] LT",nextWeek:"dddd [\u0432] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430 \u0432] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[\u0412 \u0438\u0437\u043c\u0438\u043d\u0430\u043b\u0430\u0442\u0430] dddd [\u0432] LT";case 1:case 2:case 4:case 5:return"[\u0412 \u0438\u0437\u043c\u0438\u043d\u0430\u043b\u0438\u044f] dddd [\u0432] LT"}},sameElse:"L"},relativeTime:{future:"\u0441\u043b\u0435\u0434 %s",past:"\u043f\u0440\u0435\u0434\u0438 %s",s:"\u043d\u044f\u043a\u043e\u043b\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434\u0438",m:"\u043c\u0438\u043d\u0443\u0442\u0430",mm:"%d \u043c\u0438\u043d\u0443\u0442\u0438",h:"\u0447\u0430\u0441",hh:"%d \u0447\u0430\u0441\u0430",d:"\u0434\u0435\u043d",dd:"%d \u0434\u043d\u0438",M:"\u043c\u0435\u0441\u0435\u0446",MM:"%d \u043c\u0435\u0441\u0435\u0446\u0430",y:"\u0433\u043e\u0434\u0438\u043d\u0430",yy:"%d \u0433\u043e\u0434\u0438\u043d\u0438"},ordinal:function(e){var t=e%10,a=e%100;return 0===e?e+"-\u0435\u0432":0===a?e+"-\u0435\u043d":a>10&&20>a?e+"-\u0442\u0438":1===t?e+"-\u0432\u0438":2===t?e+"-\u0440\u0438":7===t||8===t?e+"-\u043c\u0438":e+"-\u0442\u0438"},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/br.js b/node_modules/moment/min/lang/br.js new file mode 100644 index 0000000..077cc93 --- /dev/null +++ b/node_modules/moment/min/lang/br.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : breton (br) +// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou +!function(){function e(e){function t(e,t,a){var n={mm:"munutenn",MM:"miz",dd:"devezh"};return e+" "+_(n[a],e)}function a(e){switch(n(e)){case 1:case 3:case 4:case 5:case 9:return e+" bloaz";default:return e+" vloaz"}}function n(e){return e>9?n(e%10):e}function _(e,t){return 2===t?s(e):e}function s(e){var t={m:"v",b:"v",d:"z"};return void 0===t[e.charAt(0)]?e:t[e.charAt(0)]+e.substring(1)}e.lang("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),longDateFormat:{LT:"h[e]mm A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY LT",LLLL:"dddd, D [a viz] MMMM YYYY LT"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondenno\xf9",m:"ur vunutenn",mm:t,h:"un eur",hh:"%d eur",d:"un devezh",dd:t,M:"ur miz",MM:t,y:"ur bloaz",yy:a},ordinal:function(e){var t=1===e?"a\xf1":"vet";return e+t},week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ca.js b/node_modules/moment/min/lang/ca.js new file mode 100644 index 0000000..74052cb --- /dev/null +++ b/node_modules/moment/min/lang/ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : catalan (ca) +// author : Juan G. Hurtado : https://github.com/juanghurtado +!function(){function e(e){e.lang("ca",{months:"Gener_Febrer_Mar\xe7_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"),monthsShort:"Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"),weekdays:"Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"),weekdaysShort:"Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[dem\xe0 a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:"%d\xba",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/cs.js b/node_modules/moment/min/lang/cs.js new file mode 100644 index 0000000..a6a3f9c --- /dev/null +++ b/node_modules/moment/min/lang/cs.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : czech (cs) +// author : petrbela : https://github.com/petrbela +!function(){function e(e){function t(e){return e>1&&5>e&&1!==~~(e/10)}function a(e,a,n,_){var s=e+" ";switch(n){case"s":return a||_?"p\xe1r vte\u0159in":"p\xe1r vte\u0159inami";case"m":return a?"minuta":_?"minutu":"minutou";case"mm":return a||_?s+(t(e)?"minuty":"minut"):s+"minutami";break;case"h":return a?"hodina":_?"hodinu":"hodinou";case"hh":return a||_?s+(t(e)?"hodiny":"hodin"):s+"hodinami";break;case"d":return a||_?"den":"dnem";case"dd":return a||_?s+(t(e)?"dny":"dn\xed"):s+"dny";break;case"M":return a||_?"m\u011bs\xedc":"m\u011bs\xedcem";case"MM":return a||_?s+(t(e)?"m\u011bs\xedce":"m\u011bs\xedc\u016f"):s+"m\u011bs\xedci";break;case"y":return a||_?"rok":"rokem";case"yy":return a||_?s+(t(e)?"roky":"let"):s+"lety"}}var n="leden_\xfanor_b\u0159ezen_duben_kv\u011bten_\u010derven_\u010dervenec_srpen_z\xe1\u0159\xed_\u0159\xedjen_listopad_prosinec".split("_"),_="led_\xfano_b\u0159e_dub_kv\u011b_\u010dvn_\u010dvc_srp_z\xe1\u0159_\u0159\xedj_lis_pro".split("_");e.lang("cs",{months:n,monthsShort:_,monthsParse:function(e,t){var a,n=[];for(a=0;12>a;a++)n[a]=new RegExp("^"+e[a]+"$|^"+t[a]+"$","i");return n}(n,_),weekdays:"ned\u011ble_pond\u011bl\xed_\xfater\xfd_st\u0159eda_\u010dtvrtek_p\xe1tek_sobota".split("_"),weekdaysShort:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),weekdaysMin:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes v] LT",nextDay:"[z\xedtra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v ned\u011bli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve st\u0159edu v] LT";case 4:return"[ve \u010dtvrtek v] LT";case 5:return"[v p\xe1tek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[v\u010dera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou ned\u011bli v] LT";case 1:case 2:return"[minul\xe9] dddd [v] LT";case 3:return"[minulou st\u0159edu v] LT";case 4:case 5:return"[minul\xfd] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"p\u0159ed %s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/cv.js b/node_modules/moment/min/lang/cv.js new file mode 100644 index 0000000..3d9e8ce --- /dev/null +++ b/node_modules/moment/min/lang/cv.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : chuvash (cv) +// author : Anatoly Mironov : https://github.com/mirontoli +!function(){function e(e){e.lang("cv",{months:"\u043a\u0103\u0440\u043b\u0430\u0447_\u043d\u0430\u0440\u0103\u0441_\u043f\u0443\u0448_\u0430\u043a\u0430_\u043c\u0430\u0439_\xe7\u0115\u0440\u0442\u043c\u0435_\u0443\u0442\u0103_\xe7\u0443\u0440\u043b\u0430_\u0430\u0432\u0103\u043d_\u044e\u043f\u0430_\u0447\u04f3\u043a_\u0440\u0430\u0448\u0442\u0430\u0432".split("_"),monthsShort:"\u043a\u0103\u0440_\u043d\u0430\u0440_\u043f\u0443\u0448_\u0430\u043a\u0430_\u043c\u0430\u0439_\xe7\u0115\u0440_\u0443\u0442\u0103_\xe7\u0443\u0440_\u0430\u0432_\u044e\u043f\u0430_\u0447\u04f3\u043a_\u0440\u0430\u0448".split("_"),weekdays:"\u0432\u044b\u0440\u0441\u0430\u0440\u043d\u0438\u043a\u0443\u043d_\u0442\u0443\u043d\u0442\u0438\u043a\u0443\u043d_\u044b\u0442\u043b\u0430\u0440\u0438\u043a\u0443\u043d_\u044e\u043d\u043a\u0443\u043d_\u043a\u0115\xe7\u043d\u0435\u0440\u043d\u0438\u043a\u0443\u043d_\u044d\u0440\u043d\u0435\u043a\u0443\u043d_\u0448\u0103\u043c\u0430\u0442\u043a\u0443\u043d".split("_"),weekdaysShort:"\u0432\u044b\u0440_\u0442\u0443\u043d_\u044b\u0442\u043b_\u044e\u043d_\u043a\u0115\xe7_\u044d\u0440\u043d_\u0448\u0103\u043c".split("_"),weekdaysMin:"\u0432\u0440_\u0442\u043d_\u044b\u0442_\u044e\u043d_\u043a\xe7_\u044d\u0440_\u0448\u043c".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY [\xe7\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u0103\u0445\u0115\u043d] D[-\u043c\u0115\u0448\u0115]",LLL:"YYYY [\xe7\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u0103\u0445\u0115\u043d] D[-\u043c\u0115\u0448\u0115], LT",LLLL:"dddd, YYYY [\xe7\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u0103\u0445\u0115\u043d] D[-\u043c\u0115\u0448\u0115], LT"},calendar:{sameDay:"[\u041f\u0430\u044f\u043d] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",nextDay:"[\u042b\u0440\u0430\u043d] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",lastDay:"[\u0114\u043d\u0435\u0440] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",nextWeek:"[\xc7\u0438\u0442\u0435\u0441] dddd LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",lastWeek:"[\u0418\u0440\u0442\u043d\u0115] dddd LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",sameElse:"L"},relativeTime:{future:function(e){var t=/\u0441\u0435\u0445\u0435\u0442$/i.exec(e)?"\u0440\u0435\u043d":/\xe7\u0443\u043b$/i.exec(e)?"\u0442\u0430\u043d":"\u0440\u0430\u043d";return e+t},past:"%s \u043a\u0430\u044f\u043b\u043b\u0430",s:"\u043f\u0115\u0440-\u0438\u043a \xe7\u0435\u043a\u043a\u0443\u043d\u0442",m:"\u043f\u0115\u0440 \u043c\u0438\u043d\u0443\u0442",mm:"%d \u043c\u0438\u043d\u0443\u0442",h:"\u043f\u0115\u0440 \u0441\u0435\u0445\u0435\u0442",hh:"%d \u0441\u0435\u0445\u0435\u0442",d:"\u043f\u0115\u0440 \u043a\u0443\u043d",dd:"%d \u043a\u0443\u043d",M:"\u043f\u0115\u0440 \u0443\u0439\u0103\u0445",MM:"%d \u0443\u0439\u0103\u0445",y:"\u043f\u0115\u0440 \xe7\u0443\u043b",yy:"%d \xe7\u0443\u043b"},ordinal:"%d-\u043c\u0115\u0448",week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/da.js b/node_modules/moment/min/lang/da.js new file mode 100644 index 0000000..4fd21b1 --- /dev/null +++ b/node_modules/moment/min/lang/da.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : danish (da) +// author : Ulrik Nielsen : https://github.com/mrbase +!function(){function e(e){e.lang("da",{months:"Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"),weekdays:"S\xf8ndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_L\xf8rdag".split("_"),weekdaysShort:"S\xf8n_Man_Tir_Ons_Tor_Fre_L\xf8r".split("_"),weekdaysMin:"S\xf8_Ma_Ti_On_To_Fr_L\xf8".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D. MMMM, YYYY LT"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I g\xe5r kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"f\xe5 sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en m\xe5ned",MM:"%d m\xe5neder",y:"et \xe5r",yy:"%d \xe5r"},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/de.js b/node_modules/moment/min/lang/de.js new file mode 100644 index 0000000..d5886c4 --- /dev/null +++ b/node_modules/moment/min/lang/de.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : german (de) +// author : lluchs : https://github.com/lluchs +// author: Menelion Elensúle: https://github.com/Oire +!function(){function e(e){function t(e,t,a){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return t?n[a][0]:n[a][1]}e.lang("de",{months:"Januar_Februar_M\xe4rz_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm [Uhr]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:t,mm:"%d Minuten",h:t,hh:"%d Stunden",d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/el.js b/node_modules/moment/min/lang/el.js new file mode 100644 index 0000000..2f5c03b --- /dev/null +++ b/node_modules/moment/min/lang/el.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : modern greek (el) +// author : Aggelos Karalias : https://github.com/mehiel +!function(){function e(e){e.lang("el",{monthsNominativeEl:"\u0399\u03b1\u03bd\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2_\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2_\u039c\u03ac\u03c1\u03c4\u03b9\u03bf\u03c2_\u0391\u03c0\u03c1\u03af\u03bb\u03b9\u03bf\u03c2_\u039c\u03ac\u03b9\u03bf\u03c2_\u0399\u03bf\u03cd\u03bd\u03b9\u03bf\u03c2_\u0399\u03bf\u03cd\u03bb\u03b9\u03bf\u03c2_\u0391\u03cd\u03b3\u03bf\u03c5\u03c3\u03c4\u03bf\u03c2_\u03a3\u03b5\u03c0\u03c4\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2_\u039f\u03ba\u03c4\u03ce\u03b2\u03c1\u03b9\u03bf\u03c2_\u039d\u03bf\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2_\u0394\u03b5\u03ba\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2".split("_"),monthsGenitiveEl:"\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5_\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5_\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5_\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5_\u039c\u03b1\u0390\u03bf\u03c5_\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5_\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5_\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5_\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5_\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5_\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5_\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5".split("_"),months:function(e,t){return/D/.test(t.substring(0,t.indexOf("MMMM")))?this._monthsGenitiveEl[e.month()]:this._monthsNominativeEl[e.month()]},monthsShort:"\u0399\u03b1\u03bd_\u03a6\u03b5\u03b2_\u039c\u03b1\u03c1_\u0391\u03c0\u03c1_\u039c\u03b1\u03ca_\u0399\u03bf\u03c5\u03bd_\u0399\u03bf\u03c5\u03bb_\u0391\u03c5\u03b3_\u03a3\u03b5\u03c0_\u039f\u03ba\u03c4_\u039d\u03bf\u03b5_\u0394\u03b5\u03ba".split("_"),weekdays:"\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae_\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1_\u03a4\u03c1\u03af\u03c4\u03b7_\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7_\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7_\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae_\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf".split("_"),weekdaysShort:"\u039a\u03c5\u03c1_\u0394\u03b5\u03c5_\u03a4\u03c1\u03b9_\u03a4\u03b5\u03c4_\u03a0\u03b5\u03bc_\u03a0\u03b1\u03c1_\u03a3\u03b1\u03b2".split("_"),weekdaysMin:"\u039a\u03c5_\u0394\u03b5_\u03a4\u03c1_\u03a4\u03b5_\u03a0\u03b5_\u03a0\u03b1_\u03a3\u03b1".split("_"),meridiem:function(e,t,a){return e>11?a?"\u03bc\u03bc":"\u039c\u039c":a?"\u03c0\u03bc":"\u03a0\u039c"},longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendarEl:{sameDay:"[\u03a3\u03ae\u03bc\u03b5\u03c1\u03b1 {}] LT",nextDay:"[\u0391\u03cd\u03c1\u03b9\u03bf {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[\u03a7\u03b8\u03b5\u03c2 {}] LT",lastWeek:"[\u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03b7] dddd [{}] LT",sameElse:"L"},calendar:function(e,t){var a=this._calendarEl[e],n=t&&t.hours();return a.replace("{}",1===n%12?"\u03c3\u03c4\u03b7":"\u03c3\u03c4\u03b9\u03c2")},relativeTime:{future:"\u03c3\u03b5 %s",past:"%s \u03c0\u03c1\u03b9\u03bd",s:"\u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1",m:"\u03ad\u03bd\u03b1 \u03bb\u03b5\u03c0\u03c4\u03cc",mm:"%d \u03bb\u03b5\u03c0\u03c4\u03ac",h:"\u03bc\u03af\u03b1 \u03ce\u03c1\u03b1",hh:"%d \u03ce\u03c1\u03b5\u03c2",d:"\u03bc\u03af\u03b1 \u03bc\u03ad\u03c1\u03b1",dd:"%d \u03bc\u03ad\u03c1\u03b5\u03c2",M:"\u03ad\u03bd\u03b1\u03c2 \u03bc\u03ae\u03bd\u03b1\u03c2",MM:"%d \u03bc\u03ae\u03bd\u03b5\u03c2",y:"\u03ad\u03bd\u03b1\u03c2 \u03c7\u03c1\u03cc\u03bd\u03bf\u03c2",yy:"%d \u03c7\u03c1\u03cc\u03bd\u03b9\u03b1"},ordinal:function(e){return e+"\u03b7"},week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/en-ca.js b/node_modules/moment/min/lang/en-ca.js new file mode 100644 index 0000000..f9277f6 --- /dev/null +++ b/node_modules/moment/min/lang/en-ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : canadian english (en-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +!function(){function e(e){e.lang("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(e){var t=e%10,a=1===~~(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th";return e+a}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/en-gb.js b/node_modules/moment/min/lang/en-gb.js new file mode 100644 index 0000000..1f86186 --- /dev/null +++ b/node_modules/moment/min/lang/en-gb.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : great britain english (en-gb) +// author : Chris Gedrim : https://github.com/chrisgedrim +!function(){function e(e){e.lang("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(e){var t=e%10,a=1===~~(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th";return e+a},week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/eo.js b/node_modules/moment/min/lang/eo.js new file mode 100644 index 0000000..f619932 --- /dev/null +++ b/node_modules/moment/min/lang/eo.js @@ -0,0 +1,6 @@ +// moment.js language configuration +// language : esperanto (eo) +// author : Colin Dean : https://github.com/colindean +// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. +// Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! +!function(){function e(e){e.lang("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_a\u016dgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_a\u016dg_sep_okt_nov_dec".split("_"),weekdays:"Diman\u0109o_Lundo_Mardo_Merkredo_\u0134a\u016ddo_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Mard_Merk_\u0134a\u016d_Ven_Sab".split("_"),weekdaysMin:"Di_Lu_Ma_Me_\u0134a_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D[-an de] MMMM, YYYY",LLL:"D[-an de] MMMM, YYYY LT",LLLL:"dddd, [la] D[-an de] MMMM, YYYY LT"},meridiem:function(e,t,a){return e>11?a?"p.t.m.":"P.T.M.":a?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodia\u016d je] LT",nextDay:"[Morga\u016d je] LT",nextWeek:"dddd [je] LT",lastDay:"[Hiera\u016d je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"je %s",past:"anta\u016d %s",s:"sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},ordinal:"%da",week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/es.js b/node_modules/moment/min/lang/es.js new file mode 100644 index 0000000..da7f10c --- /dev/null +++ b/node_modules/moment/min/lang/es.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : spanish (es) +// author : Julio Napurí : https://github.com/julionc +!function(){function e(e){e.lang("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),weekdays:"domingo_lunes_martes_mi\xe9rcoles_jueves_viernes_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._mi\xe9._jue._vie._s\xe1b.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_S\xe1".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[ma\xf1ana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un a\xf1o",yy:"%d a\xf1os"},ordinal:"%d\xba",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/et.js b/node_modules/moment/min/lang/et.js new file mode 100644 index 0000000..d8ade47 --- /dev/null +++ b/node_modules/moment/min/lang/et.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : estonian (et) +// author : Henry Kehlmann : https://github.com/madhenry +!function(){function e(e){function t(e,t,a,n){return n||t?"paari sekundi":"paar sekundit"}e.lang("et",{months:"jaanuar_veebruar_m\xe4rts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_m\xe4rts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"p\xfchap\xe4ev_esmasp\xe4ev_teisip\xe4ev_kolmap\xe4ev_neljap\xe4ev_reede_laup\xe4ev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[T\xe4na,] LT",nextDay:"[Homme,] LT",nextWeek:"[J\xe4rgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s p\xe4rast",past:"%s tagasi",s:t,m:"minut",mm:"%d minutit",h:"tund",hh:"%d tundi",d:"p\xe4ev",dd:"%d p\xe4eva",M:"kuu",MM:"%d kuud",y:"aasta",yy:"%d aastat"},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/eu.js b/node_modules/moment/min/lang/eu.js new file mode 100644 index 0000000..e88821d --- /dev/null +++ b/node_modules/moment/min/lang/eu.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : euskara (eu) +// author : Eneko Illarramendi : https://github.com/eillarra +!function(){function e(e){e.lang("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] LT",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] LT",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] LT",llll:"ddd, YYYY[ko] MMM D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:"%d.",week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/fa.js b/node_modules/moment/min/lang/fa.js new file mode 100644 index 0000000..0a03570 --- /dev/null +++ b/node_modules/moment/min/lang/fa.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : Persian Language +// author : Ebrahim Byagowi : https://github.com/ebraminio +!function(){function e(e){var t={1:"\u06f1",2:"\u06f2",3:"\u06f3",4:"\u06f4",5:"\u06f5",6:"\u06f6",7:"\u06f7",8:"\u06f8",9:"\u06f9",0:"\u06f0"},a={"\u06f1":"1","\u06f2":"2","\u06f3":"3","\u06f4":"4","\u06f5":"5","\u06f6":"6","\u06f7":"7","\u06f8":"8","\u06f9":"9","\u06f0":"0"};e.lang("fa",{months:"\u0698\u0627\u0646\u0648\u06cc\u0647_\u0641\u0648\u0631\u06cc\u0647_\u0645\u0627\u0631\u0633_\u0622\u0648\u0631\u06cc\u0644_\u0645\u0647_\u0698\u0648\u0626\u0646_\u0698\u0648\u0626\u06cc\u0647_\u0627\u0648\u062a_\u0633\u067e\u062a\u0627\u0645\u0628\u0631_\u0627\u06a9\u062a\u0628\u0631_\u0646\u0648\u0627\u0645\u0628\u0631_\u062f\u0633\u0627\u0645\u0628\u0631".split("_"),monthsShort:"\u0698\u0627\u0646\u0648\u06cc\u0647_\u0641\u0648\u0631\u06cc\u0647_\u0645\u0627\u0631\u0633_\u0622\u0648\u0631\u06cc\u0644_\u0645\u0647_\u0698\u0648\u0626\u0646_\u0698\u0648\u0626\u06cc\u0647_\u0627\u0648\u062a_\u0633\u067e\u062a\u0627\u0645\u0628\u0631_\u0627\u06a9\u062a\u0628\u0631_\u0646\u0648\u0627\u0645\u0628\u0631_\u062f\u0633\u0627\u0645\u0628\u0631".split("_"),weekdays:"\u06cc\u06a9\u200c\u0634\u0646\u0628\u0647_\u062f\u0648\u0634\u0646\u0628\u0647_\u0633\u0647\u200c\u0634\u0646\u0628\u0647_\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647_\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647_\u062c\u0645\u0639\u0647_\u0634\u0646\u0628\u0647".split("_"),weekdaysShort:"\u06cc\u06a9\u200c\u0634\u0646\u0628\u0647_\u062f\u0648\u0634\u0646\u0628\u0647_\u0633\u0647\u200c\u0634\u0646\u0628\u0647_\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647_\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647_\u062c\u0645\u0639\u0647_\u0634\u0646\u0628\u0647".split("_"),weekdaysMin:"\u06cc_\u062f_\u0633_\u0686_\u067e_\u062c_\u0634".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},meridiem:function(e){return 12>e?"\u0642\u0628\u0644 \u0627\u0632 \u0638\u0647\u0631":"\u0628\u0639\u062f \u0627\u0632 \u0638\u0647\u0631"},calendar:{sameDay:"[\u0627\u0645\u0631\u0648\u0632 \u0633\u0627\u0639\u062a] LT",nextDay:"[\u0641\u0631\u062f\u0627 \u0633\u0627\u0639\u062a] LT",nextWeek:"dddd [\u0633\u0627\u0639\u062a] LT",lastDay:"[\u062f\u06cc\u0631\u0648\u0632 \u0633\u0627\u0639\u062a] LT",lastWeek:"dddd [\u067e\u06cc\u0634] [\u0633\u0627\u0639\u062a] LT",sameElse:"L"},relativeTime:{future:"\u062f\u0631 %s",past:"%s \u067e\u06cc\u0634",s:"\u0686\u0646\u062f\u06cc\u0646 \u062b\u0627\u0646\u06cc\u0647",m:"\u06cc\u06a9 \u062f\u0642\u06cc\u0642\u0647",mm:"%d \u062f\u0642\u06cc\u0642\u0647",h:"\u06cc\u06a9 \u0633\u0627\u0639\u062a",hh:"%d \u0633\u0627\u0639\u062a",d:"\u06cc\u06a9 \u0631\u0648\u0632",dd:"%d \u0631\u0648\u0632",M:"\u06cc\u06a9 \u0645\u0627\u0647",MM:"%d \u0645\u0627\u0647",y:"\u06cc\u06a9 \u0633\u0627\u0644",yy:"%d \u0633\u0627\u0644"},preparse:function(e){return e.replace(/[\u06f0-\u06f9]/g,function(e){return a[e]}).replace(/\u060c/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]}).replace(/,/g,"\u060c")},ordinal:"%d\u0645",week:{dow:6,doy:12}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/fi.js b/node_modules/moment/min/lang/fi.js new file mode 100644 index 0000000..4075a6f --- /dev/null +++ b/node_modules/moment/min/lang/fi.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : finnish (fi) +// author : Tarmo Aidantausta : https://github.com/bleadof +!function(){function e(e){function t(e,t,n,_){var s="";switch(n){case"s":return _?"muutaman sekunnin":"muutama sekunti";case"m":return _?"minuutin":"minuutti";case"mm":s=_?"minuutin":"minuuttia";break;case"h":return _?"tunnin":"tunti";case"hh":s=_?"tunnin":"tuntia";break;case"d":return _?"p\xe4iv\xe4n":"p\xe4iv\xe4";case"dd":s=_?"p\xe4iv\xe4n":"p\xe4iv\xe4\xe4";break;case"M":return _?"kuukauden":"kuukausi";case"MM":s=_?"kuukauden":"kuukautta";break;case"y":return _?"vuoden":"vuosi";case"yy":s=_?"vuoden":"vuotta"}return s=a(e,_)+" "+s}function a(e,t){return 10>e?t?_[e]:n[e]:e}var n="nolla yksi kaksi kolme nelj\xe4 viisi kuusi seitsem\xe4n kahdeksan yhdeks\xe4n".split(" "),_=["nolla","yhden","kahden","kolmen","nelj\xe4n","viiden","kuuden",n[7],n[8],n[9]];e.lang("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kes\xe4kuu_hein\xe4kuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kes\xe4_hein\xe4_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] LT",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] LT",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] LT",llll:"ddd, Do MMM YYYY, [klo] LT"},calendar:{sameDay:"[t\xe4n\xe4\xe4n] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s p\xe4\xe4st\xe4",past:"%s sitten",s:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/fr-ca.js b/node_modules/moment/min/lang/fr-ca.js new file mode 100644 index 0000000..f8f314a --- /dev/null +++ b/node_modules/moment/min/lang/fr-ca.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : canadian french (fr-ca) +// author : Jonathan Abourbih : https://github.com/jonbca +!function(){function e(e){e.lang("fr-ca",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(e){return e+(1===e?"er":"")}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/fr.js b/node_modules/moment/min/lang/fr.js new file mode 100644 index 0000000..a8325d8 --- /dev/null +++ b/node_modules/moment/min/lang/fr.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : french (fr) +// author : John Fischer : https://github.com/jfroffice +!function(){function e(e){e.lang("fr",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(e){return e+(1===e?"er":"")},week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/gl.js b/node_modules/moment/min/lang/gl.js new file mode 100644 index 0000000..aac8504 --- /dev/null +++ b/node_modules/moment/min/lang/gl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : galician (gl) +// author : Juan G. Hurtado : https://github.com/juanghurtado +!function(){function e(e){e.lang("gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xu\xf1o_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xu\xf1._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_M\xe9rcores_Xoves_Venres_S\xe1bado".split("_"),weekdaysShort:"Dom._Lun._Mar._M\xe9r._Xov._Ven._S\xe1b.".split("_"),weekdaysMin:"Do_Lu_Ma_M\xe9_Xo_Ve_S\xe1".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"\xe1s":"\xe1")+"] LT"},nextDay:function(){return"[ma\xf1\xe1 "+(1!==this.hours()?"\xe1s":"\xe1")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"\xe1s":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"\xe1":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"\xe1s":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(e){return"uns segundos"===e?"nuns segundos":"en "+e},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:"%d\xba",week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/he.js b/node_modules/moment/min/lang/he.js new file mode 100644 index 0000000..46dec54 --- /dev/null +++ b/node_modules/moment/min/lang/he.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : Hebrew (he) +// author : Tomer Cohen : https://github.com/tomer +// author : Moshe Simantov : https://github.com/DevelopmentIL +!function(){function e(e){e.lang("he",{months:"\u05d9\u05e0\u05d5\u05d0\u05e8_\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8_\u05de\u05e8\u05e5_\u05d0\u05e4\u05e8\u05d9\u05dc_\u05de\u05d0\u05d9_\u05d9\u05d5\u05e0\u05d9_\u05d9\u05d5\u05dc\u05d9_\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8_\u05e1\u05e4\u05d8\u05de\u05d1\u05e8_\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8_\u05e0\u05d5\u05d1\u05de\u05d1\u05e8_\u05d3\u05e6\u05de\u05d1\u05e8".split("_"),monthsShort:"\u05d9\u05e0\u05d5\u05f3_\u05e4\u05d1\u05e8\u05f3_\u05de\u05e8\u05e5_\u05d0\u05e4\u05e8\u05f3_\u05de\u05d0\u05d9_\u05d9\u05d5\u05e0\u05d9_\u05d9\u05d5\u05dc\u05d9_\u05d0\u05d5\u05d2\u05f3_\u05e1\u05e4\u05d8\u05f3_\u05d0\u05d5\u05e7\u05f3_\u05e0\u05d5\u05d1\u05f3_\u05d3\u05e6\u05de\u05f3".split("_"),weekdays:"\u05e8\u05d0\u05e9\u05d5\u05df_\u05e9\u05e0\u05d9_\u05e9\u05dc\u05d9\u05e9\u05d9_\u05e8\u05d1\u05d9\u05e2\u05d9_\u05d7\u05de\u05d9\u05e9\u05d9_\u05e9\u05d9\u05e9\u05d9_\u05e9\u05d1\u05ea".split("_"),weekdaysShort:"\u05d0\u05f3_\u05d1\u05f3_\u05d2\u05f3_\u05d3\u05f3_\u05d4\u05f3_\u05d5\u05f3_\u05e9\u05f3".split("_"),weekdaysMin:"\u05d0_\u05d1_\u05d2_\u05d3_\u05d4_\u05d5_\u05e9".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [\u05d1]MMMM YYYY",LLL:"D [\u05d1]MMMM YYYY LT",LLLL:"dddd, D [\u05d1]MMMM YYYY LT",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY LT",llll:"ddd, D MMM YYYY LT"},calendar:{sameDay:"[\u05d4\u05d9\u05d5\u05dd \u05d1\u05be]LT",nextDay:"[\u05de\u05d7\u05e8 \u05d1\u05be]LT",nextWeek:"dddd [\u05d1\u05e9\u05e2\u05d4] LT",lastDay:"[\u05d0\u05ea\u05de\u05d5\u05dc \u05d1\u05be]LT",lastWeek:"[\u05d1\u05d9\u05d5\u05dd] dddd [\u05d4\u05d0\u05d7\u05e8\u05d5\u05df \u05d1\u05e9\u05e2\u05d4] LT",sameElse:"L"},relativeTime:{future:"\u05d1\u05e2\u05d5\u05d3 %s",past:"\u05dc\u05e4\u05e0\u05d9 %s",s:"\u05de\u05e1\u05e4\u05e8 \u05e9\u05e0\u05d9\u05d5\u05ea",m:"\u05d3\u05e7\u05d4",mm:"%d \u05d3\u05e7\u05d5\u05ea",h:"\u05e9\u05e2\u05d4",hh:"%d \u05e9\u05e2\u05d5\u05ea",d:"\u05d9\u05d5\u05dd",dd:"%d \u05d9\u05de\u05d9\u05dd",M:"\u05d7\u05d5\u05d3\u05e9",MM:"%d \u05d7\u05d5\u05d3\u05e9\u05d9\u05dd",y:"\u05e9\u05e0\u05d4",yy:"%d \u05e9\u05e0\u05d9\u05dd"}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/hi.js b/node_modules/moment/min/lang/hi.js new file mode 100644 index 0000000..60a171d --- /dev/null +++ b/node_modules/moment/min/lang/hi.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : hindi (hi) +// author : Mayank Singhal : https://github.com/mayanksinghal +!function(){function e(e){var t={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},a={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};e.lang("hi",{months:"\u091c\u0928\u0935\u0930\u0940_\u092b\u093c\u0930\u0935\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u0948\u0932_\u092e\u0908_\u091c\u0942\u0928_\u091c\u0941\u0932\u093e\u0908_\u0905\u0917\u0938\u094d\u0924_\u0938\u093f\u0924\u092e\u094d\u092c\u0930_\u0905\u0915\u094d\u091f\u0942\u092c\u0930_\u0928\u0935\u092e\u094d\u092c\u0930_\u0926\u093f\u0938\u092e\u094d\u092c\u0930".split("_"),monthsShort:"\u091c\u0928._\u092b\u093c\u0930._\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u0948._\u092e\u0908_\u091c\u0942\u0928_\u091c\u0941\u0932._\u0905\u0917._\u0938\u093f\u0924._\u0905\u0915\u094d\u091f\u0942._\u0928\u0935._\u0926\u093f\u0938.".split("_"),weekdays:"\u0930\u0935\u093f\u0935\u093e\u0930_\u0938\u094b\u092e\u0935\u093e\u0930_\u092e\u0902\u0917\u0932\u0935\u093e\u0930_\u092c\u0941\u0927\u0935\u093e\u0930_\u0917\u0941\u0930\u0942\u0935\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930_\u0936\u0928\u093f\u0935\u093e\u0930".split("_"),weekdaysShort:"\u0930\u0935\u093f_\u0938\u094b\u092e_\u092e\u0902\u0917\u0932_\u092c\u0941\u0927_\u0917\u0941\u0930\u0942_\u0936\u0941\u0915\u094d\u0930_\u0936\u0928\u093f".split("_"),weekdaysMin:"\u0930_\u0938\u094b_\u092e\u0902_\u092c\u0941_\u0917\u0941_\u0936\u0941_\u0936".split("_"),longDateFormat:{LT:"A h:mm \u092c\u091c\u0947",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u0915\u0932] LT",nextWeek:"dddd, LT",lastDay:"[\u0915\u0932] LT",lastWeek:"[\u092a\u093f\u091b\u0932\u0947] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u092e\u0947\u0902",past:"%s \u092a\u0939\u0932\u0947",s:"\u0915\u0941\u091b \u0939\u0940 \u0915\u094d\u0937\u0923",m:"\u090f\u0915 \u092e\u093f\u0928\u091f",mm:"%d \u092e\u093f\u0928\u091f",h:"\u090f\u0915 \u0918\u0902\u091f\u093e",hh:"%d \u0918\u0902\u091f\u0947",d:"\u090f\u0915 \u0926\u093f\u0928",dd:"%d \u0926\u093f\u0928",M:"\u090f\u0915 \u092e\u0939\u0940\u0928\u0947",MM:"%d \u092e\u0939\u0940\u0928\u0947",y:"\u090f\u0915 \u0935\u0930\u094d\u0937",yy:"%d \u0935\u0930\u094d\u0937"},preparse:function(e){return e.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(e){return a[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]})},meridiem:function(e){return 4>e?"\u0930\u093e\u0924":10>e?"\u0938\u0941\u092c\u0939":17>e?"\u0926\u094b\u092a\u0939\u0930":20>e?"\u0936\u093e\u092e":"\u0930\u093e\u0924"},week:{dow:0,doy:6}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/hu.js b/node_modules/moment/min/lang/hu.js new file mode 100644 index 0000000..90c0d81 --- /dev/null +++ b/node_modules/moment/min/lang/hu.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : hungarian (hu) +// author : Adam Brunner : https://github.com/adambrunner +!function(){function e(e){function t(e,t,n,a){var _=e;switch(n){case"s":return a||t?"n\xe9h\xe1ny m\xe1sodperc":"n\xe9h\xe1ny m\xe1sodperce";case"m":return"egy"+(a||t?" perc":" perce");case"mm":return _+(a||t?" perc":" perce");case"h":return"egy"+(a||t?" \xf3ra":" \xf3r\xe1ja");case"hh":return _+(a||t?" \xf3ra":" \xf3r\xe1ja");case"d":return"egy"+(a||t?" nap":" napja");case"dd":return _+(a||t?" nap":" napja");case"M":return"egy"+(a||t?" h\xf3nap":" h\xf3napja");case"MM":return _+(a||t?" h\xf3nap":" h\xf3napja");case"y":return"egy"+(a||t?" \xe9v":" \xe9ve");case"yy":return _+(a||t?" \xe9v":" \xe9ve")}return""}function n(e){return(e?"":"[m\xfalt] ")+"["+a[this.day()]+"] LT[-kor]"}var a="vas\xe1rnap h\xe9tf\u0151n kedden szerd\xe1n cs\xfct\xf6rt\xf6k\xf6n p\xe9nteken szombaton".split(" ");e.lang("hu",{months:"janu\xe1r_febru\xe1r_m\xe1rcius_\xe1prilis_m\xe1jus_j\xfanius_j\xfalius_augusztus_szeptember_okt\xf3ber_november_december".split("_"),monthsShort:"jan_feb_m\xe1rc_\xe1pr_m\xe1j_j\xfan_j\xfal_aug_szept_okt_nov_dec".split("_"),weekdays:"vas\xe1rnap_h\xe9tf\u0151_kedd_szerda_cs\xfct\xf6rt\xf6k_p\xe9ntek_szombat".split("_"),weekdaysShort:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return n.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return n.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s m\xfalva",past:"%s",s:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinal:"%d.",week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/id.js b/node_modules/moment/min/lang/id.js new file mode 100644 index 0000000..18ac26c --- /dev/null +++ b/node_modules/moment/min/lang/id.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : Bahasa Indonesia (id) +// author : Mohammad Satrio Utomo : https://github.com/tyok +// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan +!function(){function e(e){e.lang("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(e){return 11>e?"pagi":15>e?"siang":19>e?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/is.js b/node_modules/moment/min/lang/is.js new file mode 100644 index 0000000..221f7ef --- /dev/null +++ b/node_modules/moment/min/lang/is.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : icelandic (is) +// author : Hinrik Örn Sigurðsson : https://github.com/hinrik +!function(){function e(e){function t(e){return 11===e%100?!0:1===e%10?!1:!0}function n(e,n,a,_){var s=e+" ";switch(a){case"s":return n||_?"nokkrar sek\xfandur":"nokkrum sek\xfandum";case"m":return n?"m\xedn\xfata":"m\xedn\xfatu";case"mm":return t(e)?s+(n||_?"m\xedn\xfatur":"m\xedn\xfatum"):n?s+"m\xedn\xfata":s+"m\xedn\xfatu";case"hh":return t(e)?s+(n||_?"klukkustundir":"klukkustundum"):s+"klukkustund";case"d":return n?"dagur":_?"dag":"degi";case"dd":return t(e)?n?s+"dagar":s+(_?"daga":"d\xf6gum"):n?s+"dagur":s+(_?"dag":"degi");case"M":return n?"m\xe1nu\xf0ur":_?"m\xe1nu\xf0":"m\xe1nu\xf0i";case"MM":return t(e)?n?s+"m\xe1nu\xf0ir":s+(_?"m\xe1nu\xf0i":"m\xe1nu\xf0um"):n?s+"m\xe1nu\xf0ur":s+(_?"m\xe1nu\xf0":"m\xe1nu\xf0i");case"y":return n||_?"\xe1r":"\xe1ri";case"yy":return t(e)?s+(n||_?"\xe1r":"\xe1rum"):s+(n||_?"\xe1r":"\xe1ri")}}e.lang("is",{months:"jan\xfaar_febr\xfaar_mars_apr\xedl_ma\xed_j\xfan\xed_j\xfal\xed_\xe1g\xfast_september_okt\xf3ber_n\xf3vember_desember".split("_"),monthsShort:"jan_feb_mar_apr_ma\xed_j\xfan_j\xfal_\xe1g\xfa_sep_okt_n\xf3v_des".split("_"),weekdays:"sunnudagur_m\xe1nudagur_\xferi\xf0judagur_mi\xf0vikudagur_fimmtudagur_f\xf6studagur_laugardagur".split("_"),weekdaysShort:"sun_m\xe1n_\xferi_mi\xf0_fim_f\xf6s_lau".split("_"),weekdaysMin:"Su_M\xe1_\xder_Mi_Fi_F\xf6_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd, D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[\xed dag kl.] LT",nextDay:"[\xe1 morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[\xed g\xe6r kl.] LT",lastWeek:"[s\xed\xf0asta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s s\xed\xf0an",s:n,m:n,mm:n,h:"klukkustund",hh:n,d:n,dd:n,M:n,MM:n,y:n,yy:n},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/it.js b/node_modules/moment/min/lang/it.js new file mode 100644 index 0000000..8b2e081 --- /dev/null +++ b/node_modules/moment/min/lang/it.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : italian (it) +// author : Lorenzo : https://github.com/aliem +// author: Mattia Larentis: https://github.com/nostalgiaz +!function(){function e(e){e.lang("it",{months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Luned\xec_Marted\xec_Mercoled\xec_Gioved\xec_Venerd\xec_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:function(e){return(/^[0-9].+$/.test(e)?"tra":"in")+" "+e},past:"%s fa",s:"secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:"%d\xba",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ja.js b/node_modules/moment/min/lang/ja.js new file mode 100644 index 0000000..ec00b2f --- /dev/null +++ b/node_modules/moment/min/lang/ja.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : japanese (ja) +// author : LI Long : https://github.com/baryon +!function(){function e(e){e.lang("ja",{months:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u65e5\u66dc\u65e5_\u6708\u66dc\u65e5_\u706b\u66dc\u65e5_\u6c34\u66dc\u65e5_\u6728\u66dc\u65e5_\u91d1\u66dc\u65e5_\u571f\u66dc\u65e5".split("_"),weekdaysShort:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),weekdaysMin:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),longDateFormat:{LT:"Ah\u6642m\u5206",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5LT",LLLL:"YYYY\u5e74M\u6708D\u65e5LT dddd"},meridiem:function(e){return 12>e?"\u5348\u524d":"\u5348\u5f8c"},calendar:{sameDay:"[\u4eca\u65e5] LT",nextDay:"[\u660e\u65e5] LT",nextWeek:"[\u6765\u9031]dddd LT",lastDay:"[\u6628\u65e5] LT",lastWeek:"[\u524d\u9031]dddd LT",sameElse:"L"},relativeTime:{future:"%s\u5f8c",past:"%s\u524d",s:"\u6570\u79d2",m:"1\u5206",mm:"%d\u5206",h:"1\u6642\u9593",hh:"%d\u6642\u9593",d:"1\u65e5",dd:"%d\u65e5",M:"1\u30f6\u6708",MM:"%d\u30f6\u6708",y:"1\u5e74",yy:"%d\u5e74"}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ka.js b/node_modules/moment/min/lang/ka.js new file mode 100644 index 0000000..381f9f7 --- /dev/null +++ b/node_modules/moment/min/lang/ka.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : Georgian (ka) +// author : Irakli Janiashvili : https://github.com/irakli-janiashvili +!function(){function e(e){function t(e,t){var n={nominative:"\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8_\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10d8_\u10db\u10d0\u10e0\u10e2\u10d8_\u10d0\u10de\u10e0\u10d8\u10da\u10d8_\u10db\u10d0\u10d8\u10e1\u10d8_\u10d8\u10d5\u10dc\u10d8\u10e1\u10d8_\u10d8\u10d5\u10da\u10d8\u10e1\u10d8_\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10dd_\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10d8_\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10d8_\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10d8_\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10d8".split("_"),accusative:"\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10e1_\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10e1_\u10db\u10d0\u10e0\u10e2\u10e1_\u10d0\u10de\u10e0\u10d8\u10da\u10d8\u10e1_\u10db\u10d0\u10d8\u10e1\u10e1_\u10d8\u10d5\u10dc\u10d8\u10e1\u10e1_\u10d8\u10d5\u10da\u10d8\u10e1\u10e1_\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10e1_\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10e1_\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10e1_\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10e1_\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10e1".split("_")},a=/D[oD] *MMMM?/.test(t)?"accusative":"nominative";return n[a][e.month()]}function n(e,t){var n={nominative:"\u10d9\u10d5\u10d8\u10e0\u10d0_\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8_\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8".split("_"),accusative:"\u10d9\u10d5\u10d8\u10e0\u10d0\u10e1_\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10e1_\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1".split("_")},a=/(\u10ec\u10d8\u10dc\u10d0|\u10e8\u10d4\u10db\u10d3\u10d4\u10d2)/.test(t)?"accusative":"nominative";return n[a][e.day()]}e.lang("ka",{months:t,monthsShort:"\u10d8\u10d0\u10dc_\u10d7\u10d4\u10d1_\u10db\u10d0\u10e0_\u10d0\u10de\u10e0_\u10db\u10d0\u10d8_\u10d8\u10d5\u10dc_\u10d8\u10d5\u10da_\u10d0\u10d2\u10d5_\u10e1\u10d4\u10e5_\u10dd\u10e5\u10e2_\u10dc\u10dd\u10d4_\u10d3\u10d4\u10d9".split("_"),weekdays:n,weekdaysShort:"\u10d9\u10d5\u10d8_\u10dd\u10e0\u10e8_\u10e1\u10d0\u10db_\u10dd\u10d7\u10ee_\u10ee\u10e3\u10d7_\u10de\u10d0\u10e0_\u10e8\u10d0\u10d1".split("_"),weekdaysMin:"\u10d9\u10d5_\u10dd\u10e0_\u10e1\u10d0_\u10dd\u10d7_\u10ee\u10e3_\u10de\u10d0_\u10e8\u10d0".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[\u10d3\u10e6\u10d4\u10e1] LT[-\u10d6\u10d4]",nextDay:"[\u10ee\u10d5\u10d0\u10da] LT[-\u10d6\u10d4]",lastDay:"[\u10d2\u10e3\u10e8\u10d8\u10dc] LT[-\u10d6\u10d4]",nextWeek:"[\u10e8\u10d4\u10db\u10d3\u10d4\u10d2] dddd LT[-\u10d6\u10d4]",lastWeek:"[\u10ec\u10d8\u10dc\u10d0] dddd LT-\u10d6\u10d4",sameElse:"L"},relativeTime:{future:function(e){return/(\u10ec\u10d0\u10db\u10d8|\u10ec\u10e3\u10d7\u10d8|\u10e1\u10d0\u10d0\u10d7\u10d8|\u10ec\u10d4\u10da\u10d8)/.test(e)?e.replace(/\u10d8$/,"\u10e8\u10d8"):e+"\u10e8\u10d8"},past:function(e){return/(\u10ec\u10d0\u10db\u10d8|\u10ec\u10e3\u10d7\u10d8|\u10e1\u10d0\u10d0\u10d7\u10d8|\u10d3\u10e6\u10d4|\u10d7\u10d5\u10d4)/.test(e)?e.replace(/(\u10d8|\u10d4)$/,"\u10d8\u10e1 \u10ec\u10d8\u10dc"):/\u10ec\u10d4\u10da\u10d8/.test(e)?e.replace(/\u10ec\u10d4\u10da\u10d8$/,"\u10ec\u10da\u10d8\u10e1 \u10ec\u10d8\u10dc"):void 0},s:"\u10e0\u10d0\u10db\u10d3\u10d4\u10dc\u10d8\u10db\u10d4 \u10ec\u10d0\u10db\u10d8",m:"\u10ec\u10e3\u10d7\u10d8",mm:"%d \u10ec\u10e3\u10d7\u10d8",h:"\u10e1\u10d0\u10d0\u10d7\u10d8",hh:"%d \u10e1\u10d0\u10d0\u10d7\u10d8",d:"\u10d3\u10e6\u10d4",dd:"%d \u10d3\u10e6\u10d4",M:"\u10d7\u10d5\u10d4",MM:"%d \u10d7\u10d5\u10d4",y:"\u10ec\u10d4\u10da\u10d8",yy:"%d \u10ec\u10d4\u10da\u10d8"},ordinal:function(e){return 0===e?e:1===e?e+"-\u10da\u10d8":20>e||100>=e&&0===e%20||0===e%100?"\u10db\u10d4-"+e:e+"-\u10d4"},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ko.js b/node_modules/moment/min/lang/ko.js new file mode 100644 index 0000000..1634bb9 --- /dev/null +++ b/node_modules/moment/min/lang/ko.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : korean (ko) +// author : Kyungwook, Park : https://github.com/kyungw00k +!function(){function e(e){e.lang("ko",{months:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),monthsShort:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),weekdays:"\uc77c\uc694\uc77c_\uc6d4\uc694\uc77c_\ud654\uc694\uc77c_\uc218\uc694\uc77c_\ubaa9\uc694\uc77c_\uae08\uc694\uc77c_\ud1a0\uc694\uc77c".split("_"),weekdaysShort:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),weekdaysMin:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),longDateFormat:{LT:"A h\uc2dc mm\ubd84",L:"YYYY.MM.DD",LL:"YYYY\ub144 MMMM D\uc77c",LLL:"YYYY\ub144 MMMM D\uc77c LT",LLLL:"YYYY\ub144 MMMM D\uc77c dddd LT"},meridiem:function(e){return 12>e?"\uc624\uc804":"\uc624\ud6c4"},calendar:{sameDay:"\uc624\ub298 LT",nextDay:"\ub0b4\uc77c LT",nextWeek:"dddd LT",lastDay:"\uc5b4\uc81c LT",lastWeek:"\uc9c0\ub09c\uc8fc dddd LT",sameElse:"L"},relativeTime:{future:"%s \ud6c4",past:"%s \uc804",s:"\uba87\ucd08",ss:"%d\ucd08",m:"\uc77c\ubd84",mm:"%d\ubd84",h:"\ud55c\uc2dc\uac04",hh:"%d\uc2dc\uac04",d:"\ud558\ub8e8",dd:"%d\uc77c",M:"\ud55c\ub2ec",MM:"%d\ub2ec",y:"\uc77c\ub144",yy:"%d\ub144"},ordinal:"%d\uc77c"})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/lv.js b/node_modules/moment/min/lang/lv.js new file mode 100644 index 0000000..f4b9f97 --- /dev/null +++ b/node_modules/moment/min/lang/lv.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : latvian (lv) +// author : Kristaps Karlsons : https://github.com/skakri +!function(){function e(e){function t(e,t,n){var a=e.split("_");return n?1===t%10&&11!==t?a[2]:a[3]:1===t%10&&11!==t?a[0]:a[1]}function n(e,n,_){return e+" "+t(a[_],e,n)}var a={mm:"min\u016bti_min\u016btes_min\u016bte_min\u016btes",hh:"stundu_stundas_stunda_stundas",dd:"dienu_dienas_diena_dienas",MM:"m\u0113nesi_m\u0113ne\u0161us_m\u0113nesis_m\u0113ne\u0161i",yy:"gadu_gadus_gads_gadi"};e.lang("lv",{months:"janv\u0101ris_febru\u0101ris_marts_apr\u012blis_maijs_j\u016bnijs_j\u016blijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_j\u016bn_j\u016bl_aug_sep_okt_nov_dec".split("_"),weekdays:"sv\u0113tdiena_pirmdiena_otrdiena_tre\u0161diena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, LT",LLLL:"YYYY. [gada] D. MMMM, dddd, LT"},calendar:{sameDay:"[\u0160odien pulksten] LT",nextDay:"[R\u012bt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pag\u0101ju\u0161\u0101] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"%s v\u0113l\u0101k",past:"%s agr\u0101k",s:"da\u017eas sekundes",m:"min\u016bti",mm:n,h:"stundu",hh:n,d:"dienu",dd:n,M:"m\u0113nesi",MM:n,y:"gadu",yy:n},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ms-my.js b/node_modules/moment/min/lang/ms-my.js new file mode 100644 index 0000000..57d7383 --- /dev/null +++ b/node_modules/moment/min/lang/ms-my.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : Bahasa Malaysia (ms-MY) +// author : Weldan Jamili : https://github.com/weldan +!function(){function e(e){e.lang("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(e){return 11>e?"pagi":15>e?"tengahari":19>e?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/nb.js b/node_modules/moment/min/lang/nb.js new file mode 100644 index 0000000..ed039b7 --- /dev/null +++ b/node_modules/moment/min/lang/nb.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : norwegian bokmål (nb) +// author : Espen Hovlandsdal : https://github.com/rexxars +!function(){function e(e){e.lang("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"s\xf8ndag_mandag_tirsdag_onsdag_torsdag_fredag_l\xf8rdag".split("_"),weekdaysShort:"s\xf8n_man_tir_ons_tor_fre_l\xf8r".split("_"),weekdaysMin:"s\xf8_ma_ti_on_to_fr_l\xf8".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokken] LT",nextDay:"[I morgen klokken] LT",nextWeek:"dddd [klokken] LT",lastDay:"[I g\xe5r klokken] LT",lastWeek:"[Forrige] dddd [klokken] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en m\xe5ned",MM:"%d m\xe5neder",y:"ett \xe5r",yy:"%d \xe5r"},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ne.js b/node_modules/moment/min/lang/ne.js new file mode 100644 index 0000000..615734b --- /dev/null +++ b/node_modules/moment/min/lang/ne.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : nepali/nepalese +// author : suvash : https://github.com/suvash +!function(){function e(e){var t={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},n={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};e.lang("ne",{months:"\u091c\u0928\u0935\u0930\u0940_\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u093f\u0932_\u092e\u0908_\u091c\u0941\u0928_\u091c\u0941\u0932\u093e\u0908_\u0905\u0917\u0937\u094d\u091f_\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930_\u0905\u0915\u094d\u091f\u094b\u092c\u0930_\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930_\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930".split("_"),monthsShort:"\u091c\u0928._\u092b\u0947\u092c\u094d\u0930\u0941._\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u093f._\u092e\u0908_\u091c\u0941\u0928_\u091c\u0941\u0932\u093e\u0908._\u0905\u0917._\u0938\u0947\u092a\u094d\u091f._\u0905\u0915\u094d\u091f\u094b._\u0928\u094b\u092d\u0947._\u0921\u093f\u0938\u0947.".split("_"),weekdays:"\u0906\u0907\u0924\u092c\u093e\u0930_\u0938\u094b\u092e\u092c\u093e\u0930_\u092e\u0919\u094d\u0917\u0932\u092c\u093e\u0930_\u092c\u0941\u0927\u092c\u093e\u0930_\u092c\u093f\u0939\u093f\u092c\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930_\u0936\u0928\u093f\u092c\u093e\u0930".split("_"),weekdaysShort:"\u0906\u0907\u0924._\u0938\u094b\u092e._\u092e\u0919\u094d\u0917\u0932._\u092c\u0941\u0927._\u092c\u093f\u0939\u093f._\u0936\u0941\u0915\u094d\u0930._\u0936\u0928\u093f.".split("_"),weekdaysMin:"\u0906\u0907._\u0938\u094b._\u092e\u0919\u094d_\u092c\u0941._\u092c\u093f._\u0936\u0941._\u0936.".split("_"),longDateFormat:{LT:"A\u0915\u094b h:mm \u092c\u091c\u0947",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},preparse:function(e){return e.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(e){return n[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]})},meridiem:function(e){return 3>e?"\u0930\u093e\u0924\u0940":10>e?"\u092c\u093f\u0939\u093e\u0928":15>e?"\u0926\u093f\u0909\u0901\u0938\u094b":18>e?"\u092c\u0947\u0932\u0941\u0915\u093e":20>e?"\u0938\u093e\u0901\u091d":"\u0930\u093e\u0924\u0940"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u092d\u094b\u0932\u0940] LT",nextWeek:"[\u0906\u0909\u0901\u0926\u094b] dddd[,] LT",lastDay:"[\u0939\u093f\u091c\u094b] LT",lastWeek:"[\u0917\u090f\u0915\u094b] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s\u092e\u093e",past:"%s \u0905\u0917\u093e\u0921\u0940",s:"\u0915\u0947\u0939\u0940 \u0938\u092e\u092f",m:"\u090f\u0915 \u092e\u093f\u0928\u0947\u091f",mm:"%d \u092e\u093f\u0928\u0947\u091f",h:"\u090f\u0915 \u0918\u0923\u094d\u091f\u093e",hh:"%d \u0918\u0923\u094d\u091f\u093e",d:"\u090f\u0915 \u0926\u093f\u0928",dd:"%d \u0926\u093f\u0928",M:"\u090f\u0915 \u092e\u0939\u093f\u0928\u093e",MM:"%d \u092e\u0939\u093f\u0928\u093e",y:"\u090f\u0915 \u092c\u0930\u094d\u0937",yy:"%d \u092c\u0930\u094d\u0937"},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/nl.js b/node_modules/moment/min/lang/nl.js new file mode 100644 index 0000000..7cf3e16 --- /dev/null +++ b/node_modules/moment/min/lang/nl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : dutch (nl) +// author : Joris Röling : https://github.com/jjupiter +!function(){function e(e){var t="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),n="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");e.lang("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,a){return/-MMM-/.test(a)?n[e.month()]:t[e.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Vandaag om] LT",nextDay:"[Morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"\xe9\xe9n minuut",mm:"%d minuten",h:"\xe9\xe9n uur",hh:"%d uur",d:"\xe9\xe9n dag",dd:"%d dagen",M:"\xe9\xe9n maand",MM:"%d maanden",y:"\xe9\xe9n jaar",yy:"%d jaar"},ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/nn.js b/node_modules/moment/min/lang/nn.js new file mode 100644 index 0000000..f784115 --- /dev/null +++ b/node_modules/moment/min/lang/nn.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : norwegian nynorsk (nn) +// author : https://github.com/mechuwind +!function(){function e(e){e.lang("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_m\xe5ndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_m\xe5n_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_m\xe5_ty_on_to_fr_l\xf8".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I g\xe5r klokka] LT",lastWeek:"[F\xf8reg\xe5ende] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekund",m:"ett minutt",mm:"%d minutt",h:"en time",hh:"%d timar",d:"en dag",dd:"%d dagar",M:"en m\xe5nad",MM:"%d m\xe5nader",y:"ett \xe5r",yy:"%d \xe5r"},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/pl.js b/node_modules/moment/min/lang/pl.js new file mode 100644 index 0000000..3064c54 --- /dev/null +++ b/node_modules/moment/min/lang/pl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : polish (pl) +// author : Rafal Hirsz : https://github.com/evoL +!function(){function e(e){function t(e){return 5>e%10&&e%10>1&&1!==~~(e/10)}function n(e,n,a){var _=e+" ";switch(a){case"m":return n?"minuta":"minut\u0119";case"mm":return _+(t(e)?"minuty":"minut");case"h":return n?"godzina":"godzin\u0119";case"hh":return _+(t(e)?"godziny":"godzin");case"MM":return _+(t(e)?"miesi\u0105ce":"miesi\u0119cy");case"yy":return _+(t(e)?"lata":"lat")}}var a="stycze\u0144_luty_marzec_kwiecie\u0144_maj_czerwiec_lipiec_sierpie\u0144_wrzesie\u0144_pa\u017adziernik_listopad_grudzie\u0144".split("_"),_="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_wrze\u015bnia_pa\u017adziernika_listopada_grudnia".split("_");e.lang("pl",{months:function(e,t){return/D MMMM/.test(t)?_[e.month()]:a[e.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_pa\u017a_lis_gru".split("_"),weekdays:"niedziela_poniedzia\u0142ek_wtorek_\u015broda_czwartek_pi\u0105tek_sobota".split("_"),weekdaysShort:"nie_pon_wt_\u015br_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_\u015ar_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dzi\u015b o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zesz\u0142\u0105 niedziel\u0119 o] LT";case 3:return"[W zesz\u0142\u0105 \u015brod\u0119 o] LT";case 6:return"[W zesz\u0142\u0105 sobot\u0119 o] LT";default:return"[W zesz\u0142y] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:n,mm:n,h:n,hh:n,d:"1 dzie\u0144",dd:"%d dni",M:"miesi\u0105c",MM:n,y:"rok",yy:n},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/pt-br.js b/node_modules/moment/min/lang/pt-br.js new file mode 100644 index 0000000..34c6123 --- /dev/null +++ b/node_modules/moment/min/lang/pt-br.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : brazilian portuguese (pt-br) +// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira +!function(){function e(e){e.lang("pt-br",{months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Dom_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1b".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atr\xe1s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%d\xba"})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/pt.js b/node_modules/moment/min/lang/pt.js new file mode 100644 index 0000000..fe54406 --- /dev/null +++ b/node_modules/moment/min/lang/pt.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : portuguese (pt) +// author : Jefferson : https://github.com/jalex79 +!function(){function e(e){e.lang("pt",{months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Dom_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1b".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atr\xe1s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%d\xba",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ro.js b/node_modules/moment/min/lang/ro.js new file mode 100644 index 0000000..00ce440 --- /dev/null +++ b/node_modules/moment/min/lang/ro.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : romanian (ro) +// author : Vlad Gurdiga : https://github.com/gurdiga +// author : Valentin Agachi : https://github.com/avaly +!function(){function e(e){e.lang("ro",{months:"Ianuarie_Februarie_Martie_Aprilie_Mai_Iunie_Iulie_August_Septembrie_Octombrie_Noiembrie_Decembrie".split("_"),monthsShort:"Ian_Feb_Mar_Apr_Mai_Iun_Iul_Aug_Sep_Oct_Noi_Dec".split("_"),weekdays:"Duminic\u0103_Luni_Mar\u0163i_Miercuri_Joi_Vineri_S\xe2mb\u0103t\u0103".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_S\xe2m".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_S\xe2".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[m\xe2ine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s \xeen urm\u0103",s:"c\xe2teva secunde",m:"un minut",mm:"%d minute",h:"o or\u0103",hh:"%d ore",d:"o zi",dd:"%d zile",M:"o lun\u0103",MM:"%d luni",y:"un an",yy:"%d ani"},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/ru.js b/node_modules/moment/min/lang/ru.js new file mode 100644 index 0000000..a0c5153 --- /dev/null +++ b/node_modules/moment/min/lang/ru.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : russian (ru) +// author : Viktorminator : https://github.com/Viktorminator +// Author : Menelion Elensúle : https://github.com/Oire +!function(){function e(e){function t(e,t){var n=e.split("_");return 1===t%10&&11!==t%100?n[0]:t%10>=2&&4>=t%10&&(10>t%100||t%100>=20)?n[1]:n[2]}function n(e,n,a){var _={mm:"\u043c\u0438\u043d\u0443\u0442\u0430_\u043c\u0438\u043d\u0443\u0442\u044b_\u043c\u0438\u043d\u0443\u0442",hh:"\u0447\u0430\u0441_\u0447\u0430\u0441\u0430_\u0447\u0430\u0441\u043e\u0432",dd:"\u0434\u0435\u043d\u044c_\u0434\u043d\u044f_\u0434\u043d\u0435\u0439",MM:"\u043c\u0435\u0441\u044f\u0446_\u043c\u0435\u0441\u044f\u0446\u0430_\u043c\u0435\u0441\u044f\u0446\u0435\u0432",yy:"\u0433\u043e\u0434_\u0433\u043e\u0434\u0430_\u043b\u0435\u0442"};return"m"===a?n?"\u043c\u0438\u043d\u0443\u0442\u0430":"\u043c\u0438\u043d\u0443\u0442\u0443":e+" "+t(_[a],+e)}function a(e,t){var n={nominative:"\u044f\u043d\u0432\u0430\u0440\u044c_\u0444\u0435\u0432\u0440\u0430\u043b\u044c_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0435\u043b\u044c_\u043c\u0430\u0439_\u0438\u044e\u043d\u044c_\u0438\u044e\u043b\u044c_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c_\u043e\u043a\u0442\u044f\u0431\u0440\u044c_\u043d\u043e\u044f\u0431\u0440\u044c_\u0434\u0435\u043a\u0430\u0431\u0440\u044c".split("_"),accusative:"\u044f\u043d\u0432\u0430\u0440\u044f_\u0444\u0435\u0432\u0440\u0430\u043b\u044f_\u043c\u0430\u0440\u0442\u0430_\u0430\u043f\u0440\u0435\u043b\u044f_\u043c\u0430\u044f_\u0438\u044e\u043d\u044f_\u0438\u044e\u043b\u044f_\u0430\u0432\u0433\u0443\u0441\u0442\u0430_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f_\u043e\u043a\u0442\u044f\u0431\u0440\u044f_\u043d\u043e\u044f\u0431\u0440\u044f_\u0434\u0435\u043a\u0430\u0431\u0440\u044f".split("_")},a=/D[oD]? *MMMM?/.test(t)?"accusative":"nominative";return n[a][e.month()]}function _(e,t){var n={nominative:"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0435\u0440\u0433_\u043f\u044f\u0442\u043d\u0438\u0446\u0430_\u0441\u0443\u0431\u0431\u043e\u0442\u0430".split("_"),accusative:"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0443_\u0447\u0435\u0442\u0432\u0435\u0440\u0433_\u043f\u044f\u0442\u043d\u0438\u0446\u0443_\u0441\u0443\u0431\u0431\u043e\u0442\u0443".split("_")},a=/\[ ?[\u0412\u0432] ?(?:\u043f\u0440\u043e\u0448\u043b\u0443\u044e|\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e)? ?\] ?dddd/.test(t)?"accusative":"nominative";return n[a][e.day()]}e.lang("ru",{months:a,monthsShort:"\u044f\u043d\u0432_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u0438\u044e\u043d_\u0438\u044e\u043b_\u0430\u0432\u0433_\u0441\u0435\u043d_\u043e\u043a\u0442_\u043d\u043e\u044f_\u0434\u0435\u043a".split("_"),weekdays:_,weekdaysShort:"\u0432\u0441\u043a_\u043f\u043d\u0434_\u0432\u0442\u0440_\u0441\u0440\u0434_\u0447\u0442\u0432_\u043f\u0442\u043d_\u0441\u0431\u0442".split("_"),weekdaysMin:"\u0432\u0441_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0433.",LLL:"D MMMM YYYY \u0433., LT",LLLL:"dddd, D MMMM YYYY \u0433., LT"},calendar:{sameDay:"[\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432] LT",nextDay:"[\u0417\u0430\u0432\u0442\u0440\u0430 \u0432] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430 \u0432] LT",nextWeek:function(){return 2===this.day()?"[\u0412\u043e] dddd [\u0432] LT":"[\u0412] dddd [\u0432] LT"},lastWeek:function(){switch(this.day()){case 0:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0435] dddd [\u0432] LT";case 1:case 2:case 4:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439] dddd [\u0432] LT";case 3:case 5:case 6:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u0443\u044e] dddd [\u0432] LT"}},sameElse:"L"},relativeTime:{future:"\u0447\u0435\u0440\u0435\u0437 %s",past:"%s \u043d\u0430\u0437\u0430\u0434",s:"\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434",m:n,mm:n,h:"\u0447\u0430\u0441",hh:n,d:"\u0434\u0435\u043d\u044c",dd:n,M:"\u043c\u0435\u0441\u044f\u0446",MM:n,y:"\u0433\u043e\u0434",yy:n},ordinal:function(e,t){switch(t){case"M":case"d":case"DDD":return e+"-\u0439";case"D":return e+"-\u0433\u043e";case"w":case"W":return e+"-\u044f";default:return e}},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/sk.js b/node_modules/moment/min/lang/sk.js new file mode 100644 index 0000000..605abca --- /dev/null +++ b/node_modules/moment/min/lang/sk.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : slovak (sk) +// author : Martin Minka : https://github.com/k2s +// based on work of petrbela : https://github.com/petrbela +!function(){function e(e){function t(e){return e>1&&5>e}function n(e,n,a,_){var d=e+" ";switch(a){case"s":return n||_?"p\xe1r sek\xfand":"p\xe1r sekundami";case"m":return n?"min\xfata":_?"min\xfatu":"min\xfatou";case"mm":return n||_?d+(t(e)?"min\xfaty":"min\xfat"):d+"min\xfatami";break;case"h":return n?"hodina":_?"hodinu":"hodinou";case"hh":return n||_?d+(t(e)?"hodiny":"hod\xedn"):d+"hodinami";break;case"d":return n||_?"de\u0148":"d\u0148om";case"dd":return n||_?d+(t(e)?"dni":"dn\xed"):d+"d\u0148ami";break;case"M":return n||_?"mesiac":"mesiacom";case"MM":return n||_?d+(t(e)?"mesiace":"mesiacov"):d+"mesiacmi";break;case"y":return n||_?"rok":"rokom";case"yy":return n||_?d+(t(e)?"roky":"rokov"):d+"rokmi"}}var a="janu\xe1r_febru\xe1r_marec_apr\xedl_m\xe1j_j\xfan_j\xfal_august_september_okt\xf3ber_november_december".split("_"),_="jan_feb_mar_apr_m\xe1j_j\xfan_j\xfal_aug_sep_okt_nov_dec".split("_");e.lang("sk",{months:a,monthsShort:_,monthsParse:function(e,t){var n,a=[];for(n=0;12>n;n++)a[n]=new RegExp("^"+e[n]+"$|^"+t[n]+"$","i");return a}(a,_),weekdays:"nede\u013ea_pondelok_utorok_streda_\u0161tvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_\u0161t_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_\u0161t_pi_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nede\u013eu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo \u0161tvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[v\u010dera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minul\xfa nede\u013eu o] LT";case 1:case 2:return"[minul\xfd] dddd [o] LT";case 3:return"[minul\xfa stredu o] LT";case 4:case 5:return"[minul\xfd] dddd [o] LT";case 6:return"[minul\xfa sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:n,m:n,mm:n,h:n,hh:n,d:n,dd:n,M:n,MM:n,y:n,yy:n},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/sl.js b/node_modules/moment/min/lang/sl.js new file mode 100644 index 0000000..c921a9f --- /dev/null +++ b/node_modules/moment/min/lang/sl.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : slovenian (sl) +// author : Robert Sedovšek : https://github.com/sedovsek +!function(){function e(e){function n(e,n,t){var a=e+" ";switch(t){case"m":return n?"ena minuta":"eno minuto";case"mm":return a+=1===e?"minuta":2===e?"minuti":3===e||4===e?"minute":"minut";case"h":return n?"ena ura":"eno uro";case"hh":return a+=1===e?"ura":2===e?"uri":3===e||4===e?"ure":"ur";case"dd":return a+=1===e?"dan":"dni";case"MM":return a+=1===e?"mesec":2===e?"meseca":3===e||4===e?"mesece":"mesecev";case"yy":return a+=1===e?"leto":2===e?"leti":3===e||4===e?"leta":"let"}}e.lang("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedelja_ponedeljek_torek_sreda_\u010detrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._\u010det._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_\u010de_pe_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[v\u010deraj ob] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[prej\u0161nja] dddd [ob] LT";case 1:case 2:case 4:case 5:return"[prej\u0161nji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"\u010dez %s",past:"%s nazaj",s:"nekaj sekund",m:n,mm:n,h:n,hh:n,d:"en dan",dd:n,M:"en mesec",MM:n,y:"eno leto",yy:n},ordinal:"%d.",week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/sq.js b/node_modules/moment/min/lang/sq.js new file mode 100644 index 0000000..43615c2 --- /dev/null +++ b/node_modules/moment/min/lang/sq.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : Albanian (sq) +// author : Flakërim Ismani : https://github.com/flakerimi +// author: Menelion Elensúle: https://github.com/Oire (tests) +!function(){function e(e){e.lang("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_N\xebntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_N\xebn_Dhj".split("_"),weekdays:"E Diel_E H\xebn\xeb_E Marte_E M\xebrkure_E Enjte_E Premte_E Shtun\xeb".split("_"),weekdaysShort:"Die_H\xebn_Mar_M\xebr_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_M\xeb_E_P_Sh".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Sot n\xeb] LT",nextDay:"[Neser n\xeb] LT",nextWeek:"dddd [n\xeb] LT",lastDay:"[Dje n\xeb] LT",lastWeek:"dddd [e kaluar n\xeb] LT",sameElse:"L"},relativeTime:{future:"n\xeb %s",past:"%s me par\xeb",s:"disa seconda",m:"nj\xeb minut",mm:"%d minutea",h:"nj\xeb or\xeb",hh:"%d or\xeb",d:"nj\xeb dit\xeb",dd:"%d dit\xeb",M:"nj\xeb muaj",MM:"%d muaj",y:"nj\xeb vit",yy:"%d vite"},ordinal:"%d.",week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/sv.js b/node_modules/moment/min/lang/sv.js new file mode 100644 index 0000000..2640eca --- /dev/null +++ b/node_modules/moment/min/lang/sv.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : swedish (sv) +// author : Jens Alm : https://github.com/ulmus +!function(){function e(e){e.lang("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"s\xf6ndag_m\xe5ndag_tisdag_onsdag_torsdag_fredag_l\xf6rdag".split("_"),weekdaysShort:"s\xf6n_m\xe5n_tis_ons_tor_fre_l\xf6r".split("_"),weekdaysMin:"s\xf6_m\xe5_ti_on_to_fr_l\xf6".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Ig\xe5r] LT",nextWeek:"dddd LT",lastWeek:"[F\xf6rra] dddd[en] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"f\xf6r %s sedan",s:"n\xe5gra sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en m\xe5nad",MM:"%d m\xe5nader",y:"ett \xe5r",yy:"%d \xe5r"},ordinal:function(e){var n=e%10,t=1===~~(e%100/10)?"e":1===n?"a":2===n?"a":3===n?"e":"e";return e+t},week:{dow:1,doy:4}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/th.js b/node_modules/moment/min/lang/th.js new file mode 100644 index 0000000..5ba5bda --- /dev/null +++ b/node_modules/moment/min/lang/th.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : thai (th) +// author : Kridsada Thanabulpong : https://github.com/sirn +!function(){function e(e){e.lang("th",{months:"\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21_\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c_\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21_\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19_\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21_\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19_\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21_\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21_\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19_\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21_\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19_\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21".split("_"),monthsShort:"\u0e21\u0e01\u0e23\u0e32_\u0e01\u0e38\u0e21\u0e20\u0e32_\u0e21\u0e35\u0e19\u0e32_\u0e40\u0e21\u0e29\u0e32_\u0e1e\u0e24\u0e29\u0e20\u0e32_\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32_\u0e01\u0e23\u0e01\u0e0e\u0e32_\u0e2a\u0e34\u0e07\u0e2b\u0e32_\u0e01\u0e31\u0e19\u0e22\u0e32_\u0e15\u0e38\u0e25\u0e32_\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32_\u0e18\u0e31\u0e19\u0e27\u0e32".split("_"),weekdays:"\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c_\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c_\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23_\u0e1e\u0e38\u0e18_\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35_\u0e28\u0e38\u0e01\u0e23\u0e4c_\u0e40\u0e2a\u0e32\u0e23\u0e4c".split("_"),weekdaysShort:"\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c_\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c_\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23_\u0e1e\u0e38\u0e18_\u0e1e\u0e24\u0e2b\u0e31\u0e2a_\u0e28\u0e38\u0e01\u0e23\u0e4c_\u0e40\u0e2a\u0e32\u0e23\u0e4c".split("_"),weekdaysMin:"\u0e2d\u0e32._\u0e08._\u0e2d._\u0e1e._\u0e1e\u0e24._\u0e28._\u0e2a.".split("_"),longDateFormat:{LT:"H \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 m \u0e19\u0e32\u0e17\u0e35",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY \u0e40\u0e27\u0e25\u0e32 LT",LLLL:"\u0e27\u0e31\u0e19dddd\u0e17\u0e35\u0e48 D MMMM YYYY \u0e40\u0e27\u0e25\u0e32 LT"},meridiem:function(e){return 12>e?"\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07":"\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"},calendar:{sameDay:"[\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",nextDay:"[\u0e1e\u0e23\u0e38\u0e48\u0e07\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",nextWeek:"dddd[\u0e2b\u0e19\u0e49\u0e32 \u0e40\u0e27\u0e25\u0e32] LT",lastDay:"[\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e27\u0e32\u0e19\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",lastWeek:"[\u0e27\u0e31\u0e19]dddd[\u0e17\u0e35\u0e48\u0e41\u0e25\u0e49\u0e27 \u0e40\u0e27\u0e25\u0e32] LT",sameElse:"L"},relativeTime:{future:"\u0e2d\u0e35\u0e01 %s",past:"%s\u0e17\u0e35\u0e48\u0e41\u0e25\u0e49\u0e27",s:"\u0e44\u0e21\u0e48\u0e01\u0e35\u0e48\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35",m:"1 \u0e19\u0e32\u0e17\u0e35",mm:"%d \u0e19\u0e32\u0e17\u0e35",h:"1 \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07",hh:"%d \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07",d:"1 \u0e27\u0e31\u0e19",dd:"%d \u0e27\u0e31\u0e19",M:"1 \u0e40\u0e14\u0e37\u0e2d\u0e19",MM:"%d \u0e40\u0e14\u0e37\u0e2d\u0e19",y:"1 \u0e1b\u0e35",yy:"%d \u0e1b\u0e35"}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/tr.js b/node_modules/moment/min/lang/tr.js new file mode 100644 index 0000000..95d0319 --- /dev/null +++ b/node_modules/moment/min/lang/tr.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : turkish (tr) +// authors : Erhan Gundogan : https://github.com/erhangundogan, +// Burak Yiğit Kaya: https://github.com/BYK +!function(){function e(e){var n={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'\xfcnc\xfc",4:"'\xfcnc\xfc",100:"'\xfcnc\xfc",6:"'nc\u0131",9:"'uncu",10:"'uncu",30:"'uncu",60:"'\u0131nc\u0131",90:"'\u0131nc\u0131"};e.lang("tr",{months:"Ocak_\u015eubat_Mart_Nisan_May\u0131s_Haziran_Temmuz_A\u011fustos_Eyl\xfcl_Ekim_Kas\u0131m_Aral\u0131k".split("_"),monthsShort:"Oca_\u015eub_Mar_Nis_May_Haz_Tem_A\u011fu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Sal\u0131_\xc7ar\u015famba_Per\u015fembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_\xc7ar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_\xc7a_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bug\xfcn saat] LT",nextDay:"[yar\u0131n saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[d\xfcn] LT",lastWeek:"[ge\xe7en hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s \xf6nce",s:"birka\xe7 saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir g\xfcn",dd:"%d g\xfcn",M:"bir ay",MM:"%d ay",y:"bir y\u0131l",yy:"%d y\u0131l"},ordinal:function(e){if(0===e)return e+"'\u0131nc\u0131";var t=e%10,a=e%100-t,_=e>=100?100:null;return e+(n[t]||n[a]||n[_])},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/tzm-la.js b/node_modules/moment/min/lang/tzm-la.js new file mode 100644 index 0000000..93b0904 --- /dev/null +++ b/node_modules/moment/min/lang/tzm-la.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : Morocco Central Atlas Tamaziɣt in Latin (tzm-la) +// author : Abdel Said : https://github.com/abdelsaid +!function(){function e(e){e.lang("tzm-la",{months:"innayr_br\u02e4ayr\u02e4_mar\u02e4s\u02e4_ibrir_mayyw_ywnyw_ywlywz_\u0263w\u0161t_\u0161wtanbir_kt\u02e4wbr\u02e4_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_br\u02e4ayr\u02e4_mar\u02e4s\u02e4_ibrir_mayyw_ywnyw_ywlywz_\u0263w\u0161t_\u0161wtanbir_kt\u02e4wbr\u02e4_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",m:"minu\u1e0d",mm:"%d minu\u1e0d",h:"sa\u025ba",hh:"%d tassa\u025bin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/tzm.js b/node_modules/moment/min/lang/tzm.js new file mode 100644 index 0000000..e81f5cf --- /dev/null +++ b/node_modules/moment/min/lang/tzm.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : Morocco Central Atlas Tamaziɣt (tzm) +// author : Abdel Said : https://github.com/abdelsaid +!function(){function e(e){e.lang("tzm",{months:"\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54_\u2d31\u2d55\u2d30\u2d62\u2d55_\u2d4e\u2d30\u2d55\u2d5a_\u2d49\u2d31\u2d54\u2d49\u2d54_\u2d4e\u2d30\u2d62\u2d62\u2d53_\u2d62\u2d53\u2d4f\u2d62\u2d53_\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63_\u2d56\u2d53\u2d5b\u2d5c_\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d3d\u2d5f\u2d53\u2d31\u2d55_\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d37\u2d53\u2d4a\u2d4f\u2d31\u2d49\u2d54".split("_"),monthsShort:"\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54_\u2d31\u2d55\u2d30\u2d62\u2d55_\u2d4e\u2d30\u2d55\u2d5a_\u2d49\u2d31\u2d54\u2d49\u2d54_\u2d4e\u2d30\u2d62\u2d62\u2d53_\u2d62\u2d53\u2d4f\u2d62\u2d53_\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63_\u2d56\u2d53\u2d5b\u2d5c_\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d3d\u2d5f\u2d53\u2d31\u2d55_\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d37\u2d53\u2d4a\u2d4f\u2d31\u2d49\u2d54".split("_"),weekdays:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),weekdaysShort:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),weekdaysMin:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[\u2d30\u2d59\u2d37\u2d45 \u2d34] LT",nextDay:"[\u2d30\u2d59\u2d3d\u2d30 \u2d34] LT",nextWeek:"dddd [\u2d34] LT",lastDay:"[\u2d30\u2d5a\u2d30\u2d4f\u2d5c \u2d34] LT",lastWeek:"dddd [\u2d34] LT",sameElse:"L"},relativeTime:{future:"\u2d37\u2d30\u2d37\u2d45 \u2d59 \u2d62\u2d30\u2d4f %s",past:"\u2d62\u2d30\u2d4f %s",s:"\u2d49\u2d4e\u2d49\u2d3d",m:"\u2d4e\u2d49\u2d4f\u2d53\u2d3a",mm:"%d \u2d4e\u2d49\u2d4f\u2d53\u2d3a",h:"\u2d59\u2d30\u2d44\u2d30",hh:"%d \u2d5c\u2d30\u2d59\u2d59\u2d30\u2d44\u2d49\u2d4f",d:"\u2d30\u2d59\u2d59",dd:"%d o\u2d59\u2d59\u2d30\u2d4f",M:"\u2d30\u2d62o\u2d53\u2d54",MM:"%d \u2d49\u2d62\u2d62\u2d49\u2d54\u2d4f",y:"\u2d30\u2d59\u2d33\u2d30\u2d59",yy:"%d \u2d49\u2d59\u2d33\u2d30\u2d59\u2d4f"},week:{dow:6,doy:12}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/uk.js b/node_modules/moment/min/lang/uk.js new file mode 100644 index 0000000..998a295 --- /dev/null +++ b/node_modules/moment/min/lang/uk.js @@ -0,0 +1,5 @@ +// moment.js language configuration +// language : ukrainian (uk) +// author : zemlanin : https://github.com/zemlanin +// Author : Menelion Elensúle : https://github.com/Oire +!function(){function e(e){function n(e,n){var t=e.split("_");return 1===n%10&&11!==n%100?t[0]:n%10>=2&&4>=n%10&&(10>n%100||n%100>=20)?t[1]:t[2]}function t(e,t,a){var _={mm:"\u0445\u0432\u0438\u043b\u0438\u043d\u0430_\u0445\u0432\u0438\u043b\u0438\u043d\u0438_\u0445\u0432\u0438\u043b\u0438\u043d",hh:"\u0433\u043e\u0434\u0438\u043d\u0430_\u0433\u043e\u0434\u0438\u043d\u0438_\u0433\u043e\u0434\u0438\u043d",dd:"\u0434\u0435\u043d\u044c_\u0434\u043d\u0456_\u0434\u043d\u0456\u0432",MM:"\u043c\u0456\u0441\u044f\u0446\u044c_\u043c\u0456\u0441\u044f\u0446\u0456_\u043c\u0456\u0441\u044f\u0446\u0456\u0432",yy:"\u0440\u0456\u043a_\u0440\u043e\u043a\u0438_\u0440\u043e\u043a\u0456\u0432"};return"m"===a?t?"\u0445\u0432\u0438\u043b\u0438\u043d\u0430":"\u0445\u0432\u0438\u043b\u0438\u043d\u0443":"h"===a?t?"\u0433\u043e\u0434\u0438\u043d\u0430":"\u0433\u043e\u0434\u0438\u043d\u0443":e+" "+n(_[a],+e)}function a(e,n){var t={nominative:"\u0441\u0456\u0447\u0435\u043d\u044c_\u043b\u044e\u0442\u0438\u0439_\u0431\u0435\u0440\u0435\u0437\u0435\u043d\u044c_\u043a\u0432\u0456\u0442\u0435\u043d\u044c_\u0442\u0440\u0430\u0432\u0435\u043d\u044c_\u0447\u0435\u0440\u0432\u0435\u043d\u044c_\u043b\u0438\u043f\u0435\u043d\u044c_\u0441\u0435\u0440\u043f\u0435\u043d\u044c_\u0432\u0435\u0440\u0435\u0441\u0435\u043d\u044c_\u0436\u043e\u0432\u0442\u0435\u043d\u044c_\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434_\u0433\u0440\u0443\u0434\u0435\u043d\u044c".split("_"),accusative:"\u0441\u0456\u0447\u043d\u044f_\u043b\u044e\u0442\u043e\u0433\u043e_\u0431\u0435\u0440\u0435\u0437\u043d\u044f_\u043a\u0432\u0456\u0442\u043d\u044f_\u0442\u0440\u0430\u0432\u043d\u044f_\u0447\u0435\u0440\u0432\u043d\u044f_\u043b\u0438\u043f\u043d\u044f_\u0441\u0435\u0440\u043f\u043d\u044f_\u0432\u0435\u0440\u0435\u0441\u043d\u044f_\u0436\u043e\u0432\u0442\u043d\u044f_\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430_\u0433\u0440\u0443\u0434\u043d\u044f".split("_")},a=/D[oD]? *MMMM?/.test(n)?"accusative":"nominative";return t[a][e.month()]}function _(e,n){var t={nominative:"\u043d\u0435\u0434\u0456\u043b\u044f_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a_\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a_\u0441\u0435\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0435\u0440_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u044f_\u0441\u0443\u0431\u043e\u0442\u0430".split("_"),accusative:"\u043d\u0435\u0434\u0456\u043b\u044e_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a_\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a_\u0441\u0435\u0440\u0435\u0434\u0443_\u0447\u0435\u0442\u0432\u0435\u0440_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u044e_\u0441\u0443\u0431\u043e\u0442\u0443".split("_"),genitive:"\u043d\u0435\u0434\u0456\u043b\u0456_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043a\u0430_\u0432\u0456\u0432\u0442\u043e\u0440\u043a\u0430_\u0441\u0435\u0440\u0435\u0434\u0438_\u0447\u0435\u0442\u0432\u0435\u0440\u0433\u0430_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u0456_\u0441\u0443\u0431\u043e\u0442\u0438".split("_")},a=/(\[[\u0412\u0432\u0423\u0443]\]) ?dddd/.test(n)?"accusative":/\[?(?:\u043c\u0438\u043d\u0443\u043b\u043e\u0457|\u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457)? ?\] ?dddd/.test(n)?"genitive":"nominative";return t[a][e.day()]}function d(e){return function(){return e+"\u043e"+(11===this.hours()?"\u0431":"")+"] LT"}}e.lang("uk",{months:a,monthsShort:"\u0441\u0456\u0447_\u043b\u044e\u0442_\u0431\u0435\u0440_\u043a\u0432\u0456_\u0442\u0440\u0430_\u0447\u0435\u0440_\u043b\u0438\u043f_\u0441\u0435\u0440_\u0432\u0435\u0440_\u0436\u043e\u0432_\u043b\u0438\u0441_\u0433\u0440\u0443".split("_"),weekdays:_,weekdaysShort:"\u043d\u0435\u0434_\u043f\u043e\u043d_\u0432\u0456\u0432_\u0441\u0440\u0434_\u0447\u0435\u0442_\u043f\u0442\u043d_\u0441\u0443\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0440.",LLL:"D MMMM YYYY \u0440., LT",LLLL:"dddd, D MMMM YYYY \u0440., LT"},calendar:{sameDay:d("[\u0421\u044c\u043e\u0433\u043e\u0434\u043d\u0456 "),nextDay:d("[\u0417\u0430\u0432\u0442\u0440\u0430 "),lastDay:d("[\u0412\u0447\u043e\u0440\u0430 "),nextWeek:d("[\u0423] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return d("[\u041c\u0438\u043d\u0443\u043b\u043e\u0457] dddd [").call(this);case 1:case 2:case 4:return d("[\u041c\u0438\u043d\u0443\u043b\u043e\u0433\u043e] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"\u0437\u0430 %s",past:"%s \u0442\u043e\u043c\u0443",s:"\u0434\u0435\u043a\u0456\u043b\u044c\u043a\u0430 \u0441\u0435\u043a\u0443\u043d\u0434",m:t,mm:t,h:"\u0433\u043e\u0434\u0438\u043d\u0443",hh:t,d:"\u0434\u0435\u043d\u044c",dd:t,M:"\u043c\u0456\u0441\u044f\u0446\u044c",MM:t,y:"\u0440\u0456\u043a",yy:t},ordinal:function(e,n){switch(n){case"M":case"d":case"DDD":case"w":case"W":return e+"-\u0439";case"D":return e+"-\u0433\u043e";default:return e}},week:{dow:1,doy:7}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/zh-cn.js b/node_modules/moment/min/lang/zh-cn.js new file mode 100644 index 0000000..c8fa795 --- /dev/null +++ b/node_modules/moment/min/lang/zh-cn.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : chinese +// author : suupic : https://github.com/suupic +!function(){function e(e){e.lang("zh-cn",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u5468\u65e5_\u5468\u4e00_\u5468\u4e8c_\u5468\u4e09_\u5468\u56db_\u5468\u4e94_\u5468\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"Ah\u70b9mm",L:"YYYY\u5e74MMMD\u65e5",LL:"YYYY\u5e74MMMD\u65e5",LLL:"YYYY\u5e74MMMD\u65e5LT",LLLL:"YYYY\u5e74MMMD\u65e5ddddLT",l:"YYYY\u5e74MMMD\u65e5",ll:"YYYY\u5e74MMMD\u65e5",lll:"YYYY\u5e74MMMD\u65e5LT",llll:"YYYY\u5e74MMMD\u65e5ddddLT"},meridiem:function(e,n){return 9>e?"\u65e9\u4e0a":11>e&&30>n?"\u4e0a\u5348":13>e&&30>n?"\u4e2d\u5348":18>e?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},ordinal:function(e,n){switch(n){case"d":case"D":case"DDD":return e+"\u65e5";case"M":return e+"\u6708";case"w":case"W":return e+"\u5468";default:return e}},relativeTime:{future:"%s\u5185",past:"%s\u524d",s:"\u51e0\u79d2",m:"1\u5206\u949f",mm:"%d\u5206\u949f",h:"1\u5c0f\u65f6",hh:"%d\u5c0f\u65f6",d:"1\u5929",dd:"%d\u5929",M:"1\u4e2a\u6708",MM:"%d\u4e2a\u6708",y:"1\u5e74",yy:"%d\u5e74"}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/lang/zh-tw.js b/node_modules/moment/min/lang/zh-tw.js new file mode 100644 index 0000000..c0a047c --- /dev/null +++ b/node_modules/moment/min/lang/zh-tw.js @@ -0,0 +1,4 @@ +// moment.js language configuration +// language : traditional chinese (zh-tw) +// author : Ben : https://github.com/ben-lin +!function(){function e(e){e.lang("zh-tw",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u9031\u65e5_\u9031\u4e00_\u9031\u4e8c_\u9031\u4e09_\u9031\u56db_\u9031\u4e94_\u9031\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"Ah\u9edemm",L:"YYYY\u5e74MMMD\u65e5",LL:"YYYY\u5e74MMMD\u65e5",LLL:"YYYY\u5e74MMMD\u65e5LT",LLLL:"YYYY\u5e74MMMD\u65e5ddddLT",l:"YYYY\u5e74MMMD\u65e5",ll:"YYYY\u5e74MMMD\u65e5",lll:"YYYY\u5e74MMMD\u65e5LT",llll:"YYYY\u5e74MMMD\u65e5ddddLT"},meridiem:function(e,n){return 9>e?"\u65e9\u4e0a":11>e&&30>n?"\u4e0a\u5348":13>e&&30>n?"\u4e2d\u5348":18>e?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},ordinal:function(e,n){switch(n){case"d":case"D":case"DDD":return e+"\u65e5";case"M":return e+"\u6708";case"w":case"W":return e+"\u9031";default:return e}},relativeTime:{future:"%s\u5167",past:"%s\u524d",s:"\u5e7e\u79d2",m:"\u4e00\u5206\u9418",mm:"%d\u5206\u9418",h:"\u4e00\u5c0f\u6642",hh:"%d\u5c0f\u6642",d:"\u4e00\u5929",dd:"%d\u5929",M:"\u4e00\u500b\u6708",MM:"%d\u500b\u6708",y:"\u4e00\u5e74",yy:"%d\u5e74"}})}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/langs.js b/node_modules/moment/min/langs.js new file mode 100644 index 0000000..5e51fea --- /dev/null +++ b/node_modules/moment/min/langs.js @@ -0,0 +1,3693 @@ +(function(){ + function onload (moment) { +(function(){ +// moment.js language configuration +// language : Moroccan Arabic (ar-ma) +// author : ElFadili Yassine : https://github.com/ElFadiliY +// author : Abdel Said : https://github.com/abdelsaid + +moment.lang('ar-ma', { + months : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"), + monthsShort : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"), + weekdays : "الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"), + weekdaysShort : "احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"), + weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[اليوم على الساعة] LT", + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : "في %s", + past : "منذ %s", + s : "ثوان", + m : "دقيقة", + mm : "%d دقائق", + h : "ساعة", + hh : "%d ساعات", + d : "يوم", + dd : "%d أيام", + M : "شهر", + MM : "%d أشهر", + y : "سنة", + yy : "%d سنوات" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Arabic (ar) +// author : Abdel Said : https://github.com/abdelsaid +// changes in months, weekdays : Ahmed Elkhatib + +moment.lang('ar', { + months : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"), + monthsShort : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"), + weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"), + weekdaysShort : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"), + weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[اليوم على الساعة] LT", + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : "في %s", + past : "منذ %s", + s : "ثوان", + m : "دقيقة", + mm : "%d دقائق", + h : "ساعة", + hh : "%d ساعات", + d : "يوم", + dd : "%d أيام", + M : "شهر", + MM : "%d أشهر", + y : "سنة", + yy : "%d سنوات" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : bulgarian (bg) +// author : Krasen Borisov : https://github.com/kraz + +moment.lang('bg', { + months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"), + monthsShort : "янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"), + weekdays : "неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"), + weekdaysShort : "нед_пон_вто_сря_чет_пет_съб".split("_"), + weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "h:mm", + L : "D.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : "след %s", + past : "преди %s", + s : "няколко секунди", + m : "минута", + mm : "%d минути", + h : "час", + hh : "%d часа", + d : "ден", + dd : "%d дни", + M : "месец", + MM : "%d месеца", + y : "година", + yy : "%d години" + }, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : breton (br) +// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + +function relativeTimeWithMutation(number, withoutSuffix, key) { + var format = { + 'mm': "munutenn", + 'MM': "miz", + 'dd': "devezh" + }; + return number + ' ' + mutation(format[key], number); +} + +function specialMutationForYears(number) { + switch (lastNumber(number)) { + case 1: + case 3: + case 4: + case 5: + case 9: + return number + ' bloaz'; + default: + return number + ' vloaz'; + } +} + +function lastNumber(number) { + if (number > 9) { + return lastNumber(number % 10); + } + return number; +} + +function mutation(text, number) { + if (number === 2) { + return softMutation(text); + } + return text; +} + +function softMutation(text) { + var mutationTable = { + 'm': 'v', + 'b': 'v', + 'd': 'z' + }; + if (mutationTable[text.charAt(0)] === undefined) { + return text; + } + return mutationTable[text.charAt(0)] + text.substring(1); +} + +moment.lang('br', { + months : "Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"), + monthsShort : "Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"), + weekdays : "Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"), + weekdaysShort : "Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"), + weekdaysMin : "Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"), + longDateFormat : { + LT : "h[e]mm A", + L : "DD/MM/YYYY", + LL : "D [a viz] MMMM YYYY", + LLL : "D [a viz] MMMM YYYY LT", + LLLL : "dddd, D [a viz] MMMM YYYY LT" + }, + calendar : { + sameDay : '[Hiziv da] LT', + nextDay : '[Warc\'hoazh da] LT', + nextWeek : 'dddd [da] LT', + lastDay : '[Dec\'h da] LT', + lastWeek : 'dddd [paset da] LT', + sameElse : 'L' + }, + relativeTime : { + future : "a-benn %s", + past : "%s 'zo", + s : "un nebeud segondennoù", + m : "ur vunutenn", + mm : relativeTimeWithMutation, + h : "un eur", + hh : "%d eur", + d : "un devezh", + dd : relativeTimeWithMutation, + M : "ur miz", + MM : relativeTimeWithMutation, + y : "ur bloaz", + yy : specialMutationForYears + }, + ordinal : function (number) { + var output = (number === 1) ? 'añ' : 'vet'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : catalan (ca) +// author : Juan G. Hurtado : https://github.com/juanghurtado + +moment.lang('ca', { + months : "Gener_Febrer_Març_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"), + monthsShort : "Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"), + weekdays : "Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"), + weekdaysShort : "Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"), + weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "fa %s", + s : "uns segons", + m : "un minut", + mm : "%d minuts", + h : "una hora", + hh : "%d hores", + d : "un dia", + dd : "%d dies", + M : "un mes", + MM : "%d mesos", + y : "un any", + yy : "%d anys" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : czech (cs) +// author : petrbela : https://github.com/petrbela + +var months = "leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"), + monthsShort = "led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"); + +function plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); +} + +function translate(number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár vteřin' : 'pár vteřinami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minuty' : 'minut'); + } else { + return result + 'minutami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodin'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'den' : 'dnem'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dny' : 'dní'); + } else { + return result + 'dny'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'měsíce' : 'měsíců'); + } else { + return result + 'měsíci'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } +} + +moment.lang('cs', { + months : months, + monthsShort : monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(months, monthsShort)), + weekdays : "neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"), + weekdaysShort : "ne_po_út_st_čt_pá_so".split("_"), + weekdaysMin : "ne_po_út_st_čt_pá_so".split("_"), + longDateFormat : { + LT: "H:mm", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[dnes v] LT", + nextDay: '[zítra v] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v neděli v] LT'; + case 1: + case 2: + return '[v] dddd [v] LT'; + case 3: + return '[ve středu v] LT'; + case 4: + return '[ve čtvrtek v] LT'; + case 5: + return '[v pátek v] LT'; + case 6: + return '[v sobotu v] LT'; + } + }, + lastDay: '[včera v] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulou neděli v] LT'; + case 1: + case 2: + return '[minulé] dddd [v] LT'; + case 3: + return '[minulou středu v] LT'; + case 4: + case 5: + return '[minulý] dddd [v] LT'; + case 6: + return '[minulou sobotu v] LT'; + } + }, + sameElse: "L" + }, + relativeTime : { + future : "za %s", + past : "před %s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : chuvash (cv) +// author : Anatoly Mironov : https://github.com/mirontoli + + +moment.lang('cv', { + months : "кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"), + monthsShort : "кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"), + weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"), + weekdaysShort : "выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"), + weekdaysMin : "вр_тн_ыт_юн_кç_эр_шм".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]", + LLL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT", + LLLL : "dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT" + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ĕнер] LT [сехетре]', + nextWeek: '[Çитес] dddd LT [сехетре]', + lastWeek: '[Иртнĕ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : function (output) { + var affix = /сехет$/i.exec(output) ? "рен" : /çул$/i.exec(output) ? "тан" : "ран"; + return output + affix; + }, + past : "%s каялла", + s : "пĕр-ик çеккунт", + m : "пĕр минут", + mm : "%d минут", + h : "пĕр сехет", + hh : "%d сехет", + d : "пĕр кун", + dd : "%d кун", + M : "пĕр уйăх", + MM : "%d уйăх", + y : "пĕр çул", + yy : "%d çул" + }, + ordinal : '%d-мĕш', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : danish (da) +// author : Ulrik Nielsen : https://github.com/mrbase + +moment.lang('da', { + months : "Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"), + weekdays : "Søndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_Lørdag".split("_"), + weekdaysShort : "Søn_Man_Tir_Ons_Tor_Fre_Lør".split("_"), + weekdaysMin : "Sø_Ma_Ti_On_To_Fr_Lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D. MMMM, YYYY LT" + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : "om %s", + past : "%s siden", + s : "få sekunder", + m : "et minut", + mm : "%d minutter", + h : "en time", + hh : "%d timer", + d : "en dag", + dd : "%d dage", + M : "en måned", + MM : "%d måneder", + y : "et år", + yy : "%d år" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : german (de) +// author : lluchs : https://github.com/lluchs +// author: Menelion Elensúle: https://github.com/Oire + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; +} + +moment.lang('de', { + months : "Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"), + monthsShort : "Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"), + weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"), + weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"), + weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"), + longDateFormat : { + LT: "H:mm [Uhr]", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[Heute um] LT", + sameElse: "L", + nextDay: '[Morgen um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gestern um] LT', + lastWeek: '[letzten] dddd [um] LT' + }, + relativeTime : { + future : "in %s", + past : "vor %s", + s : "ein paar Sekunden", + m : processRelativeTime, + mm : "%d Minuten", + h : processRelativeTime, + hh : "%d Stunden", + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : modern greek (el) +// author : Aggelos Karalias : https://github.com/mehiel + +moment.lang('el', { + monthsNominativeEl : "Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"), + monthsGenitiveEl : "Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"), + months : function (momentToFormat, format) { + if (/D/.test(format.substring(0, format.indexOf("MMMM")))) { // if there is a day number before 'MMMM' + return this._monthsGenitiveEl[momentToFormat.month()]; + } else { + return this._monthsNominativeEl[momentToFormat.month()]; + } + }, + monthsShort : "Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"), + weekdays : "Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"), + weekdaysShort : "Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"), + weekdaysMin : "Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"), + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'μμ' : 'ΜΜ'; + } else { + return isLower ? 'πμ' : 'ΠΜ'; + } + }, + longDateFormat : { + LT : "h:mm A", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendarEl : { + sameDay : '[Σήμερα {}] LT', + nextDay : '[Αύριο {}] LT', + nextWeek : 'dddd [{}] LT', + lastDay : '[Χθες {}] LT', + lastWeek : '[την προηγούμενη] dddd [{}] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + + return output.replace("{}", (hours % 12 === 1 ? "στη" : "στις")); + }, + relativeTime : { + future : "σε %s", + past : "%s πριν", + s : "δευτερόλεπτα", + m : "ένα λεπτό", + mm : "%d λεπτά", + h : "μία ώρα", + hh : "%d ώρες", + d : "μία μέρα", + dd : "%d μέρες", + M : "ένας μήνας", + MM : "%d μήνες", + y : "ένας χρόνος", + yy : "%d χρόνια" + }, + ordinal : function (number) { + return number + 'η'; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : canadian english (en-ca) +// author : Jonathan Abourbih : https://github.com/jonbca + +moment.lang('en-ca', { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "YYYY-MM-DD", + LL : "D MMMM, YYYY", + LLL : "D MMMM, YYYY LT", + LLLL : "dddd, D MMMM, YYYY LT" + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } +}); +})(); +(function(){ +// moment.js language configuration +// language : great britain english (en-gb) +// author : Chris Gedrim : https://github.com/chrisgedrim + +moment.lang('en-gb', { + months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : esperanto (eo) +// author : Colin Dean : https://github.com/colindean +// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. +// Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! + +moment.lang('eo', { + months : "januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"), + monthsShort : "jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"), + weekdays : "Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"), + weekdaysShort : "Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D[-an de] MMMM, YYYY", + LLL : "D[-an de] MMMM, YYYY LT", + LLLL : "dddd, [la] D[-an de] MMMM, YYYY LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'p.t.m.' : 'P.T.M.'; + } else { + return isLower ? 'a.t.m.' : 'A.T.M.'; + } + }, + calendar : { + sameDay : '[Hodiaŭ je] LT', + nextDay : '[Morgaŭ je] LT', + nextWeek : 'dddd [je] LT', + lastDay : '[Hieraŭ je] LT', + lastWeek : '[pasinta] dddd [je] LT', + sameElse : 'L' + }, + relativeTime : { + future : "je %s", + past : "antaŭ %s", + s : "sekundoj", + m : "minuto", + mm : "%d minutoj", + h : "horo", + hh : "%d horoj", + d : "tago",//ne 'diurno', ĉar estas uzita por proksimumo + dd : "%d tagoj", + M : "monato", + MM : "%d monatoj", + y : "jaro", + yy : "%d jaroj" + }, + ordinal : "%da", + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : spanish (es) +// author : Julio Napurí : https://github.com/julionc + +moment.lang('es', { + months : "enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"), + monthsShort : "ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"), + weekdays : "domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"), + weekdaysShort : "dom._lun._mar._mié._jue._vie._sáb.".split("_"), + weekdaysMin : "Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D [de] MMMM [de] YYYY", + LLL : "D [de] MMMM [de] YYYY LT", + LLLL : "dddd, D [de] MMMM [de] YYYY LT" + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : "en %s", + past : "hace %s", + s : "unos segundos", + m : "un minuto", + mm : "%d minutos", + h : "una hora", + hh : "%d horas", + d : "un día", + dd : "%d días", + M : "un mes", + MM : "%d meses", + y : "un año", + yy : "%d años" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : estonian (et) +// author : Henry Kehlmann : https://github.com/madhenry + +function translateSeconds(number, withoutSuffix, key, isFuture) { + return (isFuture || withoutSuffix) ? 'paari sekundi' : 'paar sekundit'; +} + +moment.lang('et', { + months : "jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"), + monthsShort : "jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"), + weekdays : "pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"), + weekdaysShort : "P_E_T_K_N_R_L".split("_"), + weekdaysMin : "P_E_T_K_N_R_L".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay : '[Täna,] LT', + nextDay : '[Homme,] LT', + nextWeek : '[Järgmine] dddd LT', + lastDay : '[Eile,] LT', + lastWeek : '[Eelmine] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s pärast", + past : "%s tagasi", + s : translateSeconds, + m : "minut", + mm : "%d minutit", + h : "tund", + hh : "%d tundi", + d : "päev", + dd : "%d päeva", + M : "kuu", + MM : "%d kuud", + y : "aasta", + yy : "%d aastat" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : euskara (eu) +// author : Eneko Illarramendi : https://github.com/eillarra + +moment.lang('eu', { + months : "urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"), + monthsShort : "urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"), + weekdays : "igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"), + weekdaysShort : "ig._al._ar._az._og._ol._lr.".split("_"), + weekdaysMin : "ig_al_ar_az_og_ol_lr".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "YYYY[ko] MMMM[ren] D[a]", + LLL : "YYYY[ko] MMMM[ren] D[a] LT", + LLLL : "dddd, YYYY[ko] MMMM[ren] D[a] LT", + l : "YYYY-M-D", + ll : "YYYY[ko] MMM D[a]", + lll : "YYYY[ko] MMM D[a] LT", + llll : "ddd, YYYY[ko] MMM D[a] LT" + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : "%s barru", + past : "duela %s", + s : "segundo batzuk", + m : "minutu bat", + mm : "%d minutu", + h : "ordu bat", + hh : "%d ordu", + d : "egun bat", + dd : "%d egun", + M : "hilabete bat", + MM : "%d hilabete", + y : "urte bat", + yy : "%d urte" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Persian Language +// author : Ebrahim Byagowi : https://github.com/ebraminio +var symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' +}, numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' +}; + +moment.lang('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + longDateFormat : { + LT : 'HH:mm', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "قبل از ظهر"; + } else { + return "بعد از ظهر"; + } + }, + calendar : { + sameDay : '[امروز ساعت] LT', + nextDay : '[فردا ساعت] LT', + nextWeek : 'dddd [ساعت] LT', + lastDay : '[دیروز ساعت] LT', + lastWeek : 'dddd [پیش] [ساعت] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'در %s', + past : '%s پیش', + s : 'چندین ثانیه', + m : 'یک دقیقه', + mm : '%d دقیقه', + h : 'یک ساعت', + hh : '%d ساعت', + d : 'یک روز', + dd : '%d روز', + M : 'یک ماه', + MM : '%d ماه', + y : 'یک سال', + yy : '%d سال' + }, + preparse: function (string) { + return string.replace(/[۰-۹]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinal : '%dم', + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : finnish (fi) +// author : Tarmo Aidantausta : https://github.com/bleadof + +var numbers_past = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbers_future = ['nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbers_past[7], numbers_past[8], numbers_past[9]]; + +function translate(number, withoutSuffix, key, isFuture) { + var result = ""; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbal_number(number, isFuture) + " " + result; + return result; +} + +function verbal_number(number, isFuture) { + return number < 10 ? (isFuture ? numbers_future[number] : numbers_past[number]) : number; +} + +moment.lang('fi', { + months : "tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"), + monthsShort : "tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"), + weekdays : "sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"), + weekdaysShort : "su_ma_ti_ke_to_pe_la".split("_"), + weekdaysMin : "su_ma_ti_ke_to_pe_la".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD.MM.YYYY", + LL : "Do MMMM[ta] YYYY", + LLL : "Do MMMM[ta] YYYY, [klo] LT", + LLLL : "dddd, Do MMMM[ta] YYYY, [klo] LT", + l : "D.M.YYYY", + ll : "Do MMM YYYY", + lll : "Do MMM YYYY, [klo] LT", + llll : "ddd, Do MMM YYYY, [klo] LT" + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s päästä", + past : "%s sitten", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : "%d.", + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : canadian french (fr-ca) +// author : Jonathan Abourbih : https://github.com/jonbca + +moment.lang('fr-ca', { + months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"), + monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"), + weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), + weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[Aujourd'hui à] LT", + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dans %s", + past : "il y a %s", + s : "quelques secondes", + m : "une minute", + mm : "%d minutes", + h : "une heure", + hh : "%d heures", + d : "un jour", + dd : "%d jours", + M : "un mois", + MM : "%d mois", + y : "un an", + yy : "%d ans" + }, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + } +}); +})(); +(function(){ +// moment.js language configuration +// language : french (fr) +// author : John Fischer : https://github.com/jfroffice + +moment.lang('fr', { + months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"), + monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"), + weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), + weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"), + weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[Aujourd'hui à] LT", + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dans %s", + past : "il y a %s", + s : "quelques secondes", + m : "une minute", + mm : "%d minutes", + h : "une heure", + hh : "%d heures", + d : "un jour", + dd : "%d jours", + M : "un mois", + MM : "%d mois", + y : "un an", + yy : "%d ans" + }, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : galician (gl) +// author : Juan G. Hurtado : https://github.com/juanghurtado + +moment.lang('gl', { + months : "Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"), + monthsShort : "Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"), + weekdays : "Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"), + weekdaysShort : "Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"), + weekdaysMin : "Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : function (str) { + if (str === "uns segundos") { + return "nuns segundos"; + } + return "en " + str; + }, + past : "hai %s", + s : "uns segundos", + m : "un minuto", + mm : "%d minutos", + h : "unha hora", + hh : "%d horas", + d : "un día", + dd : "%d días", + M : "un mes", + MM : "%d meses", + y : "un ano", + yy : "%d anos" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Hebrew (he) +// author : Tomer Cohen : https://github.com/tomer +// author : Moshe Simantov : https://github.com/DevelopmentIL + +moment.lang('he', { + months : "ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"), + monthsShort : "ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"), + weekdays : "ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"), + weekdaysShort : "א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"), + weekdaysMin : "א_ב_ג_ד_ה_ו_ש".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D [ב]MMMM YYYY", + LLL : "D [ב]MMMM YYYY LT", + LLLL : "dddd, D [ב]MMMM YYYY LT", + l : "D/M/YYYY", + ll : "D MMM YYYY", + lll : "D MMM YYYY LT", + llll : "ddd, D MMM YYYY LT" + }, + calendar : { + sameDay : '[היום ב־]LT', + nextDay : '[מחר ב־]LT', + nextWeek : 'dddd [בשעה] LT', + lastDay : '[אתמול ב־]LT', + lastWeek : '[ביום] dddd [האחרון בשעה] LT', + sameElse : 'L' + }, + relativeTime : { + future : "בעוד %s", + past : "לפני %s", + s : "מספר שניות", + m : "דקה", + mm : "%d דקות", + h : "שעה", + hh : "%d שעות", + d : "יום", + dd : "%d ימים", + M : "חודש", + MM : "%d חודשים", + y : "שנה", + yy : "%d שנים" + } +}); +})(); +(function(){ +// moment.js language configuration +// language : hindi (hi) +// author : Mayank Singhal : https://github.com/mayanksinghal + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +moment.lang('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split("_"), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split("_"), + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split("_"), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"), + longDateFormat : { + LT : "A h:mm बजे", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY, LT", + LLLL : "dddd, D MMMM YYYY, LT" + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[कल] LT', + nextWeek : 'dddd, LT', + lastDay : '[कल] LT', + lastWeek : '[पिछले] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s में", + past : "%s पहले", + s : "कुछ ही क्षण", + m : "एक मिनट", + mm : "%d मिनट", + h : "एक घंटा", + hh : "%d घंटे", + d : "एक दिन", + dd : "%d दिन", + M : "एक महीने", + MM : "%d महीने", + y : "एक वर्ष", + yy : "%d वर्ष" + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // Hindi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return "रात"; + } else if (hour < 10) { + return "सुबह"; + } else if (hour < 17) { + return "दोपहर"; + } else if (hour < 20) { + return "शाम"; + } else { + return "रात"; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : hungarian (hu) +// author : Adam Brunner : https://github.com/adambrunner + +var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); + +function translate(number, withoutSuffix, key, isFuture) { + var num = number, + suffix; + + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + case 'm': + return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'h': + return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'd': + return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'M': + return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'y': + return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + } + + return ''; +} + +function week(isFuture) { + return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; +} + +moment.lang('hu', { + months : "január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"), + monthsShort : "jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"), + weekdays : "vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"), + weekdaysShort : "v_h_k_sze_cs_p_szo".split("_"), + longDateFormat : { + LT : "H:mm", + L : "YYYY.MM.DD.", + LL : "YYYY. MMMM D.", + LLL : "YYYY. MMMM D., LT", + LLLL : "YYYY. MMMM D., dddd LT" + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function () { + return week.call(this, true); + }, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function () { + return week.call(this, false); + }, + sameElse : 'L' + }, + relativeTime : { + future : "%s múlva", + past : "%s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Bahasa Indonesia (id) +// author : Mohammad Satrio Utomo : https://github.com/tyok +// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + +moment.lang('id', { + months : "Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"), + monthsShort : "Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"), + weekdays : "Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"), + weekdaysShort : "Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"), + weekdaysMin : "Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY [pukul] LT", + LLLL : "dddd, D MMMM YYYY [pukul] LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'siang'; + } else if (hours < 19) { + return 'sore'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Besok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kemarin pukul] LT', + lastWeek : 'dddd [lalu pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : "dalam %s", + past : "%s yang lalu", + s : "beberapa detik", + m : "semenit", + mm : "%d menit", + h : "sejam", + hh : "%d jam", + d : "sehari", + dd : "%d hari", + M : "sebulan", + MM : "%d bulan", + y : "setahun", + yy : "%d tahun" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : icelandic (is) +// author : Hinrik Örn Sigurðsson : https://github.com/hinrik + +function plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; +} + +function translate(number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } + return result + 'mínútu'; + case 'hh': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (plural(number)) { + if (withoutSuffix) { + return result + 'dagar'; + } + return result + (isFuture ? 'daga' : 'dögum'); + } else if (withoutSuffix) { + return result + 'dagur'; + } + return result + (isFuture ? 'dag' : 'degi'); + case 'M': + if (withoutSuffix) { + return 'mánuður'; + } + return isFuture ? 'mánuð' : 'mánuði'; + case 'MM': + if (plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir'; + } + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } else if (withoutSuffix) { + return result + 'mánuður'; + } + return result + (isFuture ? 'mánuð' : 'mánuði'); + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } +} + +moment.lang('is', { + months : "janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"), + monthsShort : "jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"), + weekdays : "sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"), + weekdaysShort : "sun_mán_þri_mið_fim_fös_lau".split("_"), + weekdaysMin : "Su_Má_Þr_Mi_Fi_Fö_La".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY [kl.] LT", + LLLL : "dddd, D. MMMM YYYY [kl.] LT" + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : "eftir %s", + past : "fyrir %s síðan", + s : translate, + m : translate, + mm : translate, + h : "klukkustund", + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : italian (it) +// author : Lorenzo : https://github.com/aliem +// author: Mattia Larentis: https://github.com/nostalgiaz + +moment.lang('it', { + months : "Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"), + monthsShort : "Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"), + weekdays : "Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"), + weekdaysShort : "Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"), + weekdaysMin : "D_L_Ma_Me_G_V_S".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: '[lo scorso] dddd [alle] LT', + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? "tra" : "in") + " " + s; + }, + past : "%s fa", + s : "secondi", + m : "un minuto", + mm : "%d minuti", + h : "un'ora", + hh : "%d ore", + d : "un giorno", + dd : "%d giorni", + M : "un mese", + MM : "%d mesi", + y : "un anno", + yy : "%d anni" + }, + ordinal: '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : japanese (ja) +// author : LI Long : https://github.com/baryon + +moment.lang('ja', { + months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"), + weekdaysShort : "日_月_火_水_木_金_土".split("_"), + weekdaysMin : "日_月_火_水_木_金_土".split("_"), + longDateFormat : { + LT : "Ah時m分", + L : "YYYY/MM/DD", + LL : "YYYY年M月D日", + LLL : "YYYY年M月D日LT", + LLLL : "YYYY年M月D日LT dddd" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "午前"; + } else { + return "午後"; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s後", + past : "%s前", + s : "数秒", + m : "1分", + mm : "%d分", + h : "1時間", + hh : "%d時間", + d : "1日", + dd : "%d日", + M : "1ヶ月", + MM : "%dヶ月", + y : "1年", + yy : "%d年" + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Georgian (ka) +// author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + 'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + + nounCase = (/D[oD] *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; +} + +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + 'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_') + }, + + nounCase = (/(წინა|შემდეგ)/).test(format) ? + 'accusative' : + 'nominative'; + + return weekdays[nounCase][m.day()]; +} + +moment.lang('ka', { + months : monthsCaseReplace, + monthsShort : "იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"), + weekdaysMin : "კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"), + longDateFormat : { + LT : "h:mm A", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[დღეს] LT[-ზე]', + nextDay : '[ხვალ] LT[-ზე]', + lastDay : '[გუშინ] LT[-ზე]', + nextWeek : '[შემდეგ] dddd LT[-ზე]', + lastWeek : '[წინა] dddd LT-ზე', + sameElse : 'L' + }, + relativeTime : { + future : function (s) { + return (/(წამი|წუთი|საათი|წელი)/).test(s) ? + s.replace(/ი$/, "ში") : + s + "ში"; + }, + past : function (s) { + if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { + return s.replace(/(ი|ე)$/, "ის წინ"); + } + if ((/წელი/).test(s)) { + return s.replace(/წელი$/, "წლის წინ"); + } + }, + s : "რამდენიმე წამი", + m : "წუთი", + mm : "%d წუთი", + h : "საათი", + hh : "%d საათი", + d : "დღე", + dd : "%d დღე", + M : "თვე", + MM : "%d თვე", + y : "წელი", + yy : "%d წელი" + }, + ordinal : function (number) { + if (number === 0) { + return number; + } + + if (number === 1) { + return number + "-ლი"; + } + + if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { + return "მე-" + number; + } + + return number + "-ე"; + }, + week : { + dow : 1, + doy : 7 + } +}); +})(); +(function(){ +// moment.js language configuration +// language : korean (ko) +// author : Kyungwook, Park : https://github.com/kyungw00k + +moment.lang('ko', { + months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"), + weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"), + weekdaysShort : "일_월_화_수_목_금_토".split("_"), + weekdaysMin : "일_월_화_수_목_금_토".split("_"), + longDateFormat : { + LT : "A h시 mm분", + L : "YYYY.MM.DD", + LL : "YYYY년 MMMM D일", + LLL : "YYYY년 MMMM D일 LT", + LLLL : "YYYY년 MMMM D일 dddd LT" + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s 후", + past : "%s 전", + s : "몇초", + ss : "%d초", + m : "일분", + mm : "%d분", + h : "한시간", + hh : "%d시간", + d : "하루", + dd : "%d일", + M : "한달", + MM : "%d달", + y : "일년", + yy : "%d년" + }, + ordinal : '%d일' +}); +})(); +(function(){ +// moment.js language configuration +// language : latvian (lv) +// author : Kristaps Karlsons : https://github.com/skakri + +var units = { + 'mm': 'minūti_minūtes_minūte_minūtes', + 'hh': 'stundu_stundas_stunda_stundas', + 'dd': 'dienu_dienas_diena_dienas', + 'MM': 'mēnesi_mēnešus_mēnesis_mēneši', + 'yy': 'gadu_gadus_gads_gadi' +}; + +function format(word, number, withoutSuffix) { + var forms = word.split('_'); + if (withoutSuffix) { + return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; + } else { + return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; + } +} + +function relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(units[key], number, withoutSuffix); +} + +moment.lang('lv', { + months : "janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"), + weekdays : "svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"), + weekdaysShort : "Sv_P_O_T_C_Pk_S".split("_"), + weekdaysMin : "Sv_P_O_T_C_Pk_S".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "YYYY. [gada] D. MMMM", + LLL : "YYYY. [gada] D. MMMM, LT", + LLLL : "YYYY. [gada] D. MMMM, dddd, LT" + }, + calendar : { + sameDay : '[Šodien pulksten] LT', + nextDay : '[Rīt pulksten] LT', + nextWeek : 'dddd [pulksten] LT', + lastDay : '[Vakar pulksten] LT', + lastWeek : '[Pagājušā] dddd [pulksten] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s vēlāk", + past : "%s agrāk", + s : "dažas sekundes", + m : "minūti", + mm : relativeTimeWithPlural, + h : "stundu", + hh : relativeTimeWithPlural, + d : "dienu", + dd : relativeTimeWithPlural, + M : "mēnesi", + MM : relativeTimeWithPlural, + y : "gadu", + yy : relativeTimeWithPlural + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Bahasa Malaysia (ms-MY) +// author : Weldan Jamili : https://github.com/weldan + +moment.lang('ms-my', { + months : "Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"), + monthsShort : "Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"), + weekdays : "Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"), + weekdaysShort : "Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"), + weekdaysMin : "Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"), + longDateFormat : { + LT : "HH.mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY [pukul] LT", + LLLL : "dddd, D MMMM YYYY [pukul] LT" + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : "dalam %s", + past : "%s yang lepas", + s : "beberapa saat", + m : "seminit", + mm : "%d minit", + h : "sejam", + hh : "%d jam", + d : "sehari", + dd : "%d hari", + M : "sebulan", + MM : "%d bulan", + y : "setahun", + yy : "%d tahun" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : norwegian bokmål (nb) +// author : Espen Hovlandsdal : https://github.com/rexxars + +moment.lang('nb', { + months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"), + weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"), + weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"), + weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[I dag klokken] LT', + nextDay: '[I morgen klokken] LT', + nextWeek: 'dddd [klokken] LT', + lastDay: '[I går klokken] LT', + lastWeek: '[Forrige] dddd [klokken] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "for %s siden", + s : "noen sekunder", + m : "ett minutt", + mm : "%d minutter", + h : "en time", + hh : "%d timer", + d : "en dag", + dd : "%d dager", + M : "en måned", + MM : "%d måneder", + y : "ett år", + yy : "%d år" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : nepali/nepalese +// author : suvash : https://github.com/suvash + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +moment.lang('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split("_"), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split("_"), + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split("_"), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split("_"), + weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split("_"), + longDateFormat : { + LT : "Aको h:mm बजे", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY, LT", + LLLL : "dddd, D MMMM YYYY, LT" + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 3) { + return "राती"; + } else if (hour < 10) { + return "बिहान"; + } else if (hour < 15) { + return "दिउँसो"; + } else if (hour < 18) { + return "बेलुका"; + } else if (hour < 20) { + return "साँझ"; + } else { + return "राती"; + } + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[भोली] LT', + nextWeek : '[आउँदो] dddd[,] LT', + lastDay : '[हिजो] LT', + lastWeek : '[गएको] dddd[,] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%sमा", + past : "%s अगाडी", + s : "केही समय", + m : "एक मिनेट", + mm : "%d मिनेट", + h : "एक घण्टा", + hh : "%d घण्टा", + d : "एक दिन", + dd : "%d दिन", + M : "एक महिना", + MM : "%d महिना", + y : "एक बर्ष", + yy : "%d बर्ष" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : dutch (nl) +// author : Joris Röling : https://github.com/jjupiter + +var monthsShortWithDots = "jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"), + monthsShortWithoutDots = "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"); + +moment.lang('nl', { + months : "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + weekdays : "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"), + weekdaysShort : "zo._ma._di._wo._do._vr._za.".split("_"), + weekdaysMin : "Zo_Ma_Di_Wo_Do_Vr_Za".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD-MM-YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Vandaag om] LT', + nextDay: '[Morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[Gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : "over %s", + past : "%s geleden", + s : "een paar seconden", + m : "één minuut", + mm : "%d minuten", + h : "één uur", + hh : "%d uur", + d : "één dag", + dd : "%d dagen", + M : "één maand", + MM : "%d maanden", + y : "één jaar", + yy : "%d jaar" + }, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : norwegian nynorsk (nn) +// author : https://github.com/mechuwind + +moment.lang('nn', { + months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"), + monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"), + weekdays : "sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"), + weekdaysShort : "sun_mån_tys_ons_tor_fre_lau".split("_"), + weekdaysMin : "su_må_ty_on_to_fr_lø".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[I dag klokka] LT', + nextDay: '[I morgon klokka] LT', + nextWeek: 'dddd [klokka] LT', + lastDay: '[I går klokka] LT', + lastWeek: '[Føregående] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "for %s siden", + s : "noen sekund", + m : "ett minutt", + mm : "%d minutt", + h : "en time", + hh : "%d timar", + d : "en dag", + dd : "%d dagar", + M : "en månad", + MM : "%d månader", + y : "ett år", + yy : "%d år" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : polish (pl) +// author : Rafal Hirsz : https://github.com/evoL + +var monthsNominative = "styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"), + monthsSubjective = "stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"); + +function plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && (~~(n / 10) !== 1); +} + +function translate(number, withoutSuffix, key) { + var result = number + " "; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (plural(number) ? 'lata' : 'lat'); + } +} + +moment.lang('pl', { + months : function (momentToFormat, format) { + if (/D MMMM/.test(format)) { + return monthsSubjective[momentToFormat.month()]; + } else { + return monthsNominative[momentToFormat.month()]; + } + }, + monthsShort : "sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"), + weekdays : "niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"), + weekdaysShort : "nie_pon_wt_śr_czw_pt_sb".split("_"), + weekdaysMin : "N_Pn_Wt_Śr_Cz_Pt_So".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[W zeszłą niedzielę o] LT'; + case 3: + return '[W zeszłą środę o] LT'; + case 6: + return '[W zeszłą sobotę o] LT'; + default: + return '[W zeszły] dddd [o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : "za %s", + past : "%s temu", + s : "kilka sekund", + m : translate, + mm : translate, + h : translate, + hh : translate, + d : "1 dzień", + dd : '%d dni', + M : "miesiąc", + MM : translate, + y : "rok", + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : brazilian portuguese (pt-br) +// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + +moment.lang('pt-br', { + months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"), + monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"), + weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"), + weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"), + weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D [de] MMMM [de] YYYY", + LLL : "D [de] MMMM [de] YYYY LT", + LLLL : "dddd, D [de] MMMM [de] YYYY LT" + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : "em %s", + past : "%s atrás", + s : "segundos", + m : "um minuto", + mm : "%d minutos", + h : "uma hora", + hh : "%d horas", + d : "um dia", + dd : "%d dias", + M : "um mês", + MM : "%d meses", + y : "um ano", + yy : "%d anos" + }, + ordinal : '%dº' +}); +})(); +(function(){ +// moment.js language configuration +// language : portuguese (pt) +// author : Jefferson : https://github.com/jalex79 + +moment.lang('pt', { + months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"), + monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"), + weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"), + weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"), + weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D [de] MMMM [de] YYYY", + LLL : "D [de] MMMM [de] YYYY LT", + LLLL : "dddd, D [de] MMMM [de] YYYY LT" + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : "em %s", + past : "%s atrás", + s : "segundos", + m : "um minuto", + mm : "%d minutos", + h : "uma hora", + hh : "%d horas", + d : "um dia", + dd : "%d dias", + M : "um mês", + MM : "%d meses", + y : "um ano", + yy : "%d anos" + }, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : romanian (ro) +// author : Vlad Gurdiga : https://github.com/gurdiga +// author : Valentin Agachi : https://github.com/avaly + +moment.lang('ro', { + months : "Ianuarie_Februarie_Martie_Aprilie_Mai_Iunie_Iulie_August_Septembrie_Octombrie_Noiembrie_Decembrie".split("_"), + monthsShort : "Ian_Feb_Mar_Apr_Mai_Iun_Iul_Aug_Sep_Oct_Noi_Dec".split("_"), + weekdays : "Duminică_Luni_Marţi_Miercuri_Joi_Vineri_Sâmbătă".split("_"), + weekdaysShort : "Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"), + weekdaysMin : "Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY H:mm", + LLLL : "dddd, D MMMM YYYY H:mm" + }, + calendar : { + sameDay: "[azi la] LT", + nextDay: '[mâine la] LT', + nextWeek: 'dddd [la] LT', + lastDay: '[ieri la] LT', + lastWeek: '[fosta] dddd [la] LT', + sameElse: 'L' + }, + relativeTime : { + future : "peste %s", + past : "%s în urmă", + s : "câteva secunde", + m : "un minut", + mm : "%d minute", + h : "o oră", + hh : "%d ore", + d : "o zi", + dd : "%d zile", + M : "o lună", + MM : "%d luni", + y : "un an", + yy : "%d ani" + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : russian (ru) +// author : Viktorminator : https://github.com/Viktorminator +// Author : Menelion Elensúle : https://github.com/Oire + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} + +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'минута_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, + + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; +} + +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') + }, + + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + + return weekdays[nounCase][m.day()]; +} + +moment.lang('ru', { + months : monthsCaseReplace, + monthsShort : "янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "вск_пнд_втр_срд_чтв_птн_сбт".split("_"), + weekdaysMin : "вс_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY г.", + LLL : "D MMMM YYYY г., LT", + LLLL : "dddd, D MMMM YYYY г., LT" + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function () { + return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : "через %s", + past : "%s назад", + s : "несколько секунд", + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : "час", + hh : relativeTimeWithPlural, + d : "день", + dd : relativeTimeWithPlural, + M : "месяц", + MM : relativeTimeWithPlural, + y : "год", + yy : relativeTimeWithPlural + }, + + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + return number + '-й'; + case 'D': + return number + '-го'; + case 'w': + case 'W': + return number + '-я'; + default: + return number; + } + }, + + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : slovak (sk) +// author : Martin Minka : https://github.com/k2s +// based on work of petrbela : https://github.com/petrbela + +var months = "január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"), + monthsShort = "jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_"); + +function plural(n) { + return (n > 1) && (n < 5); +} + +function translate(number, withoutSuffix, key, isFuture) { + var result = number + " "; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minúty' : 'minút'); + } else { + return result + 'minútami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodín'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dni' : 'dní'); + } else { + return result + 'dňami'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'mesiace' : 'mesiacov'); + } else { + return result + 'mesiacmi'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } +} + +moment.lang('sk', { + months : months, + monthsShort : monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(months, monthsShort)), + weekdays : "nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"), + weekdaysShort : "ne_po_ut_st_št_pi_so".split("_"), + weekdaysMin : "ne_po_ut_st_št_pi_so".split("_"), + longDateFormat : { + LT: "H:mm", + L : "DD.MM.YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd D. MMMM YYYY LT" + }, + calendar : { + sameDay: "[dnes o] LT", + nextDay: '[zajtra o] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v nedeľu o] LT'; + case 1: + case 2: + return '[v] dddd [o] LT'; + case 3: + return '[v stredu o] LT'; + case 4: + return '[vo štvrtok o] LT'; + case 5: + return '[v piatok o] LT'; + case 6: + return '[v sobotu o] LT'; + } + }, + lastDay: '[včera o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulú nedeľu o] LT'; + case 1: + case 2: + return '[minulý] dddd [o] LT'; + case 3: + return '[minulú stredu o] LT'; + case 4: + case 5: + return '[minulý] dddd [o] LT'; + case 6: + return '[minulú sobotu o] LT'; + } + }, + sameElse: "L" + }, + relativeTime : { + future : "za %s", + past : "pred %s", + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : slovenian (sl) +// author : Robert Sedovšek : https://github.com/sedovsek + +function translate(number, withoutSuffix, key) { + var result = number + " "; + switch (key) { + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2) { + result += 'minuti'; + } else if (number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minut'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += 'ura'; + } else if (number === 2) { + result += 'uri'; + } else if (number === 3 || number === 4) { + result += 'ure'; + } else { + result += 'ur'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dni'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mesec'; + } else if (number === 2) { + result += 'meseca'; + } else if (number === 3 || number === 4) { + result += 'mesece'; + } else { + result += 'mesecev'; + } + return result; + case 'yy': + if (number === 1) { + result += 'leto'; + } else if (number === 2) { + result += 'leti'; + } else if (number === 3 || number === 4) { + result += 'leta'; + } else { + result += 'let'; + } + return result; + } +} + +moment.lang('sl', { + months : "januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"), + monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"), + weekdays : "nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"), + weekdaysShort : "ned._pon._tor._sre._čet._pet._sob.".split("_"), + weekdaysMin : "ne_po_to_sr_če_pe_so".split("_"), + longDateFormat : { + LT : "H:mm", + L : "DD. MM. YYYY", + LL : "D. MMMM YYYY", + LLL : "D. MMMM YYYY LT", + LLLL : "dddd, D. MMMM YYYY LT" + }, + calendar : { + sameDay : '[danes ob] LT', + nextDay : '[jutri ob] LT', + + nextWeek : function () { + switch (this.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + }, + lastDay : '[včeraj ob] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[prejšnja] dddd [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : "čez %s", + past : "%s nazaj", + s : "nekaj sekund", + m : translate, + mm : translate, + h : translate, + hh : translate, + d : "en dan", + dd : translate, + M : "en mesec", + MM : translate, + y : "eno leto", + yy : translate + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Albanian (sq) +// author : Flakërim Ismani : https://github.com/flakerimi +// author: Menelion Elensúle: https://github.com/Oire (tests) + +moment.lang('sq', { + months : "Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"), + monthsShort : "Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"), + weekdays : "E Diel_E Hënë_E Marte_E Mërkure_E Enjte_E Premte_E Shtunë".split("_"), + weekdaysShort : "Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"), + weekdaysMin : "D_H_Ma_Më_E_P_Sh".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[Sot në] LT', + nextDay : '[Neser në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : "në %s", + past : "%s me parë", + s : "disa seconda", + m : "një minut", + mm : "%d minutea", + h : "një orë", + hh : "%d orë", + d : "një ditë", + dd : "%d ditë", + M : "një muaj", + MM : "%d muaj", + y : "një vit", + yy : "%d vite" + }, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : swedish (sv) +// author : Jens Alm : https://github.com/ulmus + +moment.lang('sv', { + months : "januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"), + monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"), + weekdays : "söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"), + weekdaysShort : "sön_mån_tis_ons_tor_fre_lör".split("_"), + weekdaysMin : "sö_må_ti_on_to_fr_lö".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "YYYY-MM-DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: '[Idag] LT', + nextDay: '[Imorgon] LT', + lastDay: '[Igår] LT', + nextWeek: 'dddd LT', + lastWeek: '[Förra] dddd[en] LT', + sameElse: 'L' + }, + relativeTime : { + future : "om %s", + past : "för %s sedan", + s : "några sekunder", + m : "en minut", + mm : "%d minuter", + h : "en timme", + hh : "%d timmar", + d : "en dag", + dd : "%d dagar", + M : "en månad", + MM : "%d månader", + y : "ett år", + yy : "%d år" + }, + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : thai (th) +// author : Kridsada Thanabulpong : https://github.com/sirn + +moment.lang('th', { + months : "มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"), + monthsShort : "มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"), + weekdays : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"), + weekdaysShort : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"), // yes, three characters difference + weekdaysMin : "อา._จ._อ._พ._พฤ._ศ._ส.".split("_"), + longDateFormat : { + LT : "H นาฬิกา m นาที", + L : "YYYY/MM/DD", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY เวลา LT", + LLLL : "วันddddที่ D MMMM YYYY เวลา LT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return "ก่อนเที่ยง"; + } else { + return "หลังเที่ยง"; + } + }, + calendar : { + sameDay : '[วันนี้ เวลา] LT', + nextDay : '[พรุ่งนี้ เวลา] LT', + nextWeek : 'dddd[หน้า เวลา] LT', + lastDay : '[เมื่อวานนี้ เวลา] LT', + lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', + sameElse : 'L' + }, + relativeTime : { + future : "อีก %s", + past : "%sที่แล้ว", + s : "ไม่กี่วินาที", + m : "1 นาที", + mm : "%d นาที", + h : "1 ชั่วโมง", + hh : "%d ชั่วโมง", + d : "1 วัน", + dd : "%d วัน", + M : "1 เดือน", + MM : "%d เดือน", + y : "1 ปี", + yy : "%d ปี" + } +}); +})(); +(function(){ +// moment.js language configuration +// language : turkish (tr) +// authors : Erhan Gundogan : https://github.com/erhangundogan, +// Burak Yiğit Kaya: https://github.com/BYK + +var suffixes = { + 1: "'inci", + 5: "'inci", + 8: "'inci", + 70: "'inci", + 80: "'inci", + + 2: "'nci", + 7: "'nci", + 20: "'nci", + 50: "'nci", + + 3: "'üncü", + 4: "'üncü", + 100: "'üncü", + + 6: "'ncı", + + 9: "'uncu", + 10: "'uncu", + 30: "'uncu", + + 60: "'ıncı", + 90: "'ıncı" +}; + +moment.lang('tr', { + months : "Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"), + monthsShort : "Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"), + weekdays : "Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"), + weekdaysShort : "Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"), + weekdaysMin : "Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd, D MMMM YYYY LT" + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : "%s sonra", + past : "%s önce", + s : "birkaç saniye", + m : "bir dakika", + mm : "%d dakika", + h : "bir saat", + hh : "%d saat", + d : "bir gün", + dd : "%d gün", + M : "bir ay", + MM : "%d ay", + y : "bir yıl", + yy : "%d yıl" + }, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + "'ıncı"; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + + return number + (suffixes[a] || suffixes[b] || suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Morocco Central Atlas Tamaziɣt in Latin (tzm-la) +// author : Abdel Said : https://github.com/abdelsaid + +moment.lang('tzm-la', { + months : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"), + monthsShort : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"), + weekdays : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"), + weekdaysShort : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"), + weekdaysMin : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[asdkh g] LT", + nextDay: '[aska g] LT', + nextWeek: 'dddd [g] LT', + lastDay: '[assant g] LT', + lastWeek: 'dddd [g] LT', + sameElse: 'L' + }, + relativeTime : { + future : "dadkh s yan %s", + past : "yan %s", + s : "imik", + m : "minuḍ", + mm : "%d minuḍ", + h : "saɛa", + hh : "%d tassaɛin", + d : "ass", + dd : "%d ossan", + M : "ayowr", + MM : "%d iyyirn", + y : "asgas", + yy : "%d isgasn" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : Morocco Central Atlas Tamaziɣt (tzm) +// author : Abdel Said : https://github.com/abdelsaid + +moment.lang('tzm', { + months : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"), + monthsShort : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"), + weekdays : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"), + weekdaysShort : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"), + weekdaysMin : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD/MM/YYYY", + LL : "D MMMM YYYY", + LLL : "D MMMM YYYY LT", + LLLL : "dddd D MMMM YYYY LT" + }, + calendar : { + sameDay: "[ⴰⵙⴷⵅ ⴴ] LT", + nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', + nextWeek: 'dddd [ⴴ] LT', + lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', + lastWeek: 'dddd [ⴴ] LT', + sameElse: 'L' + }, + relativeTime : { + future : "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s", + past : "ⵢⴰⵏ %s", + s : "ⵉⵎⵉⴽ", + m : "ⵎⵉⵏⵓⴺ", + mm : "%d ⵎⵉⵏⵓⴺ", + h : "ⵙⴰⵄⴰ", + hh : "%d ⵜⴰⵙⵙⴰⵄⵉⵏ", + d : "ⴰⵙⵙ", + dd : "%d oⵙⵙⴰⵏ", + M : "ⴰⵢoⵓⵔ", + MM : "%d ⵉⵢⵢⵉⵔⵏ", + y : "ⴰⵙⴳⴰⵙ", + yy : "%d ⵉⵙⴳⴰⵙⵏ" + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : ukrainian (uk) +// author : zemlanin : https://github.com/zemlanin +// Author : Menelion Elensúle : https://github.com/Oire + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} + +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'хвилина_хвилини_хвилин', + 'hh': 'година_години_годин', + 'dd': 'день_дні_днів', + 'MM': 'місяць_місяці_місяців', + 'yy': 'рік_роки_років' + }; + if (key === 'm') { + return withoutSuffix ? 'хвилина' : 'хвилину'; + } + else if (key === 'h') { + return withoutSuffix ? 'година' : 'годину'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), + 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') + }, + + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + + return months[nounCase][m.month()]; +} + +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), + 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), + 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') + }, + + nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? + 'accusative' : + ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? + 'genitive' : + 'nominative'); + + return weekdays[nounCase][m.day()]; +} + +function processHoursFunction(str) { + return function () { + return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; + }; +} + +moment.lang('uk', { + months : monthsCaseReplace, + monthsShort : "січ_лют_бер_кві_тра_чер_лип_сер_вер_жов_лис_гру".split("_"), + weekdays : weekdaysCaseReplace, + weekdaysShort : "нед_пон_вів_срд_чет_птн_суб".split("_"), + weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"), + longDateFormat : { + LT : "HH:mm", + L : "DD.MM.YYYY", + LL : "D MMMM YYYY р.", + LLL : "D MMMM YYYY р., LT", + LLLL : "dddd, D MMMM YYYY р., LT" + }, + calendar : { + sameDay: processHoursFunction('[Сьогодні '), + nextDay: processHoursFunction('[Завтра '), + lastDay: processHoursFunction('[Вчора '), + nextWeek: processHoursFunction('[У] dddd ['), + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return processHoursFunction('[Минулої] dddd [').call(this); + case 1: + case 2: + case 4: + return processHoursFunction('[Минулого] dddd [').call(this); + } + }, + sameElse: 'L' + }, + relativeTime : { + future : "за %s", + past : "%s тому", + s : "декілька секунд", + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : "годину", + hh : relativeTimeWithPlural, + d : "день", + dd : relativeTimeWithPlural, + M : "місяць", + MM : relativeTimeWithPlural, + y : "рік", + yy : relativeTimeWithPlural + }, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return number + '-й'; + case 'D': + return number + '-го'; + default: + return number; + } + }, + + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +})(); +(function(){ +// moment.js language configuration +// language : chinese +// author : suupic : https://github.com/suupic + +moment.lang('zh-cn', { + months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"), + weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"), + weekdaysMin : "日_一_二_三_四_五_六".split("_"), + longDateFormat : { + LT : "Ah点mm", + L : "YYYY年MMMD日", + LL : "YYYY年MMMD日", + LLL : "YYYY年MMMD日LT", + LLLL : "YYYY年MMMD日ddddLT", + l : "YYYY年MMMD日", + ll : "YYYY年MMMD日", + lll : "YYYY年MMMD日LT", + llll : "YYYY年MMMD日ddddLT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 9) { + return "早上"; + } else if (hour < 11 && minute < 30) { + return "上午"; + } else if (hour < 13 && minute < 30) { + return "中午"; + } else if (hour < 18) { + return "下午"; + } else { + return "晚上"; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinal : function (number, period) { + switch (period) { + case "d" : + case "D" : + case "DDD" : + return number + "日"; + case "M" : + return number + "月"; + case "w" : + case "W" : + return number + "周"; + default : + return number; + } + }, + relativeTime : { + future : "%s内", + past : "%s前", + s : "几秒", + m : "1分钟", + mm : "%d分钟", + h : "1小时", + hh : "%d小时", + d : "1天", + dd : "%d天", + M : "1个月", + MM : "%d个月", + y : "1年", + yy : "%d年" + } +}); +})(); +(function(){ +// moment.js language configuration +// language : traditional chinese (zh-tw) +// author : Ben : https://github.com/ben-lin + +moment.lang('zh-tw', { + months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"), + monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"), + weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"), + weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"), + weekdaysMin : "日_一_二_三_四_五_六".split("_"), + longDateFormat : { + LT : "Ah點mm", + L : "YYYY年MMMD日", + LL : "YYYY年MMMD日", + LLL : "YYYY年MMMD日LT", + LLLL : "YYYY年MMMD日ddddLT", + l : "YYYY年MMMD日", + ll : "YYYY年MMMD日", + lll : "YYYY年MMMD日LT", + llll : "YYYY年MMMD日ddddLT" + }, + meridiem : function (hour, minute, isLower) { + if (hour < 9) { + return "早上"; + } else if (hour < 11 && minute < 30) { + return "上午"; + } else if (hour < 13 && minute < 30) { + return "中午"; + } else if (hour < 18) { + return "下午"; + } else { + return "晚上"; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinal : function (number, period) { + switch (period) { + case "d" : + case "D" : + case "DDD" : + return number + "日"; + case "M" : + return number + "月"; + case "w" : + case "W" : + return number + "週"; + default : + return number; + } + }, + relativeTime : { + future : "%s內", + past : "%s前", + s : "幾秒", + m : "一分鐘", + mm : "%d分鐘", + h : "一小時", + hh : "%d小時", + d : "一天", + dd : "%d天", + M : "一個月", + MM : "%d個月", + y : "一年", + yy : "%d年" + } +}); +})(); + +moment.lang('en'); + + } + if (typeof define === "function" && define.amd) { + define(["moment"], onload); + } + if (typeof window !== "undefined" && window.moment) { + onload(window.moment); + } +})(); diff --git a/node_modules/moment/min/langs.min.js b/node_modules/moment/min/langs.min.js new file mode 100644 index 0000000..2516734 --- /dev/null +++ b/node_modules/moment/min/langs.min.js @@ -0,0 +1,3 @@ +!function(){function e(){!function(){function e(e){!function(){e.lang("ar-ma",{months:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631_\u0641\u0628\u0631\u0627\u064a\u0631_\u0645\u0627\u0631\u0633_\u0623\u0628\u0631\u064a\u0644_\u0645\u0627\u064a_\u064a\u0648\u0646\u064a\u0648_\u064a\u0648\u0644\u064a\u0648\u0632_\u063a\u0634\u062a_\u0634\u062a\u0646\u0628\u0631_\u0623\u0643\u062a\u0648\u0628\u0631_\u0646\u0648\u0646\u0628\u0631_\u062f\u062c\u0646\u0628\u0631".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062a\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u062d\u062f_\u0627\u062a\u0646\u064a\u0646_\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0631\u0628\u0639\u0627\u0621_\u062e\u0645\u064a\u0633_\u062c\u0645\u0639\u0629_\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:6,doy:12}})}(),function(){e.lang("ar",{months:"\u064a\u0646\u0627\u064a\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u0641\u0628\u0631\u0627\u064a\u0631/ \u0634\u0628\u0627\u0637_\u0645\u0627\u0631\u0633/ \u0622\u0630\u0627\u0631_\u0623\u0628\u0631\u064a\u0644/ \u0646\u064a\u0633\u0627\u0646_\u0645\u0627\u064a\u0648/ \u0623\u064a\u0627\u0631_\u064a\u0648\u0646\u064a\u0648/ \u062d\u0632\u064a\u0631\u0627\u0646_\u064a\u0648\u0644\u064a\u0648/ \u062a\u0645\u0648\u0632_\u0623\u063a\u0633\u0637\u0633/ \u0622\u0628_\u0633\u0628\u062a\u0645\u0628\u0631/ \u0623\u064a\u0644\u0648\u0644_\u0623\u0643\u062a\u0648\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644_\u0646\u0648\u0641\u0645\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u062f\u064a\u0633\u0645\u0628\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644".split("_"),monthsShort:"\u064a\u0646\u0627\u064a\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u0641\u0628\u0631\u0627\u064a\u0631/ \u0634\u0628\u0627\u0637_\u0645\u0627\u0631\u0633/ \u0622\u0630\u0627\u0631_\u0623\u0628\u0631\u064a\u0644/ \u0646\u064a\u0633\u0627\u0646_\u0645\u0627\u064a\u0648/ \u0623\u064a\u0627\u0631_\u064a\u0648\u0646\u064a\u0648/ \u062d\u0632\u064a\u0631\u0627\u0646_\u064a\u0648\u0644\u064a\u0648/ \u062a\u0645\u0648\u0632_\u0623\u063a\u0633\u0637\u0633/ \u0622\u0628_\u0633\u0628\u062a\u0645\u0628\u0631/ \u0623\u064a\u0644\u0648\u0644_\u0623\u0643\u062a\u0648\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644_\u0646\u0648\u0641\u0645\u0628\u0631/ \u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a_\u062f\u064a\u0633\u0645\u0628\u0631/ \u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644".split("_"),weekdays:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysShort:"\u0627\u0644\u0623\u062d\u062f_\u0627\u0644\u0625\u062b\u0646\u064a\u0646_\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621_\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621_\u0627\u0644\u062e\u0645\u064a\u0633_\u0627\u0644\u062c\u0645\u0639\u0629_\u0627\u0644\u0633\u0628\u062a".split("_"),weekdaysMin:"\u062d_\u0646_\u062b_\u0631_\u062e_\u062c_\u0633".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[\u0627\u0644\u064a\u0648\u0645 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextDay:"[\u063a\u062f\u0627 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",nextWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastDay:"[\u0623\u0645\u0633 \u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",lastWeek:"dddd [\u0639\u0644\u0649 \u0627\u0644\u0633\u0627\u0639\u0629] LT",sameElse:"L"},relativeTime:{future:"\u0641\u064a %s",past:"\u0645\u0646\u0630 %s",s:"\u062b\u0648\u0627\u0646",m:"\u062f\u0642\u064a\u0642\u0629",mm:"%d \u062f\u0642\u0627\u0626\u0642",h:"\u0633\u0627\u0639\u0629",hh:"%d \u0633\u0627\u0639\u0627\u062a",d:"\u064a\u0648\u0645",dd:"%d \u0623\u064a\u0627\u0645",M:"\u0634\u0647\u0631",MM:"%d \u0623\u0634\u0647\u0631",y:"\u0633\u0646\u0629",yy:"%d \u0633\u0646\u0648\u0627\u062a"},week:{dow:6,doy:12}})}(),function(){e.lang("bg",{months:"\u044f\u043d\u0443\u0430\u0440\u0438_\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0438\u043b_\u043c\u0430\u0439_\u044e\u043d\u0438_\u044e\u043b\u0438_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438_\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438_\u043d\u043e\u0435\u043c\u0432\u0440\u0438_\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438".split("_"),monthsShort:"\u044f\u043d\u0440_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u044e\u043d\u0438_\u044e\u043b\u0438_\u0430\u0432\u0433_\u0441\u0435\u043f_\u043e\u043a\u0442_\u043d\u043e\u0435_\u0434\u0435\u043a".split("_"),weekdays:"\u043d\u0435\u0434\u0435\u043b\u044f_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u044f\u0434\u0430_\u0447\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a_\u043f\u0435\u0442\u044a\u043a_\u0441\u044a\u0431\u043e\u0442\u0430".split("_"),weekdaysShort:"\u043d\u0435\u0434_\u043f\u043e\u043d_\u0432\u0442\u043e_\u0441\u0440\u044f_\u0447\u0435\u0442_\u043f\u0435\u0442_\u0441\u044a\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"h:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[\u0414\u043d\u0435\u0441 \u0432] LT",nextDay:"[\u0423\u0442\u0440\u0435 \u0432] LT",nextWeek:"dddd [\u0432] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430 \u0432] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[\u0412 \u0438\u0437\u043c\u0438\u043d\u0430\u043b\u0430\u0442\u0430] dddd [\u0432] LT";case 1:case 2:case 4:case 5:return"[\u0412 \u0438\u0437\u043c\u0438\u043d\u0430\u043b\u0438\u044f] dddd [\u0432] LT"}},sameElse:"L"},relativeTime:{future:"\u0441\u043b\u0435\u0434 %s",past:"\u043f\u0440\u0435\u0434\u0438 %s",s:"\u043d\u044f\u043a\u043e\u043b\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434\u0438",m:"\u043c\u0438\u043d\u0443\u0442\u0430",mm:"%d \u043c\u0438\u043d\u0443\u0442\u0438",h:"\u0447\u0430\u0441",hh:"%d \u0447\u0430\u0441\u0430",d:"\u0434\u0435\u043d",dd:"%d \u0434\u043d\u0438",M:"\u043c\u0435\u0441\u0435\u0446",MM:"%d \u043c\u0435\u0441\u0435\u0446\u0430",y:"\u0433\u043e\u0434\u0438\u043d\u0430",yy:"%d \u0433\u043e\u0434\u0438\u043d\u0438"},ordinal:function(e){var t=e%10,a=e%100;return 0===e?e+"-\u0435\u0432":0===a?e+"-\u0435\u043d":a>10&&20>a?e+"-\u0442\u0438":1===t?e+"-\u0432\u0438":2===t?e+"-\u0440\u0438":7===t||8===t?e+"-\u043c\u0438":e+"-\u0442\u0438"},week:{dow:1,doy:7}})}(),function(){function t(e,t,a){var n={mm:"munutenn",MM:"miz",dd:"devezh"};return e+" "+_(n[a],e)}function a(e){switch(n(e)){case 1:case 3:case 4:case 5:case 9:return e+" bloaz";default:return e+" vloaz"}}function n(e){return e>9?n(e%10):e}function _(e,t){return 2===t?s(e):e}function s(e){var t={m:"v",b:"v",d:"z"};return void 0===t[e.charAt(0)]?e:t[e.charAt(0)]+e.substring(1)}e.lang("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),longDateFormat:{LT:"h[e]mm A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY LT",LLLL:"dddd, D [a viz] MMMM YYYY LT"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondenno\xf9",m:"ur vunutenn",mm:t,h:"un eur",hh:"%d eur",d:"un devezh",dd:t,M:"ur miz",MM:t,y:"ur bloaz",yy:a},ordinal:function(e){var t=1===e?"a\xf1":"vet";return e+t},week:{dow:1,doy:4}})}(),function(){e.lang("ca",{months:"Gener_Febrer_Mar\xe7_Abril_Maig_Juny_Juliol_Agost_Setembre_Octubre_Novembre_Desembre".split("_"),monthsShort:"Gen._Febr._Mar._Abr._Mai._Jun._Jul._Ag._Set._Oct._Nov._Des.".split("_"),weekdays:"Diumenge_Dilluns_Dimarts_Dimecres_Dijous_Divendres_Dissabte".split("_"),weekdaysShort:"Dg._Dl._Dt._Dc._Dj._Dv._Ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[dem\xe0 a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:"%d\xba",week:{dow:1,doy:4}})}(),function(){function t(e){return e>1&&5>e&&1!==~~(e/10)}function a(e,a,n,_){var s=e+" ";switch(n){case"s":return a||_?"p\xe1r vte\u0159in":"p\xe1r vte\u0159inami";case"m":return a?"minuta":_?"minutu":"minutou";case"mm":return a||_?s+(t(e)?"minuty":"minut"):s+"minutami";break;case"h":return a?"hodina":_?"hodinu":"hodinou";case"hh":return a||_?s+(t(e)?"hodiny":"hodin"):s+"hodinami";break;case"d":return a||_?"den":"dnem";case"dd":return a||_?s+(t(e)?"dny":"dn\xed"):s+"dny";break;case"M":return a||_?"m\u011bs\xedc":"m\u011bs\xedcem";case"MM":return a||_?s+(t(e)?"m\u011bs\xedce":"m\u011bs\xedc\u016f"):s+"m\u011bs\xedci";break;case"y":return a||_?"rok":"rokem";case"yy":return a||_?s+(t(e)?"roky":"let"):s+"lety"}}var n="leden_\xfanor_b\u0159ezen_duben_kv\u011bten_\u010derven_\u010dervenec_srpen_z\xe1\u0159\xed_\u0159\xedjen_listopad_prosinec".split("_"),_="led_\xfano_b\u0159e_dub_kv\u011b_\u010dvn_\u010dvc_srp_z\xe1\u0159_\u0159\xedj_lis_pro".split("_");e.lang("cs",{months:n,monthsShort:_,monthsParse:function(e,t){var a,n=[];for(a=0;12>a;a++)n[a]=new RegExp("^"+e[a]+"$|^"+t[a]+"$","i");return n}(n,_),weekdays:"ned\u011ble_pond\u011bl\xed_\xfater\xfd_st\u0159eda_\u010dtvrtek_p\xe1tek_sobota".split("_"),weekdaysShort:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),weekdaysMin:"ne_po_\xfat_st_\u010dt_p\xe1_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes v] LT",nextDay:"[z\xedtra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v ned\u011bli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve st\u0159edu v] LT";case 4:return"[ve \u010dtvrtek v] LT";case 5:return"[v p\xe1tek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[v\u010dera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou ned\u011bli v] LT";case 1:case 2:return"[minul\xe9] dddd [v] LT";case 3:return"[minulou st\u0159edu v] LT";case 4:case 5:return"[minul\xfd] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"p\u0159ed %s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("cv",{months:"\u043a\u0103\u0440\u043b\u0430\u0447_\u043d\u0430\u0440\u0103\u0441_\u043f\u0443\u0448_\u0430\u043a\u0430_\u043c\u0430\u0439_\xe7\u0115\u0440\u0442\u043c\u0435_\u0443\u0442\u0103_\xe7\u0443\u0440\u043b\u0430_\u0430\u0432\u0103\u043d_\u044e\u043f\u0430_\u0447\u04f3\u043a_\u0440\u0430\u0448\u0442\u0430\u0432".split("_"),monthsShort:"\u043a\u0103\u0440_\u043d\u0430\u0440_\u043f\u0443\u0448_\u0430\u043a\u0430_\u043c\u0430\u0439_\xe7\u0115\u0440_\u0443\u0442\u0103_\xe7\u0443\u0440_\u0430\u0432_\u044e\u043f\u0430_\u0447\u04f3\u043a_\u0440\u0430\u0448".split("_"),weekdays:"\u0432\u044b\u0440\u0441\u0430\u0440\u043d\u0438\u043a\u0443\u043d_\u0442\u0443\u043d\u0442\u0438\u043a\u0443\u043d_\u044b\u0442\u043b\u0430\u0440\u0438\u043a\u0443\u043d_\u044e\u043d\u043a\u0443\u043d_\u043a\u0115\xe7\u043d\u0435\u0440\u043d\u0438\u043a\u0443\u043d_\u044d\u0440\u043d\u0435\u043a\u0443\u043d_\u0448\u0103\u043c\u0430\u0442\u043a\u0443\u043d".split("_"),weekdaysShort:"\u0432\u044b\u0440_\u0442\u0443\u043d_\u044b\u0442\u043b_\u044e\u043d_\u043a\u0115\xe7_\u044d\u0440\u043d_\u0448\u0103\u043c".split("_"),weekdaysMin:"\u0432\u0440_\u0442\u043d_\u044b\u0442_\u044e\u043d_\u043a\xe7_\u044d\u0440_\u0448\u043c".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY [\xe7\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u0103\u0445\u0115\u043d] D[-\u043c\u0115\u0448\u0115]",LLL:"YYYY [\xe7\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u0103\u0445\u0115\u043d] D[-\u043c\u0115\u0448\u0115], LT",LLLL:"dddd, YYYY [\xe7\u0443\u043b\u0445\u0438] MMMM [\u0443\u0439\u0103\u0445\u0115\u043d] D[-\u043c\u0115\u0448\u0115], LT"},calendar:{sameDay:"[\u041f\u0430\u044f\u043d] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",nextDay:"[\u042b\u0440\u0430\u043d] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",lastDay:"[\u0114\u043d\u0435\u0440] LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",nextWeek:"[\xc7\u0438\u0442\u0435\u0441] dddd LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",lastWeek:"[\u0418\u0440\u0442\u043d\u0115] dddd LT [\u0441\u0435\u0445\u0435\u0442\u0440\u0435]",sameElse:"L"},relativeTime:{future:function(e){var t=/\u0441\u0435\u0445\u0435\u0442$/i.exec(e)?"\u0440\u0435\u043d":/\xe7\u0443\u043b$/i.exec(e)?"\u0442\u0430\u043d":"\u0440\u0430\u043d";return e+t},past:"%s \u043a\u0430\u044f\u043b\u043b\u0430",s:"\u043f\u0115\u0440-\u0438\u043a \xe7\u0435\u043a\u043a\u0443\u043d\u0442",m:"\u043f\u0115\u0440 \u043c\u0438\u043d\u0443\u0442",mm:"%d \u043c\u0438\u043d\u0443\u0442",h:"\u043f\u0115\u0440 \u0441\u0435\u0445\u0435\u0442",hh:"%d \u0441\u0435\u0445\u0435\u0442",d:"\u043f\u0115\u0440 \u043a\u0443\u043d",dd:"%d \u043a\u0443\u043d",M:"\u043f\u0115\u0440 \u0443\u0439\u0103\u0445",MM:"%d \u0443\u0439\u0103\u0445",y:"\u043f\u0115\u0440 \xe7\u0443\u043b",yy:"%d \xe7\u0443\u043b"},ordinal:"%d-\u043c\u0115\u0448",week:{dow:1,doy:7}})}(),function(){e.lang("da",{months:"Januar_Februar_Marts_April_Maj_Juni_Juli_August_September_Oktober_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Maj_Jun_Jul_Aug_Sep_Okt_Nov_Dec".split("_"),weekdays:"S\xf8ndag_Mandag_Tirsdag_Onsdag_Torsdag_Fredag_L\xf8rdag".split("_"),weekdaysShort:"S\xf8n_Man_Tir_Ons_Tor_Fre_L\xf8r".split("_"),weekdaysMin:"S\xf8_Ma_Ti_On_To_Fr_L\xf8".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D. MMMM, YYYY LT"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I g\xe5r kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"f\xe5 sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en m\xe5ned",MM:"%d m\xe5neder",y:"et \xe5r",yy:"%d \xe5r"},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){function t(e,t,a){var n={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return t?n[a][0]:n[a][1]}e.lang("de",{months:"Januar_Februar_M\xe4rz_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm [Uhr]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:t,mm:"%d Minuten",h:t,hh:"%d Stunden",d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("el",{monthsNominativeEl:"\u0399\u03b1\u03bd\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2_\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2_\u039c\u03ac\u03c1\u03c4\u03b9\u03bf\u03c2_\u0391\u03c0\u03c1\u03af\u03bb\u03b9\u03bf\u03c2_\u039c\u03ac\u03b9\u03bf\u03c2_\u0399\u03bf\u03cd\u03bd\u03b9\u03bf\u03c2_\u0399\u03bf\u03cd\u03bb\u03b9\u03bf\u03c2_\u0391\u03cd\u03b3\u03bf\u03c5\u03c3\u03c4\u03bf\u03c2_\u03a3\u03b5\u03c0\u03c4\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2_\u039f\u03ba\u03c4\u03ce\u03b2\u03c1\u03b9\u03bf\u03c2_\u039d\u03bf\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2_\u0394\u03b5\u03ba\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2".split("_"),monthsGenitiveEl:"\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5_\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5_\u039c\u03b1\u03c1\u03c4\u03af\u03bf\u03c5_\u0391\u03c0\u03c1\u03b9\u03bb\u03af\u03bf\u03c5_\u039c\u03b1\u0390\u03bf\u03c5_\u0399\u03bf\u03c5\u03bd\u03af\u03bf\u03c5_\u0399\u03bf\u03c5\u03bb\u03af\u03bf\u03c5_\u0391\u03c5\u03b3\u03bf\u03cd\u03c3\u03c4\u03bf\u03c5_\u03a3\u03b5\u03c0\u03c4\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5_\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5_\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5_\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5".split("_"),months:function(e,t){return/D/.test(t.substring(0,t.indexOf("MMMM")))?this._monthsGenitiveEl[e.month()]:this._monthsNominativeEl[e.month()]},monthsShort:"\u0399\u03b1\u03bd_\u03a6\u03b5\u03b2_\u039c\u03b1\u03c1_\u0391\u03c0\u03c1_\u039c\u03b1\u03ca_\u0399\u03bf\u03c5\u03bd_\u0399\u03bf\u03c5\u03bb_\u0391\u03c5\u03b3_\u03a3\u03b5\u03c0_\u039f\u03ba\u03c4_\u039d\u03bf\u03b5_\u0394\u03b5\u03ba".split("_"),weekdays:"\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae_\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1_\u03a4\u03c1\u03af\u03c4\u03b7_\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7_\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7_\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae_\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf".split("_"),weekdaysShort:"\u039a\u03c5\u03c1_\u0394\u03b5\u03c5_\u03a4\u03c1\u03b9_\u03a4\u03b5\u03c4_\u03a0\u03b5\u03bc_\u03a0\u03b1\u03c1_\u03a3\u03b1\u03b2".split("_"),weekdaysMin:"\u039a\u03c5_\u0394\u03b5_\u03a4\u03c1_\u03a4\u03b5_\u03a0\u03b5_\u03a0\u03b1_\u03a3\u03b1".split("_"),meridiem:function(e,t,a){return e>11?a?"\u03bc\u03bc":"\u039c\u039c":a?"\u03c0\u03bc":"\u03a0\u039c"},longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendarEl:{sameDay:"[\u03a3\u03ae\u03bc\u03b5\u03c1\u03b1 {}] LT",nextDay:"[\u0391\u03cd\u03c1\u03b9\u03bf {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[\u03a7\u03b8\u03b5\u03c2 {}] LT",lastWeek:"[\u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03b7] dddd [{}] LT",sameElse:"L"},calendar:function(e,t){var a=this._calendarEl[e],n=t&&t.hours();return a.replace("{}",1===n%12?"\u03c3\u03c4\u03b7":"\u03c3\u03c4\u03b9\u03c2")},relativeTime:{future:"\u03c3\u03b5 %s",past:"%s \u03c0\u03c1\u03b9\u03bd",s:"\u03b4\u03b5\u03c5\u03c4\u03b5\u03c1\u03cc\u03bb\u03b5\u03c0\u03c4\u03b1",m:"\u03ad\u03bd\u03b1 \u03bb\u03b5\u03c0\u03c4\u03cc",mm:"%d \u03bb\u03b5\u03c0\u03c4\u03ac",h:"\u03bc\u03af\u03b1 \u03ce\u03c1\u03b1",hh:"%d \u03ce\u03c1\u03b5\u03c2",d:"\u03bc\u03af\u03b1 \u03bc\u03ad\u03c1\u03b1",dd:"%d \u03bc\u03ad\u03c1\u03b5\u03c2",M:"\u03ad\u03bd\u03b1\u03c2 \u03bc\u03ae\u03bd\u03b1\u03c2",MM:"%d \u03bc\u03ae\u03bd\u03b5\u03c2",y:"\u03ad\u03bd\u03b1\u03c2 \u03c7\u03c1\u03cc\u03bd\u03bf\u03c2",yy:"%d \u03c7\u03c1\u03cc\u03bd\u03b9\u03b1"},ordinal:function(e){return e+"\u03b7"},week:{dow:1,doy:4}})}(),function(){e.lang("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(e){var t=e%10,a=1===~~(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th";return e+a}})}(),function(){e.lang("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(e){var t=e%10,a=1===~~(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th";return e+a},week:{dow:1,doy:4}})}(),function(){e.lang("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_a\u016dgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_a\u016dg_sep_okt_nov_dec".split("_"),weekdays:"Diman\u0109o_Lundo_Mardo_Merkredo_\u0134a\u016ddo_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Mard_Merk_\u0134a\u016d_Ven_Sab".split("_"),weekdaysMin:"Di_Lu_Ma_Me_\u0134a_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D[-an de] MMMM, YYYY",LLL:"D[-an de] MMMM, YYYY LT",LLLL:"dddd, [la] D[-an de] MMMM, YYYY LT"},meridiem:function(e,t,a){return e>11?a?"p.t.m.":"P.T.M.":a?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodia\u016d je] LT",nextDay:"[Morga\u016d je] LT",nextWeek:"dddd [je] LT",lastDay:"[Hiera\u016d je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"je %s",past:"anta\u016d %s",s:"sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},ordinal:"%da",week:{dow:1,doy:7}})}(),function(){e.lang("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),weekdays:"domingo_lunes_martes_mi\xe9rcoles_jueves_viernes_s\xe1bado".split("_"),weekdaysShort:"dom._lun._mar._mi\xe9._jue._vie._s\xe1b.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_S\xe1".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[ma\xf1ana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un a\xf1o",yy:"%d a\xf1os"},ordinal:"%d\xba",week:{dow:1,doy:4}})}(),function(){function t(e,t,a,n){return n||t?"paari sekundi":"paar sekundit"}e.lang("et",{months:"jaanuar_veebruar_m\xe4rts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_m\xe4rts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"p\xfchap\xe4ev_esmasp\xe4ev_teisip\xe4ev_kolmap\xe4ev_neljap\xe4ev_reede_laup\xe4ev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[T\xe4na,] LT",nextDay:"[Homme,] LT",nextWeek:"[J\xe4rgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s p\xe4rast",past:"%s tagasi",s:t,m:"minut",mm:"%d minutit",h:"tund",hh:"%d tundi",d:"p\xe4ev",dd:"%d p\xe4eva",M:"kuu",MM:"%d kuud",y:"aasta",yy:"%d aastat"},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] LT",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] LT",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] LT",llll:"ddd, YYYY[ko] MMM D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:"%d.",week:{dow:1,doy:7}})}(),function(){var t={1:"\u06f1",2:"\u06f2",3:"\u06f3",4:"\u06f4",5:"\u06f5",6:"\u06f6",7:"\u06f7",8:"\u06f8",9:"\u06f9",0:"\u06f0"},a={"\u06f1":"1","\u06f2":"2","\u06f3":"3","\u06f4":"4","\u06f5":"5","\u06f6":"6","\u06f7":"7","\u06f8":"8","\u06f9":"9","\u06f0":"0"};e.lang("fa",{months:"\u0698\u0627\u0646\u0648\u06cc\u0647_\u0641\u0648\u0631\u06cc\u0647_\u0645\u0627\u0631\u0633_\u0622\u0648\u0631\u06cc\u0644_\u0645\u0647_\u0698\u0648\u0626\u0646_\u0698\u0648\u0626\u06cc\u0647_\u0627\u0648\u062a_\u0633\u067e\u062a\u0627\u0645\u0628\u0631_\u0627\u06a9\u062a\u0628\u0631_\u0646\u0648\u0627\u0645\u0628\u0631_\u062f\u0633\u0627\u0645\u0628\u0631".split("_"),monthsShort:"\u0698\u0627\u0646\u0648\u06cc\u0647_\u0641\u0648\u0631\u06cc\u0647_\u0645\u0627\u0631\u0633_\u0622\u0648\u0631\u06cc\u0644_\u0645\u0647_\u0698\u0648\u0626\u0646_\u0698\u0648\u0626\u06cc\u0647_\u0627\u0648\u062a_\u0633\u067e\u062a\u0627\u0645\u0628\u0631_\u0627\u06a9\u062a\u0628\u0631_\u0646\u0648\u0627\u0645\u0628\u0631_\u062f\u0633\u0627\u0645\u0628\u0631".split("_"),weekdays:"\u06cc\u06a9\u200c\u0634\u0646\u0628\u0647_\u062f\u0648\u0634\u0646\u0628\u0647_\u0633\u0647\u200c\u0634\u0646\u0628\u0647_\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647_\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647_\u062c\u0645\u0639\u0647_\u0634\u0646\u0628\u0647".split("_"),weekdaysShort:"\u06cc\u06a9\u200c\u0634\u0646\u0628\u0647_\u062f\u0648\u0634\u0646\u0628\u0647_\u0633\u0647\u200c\u0634\u0646\u0628\u0647_\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647_\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647_\u062c\u0645\u0639\u0647_\u0634\u0646\u0628\u0647".split("_"),weekdaysMin:"\u06cc_\u062f_\u0633_\u0686_\u067e_\u062c_\u0634".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},meridiem:function(e){return 12>e?"\u0642\u0628\u0644 \u0627\u0632 \u0638\u0647\u0631":"\u0628\u0639\u062f \u0627\u0632 \u0638\u0647\u0631"},calendar:{sameDay:"[\u0627\u0645\u0631\u0648\u0632 \u0633\u0627\u0639\u062a] LT",nextDay:"[\u0641\u0631\u062f\u0627 \u0633\u0627\u0639\u062a] LT",nextWeek:"dddd [\u0633\u0627\u0639\u062a] LT",lastDay:"[\u062f\u06cc\u0631\u0648\u0632 \u0633\u0627\u0639\u062a] LT",lastWeek:"dddd [\u067e\u06cc\u0634] [\u0633\u0627\u0639\u062a] LT",sameElse:"L"},relativeTime:{future:"\u062f\u0631 %s",past:"%s \u067e\u06cc\u0634",s:"\u0686\u0646\u062f\u06cc\u0646 \u062b\u0627\u0646\u06cc\u0647",m:"\u06cc\u06a9 \u062f\u0642\u06cc\u0642\u0647",mm:"%d \u062f\u0642\u06cc\u0642\u0647",h:"\u06cc\u06a9 \u0633\u0627\u0639\u062a",hh:"%d \u0633\u0627\u0639\u062a",d:"\u06cc\u06a9 \u0631\u0648\u0632",dd:"%d \u0631\u0648\u0632",M:"\u06cc\u06a9 \u0645\u0627\u0647",MM:"%d \u0645\u0627\u0647",y:"\u06cc\u06a9 \u0633\u0627\u0644",yy:"%d \u0633\u0627\u0644"},preparse:function(e){return e.replace(/[\u06f0-\u06f9]/g,function(e){return a[e]}).replace(/\u060c/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]}).replace(/,/g,"\u060c")},ordinal:"%d\u0645",week:{dow:6,doy:12}})}(),function(){function t(e,t,n,_){var s="";switch(n){case"s":return _?"muutaman sekunnin":"muutama sekunti";case"m":return _?"minuutin":"minuutti";case"mm":s=_?"minuutin":"minuuttia";break;case"h":return _?"tunnin":"tunti";case"hh":s=_?"tunnin":"tuntia";break;case"d":return _?"p\xe4iv\xe4n":"p\xe4iv\xe4";case"dd":s=_?"p\xe4iv\xe4n":"p\xe4iv\xe4\xe4";break;case"M":return _?"kuukauden":"kuukausi";case"MM":s=_?"kuukauden":"kuukautta";break;case"y":return _?"vuoden":"vuosi";case"yy":s=_?"vuoden":"vuotta"}return s=a(e,_)+" "+s}function a(e,t){return 10>e?t?_[e]:n[e]:e}var n="nolla yksi kaksi kolme nelj\xe4 viisi kuusi seitsem\xe4n kahdeksan yhdeks\xe4n".split(" "),_=["nolla","yhden","kahden","kolmen","nelj\xe4n","viiden","kuuden",n[7],n[8],n[9]];e.lang("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kes\xe4kuu_hein\xe4kuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kes\xe4_hein\xe4_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] LT",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] LT",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] LT",llll:"ddd, Do MMM YYYY, [klo] LT"},calendar:{sameDay:"[t\xe4n\xe4\xe4n] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s p\xe4\xe4st\xe4",past:"%s sitten",s:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinal:"%d.",week:{dow:1,doy:4}}) +}(),function(){e.lang("fr-ca",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(e){return e+(1===e?"er":"")}})}(),function(){e.lang("fr",{months:"janvier_f\xe9vrier_mars_avril_mai_juin_juillet_ao\xfbt_septembre_octobre_novembre_d\xe9cembre".split("_"),monthsShort:"janv._f\xe9vr._mars_avr._mai_juin_juil._ao\xfbt_sept._oct._nov._d\xe9c.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui \xe0] LT",nextDay:"[Demain \xe0] LT",nextWeek:"dddd [\xe0] LT",lastDay:"[Hier \xe0] LT",lastWeek:"dddd [dernier \xe0] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(e){return e+(1===e?"er":"")},week:{dow:1,doy:4}})}(),function(){e.lang("gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xu\xf1o_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xu\xf1._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_M\xe9rcores_Xoves_Venres_S\xe1bado".split("_"),weekdaysShort:"Dom._Lun._Mar._M\xe9r._Xov._Ven._S\xe1b.".split("_"),weekdaysMin:"Do_Lu_Ma_M\xe9_Xo_Ve_S\xe1".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"\xe1s":"\xe1")+"] LT"},nextDay:function(){return"[ma\xf1\xe1 "+(1!==this.hours()?"\xe1s":"\xe1")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"\xe1s":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"\xe1":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"\xe1s":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(e){return"uns segundos"===e?"nuns segundos":"en "+e},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un d\xeda",dd:"%d d\xedas",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:"%d\xba",week:{dow:1,doy:7}})}(),function(){e.lang("he",{months:"\u05d9\u05e0\u05d5\u05d0\u05e8_\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8_\u05de\u05e8\u05e5_\u05d0\u05e4\u05e8\u05d9\u05dc_\u05de\u05d0\u05d9_\u05d9\u05d5\u05e0\u05d9_\u05d9\u05d5\u05dc\u05d9_\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8_\u05e1\u05e4\u05d8\u05de\u05d1\u05e8_\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8_\u05e0\u05d5\u05d1\u05de\u05d1\u05e8_\u05d3\u05e6\u05de\u05d1\u05e8".split("_"),monthsShort:"\u05d9\u05e0\u05d5\u05f3_\u05e4\u05d1\u05e8\u05f3_\u05de\u05e8\u05e5_\u05d0\u05e4\u05e8\u05f3_\u05de\u05d0\u05d9_\u05d9\u05d5\u05e0\u05d9_\u05d9\u05d5\u05dc\u05d9_\u05d0\u05d5\u05d2\u05f3_\u05e1\u05e4\u05d8\u05f3_\u05d0\u05d5\u05e7\u05f3_\u05e0\u05d5\u05d1\u05f3_\u05d3\u05e6\u05de\u05f3".split("_"),weekdays:"\u05e8\u05d0\u05e9\u05d5\u05df_\u05e9\u05e0\u05d9_\u05e9\u05dc\u05d9\u05e9\u05d9_\u05e8\u05d1\u05d9\u05e2\u05d9_\u05d7\u05de\u05d9\u05e9\u05d9_\u05e9\u05d9\u05e9\u05d9_\u05e9\u05d1\u05ea".split("_"),weekdaysShort:"\u05d0\u05f3_\u05d1\u05f3_\u05d2\u05f3_\u05d3\u05f3_\u05d4\u05f3_\u05d5\u05f3_\u05e9\u05f3".split("_"),weekdaysMin:"\u05d0_\u05d1_\u05d2_\u05d3_\u05d4_\u05d5_\u05e9".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [\u05d1]MMMM YYYY",LLL:"D [\u05d1]MMMM YYYY LT",LLLL:"dddd, D [\u05d1]MMMM YYYY LT",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY LT",llll:"ddd, D MMM YYYY LT"},calendar:{sameDay:"[\u05d4\u05d9\u05d5\u05dd \u05d1\u05be]LT",nextDay:"[\u05de\u05d7\u05e8 \u05d1\u05be]LT",nextWeek:"dddd [\u05d1\u05e9\u05e2\u05d4] LT",lastDay:"[\u05d0\u05ea\u05de\u05d5\u05dc \u05d1\u05be]LT",lastWeek:"[\u05d1\u05d9\u05d5\u05dd] dddd [\u05d4\u05d0\u05d7\u05e8\u05d5\u05df \u05d1\u05e9\u05e2\u05d4] LT",sameElse:"L"},relativeTime:{future:"\u05d1\u05e2\u05d5\u05d3 %s",past:"\u05dc\u05e4\u05e0\u05d9 %s",s:"\u05de\u05e1\u05e4\u05e8 \u05e9\u05e0\u05d9\u05d5\u05ea",m:"\u05d3\u05e7\u05d4",mm:"%d \u05d3\u05e7\u05d5\u05ea",h:"\u05e9\u05e2\u05d4",hh:"%d \u05e9\u05e2\u05d5\u05ea",d:"\u05d9\u05d5\u05dd",dd:"%d \u05d9\u05de\u05d9\u05dd",M:"\u05d7\u05d5\u05d3\u05e9",MM:"%d \u05d7\u05d5\u05d3\u05e9\u05d9\u05dd",y:"\u05e9\u05e0\u05d4",yy:"%d \u05e9\u05e0\u05d9\u05dd"}})}(),function(){var t={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},a={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};e.lang("hi",{months:"\u091c\u0928\u0935\u0930\u0940_\u092b\u093c\u0930\u0935\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u0948\u0932_\u092e\u0908_\u091c\u0942\u0928_\u091c\u0941\u0932\u093e\u0908_\u0905\u0917\u0938\u094d\u0924_\u0938\u093f\u0924\u092e\u094d\u092c\u0930_\u0905\u0915\u094d\u091f\u0942\u092c\u0930_\u0928\u0935\u092e\u094d\u092c\u0930_\u0926\u093f\u0938\u092e\u094d\u092c\u0930".split("_"),monthsShort:"\u091c\u0928._\u092b\u093c\u0930._\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u0948._\u092e\u0908_\u091c\u0942\u0928_\u091c\u0941\u0932._\u0905\u0917._\u0938\u093f\u0924._\u0905\u0915\u094d\u091f\u0942._\u0928\u0935._\u0926\u093f\u0938.".split("_"),weekdays:"\u0930\u0935\u093f\u0935\u093e\u0930_\u0938\u094b\u092e\u0935\u093e\u0930_\u092e\u0902\u0917\u0932\u0935\u093e\u0930_\u092c\u0941\u0927\u0935\u093e\u0930_\u0917\u0941\u0930\u0942\u0935\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930_\u0936\u0928\u093f\u0935\u093e\u0930".split("_"),weekdaysShort:"\u0930\u0935\u093f_\u0938\u094b\u092e_\u092e\u0902\u0917\u0932_\u092c\u0941\u0927_\u0917\u0941\u0930\u0942_\u0936\u0941\u0915\u094d\u0930_\u0936\u0928\u093f".split("_"),weekdaysMin:"\u0930_\u0938\u094b_\u092e\u0902_\u092c\u0941_\u0917\u0941_\u0936\u0941_\u0936".split("_"),longDateFormat:{LT:"A h:mm \u092c\u091c\u0947",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u0915\u0932] LT",nextWeek:"dddd, LT",lastDay:"[\u0915\u0932] LT",lastWeek:"[\u092a\u093f\u091b\u0932\u0947] dddd, LT",sameElse:"L"},relativeTime:{future:"%s \u092e\u0947\u0902",past:"%s \u092a\u0939\u0932\u0947",s:"\u0915\u0941\u091b \u0939\u0940 \u0915\u094d\u0937\u0923",m:"\u090f\u0915 \u092e\u093f\u0928\u091f",mm:"%d \u092e\u093f\u0928\u091f",h:"\u090f\u0915 \u0918\u0902\u091f\u093e",hh:"%d \u0918\u0902\u091f\u0947",d:"\u090f\u0915 \u0926\u093f\u0928",dd:"%d \u0926\u093f\u0928",M:"\u090f\u0915 \u092e\u0939\u0940\u0928\u0947",MM:"%d \u092e\u0939\u0940\u0928\u0947",y:"\u090f\u0915 \u0935\u0930\u094d\u0937",yy:"%d \u0935\u0930\u094d\u0937"},preparse:function(e){return e.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(e){return a[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]})},meridiem:function(e){return 4>e?"\u0930\u093e\u0924":10>e?"\u0938\u0941\u092c\u0939":17>e?"\u0926\u094b\u092a\u0939\u0930":20>e?"\u0936\u093e\u092e":"\u0930\u093e\u0924"},week:{dow:0,doy:6}})}(),function(){function t(e,t,a,n){var _=e;switch(a){case"s":return n||t?"n\xe9h\xe1ny m\xe1sodperc":"n\xe9h\xe1ny m\xe1sodperce";case"m":return"egy"+(n||t?" perc":" perce");case"mm":return _+(n||t?" perc":" perce");case"h":return"egy"+(n||t?" \xf3ra":" \xf3r\xe1ja");case"hh":return _+(n||t?" \xf3ra":" \xf3r\xe1ja");case"d":return"egy"+(n||t?" nap":" napja");case"dd":return _+(n||t?" nap":" napja");case"M":return"egy"+(n||t?" h\xf3nap":" h\xf3napja");case"MM":return _+(n||t?" h\xf3nap":" h\xf3napja");case"y":return"egy"+(n||t?" \xe9v":" \xe9ve");case"yy":return _+(n||t?" \xe9v":" \xe9ve")}return""}function a(e){return(e?"":"[m\xfalt] ")+"["+n[this.day()]+"] LT[-kor]"}var n="vas\xe1rnap h\xe9tf\u0151n kedden szerd\xe1n cs\xfct\xf6rt\xf6k\xf6n p\xe9nteken szombaton".split(" ");e.lang("hu",{months:"janu\xe1r_febru\xe1r_m\xe1rcius_\xe1prilis_m\xe1jus_j\xfanius_j\xfalius_augusztus_szeptember_okt\xf3ber_november_december".split("_"),monthsShort:"jan_feb_m\xe1rc_\xe1pr_m\xe1j_j\xfan_j\xfal_aug_szept_okt_nov_dec".split("_"),weekdays:"vas\xe1rnap_h\xe9tf\u0151_kedd_szerda_cs\xfct\xf6rt\xf6k_p\xe9ntek_szombat".split("_"),weekdaysShort:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return a.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return a.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s m\xfalva",past:"%s",s:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},ordinal:"%d.",week:{dow:1,doy:7}})}(),function(){e.lang("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(e){return 11>e?"pagi":15>e?"siang":19>e?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}(),function(){function t(e){return 11===e%100?!0:1===e%10?!1:!0}function a(e,a,n,_){var s=e+" ";switch(n){case"s":return a||_?"nokkrar sek\xfandur":"nokkrum sek\xfandum";case"m":return a?"m\xedn\xfata":"m\xedn\xfatu";case"mm":return t(e)?s+(a||_?"m\xedn\xfatur":"m\xedn\xfatum"):a?s+"m\xedn\xfata":s+"m\xedn\xfatu";case"hh":return t(e)?s+(a||_?"klukkustundir":"klukkustundum"):s+"klukkustund";case"d":return a?"dagur":_?"dag":"degi";case"dd":return t(e)?a?s+"dagar":s+(_?"daga":"d\xf6gum"):a?s+"dagur":s+(_?"dag":"degi");case"M":return a?"m\xe1nu\xf0ur":_?"m\xe1nu\xf0":"m\xe1nu\xf0i";case"MM":return t(e)?a?s+"m\xe1nu\xf0ir":s+(_?"m\xe1nu\xf0i":"m\xe1nu\xf0um"):a?s+"m\xe1nu\xf0ur":s+(_?"m\xe1nu\xf0":"m\xe1nu\xf0i");case"y":return a||_?"\xe1r":"\xe1ri";case"yy":return t(e)?s+(a||_?"\xe1r":"\xe1rum"):s+(a||_?"\xe1r":"\xe1ri")}}e.lang("is",{months:"jan\xfaar_febr\xfaar_mars_apr\xedl_ma\xed_j\xfan\xed_j\xfal\xed_\xe1g\xfast_september_okt\xf3ber_n\xf3vember_desember".split("_"),monthsShort:"jan_feb_mar_apr_ma\xed_j\xfan_j\xfal_\xe1g\xfa_sep_okt_n\xf3v_des".split("_"),weekdays:"sunnudagur_m\xe1nudagur_\xferi\xf0judagur_mi\xf0vikudagur_fimmtudagur_f\xf6studagur_laugardagur".split("_"),weekdaysShort:"sun_m\xe1n_\xferi_mi\xf0_fim_f\xf6s_lau".split("_"),weekdaysMin:"Su_M\xe1_\xder_Mi_Fi_F\xf6_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd, D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[\xed dag kl.] LT",nextDay:"[\xe1 morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[\xed g\xe6r kl.] LT",lastWeek:"[s\xed\xf0asta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s s\xed\xf0an",s:a,m:a,mm:a,h:"klukkustund",hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("it",{months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Luned\xec_Marted\xec_Mercoled\xec_Gioved\xec_Venerd\xec_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:function(e){return(/^[0-9].+$/.test(e)?"tra":"in")+" "+e},past:"%s fa",s:"secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:"%d\xba",week:{dow:1,doy:4}})}(),function(){e.lang("ja",{months:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u65e5\u66dc\u65e5_\u6708\u66dc\u65e5_\u706b\u66dc\u65e5_\u6c34\u66dc\u65e5_\u6728\u66dc\u65e5_\u91d1\u66dc\u65e5_\u571f\u66dc\u65e5".split("_"),weekdaysShort:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),weekdaysMin:"\u65e5_\u6708_\u706b_\u6c34_\u6728_\u91d1_\u571f".split("_"),longDateFormat:{LT:"Ah\u6642m\u5206",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5LT",LLLL:"YYYY\u5e74M\u6708D\u65e5LT dddd"},meridiem:function(e){return 12>e?"\u5348\u524d":"\u5348\u5f8c"},calendar:{sameDay:"[\u4eca\u65e5] LT",nextDay:"[\u660e\u65e5] LT",nextWeek:"[\u6765\u9031]dddd LT",lastDay:"[\u6628\u65e5] LT",lastWeek:"[\u524d\u9031]dddd LT",sameElse:"L"},relativeTime:{future:"%s\u5f8c",past:"%s\u524d",s:"\u6570\u79d2",m:"1\u5206",mm:"%d\u5206",h:"1\u6642\u9593",hh:"%d\u6642\u9593",d:"1\u65e5",dd:"%d\u65e5",M:"1\u30f6\u6708",MM:"%d\u30f6\u6708",y:"1\u5e74",yy:"%d\u5e74"}})}(),function(){function t(e,t){var a={nominative:"\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10d8_\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10d8_\u10db\u10d0\u10e0\u10e2\u10d8_\u10d0\u10de\u10e0\u10d8\u10da\u10d8_\u10db\u10d0\u10d8\u10e1\u10d8_\u10d8\u10d5\u10dc\u10d8\u10e1\u10d8_\u10d8\u10d5\u10da\u10d8\u10e1\u10d8_\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10dd_\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10d8_\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10d8_\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10d8_\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10d8".split("_"),accusative:"\u10d8\u10d0\u10dc\u10d5\u10d0\u10e0\u10e1_\u10d7\u10d4\u10d1\u10d4\u10e0\u10d5\u10d0\u10da\u10e1_\u10db\u10d0\u10e0\u10e2\u10e1_\u10d0\u10de\u10e0\u10d8\u10da\u10d8\u10e1_\u10db\u10d0\u10d8\u10e1\u10e1_\u10d8\u10d5\u10dc\u10d8\u10e1\u10e1_\u10d8\u10d5\u10da\u10d8\u10e1\u10e1_\u10d0\u10d2\u10d5\u10d8\u10e1\u10e2\u10e1_\u10e1\u10d4\u10e5\u10e2\u10d4\u10db\u10d1\u10d4\u10e0\u10e1_\u10dd\u10e5\u10e2\u10dd\u10db\u10d1\u10d4\u10e0\u10e1_\u10dc\u10dd\u10d4\u10db\u10d1\u10d4\u10e0\u10e1_\u10d3\u10d4\u10d9\u10d4\u10db\u10d1\u10d4\u10e0\u10e1".split("_")},n=/D[oD] *MMMM?/.test(t)?"accusative":"nominative";return a[n][e.month()]}function a(e,t){var a={nominative:"\u10d9\u10d5\u10d8\u10e0\u10d0_\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8_\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10d8_\u10e8\u10d0\u10d1\u10d0\u10d7\u10d8".split("_"),accusative:"\u10d9\u10d5\u10d8\u10e0\u10d0\u10e1_\u10dd\u10e0\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10e1\u10d0\u10db\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10dd\u10d7\u10ee\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10ee\u10e3\u10d7\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1_\u10de\u10d0\u10e0\u10d0\u10e1\u10d9\u10d4\u10d5\u10e1_\u10e8\u10d0\u10d1\u10d0\u10d7\u10e1".split("_")},n=/(\u10ec\u10d8\u10dc\u10d0|\u10e8\u10d4\u10db\u10d3\u10d4\u10d2)/.test(t)?"accusative":"nominative";return a[n][e.day()]}e.lang("ka",{months:t,monthsShort:"\u10d8\u10d0\u10dc_\u10d7\u10d4\u10d1_\u10db\u10d0\u10e0_\u10d0\u10de\u10e0_\u10db\u10d0\u10d8_\u10d8\u10d5\u10dc_\u10d8\u10d5\u10da_\u10d0\u10d2\u10d5_\u10e1\u10d4\u10e5_\u10dd\u10e5\u10e2_\u10dc\u10dd\u10d4_\u10d3\u10d4\u10d9".split("_"),weekdays:a,weekdaysShort:"\u10d9\u10d5\u10d8_\u10dd\u10e0\u10e8_\u10e1\u10d0\u10db_\u10dd\u10d7\u10ee_\u10ee\u10e3\u10d7_\u10de\u10d0\u10e0_\u10e8\u10d0\u10d1".split("_"),weekdaysMin:"\u10d9\u10d5_\u10dd\u10e0_\u10e1\u10d0_\u10dd\u10d7_\u10ee\u10e3_\u10de\u10d0_\u10e8\u10d0".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[\u10d3\u10e6\u10d4\u10e1] LT[-\u10d6\u10d4]",nextDay:"[\u10ee\u10d5\u10d0\u10da] LT[-\u10d6\u10d4]",lastDay:"[\u10d2\u10e3\u10e8\u10d8\u10dc] LT[-\u10d6\u10d4]",nextWeek:"[\u10e8\u10d4\u10db\u10d3\u10d4\u10d2] dddd LT[-\u10d6\u10d4]",lastWeek:"[\u10ec\u10d8\u10dc\u10d0] dddd LT-\u10d6\u10d4",sameElse:"L"},relativeTime:{future:function(e){return/(\u10ec\u10d0\u10db\u10d8|\u10ec\u10e3\u10d7\u10d8|\u10e1\u10d0\u10d0\u10d7\u10d8|\u10ec\u10d4\u10da\u10d8)/.test(e)?e.replace(/\u10d8$/,"\u10e8\u10d8"):e+"\u10e8\u10d8"},past:function(e){return/(\u10ec\u10d0\u10db\u10d8|\u10ec\u10e3\u10d7\u10d8|\u10e1\u10d0\u10d0\u10d7\u10d8|\u10d3\u10e6\u10d4|\u10d7\u10d5\u10d4)/.test(e)?e.replace(/(\u10d8|\u10d4)$/,"\u10d8\u10e1 \u10ec\u10d8\u10dc"):/\u10ec\u10d4\u10da\u10d8/.test(e)?e.replace(/\u10ec\u10d4\u10da\u10d8$/,"\u10ec\u10da\u10d8\u10e1 \u10ec\u10d8\u10dc"):void 0},s:"\u10e0\u10d0\u10db\u10d3\u10d4\u10dc\u10d8\u10db\u10d4 \u10ec\u10d0\u10db\u10d8",m:"\u10ec\u10e3\u10d7\u10d8",mm:"%d \u10ec\u10e3\u10d7\u10d8",h:"\u10e1\u10d0\u10d0\u10d7\u10d8",hh:"%d \u10e1\u10d0\u10d0\u10d7\u10d8",d:"\u10d3\u10e6\u10d4",dd:"%d \u10d3\u10e6\u10d4",M:"\u10d7\u10d5\u10d4",MM:"%d \u10d7\u10d5\u10d4",y:"\u10ec\u10d4\u10da\u10d8",yy:"%d \u10ec\u10d4\u10da\u10d8"},ordinal:function(e){return 0===e?e:1===e?e+"-\u10da\u10d8":20>e||100>=e&&0===e%20||0===e%100?"\u10db\u10d4-"+e:e+"-\u10d4"},week:{dow:1,doy:7}})}(),function(){e.lang("ko",{months:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),monthsShort:"1\uc6d4_2\uc6d4_3\uc6d4_4\uc6d4_5\uc6d4_6\uc6d4_7\uc6d4_8\uc6d4_9\uc6d4_10\uc6d4_11\uc6d4_12\uc6d4".split("_"),weekdays:"\uc77c\uc694\uc77c_\uc6d4\uc694\uc77c_\ud654\uc694\uc77c_\uc218\uc694\uc77c_\ubaa9\uc694\uc77c_\uae08\uc694\uc77c_\ud1a0\uc694\uc77c".split("_"),weekdaysShort:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),weekdaysMin:"\uc77c_\uc6d4_\ud654_\uc218_\ubaa9_\uae08_\ud1a0".split("_"),longDateFormat:{LT:"A h\uc2dc mm\ubd84",L:"YYYY.MM.DD",LL:"YYYY\ub144 MMMM D\uc77c",LLL:"YYYY\ub144 MMMM D\uc77c LT",LLLL:"YYYY\ub144 MMMM D\uc77c dddd LT"},meridiem:function(e){return 12>e?"\uc624\uc804":"\uc624\ud6c4"},calendar:{sameDay:"\uc624\ub298 LT",nextDay:"\ub0b4\uc77c LT",nextWeek:"dddd LT",lastDay:"\uc5b4\uc81c LT",lastWeek:"\uc9c0\ub09c\uc8fc dddd LT",sameElse:"L"},relativeTime:{future:"%s \ud6c4",past:"%s \uc804",s:"\uba87\ucd08",ss:"%d\ucd08",m:"\uc77c\ubd84",mm:"%d\ubd84",h:"\ud55c\uc2dc\uac04",hh:"%d\uc2dc\uac04",d:"\ud558\ub8e8",dd:"%d\uc77c",M:"\ud55c\ub2ec",MM:"%d\ub2ec",y:"\uc77c\ub144",yy:"%d\ub144"},ordinal:"%d\uc77c"})}(),function(){function t(e,t,a){var n=e.split("_");return a?1===t%10&&11!==t?n[2]:n[3]:1===t%10&&11!==t?n[0]:n[1]}function a(e,a,_){return e+" "+t(n[_],e,a)}var n={mm:"min\u016bti_min\u016btes_min\u016bte_min\u016btes",hh:"stundu_stundas_stunda_stundas",dd:"dienu_dienas_diena_dienas",MM:"m\u0113nesi_m\u0113ne\u0161us_m\u0113nesis_m\u0113ne\u0161i",yy:"gadu_gadus_gads_gadi"};e.lang("lv",{months:"janv\u0101ris_febru\u0101ris_marts_apr\u012blis_maijs_j\u016bnijs_j\u016blijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_j\u016bn_j\u016bl_aug_sep_okt_nov_dec".split("_"),weekdays:"sv\u0113tdiena_pirmdiena_otrdiena_tre\u0161diena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, LT",LLLL:"YYYY. [gada] D. MMMM, dddd, LT"},calendar:{sameDay:"[\u0160odien pulksten] LT",nextDay:"[R\u012bt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pag\u0101ju\u0161\u0101] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"%s v\u0113l\u0101k",past:"%s agr\u0101k",s:"da\u017eas sekundes",m:"min\u016bti",mm:a,h:"stundu",hh:a,d:"dienu",dd:a,M:"m\u0113nesi",MM:a,y:"gadu",yy:a},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(e){return 11>e?"pagi":15>e?"tengahari":19>e?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}(),function(){e.lang("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"s\xf8ndag_mandag_tirsdag_onsdag_torsdag_fredag_l\xf8rdag".split("_"),weekdaysShort:"s\xf8n_man_tir_ons_tor_fre_l\xf8r".split("_"),weekdaysMin:"s\xf8_ma_ti_on_to_fr_l\xf8".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokken] LT",nextDay:"[I morgen klokken] LT",nextWeek:"dddd [klokken] LT",lastDay:"[I g\xe5r klokken] LT",lastWeek:"[Forrige] dddd [klokken] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en m\xe5ned",MM:"%d m\xe5neder",y:"ett \xe5r",yy:"%d \xe5r"},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){var t={1:"\u0967",2:"\u0968",3:"\u0969",4:"\u096a",5:"\u096b",6:"\u096c",7:"\u096d",8:"\u096e",9:"\u096f",0:"\u0966"},a={"\u0967":"1","\u0968":"2","\u0969":"3","\u096a":"4","\u096b":"5","\u096c":"6","\u096d":"7","\u096e":"8","\u096f":"9","\u0966":"0"};e.lang("ne",{months:"\u091c\u0928\u0935\u0930\u0940_\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u0930\u0940_\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u093f\u0932_\u092e\u0908_\u091c\u0941\u0928_\u091c\u0941\u0932\u093e\u0908_\u0905\u0917\u0937\u094d\u091f_\u0938\u0947\u092a\u094d\u091f\u0947\u092e\u094d\u092c\u0930_\u0905\u0915\u094d\u091f\u094b\u092c\u0930_\u0928\u094b\u092d\u0947\u092e\u094d\u092c\u0930_\u0921\u093f\u0938\u0947\u092e\u094d\u092c\u0930".split("_"),monthsShort:"\u091c\u0928._\u092b\u0947\u092c\u094d\u0930\u0941._\u092e\u093e\u0930\u094d\u091a_\u0905\u092a\u094d\u0930\u093f._\u092e\u0908_\u091c\u0941\u0928_\u091c\u0941\u0932\u093e\u0908._\u0905\u0917._\u0938\u0947\u092a\u094d\u091f._\u0905\u0915\u094d\u091f\u094b._\u0928\u094b\u092d\u0947._\u0921\u093f\u0938\u0947.".split("_"),weekdays:"\u0906\u0907\u0924\u092c\u093e\u0930_\u0938\u094b\u092e\u092c\u093e\u0930_\u092e\u0919\u094d\u0917\u0932\u092c\u093e\u0930_\u092c\u0941\u0927\u092c\u093e\u0930_\u092c\u093f\u0939\u093f\u092c\u093e\u0930_\u0936\u0941\u0915\u094d\u0930\u092c\u093e\u0930_\u0936\u0928\u093f\u092c\u093e\u0930".split("_"),weekdaysShort:"\u0906\u0907\u0924._\u0938\u094b\u092e._\u092e\u0919\u094d\u0917\u0932._\u092c\u0941\u0927._\u092c\u093f\u0939\u093f._\u0936\u0941\u0915\u094d\u0930._\u0936\u0928\u093f.".split("_"),weekdaysMin:"\u0906\u0907._\u0938\u094b._\u092e\u0919\u094d_\u092c\u0941._\u092c\u093f._\u0936\u0941._\u0936.".split("_"),longDateFormat:{LT:"A\u0915\u094b h:mm \u092c\u091c\u0947",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},preparse:function(e){return e.replace(/[\u0967\u0968\u0969\u096a\u096b\u096c\u096d\u096e\u096f\u0966]/g,function(e){return a[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]})},meridiem:function(e){return 3>e?"\u0930\u093e\u0924\u0940":10>e?"\u092c\u093f\u0939\u093e\u0928":15>e?"\u0926\u093f\u0909\u0901\u0938\u094b":18>e?"\u092c\u0947\u0932\u0941\u0915\u093e":20>e?"\u0938\u093e\u0901\u091d":"\u0930\u093e\u0924\u0940"},calendar:{sameDay:"[\u0906\u091c] LT",nextDay:"[\u092d\u094b\u0932\u0940] LT",nextWeek:"[\u0906\u0909\u0901\u0926\u094b] dddd[,] LT",lastDay:"[\u0939\u093f\u091c\u094b] LT",lastWeek:"[\u0917\u090f\u0915\u094b] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s\u092e\u093e",past:"%s \u0905\u0917\u093e\u0921\u0940",s:"\u0915\u0947\u0939\u0940 \u0938\u092e\u092f",m:"\u090f\u0915 \u092e\u093f\u0928\u0947\u091f",mm:"%d \u092e\u093f\u0928\u0947\u091f",h:"\u090f\u0915 \u0918\u0923\u094d\u091f\u093e",hh:"%d \u0918\u0923\u094d\u091f\u093e",d:"\u090f\u0915 \u0926\u093f\u0928",dd:"%d \u0926\u093f\u0928",M:"\u090f\u0915 \u092e\u0939\u093f\u0928\u093e",MM:"%d \u092e\u0939\u093f\u0928\u093e",y:"\u090f\u0915 \u092c\u0930\u094d\u0937",yy:"%d \u092c\u0930\u094d\u0937"},week:{dow:1,doy:7}})}(),function(){var t="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),a="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");e.lang("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,n){return/-MMM-/.test(n)?a[e.month()]:t[e.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Vandaag om] LT",nextDay:"[Morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"\xe9\xe9n minuut",mm:"%d minuten",h:"\xe9\xe9n uur",hh:"%d uur",d:"\xe9\xe9n dag",dd:"%d dagen",M:"\xe9\xe9n maand",MM:"%d maanden",y:"\xe9\xe9n jaar",yy:"%d jaar"},ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})}(),function(){e.lang("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_m\xe5ndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_m\xe5n_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_m\xe5_ty_on_to_fr_l\xf8".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I g\xe5r klokka] LT",lastWeek:"[F\xf8reg\xe5ende] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekund",m:"ett minutt",mm:"%d minutt",h:"en time",hh:"%d timar",d:"en dag",dd:"%d dagar",M:"en m\xe5nad",MM:"%d m\xe5nader",y:"ett \xe5r",yy:"%d \xe5r"},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){function t(e){return 5>e%10&&e%10>1&&1!==~~(e/10)}function a(e,a,n){var _=e+" ";switch(n){case"m":return a?"minuta":"minut\u0119";case"mm":return _+(t(e)?"minuty":"minut");case"h":return a?"godzina":"godzin\u0119";case"hh":return _+(t(e)?"godziny":"godzin");case"MM":return _+(t(e)?"miesi\u0105ce":"miesi\u0119cy");case"yy":return _+(t(e)?"lata":"lat")}}var n="stycze\u0144_luty_marzec_kwiecie\u0144_maj_czerwiec_lipiec_sierpie\u0144_wrzesie\u0144_pa\u017adziernik_listopad_grudzie\u0144".split("_"),_="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_wrze\u015bnia_pa\u017adziernika_listopada_grudnia".split("_");e.lang("pl",{months:function(e,t){return/D MMMM/.test(t)?_[e.month()]:n[e.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_pa\u017a_lis_gru".split("_"),weekdays:"niedziela_poniedzia\u0142ek_wtorek_\u015broda_czwartek_pi\u0105tek_sobota".split("_"),weekdaysShort:"nie_pon_wt_\u015br_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_\u015ar_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dzi\u015b o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zesz\u0142\u0105 niedziel\u0119 o] LT";case 3:return"[W zesz\u0142\u0105 \u015brod\u0119 o] LT";case 6:return"[W zesz\u0142\u0105 sobot\u0119 o] LT";default:return"[W zesz\u0142y] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:a,mm:a,h:a,hh:a,d:"1 dzie\u0144",dd:"%d dni",M:"miesi\u0105c",MM:a,y:"rok",yy:a},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("pt-br",{months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Dom_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1b".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atr\xe1s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%d\xba"})}(),function(){e.lang("pt",{months:"Janeiro_Fevereiro_Mar\xe7o_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Ter\xe7a-feira_Quarta-feira_Quinta-feira_Sexta-feira_S\xe1bado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_S\xe1b".split("_"),weekdaysMin:"Dom_2\xaa_3\xaa_4\xaa_5\xaa_6\xaa_S\xe1b".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje \xe0s] LT",nextDay:"[Amanh\xe3 \xe0s] LT",nextWeek:"dddd [\xe0s] LT",lastDay:"[Ontem \xe0s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[\xdaltimo] dddd [\xe0s] LT":"[\xdaltima] dddd [\xe0s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atr\xe1s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um m\xeas",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%d\xba",week:{dow:1,doy:4}}) +}(),function(){e.lang("ro",{months:"Ianuarie_Februarie_Martie_Aprilie_Mai_Iunie_Iulie_August_Septembrie_Octombrie_Noiembrie_Decembrie".split("_"),monthsShort:"Ian_Feb_Mar_Apr_Mai_Iun_Iul_Aug_Sep_Oct_Noi_Dec".split("_"),weekdays:"Duminic\u0103_Luni_Mar\u0163i_Miercuri_Joi_Vineri_S\xe2mb\u0103t\u0103".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_S\xe2m".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_S\xe2".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[m\xe2ine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s \xeen urm\u0103",s:"c\xe2teva secunde",m:"un minut",mm:"%d minute",h:"o or\u0103",hh:"%d ore",d:"o zi",dd:"%d zile",M:"o lun\u0103",MM:"%d luni",y:"un an",yy:"%d ani"},week:{dow:1,doy:7}})}(),function(){function t(e,t){var a=e.split("_");return 1===t%10&&11!==t%100?a[0]:t%10>=2&&4>=t%10&&(10>t%100||t%100>=20)?a[1]:a[2]}function a(e,a,n){var _={mm:"\u043c\u0438\u043d\u0443\u0442\u0430_\u043c\u0438\u043d\u0443\u0442\u044b_\u043c\u0438\u043d\u0443\u0442",hh:"\u0447\u0430\u0441_\u0447\u0430\u0441\u0430_\u0447\u0430\u0441\u043e\u0432",dd:"\u0434\u0435\u043d\u044c_\u0434\u043d\u044f_\u0434\u043d\u0435\u0439",MM:"\u043c\u0435\u0441\u044f\u0446_\u043c\u0435\u0441\u044f\u0446\u0430_\u043c\u0435\u0441\u044f\u0446\u0435\u0432",yy:"\u0433\u043e\u0434_\u0433\u043e\u0434\u0430_\u043b\u0435\u0442"};return"m"===n?a?"\u043c\u0438\u043d\u0443\u0442\u0430":"\u043c\u0438\u043d\u0443\u0442\u0443":e+" "+t(_[n],+e)}function n(e,t){var a={nominative:"\u044f\u043d\u0432\u0430\u0440\u044c_\u0444\u0435\u0432\u0440\u0430\u043b\u044c_\u043c\u0430\u0440\u0442_\u0430\u043f\u0440\u0435\u043b\u044c_\u043c\u0430\u0439_\u0438\u044e\u043d\u044c_\u0438\u044e\u043b\u044c_\u0430\u0432\u0433\u0443\u0441\u0442_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044c_\u043e\u043a\u0442\u044f\u0431\u0440\u044c_\u043d\u043e\u044f\u0431\u0440\u044c_\u0434\u0435\u043a\u0430\u0431\u0440\u044c".split("_"),accusative:"\u044f\u043d\u0432\u0430\u0440\u044f_\u0444\u0435\u0432\u0440\u0430\u043b\u044f_\u043c\u0430\u0440\u0442\u0430_\u0430\u043f\u0440\u0435\u043b\u044f_\u043c\u0430\u044f_\u0438\u044e\u043d\u044f_\u0438\u044e\u043b\u044f_\u0430\u0432\u0433\u0443\u0441\u0442\u0430_\u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f_\u043e\u043a\u0442\u044f\u0431\u0440\u044f_\u043d\u043e\u044f\u0431\u0440\u044f_\u0434\u0435\u043a\u0430\u0431\u0440\u044f".split("_")},n=/D[oD]? *MMMM?/.test(t)?"accusative":"nominative";return a[n][e.month()]}function _(e,t){var a={nominative:"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0435\u0440\u0433_\u043f\u044f\u0442\u043d\u0438\u0446\u0430_\u0441\u0443\u0431\u0431\u043e\u0442\u0430".split("_"),accusative:"\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435_\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a_\u0432\u0442\u043e\u0440\u043d\u0438\u043a_\u0441\u0440\u0435\u0434\u0443_\u0447\u0435\u0442\u0432\u0435\u0440\u0433_\u043f\u044f\u0442\u043d\u0438\u0446\u0443_\u0441\u0443\u0431\u0431\u043e\u0442\u0443".split("_")},n=/\[ ?[\u0412\u0432] ?(?:\u043f\u0440\u043e\u0448\u043b\u0443\u044e|\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e)? ?\] ?dddd/.test(t)?"accusative":"nominative";return a[n][e.day()]}e.lang("ru",{months:n,monthsShort:"\u044f\u043d\u0432_\u0444\u0435\u0432_\u043c\u0430\u0440_\u0430\u043f\u0440_\u043c\u0430\u0439_\u0438\u044e\u043d_\u0438\u044e\u043b_\u0430\u0432\u0433_\u0441\u0435\u043d_\u043e\u043a\u0442_\u043d\u043e\u044f_\u0434\u0435\u043a".split("_"),weekdays:_,weekdaysShort:"\u0432\u0441\u043a_\u043f\u043d\u0434_\u0432\u0442\u0440_\u0441\u0440\u0434_\u0447\u0442\u0432_\u043f\u0442\u043d_\u0441\u0431\u0442".split("_"),weekdaysMin:"\u0432\u0441_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0433.",LLL:"D MMMM YYYY \u0433., LT",LLLL:"dddd, D MMMM YYYY \u0433., LT"},calendar:{sameDay:"[\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432] LT",nextDay:"[\u0417\u0430\u0432\u0442\u0440\u0430 \u0432] LT",lastDay:"[\u0412\u0447\u0435\u0440\u0430 \u0432] LT",nextWeek:function(){return 2===this.day()?"[\u0412\u043e] dddd [\u0432] LT":"[\u0412] dddd [\u0432] LT"},lastWeek:function(){switch(this.day()){case 0:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0435] dddd [\u0432] LT";case 1:case 2:case 4:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439] dddd [\u0432] LT";case 3:case 5:case 6:return"[\u0412 \u043f\u0440\u043e\u0448\u043b\u0443\u044e] dddd [\u0432] LT"}},sameElse:"L"},relativeTime:{future:"\u0447\u0435\u0440\u0435\u0437 %s",past:"%s \u043d\u0430\u0437\u0430\u0434",s:"\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434",m:a,mm:a,h:"\u0447\u0430\u0441",hh:a,d:"\u0434\u0435\u043d\u044c",dd:a,M:"\u043c\u0435\u0441\u044f\u0446",MM:a,y:"\u0433\u043e\u0434",yy:a},ordinal:function(e,t){switch(t){case"M":case"d":case"DDD":return e+"-\u0439";case"D":return e+"-\u0433\u043e";case"w":case"W":return e+"-\u044f";default:return e}},week:{dow:1,doy:7}})}(),function(){function t(e){return e>1&&5>e}function a(e,a,n,_){var s=e+" ";switch(n){case"s":return a||_?"p\xe1r sek\xfand":"p\xe1r sekundami";case"m":return a?"min\xfata":_?"min\xfatu":"min\xfatou";case"mm":return a||_?s+(t(e)?"min\xfaty":"min\xfat"):s+"min\xfatami";break;case"h":return a?"hodina":_?"hodinu":"hodinou";case"hh":return a||_?s+(t(e)?"hodiny":"hod\xedn"):s+"hodinami";break;case"d":return a||_?"de\u0148":"d\u0148om";case"dd":return a||_?s+(t(e)?"dni":"dn\xed"):s+"d\u0148ami";break;case"M":return a||_?"mesiac":"mesiacom";case"MM":return a||_?s+(t(e)?"mesiace":"mesiacov"):s+"mesiacmi";break;case"y":return a||_?"rok":"rokom";case"yy":return a||_?s+(t(e)?"roky":"rokov"):s+"rokmi"}}var n="janu\xe1r_febru\xe1r_marec_apr\xedl_m\xe1j_j\xfan_j\xfal_august_september_okt\xf3ber_november_december".split("_"),_="jan_feb_mar_apr_m\xe1j_j\xfan_j\xfal_aug_sep_okt_nov_dec".split("_");e.lang("sk",{months:n,monthsShort:_,monthsParse:function(e,t){var a,n=[];for(a=0;12>a;a++)n[a]=new RegExp("^"+e[a]+"$|^"+t[a]+"$","i");return n}(n,_),weekdays:"nede\u013ea_pondelok_utorok_streda_\u0161tvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_\u0161t_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_\u0161t_pi_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nede\u013eu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo \u0161tvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[v\u010dera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minul\xfa nede\u013eu o] LT";case 1:case 2:return"[minul\xfd] dddd [o] LT";case 3:return"[minul\xfa stredu o] LT";case 4:case 5:return"[minul\xfd] dddd [o] LT";case 6:return"[minul\xfa sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){function t(e,t,a){var n=e+" ";switch(a){case"m":return t?"ena minuta":"eno minuto";case"mm":return n+=1===e?"minuta":2===e?"minuti":3===e||4===e?"minute":"minut";case"h":return t?"ena ura":"eno uro";case"hh":return n+=1===e?"ura":2===e?"uri":3===e||4===e?"ure":"ur";case"dd":return n+=1===e?"dan":"dni";case"MM":return n+=1===e?"mesec":2===e?"meseca":3===e||4===e?"mesece":"mesecev";case"yy":return n+=1===e?"leto":2===e?"leti":3===e||4===e?"leta":"let"}}e.lang("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedelja_ponedeljek_torek_sreda_\u010detrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._\u010det._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_\u010de_pe_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[v\u010deraj ob] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[prej\u0161nja] dddd [ob] LT";case 1:case 2:case 4:case 5:return"[prej\u0161nji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"\u010dez %s",past:"%s nazaj",s:"nekaj sekund",m:t,mm:t,h:t,hh:t,d:"en dan",dd:t,M:"en mesec",MM:t,y:"eno leto",yy:t},ordinal:"%d.",week:{dow:1,doy:7}})}(),function(){e.lang("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_N\xebntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_N\xebn_Dhj".split("_"),weekdays:"E Diel_E H\xebn\xeb_E Marte_E M\xebrkure_E Enjte_E Premte_E Shtun\xeb".split("_"),weekdaysShort:"Die_H\xebn_Mar_M\xebr_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_M\xeb_E_P_Sh".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Sot n\xeb] LT",nextDay:"[Neser n\xeb] LT",nextWeek:"dddd [n\xeb] LT",lastDay:"[Dje n\xeb] LT",lastWeek:"dddd [e kaluar n\xeb] LT",sameElse:"L"},relativeTime:{future:"n\xeb %s",past:"%s me par\xeb",s:"disa seconda",m:"nj\xeb minut",mm:"%d minutea",h:"nj\xeb or\xeb",hh:"%d or\xeb",d:"nj\xeb dit\xeb",dd:"%d dit\xeb",M:"nj\xeb muaj",MM:"%d muaj",y:"nj\xeb vit",yy:"%d vite"},ordinal:"%d.",week:{dow:1,doy:4}})}(),function(){e.lang("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"s\xf6ndag_m\xe5ndag_tisdag_onsdag_torsdag_fredag_l\xf6rdag".split("_"),weekdaysShort:"s\xf6n_m\xe5n_tis_ons_tor_fre_l\xf6r".split("_"),weekdaysMin:"s\xf6_m\xe5_ti_on_to_fr_l\xf6".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Ig\xe5r] LT",nextWeek:"dddd LT",lastWeek:"[F\xf6rra] dddd[en] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"f\xf6r %s sedan",s:"n\xe5gra sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en m\xe5nad",MM:"%d m\xe5nader",y:"ett \xe5r",yy:"%d \xe5r"},ordinal:function(e){var t=e%10,a=1===~~(e%100/10)?"e":1===t?"a":2===t?"a":3===t?"e":"e";return e+a},week:{dow:1,doy:4}})}(),function(){e.lang("th",{months:"\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21_\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c_\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21_\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19_\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21_\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19_\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21_\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21_\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19_\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21_\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19_\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21".split("_"),monthsShort:"\u0e21\u0e01\u0e23\u0e32_\u0e01\u0e38\u0e21\u0e20\u0e32_\u0e21\u0e35\u0e19\u0e32_\u0e40\u0e21\u0e29\u0e32_\u0e1e\u0e24\u0e29\u0e20\u0e32_\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32_\u0e01\u0e23\u0e01\u0e0e\u0e32_\u0e2a\u0e34\u0e07\u0e2b\u0e32_\u0e01\u0e31\u0e19\u0e22\u0e32_\u0e15\u0e38\u0e25\u0e32_\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32_\u0e18\u0e31\u0e19\u0e27\u0e32".split("_"),weekdays:"\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c_\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c_\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23_\u0e1e\u0e38\u0e18_\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35_\u0e28\u0e38\u0e01\u0e23\u0e4c_\u0e40\u0e2a\u0e32\u0e23\u0e4c".split("_"),weekdaysShort:"\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c_\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c_\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23_\u0e1e\u0e38\u0e18_\u0e1e\u0e24\u0e2b\u0e31\u0e2a_\u0e28\u0e38\u0e01\u0e23\u0e4c_\u0e40\u0e2a\u0e32\u0e23\u0e4c".split("_"),weekdaysMin:"\u0e2d\u0e32._\u0e08._\u0e2d._\u0e1e._\u0e1e\u0e24._\u0e28._\u0e2a.".split("_"),longDateFormat:{LT:"H \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 m \u0e19\u0e32\u0e17\u0e35",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY \u0e40\u0e27\u0e25\u0e32 LT",LLLL:"\u0e27\u0e31\u0e19dddd\u0e17\u0e35\u0e48 D MMMM YYYY \u0e40\u0e27\u0e25\u0e32 LT"},meridiem:function(e){return 12>e?"\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07":"\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07"},calendar:{sameDay:"[\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",nextDay:"[\u0e1e\u0e23\u0e38\u0e48\u0e07\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",nextWeek:"dddd[\u0e2b\u0e19\u0e49\u0e32 \u0e40\u0e27\u0e25\u0e32] LT",lastDay:"[\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e27\u0e32\u0e19\u0e19\u0e35\u0e49 \u0e40\u0e27\u0e25\u0e32] LT",lastWeek:"[\u0e27\u0e31\u0e19]dddd[\u0e17\u0e35\u0e48\u0e41\u0e25\u0e49\u0e27 \u0e40\u0e27\u0e25\u0e32] LT",sameElse:"L"},relativeTime:{future:"\u0e2d\u0e35\u0e01 %s",past:"%s\u0e17\u0e35\u0e48\u0e41\u0e25\u0e49\u0e27",s:"\u0e44\u0e21\u0e48\u0e01\u0e35\u0e48\u0e27\u0e34\u0e19\u0e32\u0e17\u0e35",m:"1 \u0e19\u0e32\u0e17\u0e35",mm:"%d \u0e19\u0e32\u0e17\u0e35",h:"1 \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07",hh:"%d \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07",d:"1 \u0e27\u0e31\u0e19",dd:"%d \u0e27\u0e31\u0e19",M:"1 \u0e40\u0e14\u0e37\u0e2d\u0e19",MM:"%d \u0e40\u0e14\u0e37\u0e2d\u0e19",y:"1 \u0e1b\u0e35",yy:"%d \u0e1b\u0e35"}})}(),function(){var t={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'\xfcnc\xfc",4:"'\xfcnc\xfc",100:"'\xfcnc\xfc",6:"'nc\u0131",9:"'uncu",10:"'uncu",30:"'uncu",60:"'\u0131nc\u0131",90:"'\u0131nc\u0131"};e.lang("tr",{months:"Ocak_\u015eubat_Mart_Nisan_May\u0131s_Haziran_Temmuz_A\u011fustos_Eyl\xfcl_Ekim_Kas\u0131m_Aral\u0131k".split("_"),monthsShort:"Oca_\u015eub_Mar_Nis_May_Haz_Tem_A\u011fu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Sal\u0131_\xc7ar\u015famba_Per\u015fembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_\xc7ar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_\xc7a_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bug\xfcn saat] LT",nextDay:"[yar\u0131n saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[d\xfcn] LT",lastWeek:"[ge\xe7en hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s \xf6nce",s:"birka\xe7 saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir g\xfcn",dd:"%d g\xfcn",M:"bir ay",MM:"%d ay",y:"bir y\u0131l",yy:"%d y\u0131l"},ordinal:function(e){if(0===e)return e+"'\u0131nc\u0131";var a=e%10,n=e%100-a,_=e>=100?100:null;return e+(t[a]||t[n]||t[_])},week:{dow:1,doy:7}})}(),function(){e.lang("tzm-la",{months:"innayr_br\u02e4ayr\u02e4_mar\u02e4s\u02e4_ibrir_mayyw_ywnyw_ywlywz_\u0263w\u0161t_\u0161wtanbir_kt\u02e4wbr\u02e4_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_br\u02e4ayr\u02e4_mar\u02e4s\u02e4_ibrir_mayyw_ywnyw_ywlywz_\u0263w\u0161t_\u0161wtanbir_kt\u02e4wbr\u02e4_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asi\u1e0dyas".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",m:"minu\u1e0d",mm:"%d minu\u1e0d",h:"sa\u025ba",hh:"%d tassa\u025bin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}(),function(){e.lang("tzm",{months:"\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54_\u2d31\u2d55\u2d30\u2d62\u2d55_\u2d4e\u2d30\u2d55\u2d5a_\u2d49\u2d31\u2d54\u2d49\u2d54_\u2d4e\u2d30\u2d62\u2d62\u2d53_\u2d62\u2d53\u2d4f\u2d62\u2d53_\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63_\u2d56\u2d53\u2d5b\u2d5c_\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d3d\u2d5f\u2d53\u2d31\u2d55_\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d37\u2d53\u2d4a\u2d4f\u2d31\u2d49\u2d54".split("_"),monthsShort:"\u2d49\u2d4f\u2d4f\u2d30\u2d62\u2d54_\u2d31\u2d55\u2d30\u2d62\u2d55_\u2d4e\u2d30\u2d55\u2d5a_\u2d49\u2d31\u2d54\u2d49\u2d54_\u2d4e\u2d30\u2d62\u2d62\u2d53_\u2d62\u2d53\u2d4f\u2d62\u2d53_\u2d62\u2d53\u2d4d\u2d62\u2d53\u2d63_\u2d56\u2d53\u2d5b\u2d5c_\u2d5b\u2d53\u2d5c\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d3d\u2d5f\u2d53\u2d31\u2d55_\u2d4f\u2d53\u2d61\u2d30\u2d4f\u2d31\u2d49\u2d54_\u2d37\u2d53\u2d4a\u2d4f\u2d31\u2d49\u2d54".split("_"),weekdays:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),weekdaysShort:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),weekdaysMin:"\u2d30\u2d59\u2d30\u2d4e\u2d30\u2d59_\u2d30\u2d62\u2d4f\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4f\u2d30\u2d59_\u2d30\u2d3d\u2d54\u2d30\u2d59_\u2d30\u2d3d\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d4e\u2d61\u2d30\u2d59_\u2d30\u2d59\u2d49\u2d39\u2d62\u2d30\u2d59".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[\u2d30\u2d59\u2d37\u2d45 \u2d34] LT",nextDay:"[\u2d30\u2d59\u2d3d\u2d30 \u2d34] LT",nextWeek:"dddd [\u2d34] LT",lastDay:"[\u2d30\u2d5a\u2d30\u2d4f\u2d5c \u2d34] LT",lastWeek:"dddd [\u2d34] LT",sameElse:"L"},relativeTime:{future:"\u2d37\u2d30\u2d37\u2d45 \u2d59 \u2d62\u2d30\u2d4f %s",past:"\u2d62\u2d30\u2d4f %s",s:"\u2d49\u2d4e\u2d49\u2d3d",m:"\u2d4e\u2d49\u2d4f\u2d53\u2d3a",mm:"%d \u2d4e\u2d49\u2d4f\u2d53\u2d3a",h:"\u2d59\u2d30\u2d44\u2d30",hh:"%d \u2d5c\u2d30\u2d59\u2d59\u2d30\u2d44\u2d49\u2d4f",d:"\u2d30\u2d59\u2d59",dd:"%d o\u2d59\u2d59\u2d30\u2d4f",M:"\u2d30\u2d62o\u2d53\u2d54",MM:"%d \u2d49\u2d62\u2d62\u2d49\u2d54\u2d4f",y:"\u2d30\u2d59\u2d33\u2d30\u2d59",yy:"%d \u2d49\u2d59\u2d33\u2d30\u2d59\u2d4f"},week:{dow:6,doy:12}})}(),function(){function t(e,t){var a=e.split("_");return 1===t%10&&11!==t%100?a[0]:t%10>=2&&4>=t%10&&(10>t%100||t%100>=20)?a[1]:a[2]}function a(e,a,n){var _={mm:"\u0445\u0432\u0438\u043b\u0438\u043d\u0430_\u0445\u0432\u0438\u043b\u0438\u043d\u0438_\u0445\u0432\u0438\u043b\u0438\u043d",hh:"\u0433\u043e\u0434\u0438\u043d\u0430_\u0433\u043e\u0434\u0438\u043d\u0438_\u0433\u043e\u0434\u0438\u043d",dd:"\u0434\u0435\u043d\u044c_\u0434\u043d\u0456_\u0434\u043d\u0456\u0432",MM:"\u043c\u0456\u0441\u044f\u0446\u044c_\u043c\u0456\u0441\u044f\u0446\u0456_\u043c\u0456\u0441\u044f\u0446\u0456\u0432",yy:"\u0440\u0456\u043a_\u0440\u043e\u043a\u0438_\u0440\u043e\u043a\u0456\u0432"};return"m"===n?a?"\u0445\u0432\u0438\u043b\u0438\u043d\u0430":"\u0445\u0432\u0438\u043b\u0438\u043d\u0443":"h"===n?a?"\u0433\u043e\u0434\u0438\u043d\u0430":"\u0433\u043e\u0434\u0438\u043d\u0443":e+" "+t(_[n],+e)}function n(e,t){var a={nominative:"\u0441\u0456\u0447\u0435\u043d\u044c_\u043b\u044e\u0442\u0438\u0439_\u0431\u0435\u0440\u0435\u0437\u0435\u043d\u044c_\u043a\u0432\u0456\u0442\u0435\u043d\u044c_\u0442\u0440\u0430\u0432\u0435\u043d\u044c_\u0447\u0435\u0440\u0432\u0435\u043d\u044c_\u043b\u0438\u043f\u0435\u043d\u044c_\u0441\u0435\u0440\u043f\u0435\u043d\u044c_\u0432\u0435\u0440\u0435\u0441\u0435\u043d\u044c_\u0436\u043e\u0432\u0442\u0435\u043d\u044c_\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434_\u0433\u0440\u0443\u0434\u0435\u043d\u044c".split("_"),accusative:"\u0441\u0456\u0447\u043d\u044f_\u043b\u044e\u0442\u043e\u0433\u043e_\u0431\u0435\u0440\u0435\u0437\u043d\u044f_\u043a\u0432\u0456\u0442\u043d\u044f_\u0442\u0440\u0430\u0432\u043d\u044f_\u0447\u0435\u0440\u0432\u043d\u044f_\u043b\u0438\u043f\u043d\u044f_\u0441\u0435\u0440\u043f\u043d\u044f_\u0432\u0435\u0440\u0435\u0441\u043d\u044f_\u0436\u043e\u0432\u0442\u043d\u044f_\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430_\u0433\u0440\u0443\u0434\u043d\u044f".split("_")},n=/D[oD]? *MMMM?/.test(t)?"accusative":"nominative";return a[n][e.month()]}function _(e,t){var a={nominative:"\u043d\u0435\u0434\u0456\u043b\u044f_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a_\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a_\u0441\u0435\u0440\u0435\u0434\u0430_\u0447\u0435\u0442\u0432\u0435\u0440_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u044f_\u0441\u0443\u0431\u043e\u0442\u0430".split("_"),accusative:"\u043d\u0435\u0434\u0456\u043b\u044e_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a_\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a_\u0441\u0435\u0440\u0435\u0434\u0443_\u0447\u0435\u0442\u0432\u0435\u0440_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u044e_\u0441\u0443\u0431\u043e\u0442\u0443".split("_"),genitive:"\u043d\u0435\u0434\u0456\u043b\u0456_\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043a\u0430_\u0432\u0456\u0432\u0442\u043e\u0440\u043a\u0430_\u0441\u0435\u0440\u0435\u0434\u0438_\u0447\u0435\u0442\u0432\u0435\u0440\u0433\u0430_\u043f\u2019\u044f\u0442\u043d\u0438\u0446\u0456_\u0441\u0443\u0431\u043e\u0442\u0438".split("_")},n=/(\[[\u0412\u0432\u0423\u0443]\]) ?dddd/.test(t)?"accusative":/\[?(?:\u043c\u0438\u043d\u0443\u043b\u043e\u0457|\u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457)? ?\] ?dddd/.test(t)?"genitive":"nominative";return a[n][e.day()]}function s(e){return function(){return e+"\u043e"+(11===this.hours()?"\u0431":"")+"] LT"}}e.lang("uk",{months:n,monthsShort:"\u0441\u0456\u0447_\u043b\u044e\u0442_\u0431\u0435\u0440_\u043a\u0432\u0456_\u0442\u0440\u0430_\u0447\u0435\u0440_\u043b\u0438\u043f_\u0441\u0435\u0440_\u0432\u0435\u0440_\u0436\u043e\u0432_\u043b\u0438\u0441_\u0433\u0440\u0443".split("_"),weekdays:_,weekdaysShort:"\u043d\u0435\u0434_\u043f\u043e\u043d_\u0432\u0456\u0432_\u0441\u0440\u0434_\u0447\u0435\u0442_\u043f\u0442\u043d_\u0441\u0443\u0431".split("_"),weekdaysMin:"\u043d\u0434_\u043f\u043d_\u0432\u0442_\u0441\u0440_\u0447\u0442_\u043f\u0442_\u0441\u0431".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY \u0440.",LLL:"D MMMM YYYY \u0440., LT",LLLL:"dddd, D MMMM YYYY \u0440., LT"},calendar:{sameDay:s("[\u0421\u044c\u043e\u0433\u043e\u0434\u043d\u0456 "),nextDay:s("[\u0417\u0430\u0432\u0442\u0440\u0430 "),lastDay:s("[\u0412\u0447\u043e\u0440\u0430 "),nextWeek:s("[\u0423] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return s("[\u041c\u0438\u043d\u0443\u043b\u043e\u0457] dddd [").call(this);case 1:case 2:case 4:return s("[\u041c\u0438\u043d\u0443\u043b\u043e\u0433\u043e] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"\u0437\u0430 %s",past:"%s \u0442\u043e\u043c\u0443",s:"\u0434\u0435\u043a\u0456\u043b\u044c\u043a\u0430 \u0441\u0435\u043a\u0443\u043d\u0434",m:a,mm:a,h:"\u0433\u043e\u0434\u0438\u043d\u0443",hh:a,d:"\u0434\u0435\u043d\u044c",dd:a,M:"\u043c\u0456\u0441\u044f\u0446\u044c",MM:a,y:"\u0440\u0456\u043a",yy:a},ordinal:function(e,t){switch(t){case"M":case"d":case"DDD":case"w":case"W":return e+"-\u0439";case"D":return e+"-\u0433\u043e";default:return e}},week:{dow:1,doy:7}})}(),function(){e.lang("zh-cn",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u5468\u65e5_\u5468\u4e00_\u5468\u4e8c_\u5468\u4e09_\u5468\u56db_\u5468\u4e94_\u5468\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"Ah\u70b9mm",L:"YYYY\u5e74MMMD\u65e5",LL:"YYYY\u5e74MMMD\u65e5",LLL:"YYYY\u5e74MMMD\u65e5LT",LLLL:"YYYY\u5e74MMMD\u65e5ddddLT",l:"YYYY\u5e74MMMD\u65e5",ll:"YYYY\u5e74MMMD\u65e5",lll:"YYYY\u5e74MMMD\u65e5LT",llll:"YYYY\u5e74MMMD\u65e5ddddLT"},meridiem:function(e,t){return 9>e?"\u65e9\u4e0a":11>e&&30>t?"\u4e0a\u5348":13>e&&30>t?"\u4e2d\u5348":18>e?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"\u65e5";case"M":return e+"\u6708";case"w":case"W":return e+"\u5468";default:return e}},relativeTime:{future:"%s\u5185",past:"%s\u524d",s:"\u51e0\u79d2",m:"1\u5206\u949f",mm:"%d\u5206\u949f",h:"1\u5c0f\u65f6",hh:"%d\u5c0f\u65f6",d:"1\u5929",dd:"%d\u5929",M:"1\u4e2a\u6708",MM:"%d\u4e2a\u6708",y:"1\u5e74",yy:"%d\u5e74"}})}(),function(){e.lang("zh-tw",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u9031\u65e5_\u9031\u4e00_\u9031\u4e8c_\u9031\u4e09_\u9031\u56db_\u9031\u4e94_\u9031\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"Ah\u9edemm",L:"YYYY\u5e74MMMD\u65e5",LL:"YYYY\u5e74MMMD\u65e5",LLL:"YYYY\u5e74MMMD\u65e5LT",LLLL:"YYYY\u5e74MMMD\u65e5ddddLT",l:"YYYY\u5e74MMMD\u65e5",ll:"YYYY\u5e74MMMD\u65e5",lll:"YYYY\u5e74MMMD\u65e5LT",llll:"YYYY\u5e74MMMD\u65e5ddddLT"},meridiem:function(e,t){return 9>e?"\u65e9\u4e0a":11>e&&30>t?"\u4e0a\u5348":13>e&&30>t?"\u4e2d\u5348":18>e?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"\u65e5";case"M":return e+"\u6708";case"w":case"W":return e+"\u9031";default:return e}},relativeTime:{future:"%s\u5167",past:"%s\u524d",s:"\u5e7e\u79d2",m:"\u4e00\u5206\u9418",mm:"%d\u5206\u9418",h:"\u4e00\u5c0f\u6642",hh:"%d\u5c0f\u6642",d:"\u4e00\u5929",dd:"%d\u5929",M:"\u4e00\u500b\u6708",MM:"%d\u500b\u6708",y:"\u4e00\u5e74",yy:"%d\u5e74"}})}(),e.lang("en")}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}()}"function"==typeof define&&define.amd&&define(["moment"],e),"undefined"!=typeof window&&window.moment&&e(window.moment)}(); \ No newline at end of file diff --git a/node_modules/moment/min/moment.min.js b/node_modules/moment/min/moment.min.js new file mode 100644 index 0000000..62b1697 --- /dev/null +++ b/node_modules/moment/min/moment.min.js @@ -0,0 +1,6 @@ +// moment.js +// version : 2.1.0 +// author : Tim Wood +// license : MIT +// momentjs.com +!function(t){function e(t,e){return function(n){return u(t.call(this,n),e)}}function n(t,e){return function(n){return this.lang().ordinal(t.call(this,n),e)}}function s(){}function i(t){a(this,t)}function r(t){var e=t.years||t.year||t.y||0,n=t.months||t.month||t.M||0,s=t.weeks||t.week||t.w||0,i=t.days||t.day||t.d||0,r=t.hours||t.hour||t.h||0,a=t.minutes||t.minute||t.m||0,o=t.seconds||t.second||t.s||0,u=t.milliseconds||t.millisecond||t.ms||0;this._input=t,this._milliseconds=u+1e3*o+6e4*a+36e5*r,this._days=i+7*s,this._months=n+12*e,this._data={},this._bubble()}function a(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}function o(t){return 0>t?Math.ceil(t):Math.floor(t)}function u(t,e){for(var n=t+"";n.lengthn;n++)~~t[n]!==~~e[n]&&r++;return r+i}function f(t){return t?ie[t]||t.toLowerCase().replace(/(.)s$/,"$1"):t}function l(t,e){return e.abbr=t,x[t]||(x[t]=new s),x[t].set(e),x[t]}function _(t){if(!t)return H.fn._lang;if(!x[t]&&A)try{require("./lang/"+t)}catch(e){return H.fn._lang}return x[t]}function m(t){return t.match(/\[.*\]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function y(t){var e,n,s=t.match(E);for(e=0,n=s.length;n>e;e++)s[e]=ue[s[e]]?ue[s[e]]:m(s[e]);return function(i){var r="";for(e=0;n>e;e++)r+=s[e]instanceof Function?s[e].call(i,t):s[e];return r}}function M(t,e){function n(e){return t.lang().longDateFormat(e)||e}for(var s=5;s--&&N.test(e);)e=e.replace(N,n);return re[e]||(re[e]=y(e)),re[e](t)}function g(t,e){switch(t){case"DDDD":return V;case"YYYY":return X;case"YYYYY":return $;case"S":case"SS":case"SSS":case"DDD":return I;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return R;case"a":case"A":return _(e._l)._meridiemParse;case"X":return B;case"Z":case"ZZ":return j;case"T":return q;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return J;default:return new RegExp(t.replace("\\",""))}}function p(t){var e=(j.exec(t)||[])[0],n=(e+"").match(ee)||["-",0,0],s=+(60*n[1])+~~n[2];return"+"===n[0]?-s:s}function D(t,e,n){var s,i=n._a;switch(t){case"M":case"MM":i[1]=null==e?0:~~e-1;break;case"MMM":case"MMMM":s=_(n._l).monthsParse(e),null!=s?i[1]=s:n._isValid=!1;break;case"D":case"DD":case"DDD":case"DDDD":null!=e&&(i[2]=~~e);break;case"YY":i[0]=~~e+(~~e>68?1900:2e3);break;case"YYYY":case"YYYYY":i[0]=~~e;break;case"a":case"A":n._isPm=_(n._l).isPM(e);break;case"H":case"HH":case"h":case"hh":i[3]=~~e;break;case"m":case"mm":i[4]=~~e;break;case"s":case"ss":i[5]=~~e;break;case"S":case"SS":case"SSS":i[6]=~~(1e3*("0."+e));break;case"X":n._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":n._useUTC=!0,n._tzm=p(e)}null==e&&(n._isValid=!1)}function Y(t){var e,n,s=[];if(!t._d){for(e=0;7>e;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];s[3]+=~~((t._tzm||0)/60),s[4]+=~~((t._tzm||0)%60),n=new Date(0),t._useUTC?(n.setUTCFullYear(s[0],s[1],s[2]),n.setUTCHours(s[3],s[4],s[5],s[6])):(n.setFullYear(s[0],s[1],s[2]),n.setHours(s[3],s[4],s[5],s[6])),t._d=n}}function w(t){var e,n,s=t._f.match(E),i=t._i;for(t._a=[],e=0;eo&&(u=o,s=n);a(t,s)}function v(t){var e,n=t._i,s=K.exec(n);if(s){for(t._f="YYYY-MM-DD"+(s[2]||" "),e=0;4>e;e++)if(te[e][1].exec(n)){t._f+=te[e][0];break}j.exec(n)&&(t._f+=" Z"),w(t)}else t._d=new Date(n)}function T(e){var n=e._i,s=G.exec(n);n===t?e._d=new Date:s?e._d=new Date(+s[1]):"string"==typeof n?v(e):d(n)?(e._a=n.slice(0),Y(e)):e._d=n instanceof Date?new Date(+n):new Date(n)}function b(t,e,n,s,i){return i.relativeTime(e||1,!!n,t,s)}function S(t,e,n){var s=W(Math.abs(t)/1e3),i=W(s/60),r=W(i/60),a=W(r/24),o=W(a/365),u=45>s&&["s",s]||1===i&&["m"]||45>i&&["mm",i]||1===r&&["h"]||22>r&&["hh",r]||1===a&&["d"]||25>=a&&["dd",a]||45>=a&&["M"]||345>a&&["MM",W(a/30)]||1===o&&["y"]||["yy",o];return u[2]=e,u[3]=t>0,u[4]=n,b.apply({},u)}function F(t,e,n){var s,i=n-e,r=n-t.day();return r>i&&(r-=7),i-7>r&&(r+=7),s=H(t).add("d",r),{week:Math.ceil(s.dayOfYear()/7),year:s.year()}}function O(t){var e=t._i,n=t._f;return null===e||""===e?null:("string"==typeof e&&(t._i=e=_().preparse(e)),H.isMoment(e)?(t=a({},e),t._d=new Date(+e._d)):n?d(n)?k(t):w(t):T(t),new i(t))}function z(t,e){H.fn[t]=H.fn[t+"s"]=function(t){var n=this._isUTC?"UTC":"";return null!=t?(this._d["set"+n+e](t),H.updateOffset(this),this):this._d["get"+n+e]()}}function C(t){H.duration.fn[t]=function(){return this._data[t]}}function L(t,e){H.duration.fn["as"+t]=function(){return+this/e}}for(var H,P,U="2.1.0",W=Math.round,x={},A="undefined"!=typeof module&&module.exports,G=/^\/?Date\((\-?\d+)/i,Z=/(\-)?(\d*)?\.?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,E=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,N=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,J=/\d\d?/,I=/\d{1,3}/,V=/\d{3}/,X=/\d{1,4}/,$=/[+\-]?\d{1,6}/,R=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,j=/Z|[\+\-]\d\d:?\d\d/i,q=/T/i,B=/[\+\-]?\d+(\.\d{1,3})?/,K=/^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,Q="YYYY-MM-DDTHH:mm:ssZ",te=[["HH:mm:ss.S",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],ee=/([\+\-]|\d\d)/gi,ne="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),se={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},ie={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",w:"week",M:"month",y:"year"},re={},ae="DDD w W M D d".split(" "),oe="M D H h m s w W".split(" "),ue={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return u(this.year()%100,2)},YYYY:function(){return u(this.year(),4)},YYYYY:function(){return u(this.year(),5)},gg:function(){return u(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return u(this.weekYear(),5)},GG:function(){return u(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return u(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return u(~~(this.milliseconds()/10),2)},SSS:function(){return u(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+u(~~(t/60),2)+":"+u(~~t%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+u(~~(10*t/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}};ae.length;)P=ae.pop(),ue[P+"o"]=n(ue[P],P);for(;oe.length;)P=oe.pop(),ue[P+P]=e(ue[P],2);for(ue.DDDD=e(ue.DDD,3),s.prototype={set:function(t){var e,n;for(n in t)e=t[n],"function"==typeof e?this[n]=e:this["_"+n]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,n,s;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(n=H([2e3,e]),s="^"+this.months(n,"")+"|^"+this.monthsShort(n,""),this._monthsParse[e]=new RegExp(s.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,n,s;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(n=H([2e3,1]).day(e),s="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[e]=new RegExp(s.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase()[0]},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var n=this._calendar[t];return"function"==typeof n?n.apply(e):n},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,n,s){var i=this._relativeTime[n];return"function"==typeof i?i(t,e,n,s):i.replace(/%d/i,t)},pastFuture:function(t,e){var n=this._relativeTime[t>0?"future":"past"];return"function"==typeof n?n(e):n.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return F(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6}},H=function(t,e,n){return O({_i:t,_f:e,_l:n,_isUTC:!1})},H.utc=function(t,e,n){return O({_useUTC:!0,_isUTC:!0,_l:n,_i:t,_f:e})},H.unix=function(t){return H(1e3*t)},H.duration=function(t,e){var n,s,i=H.isDuration(t),a="number"==typeof t,o=i?t._input:a?{}:t,u=Z.exec(t);return a?e?o[e]=t:o.milliseconds=t:u&&(n="-"===u[1]?-1:1,o={y:0,d:~~u[2]*n,h:~~u[3]*n,m:~~u[4]*n,s:~~u[5]*n,ms:~~u[6]*n}),s=new r(o),i&&t.hasOwnProperty("_lang")&&(s._lang=t._lang),s},H.version=U,H.defaultFormat=Q,H.updateOffset=function(){},H.lang=function(t,e){return t?(e?l(t,e):x[t]||_(t),H.duration.fn._lang=H.fn._lang=_(t),void 0):H.fn._lang._abbr},H.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),_(t)},H.isMoment=function(t){return t instanceof i},H.isDuration=function(t){return t instanceof r},H.fn=i.prototype={clone:function(){return H(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return M(H(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var t=this;return[t.year(),t.month(),t.date(),t.hours(),t.minutes(),t.seconds(),t.milliseconds()]},isValid:function(){return null==this._isValid&&(this._isValid=this._a?!c(this._a,(this._isUTC?H.utc(this._a):H(this._a)).toArray()):!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=M(this,t||H.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var n;return n="string"==typeof t?H.duration(+e,t):H.duration(t,e),h(this,n,1),this},subtract:function(t,e){var n;return n="string"==typeof t?H.duration(+e,t):H.duration(t,e),h(this,n,-1),this},diff:function(t,e,n){var s,i,r=this._isUTC?H(t).zone(this._offset||0):H(t).local(),a=6e4*(this.zone()-r.zone());return e=f(e),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+r.daysInMonth()),i=12*(this.year()-r.year())+(this.month()-r.month()),i+=(this-H(this).startOf("month")-(r-H(r).startOf("month")))/s,i-=6e4*(this.zone()-H(this).startOf("month").zone()-(r.zone()-H(r).startOf("month").zone()))/s,"year"===e&&(i/=12)):(s=this-r,i="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?(s-a)/864e5:"week"===e?(s-a)/6048e5:s),n?i:o(i)},from:function(t,e){return H.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(H(),t)},calendar:function(){var t=this.diff(H().startOf("day"),"days",!0),e=-6>t?"sameElse":-1>t?"lastWeek":0>t?"lastDay":1>t?"sameDay":2>t?"nextDay":7>t?"nextWeek":"sameElse";return this.format(this.lang().calendar(e,this))},isLeapYear:function(){var t=this.year();return 0===t%4&&0!==t%100||0===t%400},isDST:function(){return this.zone()+H(t).startOf(e)},isBefore:function(t,e){return e="undefined"!=typeof e?e:"millisecond",+this.clone().startOf(e)<+H(t).startOf(e)},isSame:function(t,e){return e="undefined"!=typeof e?e:"millisecond",+this.clone().startOf(e)===+H(t).startOf(e)},min:function(t){return t=H.apply(null,arguments),this>t?this:t},max:function(t){return t=H.apply(null,arguments),t>this?this:t},zone:function(t){var e=this._offset||0;return null==t?this._isUTC?e:this._d.getTimezoneOffset():("string"==typeof t&&(t=p(t)),Math.abs(t)<16&&(t=60*t),this._offset=t,this._isUTC=!0,e!==t&&h(this,H.duration(e-t,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},daysInMonth:function(){return H.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(t){var e=W((H(this).startOf("day")-H(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},weekYear:function(t){var e=F(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=F(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=F(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this._d.getDay()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},lang:function(e){return e===t?this._lang:(this._lang=_(e),this)}},P=0;P ["10", "00"] or "-1530" > ["-15", "30"] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, + + // getter and setter names + proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, + + unitAliases = { + ms : 'millisecond', + s : 'second', + m : 'minute', + h : 'hour', + d : 'day', + w : 'week', + M : 'month', + y : 'year' + }, + + // format function strings + formatFunctions = {}, + + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), + + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.lang().monthsShort(this, format); + }, + MMMM : function (format) { + return this.lang().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.lang().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.lang().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.lang().weekdays(this, format); + }, + w : function () { + return this.week(); + }, + W : function () { + return this.isoWeek(); + }, + YY : function () { + return leftZeroFill(this.year() % 100, 2); + }, + YYYY : function () { + return leftZeroFill(this.year(), 4); + }, + YYYYY : function () { + return leftZeroFill(this.year(), 5); + }, + gg : function () { + return leftZeroFill(this.weekYear() % 100, 2); + }, + gggg : function () { + return this.weekYear(); + }, + ggggg : function () { + return leftZeroFill(this.weekYear(), 5); + }, + GG : function () { + return leftZeroFill(this.isoWeekYear() % 100, 2); + }, + GGGG : function () { + return this.isoWeekYear(); + }, + GGGGG : function () { + return leftZeroFill(this.isoWeekYear(), 5); + }, + e : function () { + return this.weekday(); + }, + E : function () { + return this.isoWeekday(); + }, + a : function () { + return this.lang().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.lang().meridiem(this.hours(), this.minutes(), false); + }, + H : function () { + return this.hours(); + }, + h : function () { + return this.hours() % 12 || 12; + }, + m : function () { + return this.minutes(); + }, + s : function () { + return this.seconds(); + }, + S : function () { + return ~~(this.milliseconds() / 100); + }, + SS : function () { + return leftZeroFill(~~(this.milliseconds() / 10), 2); + }, + SSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + Z : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2); + }, + ZZ : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(~~(10 * a / 6), 4); + }, + z : function () { + return this.zoneAbbr(); + }, + zz : function () { + return this.zoneName(); + }, + X : function () { + return this.unix(); + } + }; + + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; + } + function ordinalizeToken(func, period) { + return function (a) { + return this.lang().ordinal(func.call(this, a), period); + }; + } + + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); + } + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + + + /************************************ + Constructors + ************************************/ + + function Language() { + + } + + // Moment prototype object + function Moment(config) { + extend(this, config); + } + + // Duration Constructor + function Duration(duration) { + var years = duration.years || duration.year || duration.y || 0, + months = duration.months || duration.month || duration.M || 0, + weeks = duration.weeks || duration.week || duration.w || 0, + days = duration.days || duration.day || duration.d || 0, + hours = duration.hours || duration.hour || duration.h || 0, + minutes = duration.minutes || duration.minute || duration.m || 0, + seconds = duration.seconds || duration.second || duration.s || 0, + milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0; + + // store reference to input for deterministic cloning + this._input = duration; + + // representation for dateAddRemove + this._milliseconds = milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = months + + years * 12; + + this._data = {}; + + this._bubble(); + } + + + /************************************ + Helpers + ************************************/ + + + function extend(a, b) { + for (var i in b) { + if (b.hasOwnProperty(i)) { + a[i] = b[i]; + } + } + return a; + } + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength) { + var output = number + ''; + while (output.length < targetLength) { + output = '0' + output; + } + return output; + } + + // helper function for _.addTime and _.subtractTime + function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months, + minutes, + hours, + currentDate; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + // store the minutes and hours so we can restore them + if (days || months) { + minutes = mom.minute(); + hours = mom.hour(); + } + if (days) { + mom.date(mom.date() + days * isAdding); + } + if (months) { + mom.month(mom.month() + months * isAdding); + } + if (milliseconds && !ignoreUpdateOffset) { + moment.updateOffset(mom); + } + // restore the minutes and hours after possibly changing dst + if (days || months) { + mom.minute(minutes); + mom.hour(hours); + } + } + + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if (~~array1[i] !== ~~array2[i]) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function normalizeUnits(units) { + return units ? unitAliases[units] || units.toLowerCase().replace(/(.)s$/, '$1') : units; + } + + + /************************************ + Languages + ************************************/ + + + Language.prototype = { + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + }, + + _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + months : function (m) { + return this._months[m.month()]; + }, + + _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, + + monthsParse : function (monthName) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + if (!this._monthsParse[i]) { + mom = moment([2000, i]); + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._monthsParse[i].test(monthName)) { + return i; + } + } + }, + + _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, + + _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, + + _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, + + weekdaysParse : function (weekdayName) { + var i, mom, regex; + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + if (!this._weekdaysParse[i]) { + mom = moment([2000, 1]).day(i); + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + }, + + _longDateFormat : { + LT : "h:mm A", + L : "MM/DD/YYYY", + LL : "MMMM D YYYY", + LLL : "MMMM D YYYY LT", + LLLL : "dddd, MMMM D YYYY LT" + }, + longDateFormat : function (key) { + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; + } + return output; + }, + + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'p'); + }, + + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, + + _calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, + + _relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + relativeTime : function (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + }, + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, + + ordinal : function (number) { + return this._ordinal.replace("%d", number); + }, + _ordinal : "%d", + + preparse : function (string) { + return string; + }, + + postformat : function (string) { + return string; + }, + + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, + _week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }; + + // Loads a language definition into the `languages` cache. The function + // takes a key and optionally values. If not in the browser and no values + // are provided, it will load the language file module. As a convenience, + // this function also returns the language values. + function loadLang(key, values) { + values.abbr = key; + if (!languages[key]) { + languages[key] = new Language(); + } + languages[key].set(values); + return languages[key]; + } + + // Determines which language definition to use and returns it. + // + // With no parameters, it will return the global language. If you + // pass in a language key, such as 'en', it will return the + // definition for 'en', so long as 'en' has already been loaded using + // moment.lang. + function getLangDefinition(key) { + if (!key) { + return moment.fn._lang; + } + if (!languages[key] && hasModule) { + try { + require('./lang/' + key); + } catch (e) { + // call with no params to set to default + return moment.fn._lang; + } + } + return languages[key]; + } + + + /************************************ + Formatting + ************************************/ + + + function removeFormattingTokens(input) { + if (input.match(/\[.*\]/)) { + return input.replace(/^\[|\]$/g, ""); + } + return input.replace(/\\/g, ""); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = ""; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return m.lang().longDateFormat(input) || input; + } + + while (i-- && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + } + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); + } + + + /************************************ + Parsing + ************************************/ + + + // get the regex to find the next token + function getParseRegexForToken(token, config) { + switch (token) { + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + return parseTokenFourDigits; + case 'YYYYY': + return parseTokenSixDigits; + case 'S': + case 'SS': + case 'SSS': + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + return parseTokenWord; + case 'a': + case 'A': + return getLangDefinition(config._l)._meridiemParse; + case 'X': + return parseTokenTimestampMs; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'MM': + case 'DD': + case 'YY': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + return parseTokenOneOrTwoDigits; + default : + return new RegExp(token.replace('\\', '')); + } + } + + function timezoneMinutesFromString(string) { + var tzchunk = (parseTokenTimezone.exec(string) || [])[0], + parts = (tzchunk + '').match(parseTimezoneChunker) || ['-', 0, 0], + minutes = +(parts[1] * 60) + ~~parts[2]; + + return parts[0] === '+' ? -minutes : minutes; + } + + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; + + switch (token) { + // MONTH + case 'M' : // fall through to MM + case 'MM' : + datePartArray[1] = (input == null) ? 0 : ~~input - 1; + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + a = getLangDefinition(config._l).monthsParse(input); + // if we didn't find a month name, mark the date as invalid. + if (a != null) { + datePartArray[1] = a; + } else { + config._isValid = false; + } + break; + // DAY OF MONTH + case 'D' : // fall through to DDDD + case 'DD' : // fall through to DDDD + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + datePartArray[2] = ~~input; + } + break; + // YEAR + case 'YY' : + datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000); + break; + case 'YYYY' : + case 'YYYYY' : + datePartArray[0] = ~~input; + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config._isPm = getLangDefinition(config._l).isPM(input); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[3] = ~~input; + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[4] = ~~input; + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[5] = ~~input; + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + datePartArray[6] = ~~ (('0.' + input) * 1000); + break; + // UNIX TIMESTAMP WITH MS + case 'X': + config._d = new Date(parseFloat(input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config._useUTC = true; + config._tzm = timezoneMinutesFromString(input); + break; + } + + // if the input is null, the date is not valid + if (input == null) { + config._isValid = false; + } + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromArray(config) { + var i, date, input = []; + + if (config._d) { + return; + } + + for (i = 0; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // add the offsets to the time to be parsed so that we can have a clean array for checking isValid + input[3] += ~~((config._tzm || 0) / 60); + input[4] += ~~((config._tzm || 0) % 60); + + date = new Date(0); + + if (config._useUTC) { + date.setUTCFullYear(input[0], input[1], input[2]); + date.setUTCHours(input[3], input[4], input[5], input[6]); + } else { + date.setFullYear(input[0], input[1], input[2]); + date.setHours(input[3], input[4], input[5], input[6]); + } + + config._d = date; + } + + // date from string and format string + function makeDateFromStringAndFormat(config) { + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var tokens = config._f.match(formattingTokens), + string = config._i, + i, parsedInput; + + config._a = []; + + for (i = 0; i < tokens.length; i++) { + parsedInput = (getParseRegexForToken(tokens[i], config).exec(string) || [])[0]; + if (parsedInput) { + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + } + // don't parse if its not a known token + if (formatTokenFunctions[tokens[i]]) { + addTimeToArrayFromToken(tokens[i], parsedInput, config); + } + } + + // add remaining unparsed input to the string + if (string) { + config._il = string; + } + + // handle am pm + if (config._isPm && config._a[3] < 12) { + config._a[3] += 12; + } + // if is 12 am, change hours to 0 + if (config._isPm === false && config._a[3] === 12) { + config._a[3] = 0; + } + // return + dateFromArray(config); + } + + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + tempMoment, + bestMoment, + + scoreToBeat = 99, + i, + currentScore; + + for (i = 0; i < config._f.length; i++) { + tempConfig = extend({}, config); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); + tempMoment = new Moment(tempConfig); + + currentScore = compareArrays(tempConfig._a, tempMoment.toArray()); + + // if there is any input that was not parsed + // add a penalty for that format + if (tempMoment._il) { + currentScore += tempMoment._il.length; + } + + if (currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempMoment; + } + } + + extend(config, bestMoment); + } + + // date from iso format + function makeDateFromString(config) { + var i, + string = config._i, + match = isoRegex.exec(string); + + if (match) { + // match[2] should be "T" or undefined + config._f = 'YYYY-MM-DD' + (match[2] || " "); + for (i = 0; i < 4; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (parseTokenTimezone.exec(string)) { + config._f += " Z"; + } + makeDateFromStringAndFormat(config); + } else { + config._d = new Date(string); + } + } + + function makeDateFromInput(config) { + var input = config._i, + matched = aspNetJsonRegex.exec(input); + + if (input === undefined) { + config._d = new Date(); + } else if (matched) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = input.slice(0); + dateFromArray(config); + } else { + config._d = input instanceof Date ? new Date(+input) : new Date(input); + } + } + + + /************************************ + Relative Time + ************************************/ + + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { + return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function relativeTime(milliseconds, withoutSuffix, lang) { + var seconds = round(Math.abs(milliseconds) / 1000), + minutes = round(seconds / 60), + hours = round(minutes / 60), + days = round(hours / 24), + years = round(days / 365), + args = seconds < 45 && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < 45 && ['mm', minutes] || + hours === 1 && ['h'] || + hours < 22 && ['hh', hours] || + days === 1 && ['d'] || + days <= 25 && ['dd', days] || + days <= 45 && ['M'] || + days < 345 && ['MM', round(days / 30)] || + years === 1 && ['y'] || ['yy', years]; + args[2] = withoutSuffix; + args[3] = milliseconds > 0; + args[4] = lang; + return substituteTimeAgo.apply({}, args); + } + + + /************************************ + Week of Year + ************************************/ + + + // firstDayOfWeek 0 = sun, 6 = sat + // the day of the week that starts the week + // (usually sunday or monday) + // firstDayOfWeekOfYear 0 = sun, 6 = sat + // the first week is the week that contains the first + // of this day of the week + // (eg. ISO weeks use thursday (4)) + function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { + var end = firstDayOfWeekOfYear - firstDayOfWeek, + daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), + adjustedMoment; + + + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } + + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } + + adjustedMoment = moment(mom).add('d', daysToDayOfWeek); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } + + + /************************************ + Top Level Functions + ************************************/ + + function makeMoment(config) { + var input = config._i, + format = config._f; + + if (input === null || input === '') { + return null; + } + + if (typeof input === 'string') { + config._i = input = getLangDefinition().preparse(input); + } + + if (moment.isMoment(input)) { + config = extend({}, input); + config._d = new Date(+input._d); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } + + return new Moment(config); + } + + moment = function (input, format, lang) { + return makeMoment({ + _i : input, + _f : format, + _l : lang, + _isUTC : false + }); + }; + + // creating with utc + moment.utc = function (input, format, lang) { + return makeMoment({ + _useUTC : true, + _isUTC : true, + _l : lang, + _i : input, + _f : format + }); + }; + + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; + + // duration + moment.duration = function (input, key) { + var isDuration = moment.isDuration(input), + isNumber = (typeof input === 'number'), + duration = (isDuration ? input._input : (isNumber ? {} : input)), + matched = aspNetTimeSpanJsonRegex.exec(input), + sign, + ret; + + if (isNumber) { + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (matched) { + sign = (matched[1] === "-") ? -1 : 1; + duration = { + y: 0, + d: ~~matched[2] * sign, + h: ~~matched[3] * sign, + m: ~~matched[4] * sign, + s: ~~matched[5] * sign, + ms: ~~matched[6] * sign + }; + } + + ret = new Duration(duration); + + if (isDuration && input.hasOwnProperty('_lang')) { + ret._lang = input._lang; + } + + return ret; + }; + + // version number + moment.version = VERSION; + + // default format + moment.defaultFormat = isoFormat; + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + moment.updateOffset = function () {}; + + // This function will load languages and then set the global language. If + // no arguments are passed in, it will simply return the current global + // language key. + moment.lang = function (key, values) { + if (!key) { + return moment.fn._lang._abbr; + } + if (values) { + loadLang(key, values); + } else if (!languages[key]) { + getLangDefinition(key); + } + moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); + }; + + // returns language data + moment.langData = function (key) { + if (key && key._lang && key._lang._abbr) { + key = key._lang._abbr; + } + return getLangDefinition(key); + }; + + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment; + }; + + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; + + + /************************************ + Moment Prototype + ************************************/ + + + moment.fn = Moment.prototype = { + + clone : function () { + return moment(this); + }, + + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, + + unix : function () { + return Math.floor(+this / 1000); + }, + + toString : function () { + return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); + }, + + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, + + toISOString : function () { + return formatMoment(moment(this).utc(), 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + }, + + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, + + isValid : function () { + if (this._isValid == null) { + if (this._a) { + this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()); + } else { + this._isValid = !isNaN(this._d.getTime()); + } + } + return !!this._isValid; + }, + + utc : function () { + return this.zone(0); + }, + + local : function () { + this.zone(0); + this._isUTC = false; + return this; + }, + + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.lang().postformat(output); + }, + + add : function (input, val) { + var dur; + // switch args to support add('s', 1) and add(1, 's') + if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, 1); + return this; + }, + + subtract : function (input, val) { + var dur; + // switch args to support subtract('s', 1) and subtract(1, 's') + if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, -1); + return this; + }, + + diff : function (input, units, asFloat) { + var that = this._isUTC ? moment(input).zone(this._offset || 0) : moment(input).local(), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month') { + // average number of days in the months in the given dates + diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 + // difference in months + output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); + // adjust by taking difference in days, average number of days + // and dst in the given months. + output += ((this - moment(this).startOf('month')) - + (that - moment(that).startOf('month'))) / diff; + // same as above but with zones, to negate all dst + output -= ((this.zone() - moment(this).startOf('month').zone()) - + (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; + if (units === 'year') { + output = output / 12; + } + } else { + diff = (this - that); + output = units === 'second' ? diff / 1e3 : // 1000 + units === 'minute' ? diff / 6e4 : // 1000 * 60 + units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + diff; + } + return asFloat ? output : absRound(output); + }, + + from : function (time, withoutSuffix) { + return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); + }, + + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, + + calendar : function () { + var diff = this.diff(moment().startOf('day'), 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + return this.format(this.lang().calendar(format, this)); + }, + + isLeapYear : function () { + var year = this.year(); + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + }, + + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, + + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + if (typeof input === 'string') { + input = this.lang().weekdaysParse(input); + if (typeof input !== 'number') { + return this; + } + } + return this.add({ d : input - day }); + } else { + return day; + } + }, + + month : function (input) { + var utc = this._isUTC ? 'UTC' : '', + dayOfMonth, + daysInMonth; + + if (input != null) { + if (typeof input === 'string') { + input = this.lang().monthsParse(input); + if (typeof input !== 'number') { + return this; + } + } + + dayOfMonth = this.date(); + this.date(1); + this._d['set' + utc + 'Month'](input); + this.date(Math.min(dayOfMonth, this.daysInMonth())); + + moment.updateOffset(this); + return this; + } else { + return this._d['get' + utc + 'Month'](); + } + }, + + startOf: function (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + + return this; + }, + + endOf: function (units) { + return this.startOf(units).add(units, 1).subtract('ms', 1); + }, + + isAfter: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) > +moment(input).startOf(units); + }, + + isBefore: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) < +moment(input).startOf(units); + }, + + isSame: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) === +moment(input).startOf(units); + }, + + min: function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + }, + + max: function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + }, + + zone : function (input) { + var offset = this._offset || 0; + if (input != null) { + if (typeof input === "string") { + input = timezoneMinutesFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + this._offset = input; + this._isUTC = true; + if (offset !== input) { + addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true); + } + } else { + return this._isUTC ? offset : this._d.getTimezoneOffset(); + } + return this; + }, + + zoneAbbr : function () { + return this._isUTC ? "UTC" : ""; + }, + + zoneName : function () { + return this._isUTC ? "Coordinated Universal Time" : ""; + }, + + daysInMonth : function () { + return moment.utc([this.year(), this.month() + 1, 0]).date(); + }, + + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); + }, + + weekYear : function (input) { + var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; + return input == null ? year : this.add("y", (input - year)); + }, + + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add("y", (input - year)); + }, + + week : function (input) { + var week = this.lang().week(this); + return input == null ? week : this.add("d", (input - week) * 7); + }, + + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add("d", (input - week) * 7); + }, + + weekday : function (input) { + var weekday = (this._d.getDay() + 7 - this.lang()._week.dow) % 7; + return input == null ? weekday : this.add("d", input - weekday); + }, + + isoWeekday : function (input) { + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + }, + + // If passed a language key, it will set the language for this + // instance. Otherwise, it will return the language configuration + // variables for this instance. + lang : function (key) { + if (key === undefined) { + return this._lang; + } else { + this._lang = getLangDefinition(key); + return this; + } + } + }; + + // helper for adding shortcuts + function makeGetterAndSetter(name, key) { + moment.fn[name] = moment.fn[name + 's'] = function (input) { + var utc = this._isUTC ? 'UTC' : ''; + if (input != null) { + this._d['set' + utc + key](input); + moment.updateOffset(this); + return this; + } else { + return this._d['get' + utc + key](); + } + }; + } + + // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds) + for (i = 0; i < proxyGettersAndSetters.length; i ++) { + makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]); + } + + // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') + makeGetterAndSetter('year', 'FullYear'); + + // add plural methods + moment.fn.days = moment.fn.day; + moment.fn.months = moment.fn.month; + moment.fn.weeks = moment.fn.week; + moment.fn.isoWeeks = moment.fn.isoWeek; + + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; + + /************************************ + Duration Prototype + ************************************/ + + + moment.duration.fn = Duration.prototype = { + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; + + hours = absRound(minutes / 60); + data.hours = hours % 24; + + days += absRound(hours / 24); + data.days = days % 30; + + months += absRound(days / 30); + data.months = months % 12; + + years = absRound(months / 12); + data.years = years; + }, + + weeks : function () { + return absRound(this.days() / 7); + }, + + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + ~~(this._months / 12) * 31536e6; + }, + + humanize : function (withSuffix) { + var difference = +this, + output = relativeTime(difference, !withSuffix, this.lang()); + + if (withSuffix) { + output = this.lang().pastFuture(difference, output); + } + + return this.lang().postformat(output); + }, + + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); + + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; + + this._bubble(); + + return this; + }, + + subtract : function (input, val) { + var dur = moment.duration(input, val); + + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; + + this._bubble(); + + return this; + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, + + as : function (units) { + units = normalizeUnits(units); + return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); + }, + + lang : moment.fn.lang + }; + + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; + } + + function makeDurationAsGetter(name, factor) { + moment.duration.fn['as' + name] = function () { + return +this / factor; + }; + } + + for (i in unitMillisecondFactors) { + if (unitMillisecondFactors.hasOwnProperty(i)) { + makeDurationAsGetter(i, unitMillisecondFactors[i]); + makeDurationGetter(i.toLowerCase()); + } + } + + makeDurationAsGetter('Weeks', 6048e5); + moment.duration.fn.asMonths = function () { + return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; + }; + + + /************************************ + Default Lang + ************************************/ + + + // Set default language, other languages will inherit from English. + moment.lang('en', { + ordinal : function (number) { + var b = number % 10, + output = (~~ (number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + + /************************************ + Exposing Moment + ************************************/ + + + // CommonJS module is defined + if (hasModule) { + module.exports = moment; + } + /*global ender:false */ + if (typeof ender === 'undefined') { + // here, `this` means `window` in the browser, or `global` on the server + // add `moment` as a global object via a string identifier, + // for Closure Compiler "advanced" mode + this['moment'] = moment; + } + /*global define:false */ + if (typeof define === "function" && define.amd) { + define("moment", [], function () { + return moment; + }); + } +}).call(this); diff --git a/node_modules/moment/package.js b/node_modules/moment/package.js new file mode 100644 index 0000000..aba8d50 --- /dev/null +++ b/node_modules/moment/package.js @@ -0,0 +1,11 @@ +var profile = { + resourceTags: { + ignore: function(filename, mid){ + // only include moment/moment + return mid != "moment/moment"; + }, + amd: function(filename, mid){ + return /\.js$/.test(filename); + } + } +}; diff --git a/node_modules/moment/package.json b/node_modules/moment/package.json new file mode 100644 index 0000000..f2a1e36 --- /dev/null +++ b/node_modules/moment/package.json @@ -0,0 +1,73 @@ +{ + "name": "moment", + "version": "2.1.0", + "description": "Parse, manipulate, and display dates.", + "homepage": "http://momentjs.com", + "author": { + "name": "Tim Wood", + "email": "washwithcare@gmail.com", + "url": "http://timwoodcreates.com/" + }, + "contributors": [ + { + "name": "Rocky Meza", + "url": "http://rockymeza.com" + }, + { + "name": "Iskren Ivov Chernev", + "email": "iskren.chernev@gmail.com", + "url": "https://github.com/ichernev" + } + ], + "keywords": [ + "moment", + "date", + "time", + "parse", + "format", + "validate", + "i18n", + "l10n", + "ender" + ], + "main": "./moment.js", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/timrwood/moment.git" + }, + "bugs": { + "url": "https://github.com/timrwood/moment/issues" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "devDependencies": { + "uglify-js": "latest", + "grunt": "latest", + "nodeunit": "latest", + "grunt-contrib-jshint": "latest", + "grunt-contrib-nodeunit": "latest", + "grunt-contrib-concat": "latest", + "grunt-contrib-uglify": "latest", + "grunt-contrib-watch": "latest", + "grunt-lib-legacyhelpers": "latest" + }, + "scripts": { + "test": "grunt" + }, + "ender": "./ender.js", + "dojoBuild": "package.js", + "readme": "A lightweight javascript date library for parsing, validating, manipulating, and formatting dates.\n\n# [Documentation](http://momentjs.com/docs/)\n\nUpgrading to 2.0.0\n==================\n\nThere are a number of small backwards incompatible changes with version 2.0.0.\n\n[See them and their descriptions here](https://gist.github.com/timrwood/e72f2eef320ed9e37c51#backwards-incompatible-changes)\n\nChanged language ordinal method to return the number + ordinal instead of just the ordinal.\n\nChanged two digit year parsing cutoff to match strptime.\n\nRemoved `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.\n\nRemoved `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.\n\nRemoved the lang data objects from the top level namespace.\n\nDuplicate `Date` passed to `moment()` instead of referencing it.\n\nTravis Build Status\n===================\n\nDevelop [![Build Status](https://travis-ci.org/timrwood/moment.png?branch=develop)](https://travis-ci.org/timrwood/moment)\n\nMaster [![Build Status](https://travis-ci.org/timrwood/moment.png)](https://travis-ci.org/timrwood/moment)\n\nChangelog\n=========\n\n### 2.1.0 [See changelog](https://gist.github.com/timrwood/b8c2d90d528eddb53ab5)\n\nAdded better week support.\n\nAdded ability to set offset with `moment#zone`.\n\nAdded ability to set month or weekday from a string.\n\nAdded `moment#min` and `moment#max`\n\n### 2.0.0 [See changelog](https://gist.github.com/timrwood/e72f2eef320ed9e37c51)\n\nAdded short form localized tokens.\n\nAdded ability to define language a string should be parsed in.\n\nAdded support for reversed add/subtract arguments.\n\nAdded support for `endOf('week')` and `startOf('week')`.\n\nFixed the logic for `moment#diff(Moment, 'months')` and `moment#diff(Moment, 'years')`\n\n`moment#diff` now floors instead of rounds.\n\nNormalized `moment#toString`.\n\nAdded `isSame`, `isAfter`, and `isBefore` methods.\n\nAdded better week support.\n\nAdded `moment#toJSON`\n\nBugfix: Fixed parsing of first century dates\n\nBugfix: Parsing 10Sep2001 should work as expected\n\nBugfix: Fixed wierdness with `moment.utc()` parsing.\n\nChanged language ordinal method to return the number + ordinal instead of just the ordinal.\n\nChanged two digit year parsing cutoff to match strptime.\n\nRemoved `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.\n\nRemoved `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.\n\nRemoved the lang data objects from the top level namespace.\n\nDuplicate `Date` passed to `moment()` instead of referencing it.\n\n### 1.7.2 [See discussion](https://github.com/timrwood/moment/issues/456)\n\nBugfixes\n\n### 1.7.1 [See discussion](https://github.com/timrwood/moment/issues/384)\n\nBugfixes\n\n### 1.7.0 [See discussion](https://github.com/timrwood/moment/issues/288)\n\nAdded `moment.fn.endOf()` and `moment.fn.startOf()`.\n\nAdded validation via `moment.fn.isValid()`.\n\nMade formatting method 3x faster. http://jsperf.com/momentjs-cached-format-functions\n\nAdd support for month/weekday callbacks in `moment.fn.format()`\n\nAdded instance specific languages.\n\nAdded two letter weekday abbreviations with the formatting token `dd`.\n\nVarious language updates.\n\nVarious bugfixes.\n\n### 1.6.0 [See discussion](https://github.com/timrwood/moment/pull/268)\n\nAdded Durations.\n\nRevamped parser to support parsing non-separated strings (YYYYMMDD vs YYYY-MM-DD).\n\nAdded support for millisecond parsing and formatting tokens (S SS SSS)\n\nAdded a getter for `moment.lang()`\n\nVarious bugfixes.\n\nThere are a few things deprecated in the 1.6.0 release.\n\n1. The format tokens `z` and `zz` (timezone abbreviations like EST CST MST etc) will no longer be supported. Due to inconsistent browser support, we are unable to consistently produce this value. See [this issue](https://github.com/timrwood/moment/issues/162) for more background.\n\n2. The method `moment.fn.native` is deprecated in favor of `moment.fn.toDate`. There continue to be issues with Google Closure Compiler throwing errors when using `native`, even in valid instances.\n\n3. The way to customize am/pm strings is being changed. This would only affect you if you created a custom language file. For more information, see [this issue](https://github.com/timrwood/moment/pull/222).\n\n### 1.5.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=10&page=1&state=closed)\n\nAdded UTC mode.\n\nAdded automatic ISO8601 parsing.\n\nVarious bugfixes.\n\n### 1.4.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=8&state=closed)\n\nAdded `moment.fn.toDate` as a replacement for `moment.fn.native`.\n\nAdded `moment.fn.sod` and `moment.fn.eod` to get the start and end of day.\n\nVarious bugfixes.\n\n### 1.3.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=7&state=closed)\n\nAdded support for parsing month names in the current language.\n\nAdded escape blocks for parsing tokens.\n\nAdded `moment.fn.calendar` to format strings like 'Today 2:30 PM', 'Tomorrow 1:25 AM', and 'Last Sunday 4:30 AM'.\n\nAdded `moment.fn.day` as a setter.\n\nVarious bugfixes\n\n### 1.2.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=4&state=closed)\n\nAdded timezones to parser and formatter.\n\nAdded `moment.fn.isDST`.\n\nAdded `moment.fn.zone` to get the timezone offset in minutes.\n\n### 1.1.2 [See milestone](https://github.com/timrwood/moment/issues?milestone=6&state=closed)\n\nVarious bugfixes\n\n### 1.1.1 [See milestone](https://github.com/timrwood/moment/issues?milestone=5&state=closed)\n\nAdded time specific diffs (months, days, hours, etc)\n\n### 1.1.0\n\nAdded `moment.fn.format` localized masks. 'L LL LLL LLLL' [issue 29](https://github.com/timrwood/moment/pull/29)\n\nFixed [issue 31](https://github.com/timrwood/moment/pull/31).\n\n### 1.0.1\n\nAdded `moment.version` to get the current version.\n\nRemoved `window !== undefined` when checking if module exists to support browserify. [issue 25](https://github.com/timrwood/moment/pull/25)\n\n### 1.0.0\n\nAdded convenience methods for getting and setting date parts.\n\nAdded better support for `moment.add()`.\n\nAdded better lang support in NodeJS.\n\nRenamed library from underscore.date to Moment.js\n\n### 0.6.1\n\nAdded Portuguese, Italian, and French language support\n\n### 0.6.0\n\nAdded _date.lang() support.\nAdded support for passing multiple formats to try to parse a date. _date(\"07-10-1986\", [\"MM-DD-YYYY\", \"YYYY-MM-DD\"]);\nMade parse from string and single format 25% faster.\n\n### 0.5.2\n\nBugfix for [issue 8](https://github.com/timrwood/underscore.date/pull/8) and [issue 9](https://github.com/timrwood/underscore.date/pull/9).\n\n### 0.5.1\n\nBugfix for [issue 5](https://github.com/timrwood/underscore.date/pull/5).\n\n### 0.5.0\n\nDropped the redundant `_date.date()` in favor of `_date()`.\nRemoved `_date.now()`, as it is a duplicate of `_date()` with no parameters.\nRemoved `_date.isLeapYear(yearNumber)`. Use `_date([yearNumber]).isLeapYear()` instead.\nExposed customization options through the `_date.relativeTime`, `_date.weekdays`, `_date.weekdaysShort`, `_date.months`, `_date.monthsShort`, and `_date.ordinal` variables instead of the `_date.customize()` function.\n\n### 0.4.1\n\nAdded date input formats for input strings.\n\n### 0.4.0\n\nAdded underscore.date to npm. Removed dependencies on underscore.\n\n### 0.3.2\n\nAdded `'z'` and `'zz'` to `_.date().format()`. Cleaned up some redundant code to trim off some bytes.\n\n### 0.3.1\n\nCleaned up the namespace. Moved all date manipulation and display functions to the _.date() object.\n\n### 0.3.0\n\nSwitched to the Underscore methodology of not mucking with the native objects' prototypes.\nMade chaining possible.\n\n### 0.2.1\n\nChanged date names to be a more pseudo standardized 'dddd, MMMM Do YYYY, h:mm:ss a'.\nAdded `Date.prototype` functions `add`, `subtract`, `isdst`, and `isleapyear`.\n\n### 0.2.0\n\nChanged function names to be more concise.\nChanged date format from php date format to custom format.\n\n### 0.1.0\n\nInitial release\n\nLicense\n=======\n\nMoment.js is freely distributable under the terms of the MIT license.\n\nCopyright (c) 2011-2012 Tim Wood\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use,\ncopy, 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n", + "readmeFilename": "readme.md", + "_id": "moment@2.1.0", + "dist": { + "shasum": "0b898042353aaa77ceedc8979b975e7c636dc002" + }, + "_from": "moment@", + "_resolved": "https://registry.npmjs.org/moment/-/moment-2.1.0.tgz" +} diff --git a/node_modules/moment/readme.md b/node_modules/moment/readme.md new file mode 100644 index 0000000..72f6a2a --- /dev/null +++ b/node_modules/moment/readme.md @@ -0,0 +1,269 @@ +A lightweight javascript date library for parsing, validating, manipulating, and formatting dates. + +# [Documentation](http://momentjs.com/docs/) + +Upgrading to 2.0.0 +================== + +There are a number of small backwards incompatible changes with version 2.0.0. + +[See them and their descriptions here](https://gist.github.com/timrwood/e72f2eef320ed9e37c51#backwards-incompatible-changes) + +Changed language ordinal method to return the number + ordinal instead of just the ordinal. + +Changed two digit year parsing cutoff to match strptime. + +Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`. + +Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`. + +Removed the lang data objects from the top level namespace. + +Duplicate `Date` passed to `moment()` instead of referencing it. + +Travis Build Status +=================== + +Develop [![Build Status](https://travis-ci.org/timrwood/moment.png?branch=develop)](https://travis-ci.org/timrwood/moment) + +Master [![Build Status](https://travis-ci.org/timrwood/moment.png)](https://travis-ci.org/timrwood/moment) + +Changelog +========= + +### 2.1.0 [See changelog](https://gist.github.com/timrwood/b8c2d90d528eddb53ab5) + +Added better week support. + +Added ability to set offset with `moment#zone`. + +Added ability to set month or weekday from a string. + +Added `moment#min` and `moment#max` + +### 2.0.0 [See changelog](https://gist.github.com/timrwood/e72f2eef320ed9e37c51) + +Added short form localized tokens. + +Added ability to define language a string should be parsed in. + +Added support for reversed add/subtract arguments. + +Added support for `endOf('week')` and `startOf('week')`. + +Fixed the logic for `moment#diff(Moment, 'months')` and `moment#diff(Moment, 'years')` + +`moment#diff` now floors instead of rounds. + +Normalized `moment#toString`. + +Added `isSame`, `isAfter`, and `isBefore` methods. + +Added better week support. + +Added `moment#toJSON` + +Bugfix: Fixed parsing of first century dates + +Bugfix: Parsing 10Sep2001 should work as expected + +Bugfix: Fixed wierdness with `moment.utc()` parsing. + +Changed language ordinal method to return the number + ordinal instead of just the ordinal. + +Changed two digit year parsing cutoff to match strptime. + +Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`. + +Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`. + +Removed the lang data objects from the top level namespace. + +Duplicate `Date` passed to `moment()` instead of referencing it. + +### 1.7.2 [See discussion](https://github.com/timrwood/moment/issues/456) + +Bugfixes + +### 1.7.1 [See discussion](https://github.com/timrwood/moment/issues/384) + +Bugfixes + +### 1.7.0 [See discussion](https://github.com/timrwood/moment/issues/288) + +Added `moment.fn.endOf()` and `moment.fn.startOf()`. + +Added validation via `moment.fn.isValid()`. + +Made formatting method 3x faster. http://jsperf.com/momentjs-cached-format-functions + +Add support for month/weekday callbacks in `moment.fn.format()` + +Added instance specific languages. + +Added two letter weekday abbreviations with the formatting token `dd`. + +Various language updates. + +Various bugfixes. + +### 1.6.0 [See discussion](https://github.com/timrwood/moment/pull/268) + +Added Durations. + +Revamped parser to support parsing non-separated strings (YYYYMMDD vs YYYY-MM-DD). + +Added support for millisecond parsing and formatting tokens (S SS SSS) + +Added a getter for `moment.lang()` + +Various bugfixes. + +There are a few things deprecated in the 1.6.0 release. + +1. The format tokens `z` and `zz` (timezone abbreviations like EST CST MST etc) will no longer be supported. Due to inconsistent browser support, we are unable to consistently produce this value. See [this issue](https://github.com/timrwood/moment/issues/162) for more background. + +2. The method `moment.fn.native` is deprecated in favor of `moment.fn.toDate`. There continue to be issues with Google Closure Compiler throwing errors when using `native`, even in valid instances. + +3. The way to customize am/pm strings is being changed. This would only affect you if you created a custom language file. For more information, see [this issue](https://github.com/timrwood/moment/pull/222). + +### 1.5.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=10&page=1&state=closed) + +Added UTC mode. + +Added automatic ISO8601 parsing. + +Various bugfixes. + +### 1.4.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=8&state=closed) + +Added `moment.fn.toDate` as a replacement for `moment.fn.native`. + +Added `moment.fn.sod` and `moment.fn.eod` to get the start and end of day. + +Various bugfixes. + +### 1.3.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=7&state=closed) + +Added support for parsing month names in the current language. + +Added escape blocks for parsing tokens. + +Added `moment.fn.calendar` to format strings like 'Today 2:30 PM', 'Tomorrow 1:25 AM', and 'Last Sunday 4:30 AM'. + +Added `moment.fn.day` as a setter. + +Various bugfixes + +### 1.2.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=4&state=closed) + +Added timezones to parser and formatter. + +Added `moment.fn.isDST`. + +Added `moment.fn.zone` to get the timezone offset in minutes. + +### 1.1.2 [See milestone](https://github.com/timrwood/moment/issues?milestone=6&state=closed) + +Various bugfixes + +### 1.1.1 [See milestone](https://github.com/timrwood/moment/issues?milestone=5&state=closed) + +Added time specific diffs (months, days, hours, etc) + +### 1.1.0 + +Added `moment.fn.format` localized masks. 'L LL LLL LLLL' [issue 29](https://github.com/timrwood/moment/pull/29) + +Fixed [issue 31](https://github.com/timrwood/moment/pull/31). + +### 1.0.1 + +Added `moment.version` to get the current version. + +Removed `window !== undefined` when checking if module exists to support browserify. [issue 25](https://github.com/timrwood/moment/pull/25) + +### 1.0.0 + +Added convenience methods for getting and setting date parts. + +Added better support for `moment.add()`. + +Added better lang support in NodeJS. + +Renamed library from underscore.date to Moment.js + +### 0.6.1 + +Added Portuguese, Italian, and French language support + +### 0.6.0 + +Added _date.lang() support. +Added support for passing multiple formats to try to parse a date. _date("07-10-1986", ["MM-DD-YYYY", "YYYY-MM-DD"]); +Made parse from string and single format 25% faster. + +### 0.5.2 + +Bugfix for [issue 8](https://github.com/timrwood/underscore.date/pull/8) and [issue 9](https://github.com/timrwood/underscore.date/pull/9). + +### 0.5.1 + +Bugfix for [issue 5](https://github.com/timrwood/underscore.date/pull/5). + +### 0.5.0 + +Dropped the redundant `_date.date()` in favor of `_date()`. +Removed `_date.now()`, as it is a duplicate of `_date()` with no parameters. +Removed `_date.isLeapYear(yearNumber)`. Use `_date([yearNumber]).isLeapYear()` instead. +Exposed customization options through the `_date.relativeTime`, `_date.weekdays`, `_date.weekdaysShort`, `_date.months`, `_date.monthsShort`, and `_date.ordinal` variables instead of the `_date.customize()` function. + +### 0.4.1 + +Added date input formats for input strings. + +### 0.4.0 + +Added underscore.date to npm. Removed dependencies on underscore. + +### 0.3.2 + +Added `'z'` and `'zz'` to `_.date().format()`. Cleaned up some redundant code to trim off some bytes. + +### 0.3.1 + +Cleaned up the namespace. Moved all date manipulation and display functions to the _.date() object. + +### 0.3.0 + +Switched to the Underscore methodology of not mucking with the native objects' prototypes. +Made chaining possible. + +### 0.2.1 + +Changed date names to be a more pseudo standardized 'dddd, MMMM Do YYYY, h:mm:ss a'. +Added `Date.prototype` functions `add`, `subtract`, `isdst`, and `isleapyear`. + +### 0.2.0 + +Changed function names to be more concise. +Changed date format from php date format to custom format. + +### 0.1.0 + +Initial release + +License +======= + +Moment.js is freely distributable under the terms of the MIT license. + +Copyright (c) 2011-2012 Tim Wood + +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/moment/tasks/concat-lang.js b/node_modules/moment/tasks/concat-lang.js new file mode 100644 index 0000000..c7c12d8 --- /dev/null +++ b/node_modules/moment/tasks/concat-lang.js @@ -0,0 +1,47 @@ +/*jshint onevar:false*/ + +module.exports = function (grunt) { + + var helpers = require('grunt-lib-legacyhelpers').init(grunt); + var START = "(function(){\n"; + var END = "})();\n"; + + var GLOBAL_START = [ + "(function(){", + " function onload (moment) {", + "" + ].join('\n'); + + var GLOBAL_RESET = "\nmoment.lang('en');\n"; + + var GLOBAL_END = [ + "", + " }", + " if (typeof define === \"function\" && define.amd) {", + " define([\"moment\"], onload);", + " }", + " if (typeof window !== \"undefined\" && window.moment) {", + " onload(window.moment);", + " }", + "})();", + "" + ].join('\n'); + + grunt.registerMultiTask('concatlang', 'Concatenate files.', function() { + var files = grunt.file.expand(this.data.src); + // Concat specified files. + var src = helpers.concat(files, {separator: END + START}); + grunt.file.write(this.data.dest, wrapFile(src)); + + // Fail task if errors were logged. + if (this.errorCount) { return false; } + + // Otherwise, print a success message. + grunt.log.writeln('File "' + this.data.dest + '" created.'); + }); + + function wrapFile(code) { + code = code.replace(/require\([\'\"]\.\.\/moment[\'\"]\)/g, "moment"); + return GLOBAL_START + START + code + END + GLOBAL_RESET + GLOBAL_END; + } +}; diff --git a/node_modules/moment/tasks/history.js b/node_modules/moment/tasks/history.js new file mode 100644 index 0000000..251519c --- /dev/null +++ b/node_modules/moment/tasks/history.js @@ -0,0 +1,123 @@ +var https = require("https"), + zlib = require('zlib'), + path = require('path'), + fs = require('fs'); + +var count = 0; +var resolved = 0; + +var outputs = []; + +var done; + +function check() { + if (resolved === count) { + normalize(); + display(); + } +} + +function makeBar(length) { + var i = ''; + while (i.length < length) { + i += '='; + } + return i; +} + +function normalize() { + var i, + max = 0, + max2 = 0; + for (i = 0; i < count; i ++) { + max = Math.max(max, outputs[i].gzip); + max2 = Math.max(max2, outputs[i].original); + } + for (i = 0; i < count; i ++) { + outputs[i].bargraph = makeBar((outputs[i].gzip / max) * 80); + outputs[i].bargraph2 = makeBar((outputs[i].original / max2) * 80); + } +} + +function display() { + var i; + for (i = 0; i < count; i ++) { + console.log(outputs[i].version + ' ' + outputs[i].gzip + ' ' + outputs[i].original); + console.log('gzip ' + outputs[i].bargraph); + console.log('orig ' + outputs[i].bargraph2); + } + done(); +} + +function getSizeAtVersion(version, path) { + var data = '', + op = {}, + + req = https.request({ + host: 'raw.github.com', + port: 443, + path: '/timrwood/moment/' + version + path + }, function (res) { + res.setEncoding('utf8'); + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function (e) { + zlib.gzip(data, function (error, result) { + op.version = version; + op.gzip = result.length; + op.original = data.length; + resolved ++; + check(); + }); + }); + }); + + req.on('error', function (e) { + console.log('problem with request: ' + e.message); + }); + req.end(); + count++; + outputs.push(op); +} + +function getRemote() { + var old_versions = '1.0.1 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.4.0'.split(' '), + new_versions = '1.5.0 1.5.1 1.6.0 1.6.1 1.7.0 1.7.1'.split(' '), + i; + + for (i = 0; i < old_versions.length; i++) { + getSizeAtVersion(old_versions[i], '/moment.min.js'); + } + for (i = 0; i < new_versions.length; i++) { + getSizeAtVersion(new_versions[i], '/min/moment.min.js'); + } +} + +function getLocal() { + count ++; + var op = {}; + outputs.push(op); + fs.readFile(path.normalize(__dirname + '/../min/moment.min.js'), 'utf8', function (err, data) { + if (err) { + throw err; + } + zlib.gzip(data, function (error, result) { + op.version = '.next'; + op.gzip = result.length; + op.original = data.length; + resolved ++; + check(); + }); + }); +} + + + +module.exports = function (grunt) { + grunt.registerTask('history', 'Check the codebase filesize over different releases.', function () { + done = this.async(); + getRemote(); + getLocal(); + }); +}; \ No newline at end of file diff --git a/node_modules/moment/tasks/minify-lang.js b/node_modules/moment/tasks/minify-lang.js new file mode 100644 index 0000000..e22b748 --- /dev/null +++ b/node_modules/moment/tasks/minify-lang.js @@ -0,0 +1,82 @@ +/*jshint onevar:false*/ + +var fs = require('fs'), + uglifyjs = require('uglify-js'); + + +module.exports = function (grunt) { + + var helpers = require('grunt-lib-legacyhelpers').init(grunt); + + var START = [ + "(function(){", + " function onload (moment) {", + "" + ].join('\n'); + + var END = [ + "", + " }", + " if (typeof define === \"function\" && define.amd) {", + " define([\"moment\"], onload);", + " }", + " if (typeof window !== \"undefined\" && window.moment) {", + " onload(window.moment);", + " }", + "})()", + "" + ].join('\n'); + + // UglifyJS does not support keeping the first line comments unless using the CLI. + // This multi-task ensures that the first comments are kept. + grunt.registerMultiTask('minlang', 'Minify lang files with UglifyJS.', function () { + var files = grunt.file.expand(this.data.src), + min, + code, + comments, + tok, + result; + + // Concat specified files. This should really be a single, pre-built (and + // linted) file, but it supports any number of files. + code = helpers.concat(files, {separator: this.data.separator}); + + // Add the first comments + //tok = uglifyjs.parse(code); + tok = uglifyjs.parse(code); + min = showCopyright(tok.start.comments_before); + + // Add the minified source. + result = uglifyjs.minify(wrapFile(code), grunt.config('uglify.options')); + min += result.code; + grunt.file.write(this.data.dest, min); + + // Fail task if errors were logged. + if (this.errorCount) { return false; } + + // Otherwise, print a success message.... + grunt.log.writeln('File "' + this.data.dest + '" created.'); + + // ...and report some size information. + helpers.min_max_info(min, code); + }); + + // Helper for the 'mincomment' multitask + function showCopyright(comments) { + var ret = "", i, c; + for (i = 0; i < comments.length; ++i) { + c = comments[i]; + if (c.type === "comment1") { + ret += "//" + c.value + "\n"; + } else { + ret += "/*" + c.value + "*/"; + } + } + return ret; + } + + function wrapFile(code) { + code = code.replace(/require\([\'\"]\.\.\/moment[\'\"]\)/g, "moment"); + return START + code + END; + } +}; diff --git a/node_modules/moment/tasks/minify.js b/node_modules/moment/tasks/minify.js new file mode 100644 index 0000000..c8ff9c8 --- /dev/null +++ b/node_modules/moment/tasks/minify.js @@ -0,0 +1,57 @@ +/*jshint onevar:false*/ + +var fs = require('fs'), + uglifyjs = require('uglify-js'); + + +module.exports = function (grunt) { + + var helpers = require('grunt-lib-legacyhelpers').init(grunt); + + // UglifyJS does not support keeping the first line comments unless using the CLI. + // This multi-task ensures that the first comments are kept. + grunt.registerMultiTask('minwithcomments', 'Minify lang files with UglifyJS.', function () { + var files = grunt.file.expand(this.data.src), + min, + code, + comments, + tok, + result; + + // Concat specified files. This should really be a single, pre-built (and + // linted) file, but it supports any number of files. + code = helpers.concat(files, {separator: this.data.separator}); + + // Add the first comments + tok = uglifyjs.parse(code); + min = showCopyright(tok.start.comments_before); + + // Add the minified source. + result = uglifyjs.minify(code, grunt.config('uglify.options')); + min += result.code; + grunt.file.write(this.data.dest, min); + + // Fail task if errors were logged. + if (this.errorCount) { return false; } + + // Otherwise, print a success message.... + grunt.log.writeln('File "' + this.data.dest + '" created.'); + + // ...and report some size information. + helpers.min_max_info(min, code); + }); + + // Helper for the 'mincomment' multitask + function showCopyright(comments) { + var ret = "", i, c; + for (i = 0; i < comments.length; ++i) { + c = comments[i]; + if (c.type === "comment1") { + ret += "//" + c.value + "\n"; + } else { + ret += "/*" + c.value + "*/"; + } + } + return ret; + } +}; diff --git a/node_modules/moment/tasks/size.js b/node_modules/moment/tasks/size.js new file mode 100644 index 0000000..e465e25 --- /dev/null +++ b/node_modules/moment/tasks/size.js @@ -0,0 +1,60 @@ +var https = require("https"), + zlib = require('zlib'), + path = require('path'), + fs = require('fs'); + +var stable = '1.7.1', + done; + +function getVersion(path, cb) { + var data = '', + + req = https.request({ + host: 'raw.github.com', + port: 443, + path: '/timrwood/moment/' + path + }, function (res) { + res.setEncoding('utf8'); + res.on('data', function (chunk) { + data += chunk; + }); + res.on('end', function (e) { + zlib.gzip(data, function (error, result) { + cb(data.length, result.length); + }); + }); + }); + req.on('error', function (e) { + console.log('problem with request: ' + e.message); + }); + req.end(); +} + +function printDiffs(stableLen, stableGzip, currentLen, currentGzip) { + var diff = currentLen - stableLen, + gzipDiff = currentGzip - stableGzip; + + console.log("Filesize difference from current branch to " + stable); + console.log(stable + " " + stableLen + ' / ' + stableGzip); + console.log("curr " + currentLen + ' / ' + currentGzip); + console.log("diff " + (diff > 0 ? '+' : '') + diff); + console.log("gzip " + (gzipDiff > 0 ? '+' : '') + gzipDiff); +} + + +module.exports = function (grunt) { + grunt.registerTask('size', 'Check the codebase filesize against the latest stable version.', function () { + done = this.async(); + fs.readFile(path.normalize(__dirname + '/../min/moment.min.js'), 'utf8', function (err, data) { + if (err) { + throw err; + } + zlib.gzip(data, function (error, result) { + getVersion(stable + '/min/moment.min.js', function (stableLength, stableGzipLength) { + printDiffs(stableLength, stableGzipLength, data.length, result.length); + done(); + }); + }); + }); + }); +}; \ No newline at end of file diff --git a/node_modules/moment/tasks/zone.js b/node_modules/moment/tasks/zone.js new file mode 100644 index 0000000..6ffe7bc --- /dev/null +++ b/node_modules/moment/tasks/zone.js @@ -0,0 +1,123 @@ +var path = require('path'), + nodeunit = require('nodeunit'), + moment = require('../moment'); + + +module.exports = function (grunt) { + // placeholder for an array of timezones + var ALL_ZONES, + INITIAL_ZONE, + + failedZones = [], + failedTests = [], + + logTableWidths = [4, 6, 46, 12, 12], + + failedZoneCount = 0, + passedZoneCount = 0; + + /****************************** + Grunt task + ******************************/ + + grunt.registerTask('zone', 'Run the unit tests in the current timezone.', function () { + var done = this.async(); + getCurrentTimezone(function (zone) { + testZone(zone, function() { + logFinalOutput(); + done(); + }); + }); + }); + + /****************************** + Timezones + ******************************/ + + function getCurrentTimezone(cb) { + grunt.util.spawn({ + cmd: "systemsetup", + args: ["gettimezone"] + }, function (err, result, code) { + cb(result.stdout.replace('Time Zone: ', '')); + }); + } + + /****************************** + Tests + ******************************/ + + function testZone(zone, cb) { + nodeunit.runFiles([path.join(process.cwd(), "test/moment"), path.join(process.cwd(), "test/lang")], { + testDone: function (name, assertions) { + if (assertions.failures()) { + failedTests.push([zone, name, assertions]); + } + }, + done: function (assertions) { + logZone(zone, assertions); + cb(); + } + }); + } + + /****************************** + Logging + ******************************/ + + function setupLoggingTable() { + var i, + longestZone = 0; + for (i = 0; i < ALL_ZONES.length; i++) { + longestZone = Math.max(longestZone, ALL_ZONES[i].length + 2); + } + logTableWidths[1] = longestZone; + grunt.log.writetableln(logTableWidths, ['', 'Zone', 'Offset', 'Pass', 'Fail']); + } + + function logFailedTest(zone, name, assertions) { + grunt.log.writeln(""); + grunt.log.error(zone + ' failed: ' + name); + assertions.forEach(function (a) { + var e = a.error; + if (a.failed()) { + if (a.message) { + grunt.log.error(a.message); + } + if (e && e.actual && e.expected && e.operator) { + grunt.log.error([e.actual, e.operator, e.expected].join(' ')); + } + } + }); + } + + function logZone(zone, assertions) { + var failed = assertions.failures(), + passed = assertions.length - failed, + status = failed ? "XX".red : "OK".green, + passMsg = passed + ' passed', + failMsg = failed ? (failed + ' failed').red : failed + ' failed', + offset = "" + (-moment().zone() / 60); + + grunt.log.writetableln(logTableWidths, [status, offset, zone, passMsg, failMsg]); + + if (failed) { + failedZoneCount++; + } else { + passedZoneCount++; + } + } + + function logFinalOutput() { + var i; + + if (!failedZoneCount) { + return; + } + + grunt.log.writeln(failedZoneCount + " failures"); + for (i = 0; i < failedTests.length; i++) { + logFailedTest.apply(null, failedTests[i]); + } + } +}; diff --git a/node_modules/moment/tasks/zones.js b/node_modules/moment/tasks/zones.js new file mode 100644 index 0000000..23148b3 --- /dev/null +++ b/node_modules/moment/tasks/zones.js @@ -0,0 +1,104 @@ +var path = require('path'), + nodeunit = require('nodeunit'), + moment = require('../moment'); + + +module.exports = function (grunt) { + // placeholder for an array of timezones + var ALL_ZONES, + INITIAL_ZONE, + + done; + + /****************************** + Grunt task + ******************************/ + + grunt.registerTask('zones', 'Run the unit tests in different timezones.', function () { + done = this.async(); + getCurrentTimezone(function (zone) { + // save the initial timezone so we dont break our computers + INITIAL_ZONE = zone; + getAllTimezones(function (zones) { + // store all the timezones + ALL_ZONES = zones; + // start running the tests + nextTest(function () { + // reset the timezone like nothing ever happened + resetTimezone(); + }); + }); + }); + }); + + /****************************** + Timezones + ******************************/ + + function resetTimezone() { + setTimezone(INITIAL_ZONE, function () { + grunt.log.writeln("Resetting timezone back to " + INITIAL_ZONE); + done(); + }); + } + + function getCurrentTimezone(cb) { + grunt.util.spawn({ + cmd: "systemsetup", + args: ["gettimezone"] + }, function (err, result, code) { + cb(result.stdout.replace('Time Zone: ', '')); + }); + } + + function getAllTimezones(cb) { + grunt.util.spawn({ + cmd: "systemsetup", + args: ["listtimezones"] + }, function (err, result, code) { + var zones = result.stdout.replace('Time Zones:', ''); + zones = zones.match(/\S+/g); + cb(zones); + }); + } + + function setTimezone(zone, cb) { + grunt.util.spawn({ + cmd: "systemsetup", + args: ["settimezone", zone] + }, function (err, result, code) { + cb(); + }); + } + + /****************************** + Tests + ******************************/ + + function nextTest(cb) { + var zone = ALL_ZONES.pop(); + if (zone) { + setTimezone(zone, function () { + testZone(zone, function () { + nextTest(cb); + }); + }); + } else { + cb(); + } + } + + function testZone(zone, cb) { + grunt.util.spawn({ + cmd: "grunt", + args: ["zone"] + }, function (err, result, code) { + if (err) { + resetTimezone(); + throw err; + } + console.log(result.stdout); + cb(); + }); + } +}; diff --git a/node_modules/moment/test/lang/ar-ma.js b/node_modules/moment/test/lang/ar-ma.js new file mode 100644 index 0000000..3afd38d --- /dev/null +++ b/node_modules/moment/test/lang/ar-ma.js @@ -0,0 +1,349 @@ +// moment.js Moroccan arabic (ar-ma) tests +// author: Abdel Said : https://github.com/abdelsaid +var moment = require("../../moment"); + +exports["lang:ar-ma"] = { + setUp : function (cb) { + moment.lang('ar-ma'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'يناير:يناير_فبراير:فبراير_مارس:مارس_أبريل:أبريل_ماي:ماي_يونيو:يونيو_يوليوز:يوليوز_غشت:غشت_شتنبر:شتنبر_أكتوبر:أكتوبر_نونبر:نونبر_دجنبر:دجنبر'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(':'); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'الأحد, فبراير 14 2010, 3:25:50 pm'], + ['ddd, hA', 'احد, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 فبراير فبراير'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 الأحد احد ح'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 فبراير 2010'], + ['LLL', '14 فبراير 2010 15:25'], + ['LLLL', 'الأحد 14 فبراير 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 فبراير 2010'], + ['lll', '14 فبراير 2010 15:25'], + ['llll', 'احد 14 فبراير 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'يناير يناير_فبراير فبراير_مارس مارس_أبريل أبريل_ماي ماي_يونيو يونيو_يوليوز يوليوز_غشت غشت_شتنبر شتنبر_أكتوبر أكتوبر_نونبر نونبر_دجنبر دجنبر'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'الأحد احد ح_الإتنين اتنين ن_الثلاثاء ثلاثاء ث_الأربعاء اربعاء ر_الخميس خميس خ_الجمعة جمعة ج_السبت سبت س'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "ثوان", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "دقيقة", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "دقيقة", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 دقائق", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 دقائق", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "ساعة", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "ساعة", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ساعات", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ساعات", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ساعات", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "يوم", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "يوم", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 أيام", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "يوم", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 أيام", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 أيام", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "شهر", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "شهر", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "شهر", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 أشهر", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 أشهر", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 أشهر", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "شهر", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 أشهر", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 أشهر", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "سنة", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "سنة", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 سنوات", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "سنة", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 سنوات", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "في ثوان", "prefix"); + test.equal(moment(0).from(30000), "منذ ثوان", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "منذ ثوان", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "في ثوان", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "في 5 أيام", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "اليوم على الساعة 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "اليوم على الساعة 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "اليوم على الساعة 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "غدا على الساعة 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "اليوم على الساعة 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "أمس على الساعة 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + + // Saturday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).week(), 1, "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).week(), 1, "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 2, "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).week(), 2, "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 3, "Jan 14 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2006, 11, 30]).week(), 1, "Dec 30 2006 should be week 1"); + test.equal(moment([2007, 0, 5]).week(), 1, "Jan 5 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 2, "Jan 6 2007 should be week 2"); + test.equal(moment([2007, 0, 12]).week(), 2, "Jan 12 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 3, "Jan 13 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 29]).week(), 1, "Dec 29 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 4]).week(), 1, "Jan 4 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 2, "Jan 5 2008 should be week 2"); + test.equal(moment([2008, 0, 11]).week(), 2, "Jan 11 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 3, "Jan 12 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 28]).week(), 1, "Dec 28 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 3]).week(), 1, "Jan 3 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 2, "Jan 4 2003 should be week 2"); + test.equal(moment([2003, 0, 10]).week(), 2, "Jan 10 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 3, "Jan 11 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 27]).week(), 1, "Dec 27 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 2]).week(), 1, "Jan 2 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 2, "Jan 3 2009 should be week 2"); + test.equal(moment([2009, 0, 9]).week(), 2, "Jan 9 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 3, "Jan 10 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(5); + + test.equal(moment([2009, 11, 26]).week(), 1, "Dec 26 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 2, "Jan 2 2010 should be week 2"); + test.equal(moment([2010, 0, 8]).week(), 2, "Jan 8 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 3, "Jan 9 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 7]).week(), 1, "Jan 7 2011 should be week 1"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 14]).week(), 2, "Jan 14 2011 should be week 2"); + test.equal(moment([2011, 0, 15]).week(), 3, "Jan 15 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', "Jan 14 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ar.js b/node_modules/moment/test/lang/ar.js new file mode 100644 index 0000000..d18c848 --- /dev/null +++ b/node_modules/moment/test/lang/ar.js @@ -0,0 +1,349 @@ +// moment.js arabic (ar) tests +// author: Abdel Said : https://github.com/abdelsaid +var moment = require("../../moment"); + +exports["lang:ar"] = { + setUp : function (cb) { + moment.lang('ar'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'يناير/ كانون الثاني:يناير/ كانون الثاني_فبراير/ شباط:فبراير/ شباط_مارس/ آذار:مارس/ آذار_أبريل/ نيسان:أبريل/ نيسان_مايو/ أيار:مايو/ أيار_يونيو/ حزيران:يونيو/ حزيران_يوليو/ تموز:يوليو/ تموز_أغسطس/ آب:أغسطس/ آب_سبتمبر/ أيلول:سبتمبر/ أيلول_أكتوبر/ تشرين الأول:أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني:نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول:ديسمبر/ كانون الأول'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1) + ' instead is month ' + moment(input, mmm).month()); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(':'); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'الأحد, فبراير/ شباط 14 2010, 3:25:50 pm'], + ['ddd, hA', 'الأحد, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 فبراير/ شباط فبراير/ شباط'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 الأحد الأحد ح'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 فبراير/ شباط 2010'], + ['LLL', '14 فبراير/ شباط 2010 15:25'], + ['LLLL', 'الأحد 14 فبراير/ شباط 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 فبراير/ شباط 2010'], + ['lll', '14 فبراير/ شباط 2010 15:25'], + ['llll', 'الأحد 14 فبراير/ شباط 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'يناير/ كانون الثاني يناير/ كانون الثاني_فبراير/ شباط فبراير/ شباط_مارس/ آذار مارس/ آذار_أبريل/ نيسان أبريل/ نيسان_مايو/ أيار مايو/ أيار_يونيو/ حزيران يونيو/ حزيران_يوليو/ تموز يوليو/ تموز_أغسطس/ آب أغسطس/ آب_سبتمبر/ أيلول سبتمبر/ أيلول_أكتوبر/ تشرين الأول أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول ديسمبر/ كانون الأول'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'الأحد الأحد ح_الإثنين الإثنين ن_الثلاثاء الثلاثاء ث_الأربعاء الأربعاء ر_الخميس الخميس خ_الجمعة الجمعة ج_السبت السبت س'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "ثوان", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "دقيقة", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "دقيقة", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 دقائق", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 دقائق", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "ساعة", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "ساعة", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ساعات", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ساعات", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ساعات", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "يوم", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "يوم", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 أيام", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "يوم", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 أيام", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 أيام", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "شهر", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "شهر", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "شهر", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 أشهر", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 أشهر", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 أشهر", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "شهر", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 أشهر", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 أشهر", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "سنة", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "سنة", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 سنوات", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "سنة", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 سنوات", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "في ثوان", "prefix"); + test.equal(moment(0).from(30000), "منذ ثوان", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "منذ ثوان", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "في ثوان", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "في 5 أيام", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "اليوم على الساعة 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "اليوم على الساعة 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "اليوم على الساعة 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "غدا على الساعة 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "اليوم على الساعة 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "أمس على الساعة 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [على الساعة] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + + // Saturday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).week(), 1, "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).week(), 1, "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 2, "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).week(), 2, "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 3, "Jan 14 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2006, 11, 30]).week(), 1, "Dec 30 2006 should be week 1"); + test.equal(moment([2007, 0, 5]).week(), 1, "Jan 5 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 2, "Jan 6 2007 should be week 2"); + test.equal(moment([2007, 0, 12]).week(), 2, "Jan 12 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 3, "Jan 13 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 29]).week(), 1, "Dec 29 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 4]).week(), 1, "Jan 4 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 2, "Jan 5 2008 should be week 2"); + test.equal(moment([2008, 0, 11]).week(), 2, "Jan 11 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 3, "Jan 12 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 28]).week(), 1, "Dec 28 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 3]).week(), 1, "Jan 3 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 2, "Jan 4 2003 should be week 2"); + test.equal(moment([2003, 0, 10]).week(), 2, "Jan 10 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 3, "Jan 11 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 27]).week(), 1, "Dec 27 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 2]).week(), 1, "Jan 2 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 2, "Jan 3 2009 should be week 2"); + test.equal(moment([2009, 0, 9]).week(), 2, "Jan 9 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 3, "Jan 10 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(5); + + test.equal(moment([2009, 11, 26]).week(), 1, "Dec 26 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 2, "Jan 2 2010 should be week 2"); + test.equal(moment([2010, 0, 8]).week(), 2, "Jan 8 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 3, "Jan 9 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 7]).week(), 1, "Jan 7 2011 should be week 1"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 14]).week(), 2, "Jan 14 2011 should be week 2"); + test.equal(moment([2011, 0, 15]).week(), 3, "Jan 15 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', "Jan 14 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/bg.js b/node_modules/moment/test/lang/bg.js new file mode 100644 index 0000000..7b4b993 --- /dev/null +++ b/node_modules/moment/test/lang/bg.js @@ -0,0 +1,370 @@ +var moment = require("../../moment"); + + + /************************************************** + Bulgarian + *************************************************/ + +exports["lang:bg"] = { + setUp : function (cb) { + moment.lang('bg'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'януари янр_февруари фев_март мар_април апр_май май_юни юни_юли юли_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'неделя, февруари 14-ти 2010, 3:25:50 pm'], + ['ddd, hA', 'нед, 3PM'], + ['M Mo MM MMMM MMM', '2 2-ри 02 февруари фев'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-ти 14'], + ['d do dddd ddd dd', '0 0-ев неделя нед нд'], + ['DDD DDDo DDDD', '45 45-ти 045'], + ['w wo ww', '7 7-ми 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45-ти day of the year'], + ['L', '14.02.2010'], + ['LL', '14 февруари 2010'], + ['LLL', '14 февруари 2010 3:25'], + ['LLLL', 'неделя, 14 февруари 2010 3:25'], + ['l', '14.2.2010'], + ['ll', '14 фев 2010'], + ['lll', '14 фев 2010 3:25'], + ['llll', 'нед, 14 фев 2010 3:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1-ви', '1-ви'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2-ри', '2-ри'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3-ти', '3-ти'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4-ти', '4-ти'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5-ти', '5-ти'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6-ти', '6-ти'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7-ми', '7-ми'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8-ми', '8-ми'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9-ти', '9-ти'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10-ти', '10-ти'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11-ти', '11-ти'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12-ти', '12-ти'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13-ти', '13-ти'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14-ти', '14-ти'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15-ти', '15-ти'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16-ти', '16-ти'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17-ти', '17-ти'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18-ти', '18-ти'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19-ти', '19-ти'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20-ти', '20-ти'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21-ви', '21-ви'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22-ри', '22-ри'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23-ти', '23-ти'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24-ти', '24-ти'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25-ти', '25-ти'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26-ти', '26-ти'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27-ми', '27-ми'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28-ми', '28-ми'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29-ти', '29-ти'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30-ти', '30-ти'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31-ви', '31-ви'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'януари янр_февруари фев_март мар_април апр_май май_юни юни_юли юли_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'неделя нед нд_понеделник пон пн_вторник вто вт_сряда сря ср_четвъртък чет чт_петък пет пт_събота съб сб'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "няколко секунди", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "минута", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "минута", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 минути", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 минути", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "час", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "час", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 часа", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 часа", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 часа", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "ден", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "ден", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 дни", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "ден", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 дни", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 дни", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "месец", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "месец", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "месец", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 месеца", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 месеца", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 месеца", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "месец", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 месеца", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 месеца", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "година", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "година", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 години", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "година", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 години", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "след няколко секунди", "prefix"); + test.equal(moment(0).from(30000), "преди няколко секунди", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "преди няколко секунди", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "след няколко секунди", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "след 5 дни", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Днес в 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Днес в 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Днес в 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Утре в 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Днес в 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Вчера в 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [в] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [в] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [в] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ви', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ви', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-ри', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-ри', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-ти', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/br.js b/node_modules/moment/test/lang/br.js new file mode 100644 index 0000000..14c619e --- /dev/null +++ b/node_modules/moment/test/lang/br.js @@ -0,0 +1,275 @@ +var moment = require("../../moment"); + + + /************************************************** + Breton + *************************************************/ + +exports["lang:br"] = { + setUp : function (cb) { + moment.lang('br'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('br'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = "Genver Gen_C'hwevrer C'hwe_Meurzh Meu_Ebrel Ebr_Mae Mae_Mezheven Eve_Gouere Gou_Eost Eos_Gwengolo Gwe_Here Her_Du Du_Kerzu Ker".split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + } , + + "format" : function(test) { + test.expect(17); + moment.lang('br'); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', "Sul, C'hwevrer 14vet 2010, 3:25:50 pm"], + ['ddd, h A', 'Sul, 3 PM'], + ['M Mo MM MMMM MMM', "2 2vet 02 C'hwevrer C'hwe"], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14vet 14'], + ['d do dddd ddd dd', '0 0vet Sul Sul Su'], + ['DDD DDDo DDDD', '45 45vet 045'], + ['w wo ww', '6 6vet 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['DDDo [devezh] [ar] [vloaz]', '45vet devezh ar vloaz'], + ['L', '14/02/2010'], + ['LL', "14 a viz C'hwevrer 2010"], + ['LLL', "14 a viz C'hwevrer 2010 3e25 PM"], + ['LLLL', "Sul, 14 a viz C'hwevrer 2010 3e25 PM"] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + moment.lang('br'); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1añ', '1añ'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2vet', '2vet'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3vet', '3vet'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4vet', '4vet'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5vet', '5vet'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6vet', '6vet'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7vet', '7vet'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8vet', '8vet'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9vet', '9vet'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10vet', '10vet'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11vet', '11vet'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12vet', '12vet'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13vet', '13vet'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14vet', '14vet'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15vet', '15vet'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16vet', '16vet'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17vet', '17vet'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18vet', '18vet'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19vet', '19vet'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20vet', '20vet'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21vet', '21vet'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22vet', '22vet'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23vet', '23vet'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24vet', '24vet'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25vet', '25vet'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26vet', '26vet'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27vet', '27vet'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28vet', '28vet'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29vet', '29vet'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30vet', '30vet'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31vet', '31vet'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + moment.lang('br'); + var expected = "Genver Gen_C'hwevrer C'hwe_Meurzh Meu_Ebrel Ebr_Mae Mae_Mezheven Eve_Gouere Gou_Eost Eos_Gwengolo Gwe_Here Her_Du Du_Kerzu Ker".split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + moment.lang('br'); + var expected = "Sul Sul Su_Lun Lun Lu_Meurzh Meu Me_Merc'her Mer Mer_Yaou Yao Ya_Gwener Gwe Gw_Sadorn Sad Sa".split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + moment.lang('br'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "un nebeud segondennoù", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ur vunutenn", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ur vunutenn", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 vunutenn", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 munutenn", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "un eur", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "un eur", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 eur", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 eur", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 eur", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un devezh", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un devezh", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 zevezh", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un devezh", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 devezh", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 devezh", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "ur miz", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "ur miz", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "ur miz", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 viz", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 viz", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 miz", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "ur miz", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 miz", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 miz", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ur bloaz", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ur bloaz", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 vloaz", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ur bloaz", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 bloaz", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + moment.lang('br'); + test.equal(moment(30000).from(0), "a-benn un nebeud segondennoù", "prefix"); + test.equal(moment(0).from(30000), "un nebeud segondennoù 'zo", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + moment.lang('br'); + test.equal(moment().fromNow(), "un nebeud segondennoù 'zo", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + moment.lang('br'); + test.equal(moment().add({s:30}).fromNow(), "a-benn un nebeud segondennoù", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "a-benn 5 devezh", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + moment.lang('br'); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hiziv da 2e00 AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hiziv da 2e25 AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hiziv da 3e00 AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Warc'hoazh da 2e00 AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hiziv da 1e00 AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Dec'h da 2e00 AM", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + moment.lang('br'); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [da] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [da] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [da] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + moment.lang('br'); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [paset da] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [paset da] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [paset da] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + moment.lang('br'); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "special mutations for years": function (test) { + test.expect(12); + moment.lang('br'); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), "ur bloaz", "mutation 1 year"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 2}), true), "2 vloaz", "mutation 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 3}), true), "3 bloaz", "mutation 3 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 4}), true), "4 bloaz", "mutation 4 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), "5 bloaz", "mutation 5 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 9}), true), "9 bloaz", "mutation 9 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 10}), true), "10 vloaz", "mutation 10 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 21}), true), "21 bloaz", "mutation 21 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 22}), true), "22 vloaz", "mutation 22 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 133}), true), "133 bloaz", "mutation 133 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 148}), true), "148 vloaz", "mutation 148 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y: 261}), true), "261 bloaz", "mutation 261 years"); + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ca.js b/node_modules/moment/test/lang/ca.js new file mode 100644 index 0000000..6c02a7f --- /dev/null +++ b/node_modules/moment/test/lang/ca.js @@ -0,0 +1,327 @@ +var moment = require("../../moment"); + + + /************************************************** + Català + *************************************************/ + +exports["lang:ca"] = { + setUp : function (cb) { + moment.lang('ca'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = "Gener Gen._Febrer Febr._Març Mar._Abril Abr._Maig Mai._Juny Jun._Juliol Jul._Agost Ag._Setembre Set._Octubre Oct._Novembre Nov._Desembre Des.".split("_"); + + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = "Gener Gen._Febrer Febr._Març Mar._Abril Abr._Maig Mai._Juny Jun._Juliol Jul._Agost Ag._Setembre Set._Octubre Oct._Novembre Nov._Desembre Des.".split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = "Diumenge Dg. Dg_Dilluns Dl. Dl_Dimarts Dt. Dt_Dimecres Dc. Dc_Dijous Dj. Dj_Divendres Dv. Dv_Dissabte Ds. Ds".split("_"); + + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "uns segons", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuts", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuts", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "una hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "una hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hores", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hores", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hores", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un dia", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un dia", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dies", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un dia", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dies", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dies", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mes", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mes", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mes", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mesos", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mesos", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mesos", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mes", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mesos", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mesos", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un any", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un any", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anys", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un any", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anys", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "en uns segons", "prefix"); + test.equal(moment(0).from(30000), "fa uns segons", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "fa uns segons", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "en uns segons", "en uns segons"); + test.equal(moment().add({d:5}).fromNow(), "en 5 dies", "en 5 dies"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "avui a les 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "avui a les 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "avui a les 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "demà a les 2:00", "tomorrow at the same time"); + test.equal(moment(a).add({ d: 1, h : -1 }).calendar(), "demà a la 1:00", "tomorrow minus 1 hour"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "avui a la 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "ahir a les 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/cs.js b/node_modules/moment/test/lang/cs.js new file mode 100644 index 0000000..35cb43e --- /dev/null +++ b/node_modules/moment/test/lang/cs.js @@ -0,0 +1,413 @@ +var moment = require("../../moment"); + + + /************************************************** + Czech + *************************************************/ + +exports["lang:cs"] = { + setUp : function (cb) { + moment.lang('cs'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'leden led_únor úno_březen bře_duben dub_květen kvě_červen čvn_červenec čvc_srpen srp_září zář_říjen říj_listopad lis_prosinec pro'.split("_"); + function equalTest(input, mmm, monthIndex) { + test.equal(moment(input, mmm).month(), monthIndex, input + ' should be month ' + (monthIndex + 1)); + } + for (var i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss', 'neděle, únor 14. 2010, 3:25:50'], + ['ddd, h', 'ne, 3'], + ['M Mo MM MMMM MMM', '2 2. 02 únor úno'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. neděle ne ne'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['DDDo [den v roce]', '45. den v roce'], + ['L', '14.02.2010'], + ['LL', '14. únor 2010'], + ['LLL', '14. únor 2010 15:25'], + ['LLLL', 'neděle 14. únor 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14. úno 2010'], + ['lll', '14. úno 2010 15:25'], + ['llll', 'ne 14. úno 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'leden led_únor úno_březen bře_duben dub_květen kvě_červen čvn_červenec čvc_srpen srp_září zář_říjen říj_listopad lis_prosinec pro'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'neděle ne ne_pondělí po po_úterý út út_středa st st_čtvrtek čt čt_pátek pá pá_sobota so so'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "pár vteřin", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuty", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minut", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "hodina", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "hodina", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hodiny", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hodin", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hodin", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "den", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "den", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dny", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "den", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dní", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dní", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "měsíc", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "měsíc", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "měsíc", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 měsíce", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 měsíce", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 měsíce", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "měsíc", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 měsíců", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 měsíců", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "rok", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "rok", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 roky", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "rok", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 let", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "za pár vteřin", "prefix"); + test.equal(moment(0).from(30000), "před pár vteřinami", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "před pár vteřinami", "now from now should display as in the past"); + test.done(); + }, + + "fromNow (future)" : function(test) { + test.expect(16); + test.equal(moment().add({s:30}).fromNow(), "za pár vteřin", "in a few seconds"); + test.equal(moment().add({m:1}).fromNow(), "za minutu", "in a minute"); + test.equal(moment().add({m:3}).fromNow(), "za 3 minuty", "in 3 minutes"); + test.equal(moment().add({m:10}).fromNow(), "za 10 minut", "in 10 minutes"); + test.equal(moment().add({h:1}).fromNow(), "za hodinu", "in an hour"); + test.equal(moment().add({h:3}).fromNow(), "za 3 hodiny", "in 3 hours"); + test.equal(moment().add({h:10}).fromNow(), "za 10 hodin", "in 10 hours"); + test.equal(moment().add({d:1}).fromNow(), "za den", "in a day"); + test.equal(moment().add({d:3}).fromNow(), "za 3 dny", "in 3 days"); + test.equal(moment().add({d:10}).fromNow(), "za 10 dní", "in 10 days"); + test.equal(moment().add({M:1}).fromNow(), "za měsíc", "in a month"); + test.equal(moment().add({M:3}).fromNow(), "za 3 měsíce", "in 3 months"); + test.equal(moment().add({M:10}).fromNow(), "za 10 měsíců", "in 10 months"); + test.equal(moment().add({y:1}).fromNow(), "za rok", "in a year"); + test.equal(moment().add({y:3}).fromNow(), "za 3 roky", "in 3 years"); + test.equal(moment().add({y:10}).fromNow(), "za 10 let", "in 10 years"); + test.done(); + }, + + "fromNow (past)" : function(test) { + test.expect(16); + test.equal(moment().subtract({s:30}).fromNow(), "před pár vteřinami", "a few seconds ago"); + test.equal(moment().subtract({m:1}).fromNow(), "před minutou", "a minute ago"); + test.equal(moment().subtract({m:3}).fromNow(), "před 3 minutami", "3 minutes ago"); + test.equal(moment().subtract({m:10}).fromNow(), "před 10 minutami", "10 minutes ago"); + test.equal(moment().subtract({h:1}).fromNow(), "před hodinou", "an hour ago"); + test.equal(moment().subtract({h:3}).fromNow(), "před 3 hodinami", "3 hours ago"); + test.equal(moment().subtract({h:10}).fromNow(), "před 10 hodinami", "10 hours ago"); + test.equal(moment().subtract({d:1}).fromNow(), "před dnem", "a day ago"); + test.equal(moment().subtract({d:3}).fromNow(), "před 3 dny", "3 days ago"); + test.equal(moment().subtract({d:10}).fromNow(), "před 10 dny", "10 days ago"); + test.equal(moment().subtract({M:1}).fromNow(), "před měsícem", "a month ago"); + test.equal(moment().subtract({M:3}).fromNow(), "před 3 měsíci", "3 months ago"); + test.equal(moment().subtract({M:10}).fromNow(), "před 10 měsíci", "10 months ago"); + test.equal(moment().subtract({y:1}).fromNow(), "před rokem", "a year ago"); + test.equal(moment().subtract({y:3}).fromNow(), "před 3 lety", "3 years ago"); + test.equal(moment().subtract({y:10}).fromNow(), "před 10 lety", "10 years ago"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "dnes v 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "dnes v 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "dnes v 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "zítra v 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "dnes v 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "včera v 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + for (var i = 2; i < 7; i++) { + var m = moment().add({ d: i }); + var nextDay = ''; + switch (m.day()) { + case 0: nextDay = 'v neděli'; break; + case 1: nextDay = 'v pondělí'; break; + case 2: nextDay = 'v úterý'; break; + case 3: nextDay = 've středu'; break; + case 4: nextDay = 've čtvrtek'; break; + case 5: nextDay = 'v pátek'; break; + case 6: nextDay = 'v sobotu'; break; + } + test.equal(m.calendar(), m.format('[' + nextDay + '] [v] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[' + nextDay + '] [v] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[' + nextDay + '] [v] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (var i = 2; i < 7; i++) { + var m = moment().subtract({ d: i }); + var lastDay = ''; + switch (m.day()) { + case 0: lastDay = 'minulou neděli'; break; + case 1: lastDay = 'minulé pondělí'; break; + case 2: lastDay = 'minulé úterý'; break; + case 3: lastDay = 'minulou středu'; break; + case 4: lastDay = 'minulý čtvrtek'; break; + case 5: lastDay = 'minulý pátek'; break; + case 6: lastDay = 'minulou sobotu'; break; + } + test.equal(m.calendar(), m.format('[' + lastDay + '] [v] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[' + lastDay + '] [v] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[' + lastDay + '] [v] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "humanize duration" : function(test) { + test.expect(4); + test.equal(moment.duration(1, "minutes").humanize(), "minuta", "a minute (future)"); + test.equal(moment.duration(1, "minutes").humanize(true), "za minutu", "in a minute"); + test.equal(moment.duration(-1, "minutes").humanize(), "minuta", "a minute (past)"); + test.equal(moment.duration(-1, "minutes").humanize(true), "před minutou", "a minute ago"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/cv.js b/node_modules/moment/test/lang/cv.js new file mode 100644 index 0000000..9497b71 --- /dev/null +++ b/node_modules/moment/test/lang/cv.js @@ -0,0 +1,362 @@ +var moment = require("../../moment"); + + + /************************************************** + Chuvash + *************************************************/ + +exports["lang:cv"] = { + setUp : function (cb) { + moment.lang('cv'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'кăрлач кăр_нарăс нар_пуш пуш_ака ака_май май_çĕртме çĕр_утă утă_çурла çур_авăн ав_юпа юпа_чӳк чӳк_раштав раш'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'вырсарникун, нарăс 14-мĕш 2010, 3:25:50 pm'], + ['ddd, hA', 'выр, 3PM'], + ['M Mo MM MMMM MMM', '2 2-мĕш 02 нарăс нар'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-мĕш 14'], + ['d do dddd ddd dd', '0 0-мĕш вырсарникун выр вр'], + ['DDD DDDo DDDD', '45 45-мĕш 045'], + ['w wo ww', '7 7-мĕш 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['Çулăн DDDo кунĕ', 'Çулăн 45-мĕш кунĕ'], + ['L', '14-02-2010'], + ['LL', '2010 çулхи нарăс уйăхĕн 14-мĕшĕ'], + ['LLL', '2010 çулхи нарăс уйăхĕн 14-мĕшĕ, 15:25'], + ['LLLL', 'вырсарникун, 2010 çулхи нарăс уйăхĕн 14-мĕшĕ, 15:25'], + ['l', '14-2-2010'], + ['ll', '2010 çулхи нар уйăхĕн 14-мĕшĕ'], + ['lll', '2010 çулхи нар уйăхĕн 14-мĕшĕ, 15:25'], + ['llll', 'выр, 2010 çулхи нар уйăхĕн 14-мĕшĕ, 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1-мĕш', '1-мĕш'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2-мĕш', '2-мĕш'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3-мĕш', '3-мĕш'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4-мĕш', '4-мĕш'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5-мĕш', '5-мĕш'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6-мĕш', '6-мĕш'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7-мĕш', '7-мĕш'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8-мĕш', '8-мĕш'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9-мĕш', '9-мĕш'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10-мĕш', '10-мĕш'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11-мĕш', '11-мĕш'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12-мĕш', '12-мĕш'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13-мĕш', '13-мĕш'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14-мĕш', '14-мĕш'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15-мĕш', '15-мĕш'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16-мĕш', '16-мĕш'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17-мĕш', '17-мĕш'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18-мĕш', '18-мĕш'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19-мĕш', '19-мĕш'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20-мĕш', '20-мĕш'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21-мĕш', '21-мĕш'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22-мĕш', '22-мĕш'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23-мĕш', '23-мĕш'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24-мĕш', '24-мĕш'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25-мĕш', '25-мĕш'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26-мĕш', '26-мĕш'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27-мĕш', '27-мĕш'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28-мĕш', '28-мĕш'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29-мĕш', '29-мĕш'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30-мĕш', '30-мĕш'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31-мĕш', '31-мĕш'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'кăрлач кăр_нарăс нар_пуш пуш_ака ака_май май_çĕртме çĕр_утă утă_çурла çур_авăн ав_юпа юпа_чӳк чӳк_раштав раш'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'вырсарникун выр вр_тунтикун тун тн_ытларикун ытл ыт_юнкун юн юн_кĕçнерникун кĕç кç_эрнекун эрн эр_шăматкун шăм шм'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "пĕр-ик çеккунт", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "пĕр минут", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "пĕр минут", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 минут", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 минут", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "пĕр сехет", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "пĕр сехет", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 сехет", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 сехет", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 сехет", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "пĕр кун", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "пĕр кун", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 кун", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "пĕр кун", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 кун", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 кун", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "пĕр уйăх", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "пĕр уйăх", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "пĕр уйăх", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 уйăх", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 уйăх", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 уйăх", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "пĕр уйăх", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 уйăх", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 уйăх", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "пĕр çул", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "пĕр çул", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 çул", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "пĕр çул", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 çул", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "пĕр-ик çеккунтран", "prefix"); + test.equal(moment(0).from(30000), "пĕр-ик çеккунт каялла", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "пĕр-ик çеккунт каялла", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(4); + test.equal(moment().add({s:30}).fromNow(), "пĕр-ик çеккунтран", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 кунран", "in 5 days"); + test.equal(moment().add({h:2}).fromNow(), "2 сехетрен", "in 2 hours, the right suffix!"); + test.equal(moment().add({y:3}).fromNow(), "3 çултан", "in 3 years, the right suffix!"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + var a = moment().hours(2).minutes(0).seconds(0); + test.equal(moment(a).calendar(), "Паян 02:00 сехетре", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Паян 02:25 сехетре", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Паян 03:00 сехетре", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Ыран 02:00 сехетре", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Паян 01:00 сехетре", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ĕнер 02:00 сехетре", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[Çитес] dddd LT [сехетре]'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Çитес] dddd LT [сехетре]'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Çитес] dddd LT [сехетре]'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Иртнĕ] dddd LT [сехетре]'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Иртнĕ] dddd LT [сехетре]'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Иртнĕ] dddd LT [сехетре]'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-мĕш', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-мĕш', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-мĕш', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-мĕш', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-мĕш', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/da.js b/node_modules/moment/test/lang/da.js new file mode 100644 index 0000000..eea4ca7 --- /dev/null +++ b/node_modules/moment/test/lang/da.js @@ -0,0 +1,292 @@ +var moment = require("../../moment"); + + + /************************************************** + Danish + *************************************************/ + +exports["lang:da"] = { + setUp : function (cb) { + moment.lang('da'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'Januar Jan_Februar Feb_Marts Mar_April Apr_Maj Maj_Juni Jun_Juli Jul_August Aug_September Sep_Oktober Okt_November Nov_December Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd [den] Do MMMM YYYY, h:mm:ss a', 'Søndag den 14. Februar 2010, 3:25:50 pm'], + ['ddd hA', 'Søn 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 Februar Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. Søndag Søn Sø'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[den] DDDo [dag på året]', 'den 45. dag på året'], + ['L', '14/02/2010'], + ['LL', '14 Februar 2010'], + ['LLL', '14 Februar 2010 15:25'], + ['LLLL', 'Søndag 14. Februar, 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 15:25'], + ['llll', 'Søn 14. Feb, 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'Januar Jan_Februar Feb_Marts Mar_April Apr_Maj Maj_Juni Jun_Juli Jul_August Aug_September Sep_Oktober Okt_November Nov_December Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'Søndag Søn Sø_Mandag Man Ma_Tirsdag Tir Ti_Onsdag Ons On_Torsdag Tor To_Fredag Fre Fr_Lørdag Lør Lø'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "få sekunder", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "et minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "et minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutter", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutter", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "en time", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "en time", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timer", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timer", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timer", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dage", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dage", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dage", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en måned", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en måned", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en måned", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 måneder", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 måneder", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 måneder", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en måned", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 måneder", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 måneder", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "et år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "et år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "et år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "om få sekunder", "prefix"); + test.equal(moment(0).from(30000), "få sekunder siden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "få sekunder siden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "om få sekunder", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dage", "in 5 days"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/de.js b/node_modules/moment/test/lang/de.js new file mode 100644 index 0000000..25e60a4 --- /dev/null +++ b/node_modules/moment/test/lang/de.js @@ -0,0 +1,354 @@ +var moment = require("../../moment"); + + + /************************************************** + German + *************************************************/ + +exports["lang:de"] = { + setUp : function (cb) { + moment.lang('de'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'Januar Jan._Februar Febr._März Mrz._April Apr._Mai Mai_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'Sonntag, 14. Februar 2010, 3:25:50 pm'], + ['ddd, hA', 'So., 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 Februar Febr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. Sonntag So. So'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '14.02.2010'], + ['LL', '14. Februar 2010'], + ['LLL', '14. Februar 2010 15:25 Uhr'], + ['LLLL', 'Sonntag, 14. Februar 2010 15:25 Uhr'], + ['l', '14.2.2010'], + ['ll', '14. Febr. 2010'], + ['lll', '14. Febr. 2010 15:25 Uhr'], + ['llll', 'So., 14. Febr. 2010 15:25 Uhr'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'Januar Jan._Februar Febr._März Mrz._April Apr._Mai Mai_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'Sonntag So. So_Montag Mo. Mo_Dienstag Di. Di_Mittwoch Mi. Mi_Donnerstag Do. Do_Freitag Fr. Fr_Samstag Sa. Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "ein paar Sekunden", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "eine Minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "eine Minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 Minuten", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 Minuten", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "eine Stunde", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "eine Stunde", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 Stunden", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 Stunden", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 Stunden", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "ein Tag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "ein Tag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 Tage", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "ein Tag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 Tage", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 Tage", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "ein Monat", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "ein Monat", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "ein Monat", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 Monate", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 Monate", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 Monate", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "ein Monat", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 Monate", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 Monate", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ein Jahr", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ein Jahr", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 Jahre", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ein Jahr", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 Jahre", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "in ein paar Sekunden", "prefix"); + test.equal(moment(0).from(30000), "vor ein paar Sekunden", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "in ein paar Sekunden", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 Tagen", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Heute um 2:00 Uhr", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Heute um 2:25 Uhr", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Heute um 3:00 Uhr", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Morgen um 2:00 Uhr", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Heute um 1:00 Uhr", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Gestern um 2:00 Uhr", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [um] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [um] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [um] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[letzten] dddd [um] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[letzten] dddd [um] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[letzten] dddd [um] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/el.js b/node_modules/moment/test/lang/el.js new file mode 100644 index 0000000..5011783 --- /dev/null +++ b/node_modules/moment/test/lang/el.js @@ -0,0 +1,383 @@ +var moment = require("../../moment"); + + + /************************************************** + Modern Greek + *************************************************/ + +exports["lang:el"] = { + setUp : function (cb) { + moment.lang('el'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'Ιανουάριος Ιαν_Φεβρουάριος Φεβ_Μάρτιος Μαρ_Απρίλιος Απρ_Μάιος Μαϊ_Ιούνιος Ιουν_Ιούλιος Ιουλ_Αύγουστος Αυγ_Σεπτέμβριος Σεπ_Οκτώβριος Οκτ_Νοέμβριος Νοε_Δεκέμβριος Δεκ'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(24); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Κυριακή, Φεβρουάριος 14η 2010, 3:25:50 μμ'], + ['dddd, D MMMM YYYY, h:mm:ss a', 'Κυριακή, 14 Φεβρουαρίου 2010, 3:25:50 μμ'], + ['ddd, hA', 'Κυρ, 3ΜΜ'], + ['dddd, MMMM YYYY', 'Κυριακή, Φεβρουάριος 2010'], + ['M Mo MM MMMM MMM', '2 2η 02 Φεβρουάριος Φεβ'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14η 14'], + ['d do dddd ddd dd', '0 0η Κυριακή Κυρ Κυ'], + ['DDD DDDo DDDD', '45 45η 045'], + ['w wo ww', '6 6η 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'μμ ΜΜ'], + ['[the] DDDo [day of the year]', 'the 45η day of the year'], + ['L', '14/02/2010'], + ['LL', '14 Φεβρουαρίου 2010'], + ['LLL', '14 Φεβρουαρίου 2010 3:25 ΜΜ'], + ['LLLL', 'Κυριακή, 14 Φεβρουαρίου 2010 3:25 ΜΜ'], + ['l', '14/2/2010'], + ['ll', '14 Φεβ 2010'], + ['lll', '14 Φεβ 2010 3:25 ΜΜ'], + ['llll', 'Κυρ, 14 Φεβ 2010 3:25 ΜΜ'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1η', '1η'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2η', '2η'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3η', '3η'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4η', '4η'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5η', '5η'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6η', '6η'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7η', '7η'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8η', '8η'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9η', '9η'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10η', '10η'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11η', '11η'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12η', '12η'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13η', '13η'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14η', '14η'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15η', '15η'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16η', '16η'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17η', '17η'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18η', '18η'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19η', '19η'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20η', '20η'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21η', '21η'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22η', '22η'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23η', '23η'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24η', '24η'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25η', '25η'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26η', '26η'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27η', '27η'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28η', '28η'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29η', '29η'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30η', '30η'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31η', '31η'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'Ιανουάριος Ιαν_Φεβρουάριος Φεβ_Μάρτιος Μαρ_Απρίλιος Απρ_Μάιος Μαϊ_Ιούνιος Ιουν_Ιούλιος Ιουλ_Αύγουστος Αυγ_Σεπτέμβριος Σεπ_Οκτώβριος Οκτ_Νοέμβριος Νοε_Δεκέμβριος Δεκ'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'Κυριακή Κυρ Κυ_Δευτέρα Δευ Δε_Τρίτη Τρι Τρ_Τετάρτη Τετ Τε_Πέμπτη Πεμ Πε_Παρασκευή Παρ Πα_Σάββατο Σαβ Σα'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "δευτερόλεπτα", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ένα λεπτό", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ένα λεπτό", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 λεπτά", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 λεπτά", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "μία ώρα", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "μία ώρα", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ώρες", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ώρες", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ώρες", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "μία μέρα", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "μία μέρα", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 μέρες", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "μία μέρα", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 μέρες", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 μέρες", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "ένας μήνας", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "ένας μήνας", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "ένας μήνας", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 μήνες", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 μήνες", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 μήνες", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "ένας μήνας", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 μήνες", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 μήνες", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ένας χρόνος", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ένας χρόνος", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 χρόνια", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ένας χρόνος", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 χρόνια", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "σε δευτερόλεπτα", "prefix"); + test.equal(moment(0).from(30000), "δευτερόλεπτα πριν", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "δευτερόλεπτα πριν", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "σε δευτερόλεπτα", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "σε 5 μέρες", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Σήμερα στις 2:00 ΠΜ", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Σήμερα στις 2:25 ΠΜ", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Σήμερα στις 3:00 ΠΜ", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Αύριο στις 2:00 ΠΜ", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Σήμερα στη 1:00 ΠΜ", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Χθες στις 2:00 ΠΜ", "yesterday at the same time"); + + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [' + (m.hours()%12 === 1 ? 'στη' : 'στις') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [στις] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [στις] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[την προηγούμενη] dddd [' + (m.hours()%12 === 1 ? 'στη' : 'στις') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[την προηγούμενη] dddd [στις] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[την προηγούμενη] dddd [στις] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }), + weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 52, "Dec 31 2006 should be week 52"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 52, "Dec 30 2007 should be week 52"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 52, "Dec 29 2002 should be week 52"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 52, "Dec 28 2008 should be week 52"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(7); + + test.equal(moment([2009, 11, 27]).week(), 52, "Dec 27 2009 should be week 52"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 2]).week(), 53, "Jan 2 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 9]).week(), 1, "Jan 9 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 26]).week(), 51, "Dec 26 2010 should be week 51"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 8]).week(), 1, "Jan 8 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52η', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1η', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1η', "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2η', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2η', "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/en-ca.js b/node_modules/moment/test/lang/en-ca.js new file mode 100644 index 0000000..2a65ffa --- /dev/null +++ b/node_modules/moment/test/lang/en-ca.js @@ -0,0 +1,378 @@ +var moment = require("../../moment"); + +/************************************************** + English (Canadian) +*************************************************/ + +exports["lang:en-ca"] = { + setUp : function (cb) { + moment.lang('en-ca'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sunday, February 14th 2010, 3:25:50 pm'], + ['ddd, hA', 'Sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2nd 02 February Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14th 14'], + ['d do dddd ddd dd', '0 0th Sunday Sun Su'], + ['DDD DDDo DDDD', '45 45th 045'], + ['w wo ww', '8 8th 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45th day of the year'], + ['L', '2010-02-14'], + ['LL', '14 February, 2010'], + ['LLL', '14 February, 2010 3:25 PM'], + ['LLLL', 'Sunday, 14 February, 2010 3:25 PM'], + ['l', '2010-2-14'], + ['ll', '14 Feb, 2010'], + ['lll', '14 Feb, 2010 3:25 PM'], + ['llll', 'Sun, 14 Feb, 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "a few seconds", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "a minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "a minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "an hour", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "an hour", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hours", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hours", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hours", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "a day", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "a day", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 days", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "a day", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 days", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 days", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "a month", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "a month", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "a month", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 months", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 months", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 months", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "a month", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 months", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 months", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "a year", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "a year", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 years", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "a year", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 years", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "in a few seconds", "prefix"); + test.equal(moment(0).from(30000), "a few seconds ago", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "a few seconds ago", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "in a few seconds", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 days", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at 2:00 AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at 2:25 AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at 3:00 AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at 2:00 AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at 1:00 AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at 2:00 AM", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }), + weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1st', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1st', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2nd', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2nd', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3rd', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/en-gb.js b/node_modules/moment/test/lang/en-gb.js new file mode 100644 index 0000000..a721a4d --- /dev/null +++ b/node_modules/moment/test/lang/en-gb.js @@ -0,0 +1,358 @@ +var moment = require("../../moment"); + + + /************************************************** + English + *************************************************/ + +exports["lang:en-gb"] = { + setUp : function (cb) { + moment.lang('en-gb'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sunday, February 14th 2010, 3:25:50 pm'], + ['ddd, hA', 'Sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2nd 02 February Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14th 14'], + ['d do dddd ddd dd', '0 0th Sunday Sun Su'], + ['DDD DDDo DDDD', '45 45th 045'], + ['w wo ww', '6 6th 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45th day of the year'], + ['L', '14/02/2010'], + ['LL', '14 February 2010'], + ['LLL', '14 February 2010 15:25'], + ['LLLL', 'Sunday, 14 February 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 15:25'], + ['llll', 'Sun, 14 Feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "a few seconds", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "a minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "a minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "an hour", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "an hour", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hours", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hours", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hours", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "a day", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "a day", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 days", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "a day", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 days", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 days", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "a month", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "a month", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "a month", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 months", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 months", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 months", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "a month", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 months", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 months", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "a year", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "a year", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 years", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "a year", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 years", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "in a few seconds", "prefix"); + test.equal(moment(0).from(30000), "a few seconds ago", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "a few seconds ago", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "in a few seconds", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 days", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52nd', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1st' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1st' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2nd' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2nd' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/en.js b/node_modules/moment/test/lang/en.js new file mode 100644 index 0000000..295b25e --- /dev/null +++ b/node_modules/moment/test/lang/en.js @@ -0,0 +1,379 @@ +var moment = require("../../moment"); + + + /************************************************** + English + *************************************************/ + +exports["lang:en"] = { + setUp : function (cb) { + moment.lang('en'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sunday, February 14th 2010, 3:25:50 pm'], + ['ddd, hA', 'Sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2nd 02 February Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14th 14'], + ['d do dddd ddd dd', '0 0th Sunday Sun Su'], + ['DDD DDDo DDDD', '45 45th 045'], + ['w wo ww', '8 8th 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45th day of the year'], + ['L', '02/14/2010'], + ['LL', 'February 14 2010'], + ['LLL', 'February 14 2010 3:25 PM'], + ['LLLL', 'Sunday, February 14 2010 3:25 PM'], + ['l', '2/14/2010'], + ['ll', 'Feb 14 2010'], + ['lll', 'Feb 14 2010 3:25 PM'], + ['llll', 'Sun, Feb 14 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'January Jan_February Feb_March Mar_April Apr_May May_June Jun_July Jul_August Aug_September Sep_October Oct_November Nov_December Dec'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "a few seconds", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "a minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "a minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "an hour", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "an hour", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hours", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hours", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hours", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "a day", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "a day", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 days", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "a day", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 days", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 days", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "a month", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "a month", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "a month", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 months", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 months", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 months", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "a month", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 months", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 months", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "a year", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "a year", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 years", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "a year", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 years", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "in a few seconds", "prefix"); + test.equal(moment(0).from(30000), "a few seconds ago", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "a few seconds ago", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "in a few seconds", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "in 5 days", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at 2:00 AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at 2:25 AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at 3:00 AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at 2:00 AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at 1:00 AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at 2:00 AM", "yesterday at the same time"); + + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [at] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Last] dddd [at] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }), + weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1st', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1st', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2nd', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2nd', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3rd', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/eo.js b/node_modules/moment/test/lang/eo.js new file mode 100644 index 0000000..af9e857 --- /dev/null +++ b/node_modules/moment/test/lang/eo.js @@ -0,0 +1,364 @@ +var moment = require("../../moment"); + + + /************************************************** + Esperanto + *************************************************/ + +exports["lang:eo"] = { + setUp : function (cb) { + moment.lang('eo'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'januaro jan_februaro feb_marto mar_aprilo apr_majo maj_junio jun_julio jul_aŭgusto aŭg_septembro sep_oktobro okt_novembro nov_decembro dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Dimanĉo, februaro 14a 2010, 3:25:50 p.t.m.'], + ['ddd, hA', 'Dim, 3P.T.M.'], + ['M Mo MM MMMM MMM', '2 2a 02 februaro feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14a 14'], + ['d do dddd ddd dd', '0 0a Dimanĉo Dim Di'], + ['DDD DDDo DDDD', '45 45a 045'], + ['w wo ww', '7 7a 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'p.t.m. P.T.M.'], + ['[la] DDDo [tago] [de] [la] [jaro]', 'la 45a tago de la jaro'], + ['L', '2010-02-14'], + ['LL', '14-an de februaro, 2010'], + ['LLL', '14-an de februaro, 2010 15:25'], + ['LLLL', 'Dimanĉo, la 14-an de februaro, 2010 15:25'], + ['l', '2010-2-14'], + ['ll', '14-an de feb, 2010'], + ['lll', '14-an de feb, 2010 15:25'], + ['llll', 'Dim, la 14-an de feb, 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1a', '1a'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2a', '2a'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3a', '3a'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4a', '4a'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5a', '5a'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6a', '6a'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7a', '7a'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8a', '8a'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9a', '9a'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10a', '10a'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11a', '11a'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12a', '12a'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13a', '13a'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14a', '14a'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15a', '15a'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16a', '16a'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17a', '17a'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18a', '18a'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19a', '19a'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20a', '20a'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21a', '21a'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22a', '22a'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23a', '23a'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24a', '24a'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25a', '25a'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26a', '26a'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27a', '27a'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28a', '28a'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29a', '29a'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30a', '30a'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31a', '31a'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'januaro jan_februaro feb_marto mar_aprilo apr_majo maj_junio jun_julio jul_aŭgusto aŭg_septembro sep_oktobro okt_novembro nov_decembro dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'Dimanĉo Dim Di_Lundo Lun Lu_Mardo Mard Ma_Merkredo Merk Me_Ĵaŭdo Ĵaŭ Ĵa_Vendredo Ven Ve_Sabato Sab Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "sekundoj", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutoj", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutoj", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "horo", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "horo", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horoj", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horoj", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horoj", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "tago", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "tago", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 tagoj", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "tago", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 tagoj", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 tagoj", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "monato", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "monato", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "monato", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 monatoj", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 monatoj", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 monatoj", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "monato", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 monatoj", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 monatoj", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "jaro", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "jaro", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 jaroj", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "jaro", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 jaroj", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "je sekundoj", "je prefix"); + test.equal(moment(0).from(30000), "antaŭ sekundoj", "antaŭ prefix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "antaŭ sekundoj", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "je sekundoj", "je sekundoj"); + test.equal(moment().add({d:5}).fromNow(), "je 5 tagoj", "je 5 tagoj"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hodiaŭ je 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hodiaŭ je 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hodiaŭ je 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Morgaŭ je 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hodiaŭ je 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Hieraŭ je 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [je] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [je] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [je] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[pasinta] dddd [je] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[pasinta] dddd [je] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[pasinta] dddd [je] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1a', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1a', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2a', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2a', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3a', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/es.js b/node_modules/moment/test/lang/es.js new file mode 100644 index 0000000..bd337aa --- /dev/null +++ b/node_modules/moment/test/lang/es.js @@ -0,0 +1,359 @@ +var moment = require("../../moment"); + + + /************************************************** + Spanish + *************************************************/ + +exports["lang:es"] = { + setUp : function (cb) { + moment.lang('es'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'enero ene._febrero feb._marzo mar._abril abr._mayo may._junio jun._julio jul._agosto ago._septiembre sep._octubre oct._noviembre nov._diciembre dic.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'domingo, febrero 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'dom., 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 febrero feb.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd dd', '0 0º domingo dom. Do'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '6 6º 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 de febrero de 2010'], + ['LLL', '14 de febrero de 2010 15:25'], + ['LLLL', 'domingo, 14 de febrero de 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 de feb. de 2010'], + ['lll', '14 de feb. de 2010 15:25'], + ['llll', 'dom., 14 de feb. de 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'enero ene._febrero feb._marzo mar._abril abr._mayo may._junio jun._julio jul._agosto ago._septiembre sep._octubre oct._noviembre nov._diciembre dic.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'domingo dom. Do_lunes lun. Lu_martes mar. Ma_miércoles mié. Mi_jueves jue. Ju_viernes vie. Vi_sábado sáb. Sá'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "unos segundos", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "una hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "una hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un día", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un día", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 días", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un día", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 días", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 días", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mes", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mes", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mes", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mes", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un año", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un año", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 años", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un año", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 años", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "en unos segundos", "prefix"); + test.equal(moment(0).from(30000), "hace unos segundos", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "hace unos segundos", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "en unos segundos", "en unos segundos"); + test.equal(moment().add({d:5}).fromNow(), "en 5 días", "en 5 días"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "hoy a las 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "hoy a las 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "hoy a las 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "mañana a las 2:00", "tomorrow at the same time"); + test.equal(moment(a).add({ d: 1, h : -1 }).calendar(), "mañana a la 1:00", "tomorrow minus 1 hour"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "hoy a la 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "ayer a las 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/et.js b/node_modules/moment/test/lang/et.js new file mode 100644 index 0000000..2a61c6d --- /dev/null +++ b/node_modules/moment/test/lang/et.js @@ -0,0 +1,367 @@ +var moment = require("../../moment"); + + +/************************************************** + Estonian +**************************************************/ + +exports["lang:et"] = { + setUp : function (cb) { + moment.lang('et'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'jaanuar jaan_veebruar veebr_märts märts_aprill apr_mai mai_juuni juuni_juuli juuli_august aug_september sept_oktoober okt_november nov_detsember dets'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' peaks olema kuu ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, Do MMMM YYYY, H:mm:ss', 'pühapäev, 14. veebruar 2010, 15:25:50'], + ['ddd, h', 'P, 3'], + ['M Mo MM MMMM MMM', '2 2. 02 veebruar veebr'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. pühapäev P P'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[aasta] DDDo [päev]', 'aasta 45. päev'], + ['L', '14.02.2010'], + ['LL', '14. veebruar 2010'], + ['LLL', '14. veebruar 2010 15:25'], + ['LLLL', 'pühapäev, 14. veebruar 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14. veebr 2010'], + ['lll', '14. veebr 2010 15:25'], + ['llll', 'P, 14. veebr 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'jaanuar jaan_veebruar veebr_märts märts_aprill apr_mai mai_juuni juuni_juuli juuli_august aug_september sept_oktoober okt_november nov_detsember dets'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'pühapäev P P_esmaspäev E E_teisipäev T T_kolmapäev K K_neljapäev N N_reede R R_laupäev L L'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "paari sekundi", "44 seconds = paari sekundi"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minut", "45 seconds = minut"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minut", "89 seconds = minut"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutit", "90 seconds = 2 minutit"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutit", "44 minutes = 44 minutit"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "tund", "45 minutes = tund"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "tund", "89 minutes = tund"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 tundi", "90 minutes = 2 tundi"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 tundi", "5 hours = 5 tundi"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 tundi", "21 hours = 21 tundi"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "päev", "22 hours = päev"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "päev", "35 hours = päev"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 päeva", "36 hours = 2 päeva"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "päev", "1 day = päev"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 päeva", "5 days = 5 päeva"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 päeva", "25 days = 25 päeva"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "kuu", "26 days = kuu"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "kuu", "30 days = kuu"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "kuu", "45 days = kuu"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 kuud", "46 days = 2 kuud"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 kuud", "75 days = 2 kuud"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 kuud", "76 days = 3 kuud"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "kuu", "1 month = kuu"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 kuud", "5 months = 5 kuud"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 kuud", "344 days = 11 kuud"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "aasta", "345 days = aasta"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "aasta", "547 days = aasta"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 aastat", "548 days = 2 aastat"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "aasta", "1 year = aasta"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 aastat", "5 years = 5 aastat"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "paari sekundi pärast", "prefix"); + test.equal(moment(0).from(30000), "paar sekundit tagasi", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "paar sekundit tagasi", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "paari sekundi pärast", "paari sekundi pärast"); + test.equal(moment().add({d:5}).fromNow(), "5 päeva pärast", "5 päeva pärast"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Täna, 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Täna, 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Täna, 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Homme, 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Täna, 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Eile, 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[Järgmine] dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Järgmine] dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Järgmine] dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Eelmine] dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Eelmine] dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Eelmine] dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 nädal tagasi"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "1 nädala pärast"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 nädalat tagasi"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "2 nädala pärast"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/eu.js b/node_modules/moment/test/lang/eu.js new file mode 100644 index 0000000..bdce555 --- /dev/null +++ b/node_modules/moment/test/lang/eu.js @@ -0,0 +1,363 @@ +var moment = require("../../moment"); + + + /************************************************** + Euskara + *************************************************/ + +exports["lang:eu"] = { + setUp : function (cb) { + moment.lang('eu'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'urtarrila urt._otsaila ots._martxoa mar._apirila api._maiatza mai._ekaina eka._uztaila uzt._abuztua abu._iraila ira._urria urr._azaroa aza._abendua abe.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'igandea, otsaila 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'ig., 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 otsaila ots.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. igandea ig. ig'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '7 7. 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '2010-02-14'], + ['LL', '2010ko otsailaren 14a'], + ['LLL', '2010ko otsailaren 14a 15:25'], + ['LLLL', 'igandea, 2010ko otsailaren 14a 15:25'], + ['l', '2010-2-14'], + ['ll', '2010ko ots. 14a'], + ['lll', '2010ko ots. 14a 15:25'], + ['llll', 'ig., 2010ko ots. 14a 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'urtarrila urt._otsaila ots._martxoa mar._apirila api._maiatza mai._ekaina eka._uztaila uzt._abuztua abu._iraila ira._urria urr._azaroa aza._abendua abe.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'igandea ig. ig_astelehena al. al_asteartea ar. ar_asteazkena az. az_osteguna og. og_ostirala ol. ol_larunbata lr. lr'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "segundo batzuk", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minutu bat", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minutu bat", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutu", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutu", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "ordu bat", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "ordu bat", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ordu", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ordu", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ordu", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "egun bat", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "egun bat", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 egun", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "egun bat", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 egun", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 egun", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "hilabete bat", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "hilabete bat", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "hilabete bat", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 hilabete", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 hilabete", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 hilabete", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "hilabete bat", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 hilabete", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 hilabete", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "urte bat", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "urte bat", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 urte", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "urte bat", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 urte", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "segundo batzuk barru", "prefix"); + test.equal(moment(0).from(30000), "duela segundo batzuk", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "duela segundo batzuk", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "segundo batzuk barru", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 egun barru", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "gaur 02:00etan", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "gaur 02:25etan", "now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "gaur 03:00etan", "now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "bihar 02:00etan", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "gaur 01:00etan", "now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "atzo 02:00etan", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd LT[etan]'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd LT[etan]'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd LT[etan]'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/fa.js b/node_modules/moment/test/lang/fa.js new file mode 100755 index 0000000..6b77a02 --- /dev/null +++ b/node_modules/moment/test/lang/fa.js @@ -0,0 +1,342 @@ +// moment.js Persian (fa) tests +// author: Ebrahim Byagowi : https://github.com/ebraminio +var moment = require("../../moment"); + +exports["lang:fa"] = { + setUp : function (cb) { + moment.lang('fa'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(24); + var tests = 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1) + ' instead is month ' + moment(input, mmm).month()); + } + for (i = 0; i < 12; i++) { + equalTest(tests[i], 'MMM', i); + equalTest(tests[i], 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'یک‌شنبه، فوریه ۱۴م ۲۰۱۰، ۳:۲۵:۵۰ بعد از ظهر'], + ['ddd, hA', 'یک‌شنبه، ۳بعد از ظهر'], + ['M Mo MM MMMM MMM', '۲ ۲م ۰۲ فوریه فوریه'], + ['YYYY YY', '۲۰۱۰ ۱۰'], + ['D Do DD', '۱۴ ۱۴م ۱۴'], + ['d do dddd ddd dd', '۰ ۰م یک‌شنبه یک‌شنبه ی'], + ['DDD DDDo DDDD', '۴۵ ۴۵م ۰۴۵'], + ['w wo ww', '۸ ۸م ۰۸'], + ['h hh', '۳ ۰۳'], + ['H HH', '۱۵ ۱۵'], + ['m mm', '۲۵ ۲۵'], + ['s ss', '۵۰ ۵۰'], + ['a A', 'بعد از ظهر بعد از ظهر'], + ['DDDo [روز سال]', '۴۵م روز سال'], + ['L', '۱۴/۰۲/۲۰۱۰'], + ['LL', '۱۴ فوریه ۲۰۱۰'], + ['LLL', '۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'], + ['LLLL', 'یک‌شنبه، ۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'], + ['l', '۱۴/۲/۲۰۱۰'], + ['ll', '۱۴ فوریه ۲۰۱۰'], + ['lll', '۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'], + ['llll', 'یک‌شنبه، ۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '۱م', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '۲م', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '۳م', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '۴م', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '۵م', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '۶م', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '۷م', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '۸م', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '۹م', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '۱۰م', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '۱۱م', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '۱۲م', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '۱۳م', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '۱۴م', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '۱۵م', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '۱۶م', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '۱۷م', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '۱۸م', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '۱۹م', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '۲۰م', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '۲۱م', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '۲۲م', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '۲۳م', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '۲۴م', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '۲۵م', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '۲۶م', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '۲۷م', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '۲۸م', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '۲۹م', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '۳۰م', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '۳۱م', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'ژانویه ژانویه_فوریه فوریه_مارس مارس_آوریل آوریل_مه مه_ژوئن ژوئن_ژوئیه ژوئیه_اوت اوت_سپتامبر سپتامبر_اکتبر اکتبر_نوامبر نوامبر_دسامبر دسامبر'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'یک‌شنبه یک‌شنبه ی_دوشنبه دوشنبه د_سه‌شنبه سه‌شنبه س_چهارشنبه چهارشنبه چ_پنج‌شنبه پنج‌شنبه پ_جمعه جمعه ج_شنبه شنبه ش'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "چندین ثانیه", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "یک دقیقه", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "یک دقیقه", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "۲ دقیقه", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "۴۴ دقیقه", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "یک ساعت", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "یک ساعت", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "۲ ساعت", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "۵ ساعت", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "۲۱ ساعت", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "یک روز", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "یک روز", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "۲ روز", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "یک روز", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "۵ روز", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "۲۵ روز", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "یک ماه", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "یک ماه", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "یک ماه", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "۲ ماه", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "۲ ماه", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "۳ ماه", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "یک ماه", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "۵ ماه", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "۱۱ ماه", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "یک سال", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "یک سال", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "۲ سال", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "یک سال", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "۵ سال", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "در چندین ثانیه", "prefix"); + test.equal(moment(0).from(30000), "چندین ثانیه پیش", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "چندین ثانیه پیش", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "در چندین ثانیه", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "در ۵ روز", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "امروز ساعت ۰۲:۰۰", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "امروز ساعت ۰۲:۲۵", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "امروز ساعت ۰۳:۰۰", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "فردا ساعت ۰۲:۰۰", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "امروز ساعت ۰۱:۰۰", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "دیروز ساعت ۰۲:۰۰", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [ساعت] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [ساعت] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [ساعت] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [پیش ساعت] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [پیش ساعت] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [پیش ساعت] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + + // Saturday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).week(), 1, "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).week(), 1, "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 2, "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).week(), 2, "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 3, "Jan 14 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2006, 11, 30]).week(), 1, "Dec 30 2006 should be week 1"); + test.equal(moment([2007, 0, 5]).week(), 1, "Jan 5 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 2, "Jan 6 2007 should be week 2"); + test.equal(moment([2007, 0, 12]).week(), 2, "Jan 12 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 3, "Jan 13 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 29]).week(), 1, "Dec 29 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 4]).week(), 1, "Jan 4 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 2, "Jan 5 2008 should be week 2"); + test.equal(moment([2008, 0, 11]).week(), 2, "Jan 11 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 3, "Jan 12 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 28]).week(), 1, "Dec 28 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 3]).week(), 1, "Jan 3 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 2, "Jan 4 2003 should be week 2"); + test.equal(moment([2003, 0, 10]).week(), 2, "Jan 10 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 3, "Jan 11 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 27]).week(), 1, "Dec 27 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 2]).week(), 1, "Jan 2 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 2, "Jan 3 2009 should be week 2"); + test.equal(moment([2009, 0, 9]).week(), 2, "Jan 9 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 3, "Jan 10 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(5); + + test.equal(moment([2009, 11, 26]).week(), 1, "Dec 26 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 2, "Jan 2 2010 should be week 2"); + test.equal(moment([2010, 0, 8]).week(), 2, "Jan 8 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 3, "Jan 9 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 7]).week(), 1, "Jan 7 2011 should be week 1"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 14]).week(), 2, "Jan 14 2011 should be week 2"); + test.equal(moment([2011, 0, 15]).week(), 3, "Jan 15 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).format('w ww wo'), '۱ ۰۱ ۱م', "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).format('w ww wo'), '۱ ۰۱ ۱م', "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '۲ ۰۲ ۲م', "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).format('w ww wo'), '۲ ۰۲ ۲م', "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '۳ ۰۳ ۳م', "Jan 14 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/fi.js b/node_modules/moment/test/lang/fi.js new file mode 100644 index 0000000..345eab3 --- /dev/null +++ b/node_modules/moment/test/lang/fi.js @@ -0,0 +1,357 @@ +var moment = require("../../moment"); + + + /************************************************** + Finnish + *************************************************/ + +exports["lang:fi"] = { + setUp : function (cb) { + moment.lang('fi'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'tammikuu tammi_helmikuu helmi_maaliskuu maalis_huhtikuu huhti_toukokuu touko_kesäkuu kesä_heinäkuu heinä_elokuu elo_syyskuu syys_lokakuu loka_marraskuu marras_joulukuu joulu'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'sunnuntai, helmikuu 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'su, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 helmikuu helmi'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. sunnuntai su su'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[vuoden] DDDo [päivä]', 'vuoden 45. päivä'], + ['L', '14.02.2010'], + ['LL', '14. helmikuuta 2010'], + ['LLL', '14. helmikuuta 2010, klo 15.25'], + ['LLLL', 'sunnuntai, 14. helmikuuta 2010, klo 15.25'], + ['l', '14.2.2010'], + ['ll', '14. helmi 2010'], + ['lll', '14. helmi 2010, klo 15.25'], + ['llll', 'su, 14. helmi 2010, klo 15.25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21st'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22nd'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23rd'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'tammikuu tammi_helmikuu helmi_maaliskuu maalis_huhtikuu huhti_toukokuu touko_kesäkuu kesä_heinäkuu heinä_elokuu elo_syyskuu syys_lokakuu loka_marraskuu marras_joulukuu joulu'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'sunnuntai su su_maanantai ma ma_tiistai ti ti_keskiviikko ke ke_torstai to to_perjantai pe pe_lauantai la la'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "muutama sekunti", "44 seconds = few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuutti", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuutti", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "kaksi minuuttia", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuuttia", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "tunti", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "tunti", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "kaksi tuntia", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "viisi tuntia", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 tuntia", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "päivä", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "päivä", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "kaksi päivää", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "päivä", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "viisi päivää", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 päivää", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "kuukausi", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "kuukausi", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "kuukausi", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "kaksi kuukautta", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "kaksi kuukautta", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "kolme kuukautta", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "kuukausi", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "viisi kuukautta", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 kuukautta", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "vuosi", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "vuosi", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "kaksi vuotta", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "vuosi", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "viisi vuotta", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "muutaman sekunnin päästä", "prefix"); + test.equal(moment(0).from(30000), "muutama sekunti sitten", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "muutama sekunti sitten", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "muutaman sekunnin päästä", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "viiden päivän päästä", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "tänään klo 02.00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "tänään klo 02.25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "tänään klo 03.00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "huomenna klo 02.00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "tänään klo 01.00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "eilen klo 02.00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [klo] LT'), "today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [klo] LT'), "today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [klo] LT'), "today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (var i = 2; i < 7; i++) { + var m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), "today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), "today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), "today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "yksi viikko sitten"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "yhden viikon päästä"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "kaksi viikkoa sitten"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "kaden viikon päästä"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/fr-ca.js b/node_modules/moment/test/lang/fr-ca.js new file mode 100644 index 0000000..7448253 --- /dev/null +++ b/node_modules/moment/test/lang/fr-ca.js @@ -0,0 +1,372 @@ +var moment = require("../../moment"); + +/************************************************** + French (Canadian) +*************************************************/ + +exports["lang:fr-ca"] = { + setUp : function (cb) { + moment.lang('fr-ca'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'dimanche, février 14 2010, 3:25:50 pm'], + ['ddd, hA', 'dim., 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 février févr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 dimanche dim. Di'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '2010-02-14'], + ['LL', '14 février 2010'], + ['LLL', '14 février 2010 15:25'], + ['LLLL', 'dimanche 14 février 2010 15:25'], + ['l', '2010-2-14'], + ['ll', '14 févr. 2010'], + ['lll', '14 févr. 2010 15:25'], + ['llll', 'dim. 14 févr. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1er', '1er'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'dimanche dim. Di_lundi lun. Lu_mardi mar. Ma_mercredi mer. Me_jeudi jeu. Je_vendredi ven. Ve_samedi sam. Sa'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "quelques secondes", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "une minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "une minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "une heure", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "une heure", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 heures", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 heures", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 heures", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un jour", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un jour", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 jours", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un jour", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 jours", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 jours", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mois", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mois", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mois", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mois", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mois", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mois", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mois", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mois", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mois", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un an", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un an", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ans", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un an", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ans", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "dans quelques secondes", "prefix"); + test.equal(moment(0).from(30000), "il y a quelques secondes", "suffix"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "dans quelques secondes", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "dans 5 jours", "in 5 days"); + + test.done(); + }, + + "same day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Aujourd'hui à 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Aujourd'hui à 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Aujourd'hui à 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Demain à 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Aujourd'hui à 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Hier à 02:00", "yesterday at the same time"); + test.done(); + }, + + "same next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "same last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "same all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1er', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1er', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/fr.js b/node_modules/moment/test/lang/fr.js new file mode 100644 index 0000000..18fb531 --- /dev/null +++ b/node_modules/moment/test/lang/fr.js @@ -0,0 +1,358 @@ +var moment = require("../../moment"); + + + /************************************************** + French + *************************************************/ + +exports["lang:fr"] = { + setUp : function (cb) { + moment.lang('fr'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'dimanche, février 14 2010, 3:25:50 pm'], + ['ddd, hA', 'dim., 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 février févr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 dimanche dim. Di'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '6 6 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 février 2010'], + ['LLL', '14 février 2010 15:25'], + ['LLLL', 'dimanche 14 février 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 févr. 2010'], + ['lll', '14 févr. 2010 15:25'], + ['llll', 'dim. 14 févr. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1er', '1er'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'janvier janv._février févr._mars mars_avril avr._mai mai_juin juin_juillet juil._août août_septembre sept._octobre oct._novembre nov._décembre déc.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'dimanche dim. Di_lundi lun. Lu_mardi mar. Ma_mercredi mer. Me_jeudi jeu. Je_vendredi ven. Ve_samedi sam. Sa'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "quelques secondes", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "une minute", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "une minute", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "une heure", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "une heure", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 heures", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 heures", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 heures", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un jour", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un jour", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 jours", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un jour", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 jours", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 jours", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mois", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mois", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mois", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mois", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mois", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mois", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mois", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mois", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mois", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un an", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un an", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ans", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un an", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ans", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "dans quelques secondes", "prefix"); + test.equal(moment(0).from(30000), "il y a quelques secondes", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "dans quelques secondes", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "dans 5 jours", "in 5 days"); + test.done(); + }, + + "same day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Aujourd'hui à 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Aujourd'hui à 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Aujourd'hui à 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Demain à 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Aujourd'hui à 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Hier à 02:00", "yesterday at the same time"); + test.done(); + }, + + "same next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [à] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "same last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [dernier à] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "same all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1er' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1er' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/gl.js b/node_modules/moment/test/lang/gl.js new file mode 100644 index 0000000..41992b9 --- /dev/null +++ b/node_modules/moment/test/lang/gl.js @@ -0,0 +1,342 @@ +var moment = require("../../moment"); + + + /************************************************** + Galego + *************************************************/ + +exports["lang:gl"] = { + setUp : function (cb) { + moment.lang('gl'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = "Xaneiro Xan._Febreiro Feb._Marzo Mar._Abril Abr._Maio Mai._Xuño Xuñ._Xullo Xul._Agosto Ago._Setembro Set._Outubro Out._Novembro Nov._Decembro Dec.".split("_"); + + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = "Xaneiro Xan._Febreiro Feb._Marzo Mar._Abril Abr._Maio Mai._Xuño Xuñ._Xullo Xul._Agosto Ago._Setembro Set._Outubro Out._Novembro Nov._Decembro Dec.".split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = "Domingo Dom. Do_Luns Lun. Lu_Martes Mar. Ma_Mércores Mér. Mé_Xoves Xov. Xo_Venres Ven. Ve_Sábado Sáb. Sá".split("_"); + + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "uns segundos", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "unha hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "unha hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un día", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un día", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 días", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un día", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 días", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 días", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mes", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mes", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mes", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mes", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un ano", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un ano", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anos", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un ano", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anos", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "nuns segundos", "prefix"); + test.equal(moment(0).from(30000), "hai uns segundos", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "hai uns segundos", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "nuns segundos", "en unos segundos"); + test.equal(moment().add({d:5}).fromNow(), "en 5 días", "en 5 días"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "hoxe ás 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "hoxe ás 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "hoxe ás 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "mañá ás 2:00", "tomorrow at the same time"); + test.equal(moment(a).add({ d: 1, h : -1 }).calendar(), "mañá á 1:00", "tomorrow minus 1 hour"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "hoxe á 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "onte á 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "regression tests" : function(test) { + test.expect(1); + + var lastWeek = moment().subtract({ d: 4 }).hours(1); + test.equal(lastWeek.calendar(), lastWeek.format('[o] dddd [pasado a] LT'), "1 o'clock bug"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1º', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1º', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2º', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2º', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3º', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/he.js b/node_modules/moment/test/lang/he.js new file mode 100644 index 0000000..fd4f06c --- /dev/null +++ b/node_modules/moment/test/lang/he.js @@ -0,0 +1,321 @@ +var moment = require("../../moment"); + + +/************************************************** + Hebrew +**************************************************/ + +exports["lang:he"] = { + setUp : function (cb) { + moment.lang('he'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'ינואר ינו׳_פברואר פבר׳_מרץ מרץ_אפריל אפר׳_מאי מאי_יוני יוני_יולי יולי_אוגוסט אוג׳_ספטמבר ספט׳_אוקטובר אוק׳_נובמבר נוב׳_דצמבר דצמ׳'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'ראשון, פברואר 14 2010, 3:25:50 pm'], + ['ddd, hA', 'א׳, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 פברואר פבר׳'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 ראשון א׳ א'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 בפברואר 2010'], + ['LLL', '14 בפברואר 2010 15:25'], + ['LLLL', 'ראשון, 14 בפברואר 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 פבר׳ 2010'], + ['lll', '14 פבר׳ 2010 15:25'], + ['llll', 'א׳, 14 פבר׳ 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'ינואר ינו׳_פברואר פבר׳_מרץ מרץ_אפריל אפר׳_מאי מאי_יוני יוני_יולי יולי_אוגוסט אוג׳_ספטמבר ספט׳_אוקטובר אוק׳_נובמבר נוב׳_דצמבר דצמ׳'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'ראשון א׳ א|שני ב׳ ב|שלישי ג׳ ג|רביעי ד׳ ד|חמישי ה׳ ה|שישי ו׳ ו|שבת ש׳ ש'.split("|"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "מספר שניות", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "דקה", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "דקה", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 דקות", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 דקות", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "שעה", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "שעה", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 שעות", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 שעות", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 שעות", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "יום", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "יום", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 ימים", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "יום", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 ימים", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 ימים", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "חודש", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "חודש", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "חודש", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 חודשים", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 חודשים", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 חודשים", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "חודש", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 חודשים", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 חודשים", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "שנה", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "שנה", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 שנים", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "שנה", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 שנים", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "בעוד מספר שניות", "prefix"); + test.equal(moment(0).from(30000), "לפני מספר שניות", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "לפני מספר שניות", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "בעוד מספר שניות", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "בעוד 5 ימים", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "היום ב־02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "היום ב־02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "היום ב־03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "מחר ב־02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "היום ב־01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "אתמול ב־02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [בשעה] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [בשעה] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [בשעה] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[ביום] dddd [האחרון בשעה] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[ביום] dddd [האחרון בשעה] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[ביום] dddd [האחרון בשעה] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/hi.js b/node_modules/moment/test/lang/hi.js new file mode 100644 index 0000000..6d88f66 --- /dev/null +++ b/node_modules/moment/test/lang/hi.js @@ -0,0 +1,383 @@ +var moment = require("../../moment"); + + + /************************************************** + Hindi + *************************************************/ + +exports["lang:hi"] = { + setUp : function (cb) { + moment.lang('hi'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'जनवरी जन._फ़रवरी फ़र._मार्च मार्च_अप्रैल अप्रै._मई मई_जून जून_जुलाई जुल._अगस्त अग._सितम्बर सित._अक्टूबर अक्टू._नवम्बर नव._दिसम्बर दिस.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(21); + + var a = [ + ['dddd, Do MMMM YYYY, a h:mm:ss बजे', 'रविवार, १४ फ़रवरी २०१०, दोपहर ३:२५:५० बजे'], + ['ddd, a h बजे', 'रवि, दोपहर ३ बजे'], + ['M Mo MM MMMM MMM', '२ २ ०२ फ़रवरी फ़र.'], + ['YYYY YY', '२०१० १०'], + ['D Do DD', '१४ १४ १४'], + ['d do dddd ddd dd', '० ० रविवार रवि र'], + ['DDD DDDo DDDD', '४५ ४५ ०४५'], + ['w wo ww', '८ ८ ०८'], + ['h hh', '३ ०३'], + ['H HH', '१५ १५'], + ['m mm', '२५ २५'], + ['s ss', '५० ५०'], + ['a A', 'दोपहर दोपहर'], + ['L', '१४/०२/२०१०'], + ['LL', '१४ फ़रवरी २०१०'], + ['LLL', '१४ फ़रवरी २०१०, दोपहर ३:२५ बजे'], + ['LLLL', 'रविवार, १४ फ़रवरी २०१०, दोपहर ३:२५ बजे'], + ['l', '१४/२/२०१०'], + ['ll', '१४ फ़र. २०१०'], + ['lll', '१४ फ़र. २०१०, दोपहर ३:२५ बजे'], + ['llll', 'रवि, १४ फ़र. २०१०, दोपहर ३:२५ बजे'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '१', '१'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '२', '२'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '३', '३'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '४', '४'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '५', '५'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '६', '६'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '७','७'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '८', '८'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '९', '९'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '१०', '१०'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '११', '११'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '१२', '१२'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '१३', '१३'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '१४', '१४'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '१५', '१५'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '१६', '१६'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '१७','१७'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '१८', '१८'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '१९', '१९'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '२०', '२०'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '२१', '२१'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '२२','२२'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '२३', '२३'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '२४','२४'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '२५','२५'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '२६','२६'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '२७','२७'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '२८','२८'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '२९','२९'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '३०', '३०'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '३१', '३१'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'जनवरी जन._फ़रवरी फ़र._मार्च मार्च_अप्रैल अप्रै._मई मई_जून जून_जुलाई जुल._अगस्त अग._सितम्बर सित._अक्टूबर अक्टू._नवम्बर नव._दिसम्बर दिस.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'रविवार रवि र_सोमवार सोम सो_मंगलवार मंगल मं_बुधवार बुध बु_गुरूवार गुरू गु_शुक्रवार शुक्र शु_शनिवार शनि श'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "कुछ ही क्षण", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "एक मिनट", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "एक मिनट", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "२ मिनट", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "४४ मिनट", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "एक घंटा", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "एक घंटा", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "२ घंटे", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "५ घंटे", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "२१ घंटे", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "एक दिन", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "एक दिन", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "२ दिन", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "एक दिन", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "५ दिन", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "२५ दिन", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "एक महीने", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "एक महीने", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "एक महीने", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "२ महीने", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "२ महीने", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "३ महीने", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "एक महीने", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "५ महीने", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "११ महीने", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "एक वर्ष", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "एक वर्ष", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "२ वर्ष", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "एक वर्ष", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "५ वर्ष", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "कुछ ही क्षण में", "prefix"); + test.equal(moment(0).from(30000), "कुछ ही क्षण पहले", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "कुछ ही क्षण पहले", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "कुछ ही क्षण में", "कुछ ही क्षण में"); + test.equal(moment().add({d:5}).fromNow(), "५ दिन में", "५ दिन में"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "आज रात २:०० बजे", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "आज रात २:२५ बजे", "Now plus 25 min"); + test.equal(moment(a).add({ h: 3 }).calendar(), "आज सुबह ५:०० बजे", "Now plus 3 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "कल रात २:०० बजे", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "आज रात १:०० बजे", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "कल रात २:०० बजे", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd[,] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd[,] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd[,] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[पिछले] dddd[,] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[पिछले] dddd[,] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[पिछले] dddd[,] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + "meridiem" : function(test) { + test.expect(12); + + test.equal(moment([2011, 2, 23, 2, 30]).format('a'), "रात", "before dawn"); + test.equal(moment([2011, 2, 23, 9, 30]).format('a'), "सुबह", "morning"); + test.equal(moment([2011, 2, 23, 14, 30]).format('a'), "दोपहर","during day"); + test.equal(moment([2011, 2, 23, 17, 30]).format('a'), "शाम", "evening"); + test.equal(moment([2011, 2, 23, 19, 30]).format('a'), "शाम", "late evening"); + test.equal(moment([2011, 2, 23, 21, 20]).format('a'), "रात", "night"); + + test.equal(moment([2011, 2, 23, 2, 30]).format('A'), "रात", "before dawn"); + test.equal(moment([2011, 2, 23, 9, 30]).format('A'), "सुबह", "morning"); + test.equal(moment([2011, 2, 23, 14, 30]).format('A'), "दोपहर","during day"); + test.equal(moment([2011, 2, 23, 17, 30]).format('A'), "शाम", "evening"); + test.equal(moment([2011, 2, 23, 19, 30]).format('A'), "शाम", "late evening"); + test.equal(moment([2011, 2, 23, 21, 20]).format('A'), "रात", "night"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '१ ०१ १', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '१ ०१ १', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '२ ०२ २', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '२ ०२ २', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '३ ०३ ३', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/hu.js b/node_modules/moment/test/lang/hu.js new file mode 100644 index 0000000..1bf3b40 --- /dev/null +++ b/node_modules/moment/test/lang/hu.js @@ -0,0 +1,361 @@ +var moment = require("../../moment"); + + /************************************************** + Hungarian + *************************************************/ + +exports["lang:hu"] = { + setUp : function (cb) { + moment.lang('hu'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'január jan_február feb_március márc_április ápr_május máj_június jún_július júl_augusztus aug_szeptember szept_október okt_november nov_december dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(20); + + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'vasárnap, február 14. 2010, 15:25:50'], + ['ddd, HH', 'v, 15'], + ['M Mo MM MMMM MMM', '2 2. 02 február feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd', '0 0. vasárnap v'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '7 7. 07'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['[az év] DDDo [napja]', 'az év 45. napja'], + ['L', '2010.02.14.'], + ['LL', '2010. február 14.'], + ['LLL', '2010. február 14., 15:25'], + ['LLLL', '2010. február 14., vasárnap 15:25'], + ['l', '2010.2.14.'], + ['ll', '2010. feb 14.'], + ['lll', '2010. feb 14., 15:25'], + ['llll', '2010. feb 14., v 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'január jan_február feb_március márc_április ápr_május máj_június jún_július júl_augusztus aug_szeptember szept_október okt_november nov_december dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'vasárnap v_hétfő h_kedd k_szerda sze_csütörtök cs_péntek p_szombat szo'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "néhány másodperc", "44 másodperc = néhány másodperc"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "egy perc", "45 másodperc = egy perc"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "egy perc", "89 másodperc = egy perc"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 perc", "90 másodperc = 2 perc"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 perc", "44 perc = 44 perc"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "egy óra", "45 perc = egy óra"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "egy óra", "89 perc = egy óra"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 óra", "90 perc = 2 óra"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 óra", "5 óra = 5 óra"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 óra", "21 óra = 21 óra"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "egy nap", "22 óra = egy nap"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "egy nap", "35 óra = egy nap"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 nap", "36 óra = 2 nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "egy nap", "1 nap = egy nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 nap", "5 nap = 5 nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 nap", "25 nap = 25 nap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "egy hónap", "26 nap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "egy hónap", "30 nap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "egy hónap", "45 nap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 hónap", "46 nap = 2 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 hónap", "75 nap = 2 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 hónap", "76 nap = 3 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "egy hónap", "1 hónap = egy hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 hónap", "5 hónap = 5 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 hónap", "344 nap = 11 hónap"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "egy év", "345 nap = egy év"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "egy év", "547 nap = egy év"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 év", "548 nap = 2 év"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "egy év", "1 év = egy év"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 év", "5 év = 5 év"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "néhány másodperc múlva", "prefix"); + test.equal(moment(0).from(30000), "néhány másodperce", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "néhány másodperce", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "néhány másodperc múlva", "néhány másodperc múlva"); + test.equal(moment().add({d:5}).fromNow(), "5 nap múlva", "5 nap múlva"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "ma 2:00-kor", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "ma 2:25-kor", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "ma 3:00-kor", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "holnap 2:00-kor", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "ma 1:00-kor", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "tegnap 2:00-kor", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + var days = 'vasárnap_hétfőn_kedden_szerdán_csütörtökön_pénteken_szombaton'.split('_'); + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('['+days[m.day()]+'] LT[-kor]'), "today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('['+days[m.day()]+'] LT[-kor]'), "today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('['+days[m.day()]+'] LT[-kor]'), "today + " + i + " days end of day"); + } + + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + var days = 'vasárnap_hétfőn_kedden_szerdán_csütörtökön_pénteken_szombaton'.split('_'); + + for (var i = 2; i < 7; i++) { + var m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[múlt '+days[m.day()]+'] LT[-kor]'), "today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[múlt '+days[m.day()]+'] LT[-kor]'), "today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[múlt '+days[m.day()]+'] LT[-kor]'), "today - " + i + " days end of day"); + } + + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "egy héte"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "egy hét múlva"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 hete"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "2 hét múlva"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/id.js b/node_modules/moment/test/lang/id.js new file mode 100644 index 0000000..17ff083 --- /dev/null +++ b/node_modules/moment/test/lang/id.js @@ -0,0 +1,318 @@ +var moment = require("../../moment"); + + + /************************************************** + Indonesian + *************************************************/ + +exports["lang:id"] = { + setUp : function (cb) { + moment.lang('id'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'Januari Jan_Februari Feb_Maret Mar_April Apr_Mei Mei_Juni Jun_Juli Jul_Agustus Ags_September Sep_Oktober Okt_November Nov_Desember Des'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Minggu, Februari 14 2010, 3:25:50 sore'], + ['ddd, hA', 'Min, 3sore'], + ['M Mo MM MMMM MMM', '2 2 02 Februari Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 Minggu Min Mg'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '7 7 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'sore sore'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 Februari 2010'], + ['LLL', '14 Februari 2010 pukul 15.25'], + ['LLLL', 'Minggu, 14 Februari 2010 pukul 15.25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 pukul 15.25'], + ['llll', 'Min, 14 Feb 2010 pukul 15.25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'Januari Jan_Februari Feb_Maret Mar_April Apr_Mei Mei_Juni Jun_Juli Jul_Agustus Ags_September Sep_Oktober Okt_November Nov_Desember Des'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'Minggu Min Mg_Senin Sen Sn_Selasa Sel Sl_Rabu Rab Rb_Kamis Kam Km_Jumat Jum Jm_Sabtu Sab Sb'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "beberapa detik", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "semenit", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "semenit", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 menit", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 menit", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "sejam", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "sejam", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 jam", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 jam", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 jam", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "sehari", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "sehari", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 hari", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "sehari", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 hari", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 hari", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "sebulan", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "sebulan", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "sebulan", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 bulan", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 bulan", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 bulan", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "sebulan", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 bulan", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 bulan", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "setahun", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "setahun", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 tahun", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "setahun", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 tahun", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "dalam beberapa detik", "prefix"); + test.equal(moment(0).from(30000), "beberapa detik yang lalu", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "beberapa detik yang lalu", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "dalam beberapa detik", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "dalam 5 hari", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hari ini pukul 02.00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hari ini pukul 02.25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hari ini pukul 03.00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Besok pukul 02.00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hari ini pukul 01.00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Kemarin pukul 02.00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [pukul] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [pukul] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [pukul] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [lalu pukul] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [lalu pukul] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [lalu pukul] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/is.js b/node_modules/moment/test/lang/is.js new file mode 100644 index 0000000..9ada489 --- /dev/null +++ b/node_modules/moment/test/lang/is.js @@ -0,0 +1,370 @@ +var moment = require("../../moment"); + + + /************************************************** + Icelandic + *************************************************/ + +exports["lang:is"] = { + setUp : function (cb) { + moment.lang('is'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'janúar jan_febrúar feb_mars mar_apríl apr_maí maí_júní jún_júlí júl_ágúst ágú_september sep_október okt_nóvember nóv_desember des'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'sunnudagur, 14. febrúar 2010, 3:25:50 pm'], + ['ddd, hA', 'sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 febrúar feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. sunnudagur sun Su'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '14/02/2010'], + ['LL', '14. febrúar 2010'], + ['LLL', '14. febrúar 2010 kl. 15:25'], + ['LLLL', 'sunnudagur, 14. febrúar 2010 kl. 15:25'], + ['l', '14/2/2010'], + ['ll', '14. feb 2010'], + ['lll', '14. feb 2010 kl. 15:25'], + ['llll', 'sun, 14. feb 2010 kl. 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'janúar jan_febrúar feb_mars mar_apríl apr_maí maí_júní jún_júlí júl_ágúst ágú_september sep_október okt_nóvember nóv_desember des'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'sunnudagur sun Su_mánudagur mán Má_þriðjudagur þri Þr_miðvikudagur mið Mi_fimmtudagur fim Fi_föstudagur fös Fö_laugardagur lau La'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(34); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "nokkrar sekúndur", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "mínúta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "mínúta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 mínútur", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 mínútur", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:21}), true), "21 mínúta", "21 minutes = 21 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "klukkustund", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "klukkustund", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 klukkustundir", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 klukkustundir", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 klukkustund", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "dagur", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "dagur", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagar", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "dagur", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagar", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagar", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:11}), true), "11 dagar", "11 days = 11 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:21}), true), "21 dagur", "21 days = 21 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "mánuður", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "mánuður", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "mánuður", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mánuðir", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mánuðir", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mánuðir", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "mánuður", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mánuðir", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mánuðir", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ár", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ár", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ár", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ár", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ár", "5 years = 5 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:21}), true), "21 ár", "21 years = 21 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(3); + test.equal(moment(30000).from(0), "eftir nokkrar sekúndur", "prefix"); + test.equal(moment(0).from(30000), "fyrir nokkrum sekúndum síðan", "suffix"); + test.equal(moment().subtract({m:1}).fromNow(), "fyrir mínútu síðan", "a minute ago"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "fyrir nokkrum sekúndum síðan", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(3); + test.equal(moment().add({s:30}).fromNow(), "eftir nokkrar sekúndur", "in a few seconds"); + test.equal(moment().add({m:1}).fromNow(), "eftir mínútu", "in a minute"); + test.equal(moment().add({d:5}).fromNow(), "eftir 5 daga", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "í dag kl. 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "í dag kl. 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "í dag kl. 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "á morgun kl. 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "í dag kl. 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "í gær kl. 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [kl.] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [kl.] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [kl.] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/it.js b/node_modules/moment/test/lang/it.js new file mode 100644 index 0000000..e6857c2 --- /dev/null +++ b/node_modules/moment/test/lang/it.js @@ -0,0 +1,359 @@ +var moment = require("../../moment"); + + + /************************************************** + Italian + *************************************************/ + +exports["lang:it"] = { + setUp : function (cb) { + moment.lang('it'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'Gennaio Gen_Febbraio Feb_Marzo Mar_Aprile Apr_Maggio Mag_Giugno Giu_Luglio Lug_Agosto Ago_Settembre Set_Ottobre Ott_Novembre Nov_Dicembre Dic'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domenica, Febbraio 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom, 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Febbraio Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd dd', '0 0º Domenica Dom D'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '6 6º 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 Febbraio 2010'], + ['LLL', '14 Febbraio 2010 15:25'], + ['LLLL', 'Domenica, 14 Febbraio 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 15:25'], + ['llll', 'Dom, 14 Feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'Gennaio Gen_Febbraio Feb_Marzo Mar_Aprile Apr_Maggio Mag_Giugno Giu_Luglio Lug_Agosto Ago_Settembre Set_Ottobre Ott_Novembre Nov_Dicembre Dic'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'Domenica Dom D_Lunedì Lun L_Martedì Mar Ma_Mercoledì Mer Me_Giovedì Gio G_Venerdì Ven V_Sabato Sab S'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "secondi", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuti", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuti", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "un'ora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "un'ora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ore", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ore", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ore", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "un giorno", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "un giorno", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 giorni", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "un giorno", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 giorni", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 giorni", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "un mese", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "un mese", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "un mese", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mesi", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mesi", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mesi", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "un mese", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mesi", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mesi", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un anno", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un anno", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anni", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un anno", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anni", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "in secondi", "prefix"); + test.equal(moment(0).from(30000), "secondi fa", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "in secondi", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "tra 5 giorni", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Oggi alle 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Oggi alle 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Oggi alle 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Domani alle 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Oggi alle 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ieri alle 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [alle] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [alle] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [alle] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[lo scorso] dddd [alle] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[lo scorso] dddd [alle] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[lo scorso] dddd [alle] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ja.js b/node_modules/moment/test/lang/ja.js new file mode 100644 index 0000000..cb315d9 --- /dev/null +++ b/node_modules/moment/test/lang/ja.js @@ -0,0 +1,323 @@ +var moment = require("../../moment"); + + + /************************************************** + Japanese + *************************************************/ + +exports["lang:ja"] = { + setUp : function (cb) { + moment.lang('ja'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '日曜日, 2月 14 2010, 午後 3:25:50'], + ['ddd, Ah', '日, 午後3'], + ['M Mo MM MMMM MMM', '2 2 02 2月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 日曜日 日 日'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '午後 午後'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '2010/02/14'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日午後3時25分'], + ['LLLL', '2010年2月14日午後3時25分 日曜日'], + ['l', '2010/2/14'], + ['ll', '2010年2月14日'], + ['lll', '2010年2月14日午後3時25分'], + ['llll', '2010年2月14日午後3時25分 日'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = '1月 1月_2月 2月_3月 3月_4月 4月_5月 5月_6月 6月_7月 7月_8月 8月_9月 9月_10月 10月_11月 11月_12月 12月'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = '日曜日 日 日_月曜日 月 月_火曜日 火 火_水曜日 水 水_木曜日 木 木_金曜日 金 金_土曜日 土 土'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "数秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "1分", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "1分", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "1時間", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "1時間", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2時間", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5時間", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21時間", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1日", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1日", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2日", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1日", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5日", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25日", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "1ヶ月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "1ヶ月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "1ヶ月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2ヶ月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2ヶ月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3ヶ月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "1ヶ月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5ヶ月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11ヶ月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "1年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "1年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "1年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "数秒後", "prefix"); + test.equal(moment(0).from(30000), "数秒前", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "数秒前", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "数秒後", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5日後", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今日 午前2時0分", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今日 午前2時25分", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今日 午前3時0分", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明日 午前2時0分", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今日 午前1時0分", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨日 午前2時0分", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[来週]dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[前週]dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ka.js b/node_modules/moment/test/lang/ka.js new file mode 100644 index 0000000..ab0fb89 --- /dev/null +++ b/node_modules/moment/test/lang/ka.js @@ -0,0 +1,379 @@ +// moment.js language configuration +// language : Georgian (ka) +// author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +var moment = require("../../moment"); + +exports["lang:ka"] = { + setUp : function (cb) { + moment.lang('ka'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('ka'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'იანვარი იან_თებერვალი თებ_მარტი მარ_აპრილი აპრ_მაისი მაი_ივნისი ივნ_ივლისი ივლ_აგვისტო აგვ_სექტემბერი სექ_ოქტომბერი ოქტ_ნოემბერი ნოე_დეკემბერი დეკ'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' უნდა იყოს თვე ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'კვირა, თებერვალი მე-14 2010, 3:25:50 pm'], + ['ddd, hA', 'კვი, 3PM'], + ['M Mo MM MMMM MMM', '2 მე-2 02 თებერვალი თებ'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 მე-14 14'], + ['d do dddd ddd dd', '0 0 კვირა კვი კვ'], + ['DDD DDDo DDDD', '45 45-ე 045'], + ['w wo ww', '7 მე-7 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['წლის DDDo დღე', 'წლის 45-ე დღე'], + ['L', '14/02/2010'], + ['LL', '14 თებერვალი 2010'], + ['LLL', '14 თებერვალი 2010 3:25 PM'], + ['LLLL', 'კვირა, 14 თებერვალი 2010 3:25 PM'], + ['l', '14/2/2010'], + ['ll', '14 თებ 2010'], + ['lll', '14 თებ 2010 3:25 PM'], + ['llll', 'კვი, 14 თებ 2010 3:25 PM'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(35); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1-ლი', '1-ლი'); + test.equal(moment([2011, 0, 2]).format('DDDo'), 'მე-2', 'მე-2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), 'მე-3', 'მე-3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), 'მე-4', 'მე-4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), 'მე-5', 'მე-5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), 'მე-6', 'მე-6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), 'მე-7', 'მე-7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), 'მე-8', 'მე-8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), 'მე-9', 'მე-9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), 'მე-10', 'მე-10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), 'მე-11', 'მე-11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), 'მე-12', 'მე-12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), 'მე-13', 'მე-13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), 'მე-14', 'მე-14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), 'მე-15', 'მე-15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), 'მე-16', 'მე-16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), 'მე-17', 'მე-17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), 'მე-18', 'მე-18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), 'მე-19', 'მე-19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), 'მე-20', 'მე-20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21-ე', '21-ე'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22-ე', '22-ე'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23-ე', '23-ე'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24-ე', '24-ე'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25-ე', '25-ე'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26-ე', '26-ე'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27-ე', '27-ე'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28-ე', '28-ე'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29-ე', '29-ე'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30-ე', '30-ე'); + + test.equal(moment([2011, 0, 0]).add('days', 40).format('DDDo'), 'მე-40', 'მე-40'); + test.equal(moment([2011, 0, 0]).add('days', 50).format('DDDo'), '50-ე', '50-ე'); + test.equal(moment([2011, 0, 0]).add('days', 60).format('DDDo'), 'მე-60', 'მე-60'); + test.equal(moment([2011, 0, 0]).add('days', 100).format('DDDo'), 'მე-100', 'მე-100'); + test.equal(moment([2011, 0, 0]).add('days', 101).format('DDDo'), '101-ე', '101-ე'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'იანვარი იან_თებერვალი თებ_მარტი მარ_აპრილი აპრ_მაისი მაი_ივნისი ივნ_ივლისი ივლ_აგვისტო აგვ_სექტემბერი სექ_ოქტომბერი ოქტ_ნოემბერი ნოე_დეკემბერი დეკ'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'კვირა კვი კვ_ორშაბათი ორშ ორ_სამშაბათი სამ სა_ოთხშაბათი ოთხ ოთ_ხუთშაბათი ხუთ ხუ_პარასკევი პარ პა_შაბათი შაბ შა'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "რამდენიმე წამი", "44 წამი = რამდენიმე წამი"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "წუთი", "45 წამი = წუთი"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "წუთი", "89 წამი = წუთი"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 წუთი", "90 წამი = 2 წუთი"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 წუთი", "44 წამი = 44 წუთი"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "საათი", "45 წამი = საათი"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "საათი", "89 წამი = საათი"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 საათი", "90 წამი = 2 საათი"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 საათი", "5 საათი = 5 საათი"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 საათი", "21 საათი = 21 საათი"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "დღე", "22 საათი = დღე"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "დღე", "35 საათი = დღე"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 დღე", "36 საათი = 2 დღე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "დღე", "1 დღე = დღე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 დღე", "5 დღე = 5 დღე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 დღე", "25 დღე = 25 დღე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "თვე", "26 დღე = თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "თვე", "30 დღე = თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "თვე", "45 დღე = თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 თვე", "46 დღე = 2 თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 თვე", "75 დღე = 2 თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 თვე", "76 დღე = 3 თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "თვე", "1 თვე = თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 თვე", "5 თვე = 5 თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 თვე", "344 დღე = 11 თვე"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "წელი", "345 დღე = წელი"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "წელი", "547 დღე = წელი"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 წელი", "548 დღე = 2 წელი"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "წელი", "1 წელი = წელი"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 წელი", "5 წელი = 5 წელი"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "რამდენიმე წამში", "ში სუფიქსი"); + test.equal(moment(0).from(30000), "რამდენიმე წამის წინ", "წინ სუფიქსი"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "რამდენიმე წამის წინ", "უნდა აჩვენოს როგორც წარსული"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "რამდენიმე წამში", "რამდენიმე წამში"); + test.equal(moment().add({d:5}).fromNow(), "5 დღეში", "5 დღეში"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "დღეს 2:00 AM-ზე", "დღეს ამავე დროს"); + test.equal(moment(a).add({ m: 25 }).calendar(), "დღეს 2:25 AM-ზე", "ახლანდელ დროს დამატებული 25 წუთი"); + test.equal(moment(a).add({ h: 1 }).calendar(), "დღეს 3:00 AM-ზე", "ახლანდელ დროს დამატებული 1 საათი"); + test.equal(moment(a).add({ d: 1 }).calendar(), "ხვალ 2:00 AM-ზე", "ხვალ ამავე დროს"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "დღეს 1:00 AM-ზე", "ახლანდელ დროს გამოკლებული 1 საათი"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "გუშინ 2:00 AM-ზე", "გუშინ ამავე დროს"); + + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[შემდეგ] dddd LT[-ზე]'), "დღეს + " + i + " დღე ახლანდელ დროს"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[შემდეგ] dddd LT[-ზე]'), "დღეს + " + i + " დღე დღის დასაწყისში"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[შემდეგ] dddd LT[-ზე]'), "დღეს + " + i + " დღე დღის დასასრულს"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[წინა] dddd LT[-ზე]'), "დღეს - " + i + " დღე ახლანდელ დროს"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[წინა] dddd LT[-ზე]'), "დღეს - " + i + " დღე დღის დასაწყისში"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[წინა] dddd LT[-ზე]'), "დღეს - " + i + " დღე დღის დასასრულს"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }), + weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 კვირის წინ"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "1 კვირაში"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 კვირის წინ"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "2 კვირაში"); + + test.done(); + }, + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "დეკ 26 2011 უნდა იყოს კვირა 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "იან 1 2012 უნდა იყოს კვირა 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "იან 2 2012 უნდა იყოს კვირა 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "იან 8 2012 უნდა იყოს კვირა 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "იან 9 2012 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "იან 1 2007 უნდა იყოს კვირა 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "იან 7 2007 უნდა იყოს კვირა 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "იან 8 2007 უნდა იყოს კვირა 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "იან 14 2007 უნდა იყოს კვირა 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "იან 15 2007 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "დეკ 31 2007 უნდა იყოს კვირა 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "იან 1 2008 უნდა იყოს კვირა 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "იან 6 2008 უნდა იყოს კვირა 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "იან 7 2008 უნდა იყოს კვირა 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "იან 13 2008 უნდა იყოს კვირა 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "იან 14 2008 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "დეკ 30 2002 უნდა იყოს კვირა 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "იან 1 2003 უნდა იყოს კვირა 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "იან 5 2003 უნდა იყოს კვირა 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "იან 6 2003 უნდა იყოს კვირა 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "იან 12 2003 უნდა იყოს კვირა 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "იან 13 2003 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "დეკ 29 2008 უნდა იყოს კვირა 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "იან 1 2009 უნდა იყოს კვირა 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "იან 4 2009 უნდა იყოს კვირა 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "იან 5 2009 უნდა იყოს კვირა 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "იან 11 2009 უნდა იყოს კვირა 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "იან 12 2009 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "დეკ 28 2009 უნდა იყოს კვირა 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "იან 1 2010 უნდა იყოს კვირა 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "იან 3 2010 უნდა იყოს კვირა 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "იან 4 2010 უნდა იყოს კვირა 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "იან 10 2010 უნდა იყოს კვირა 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "იან 11 2010 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "დეკ 27 2010 უნდა იყოს კვირა 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "იან 1 2011 უნდა იყოს კვირა 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "იან 2 2011 უნდა იყოს კვირა 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "იან 3 2011 უნდა იყოს კვირა 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "იან 9 2011 უნდა იყოს კვირა 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "იან 10 2011 უნდა იყოს კვირა 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ლი', "დეკ 26 2011 უნდა იყოს კვირა 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ლი', "იან 1 2012 უნდა იყოს კვირა 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 მე-2', "იან 2 2012 უნდა იყოს კვირა 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 მე-2', "იან 8 2012 უნდა იყოს კვირა 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 მე-3', "იან 9 2012 უნდა იყოს კვირა 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ko.js b/node_modules/moment/test/lang/ko.js new file mode 100644 index 0000000..24dd100 --- /dev/null +++ b/node_modules/moment/test/lang/ko.js @@ -0,0 +1,370 @@ +var moment = require("../../moment"); + + + /************************************************** + Korean + *************************************************/ + +exports["lang:kr"] = { + setUp : function (cb) { + moment.lang('ko'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = '1월 1월_2월 2월_3월 3월_4월 4월_5월 5월_6월 6월_7월 7월_8월 8월_9월 9월_10월 10월_11월 11월_12월 12월'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + "format" : function(test) { + test.expect(22); + + var a = [ + ['YYYY년 MMMM Do dddd a h:mm:ss', '2010년 2월 14일 일요일 오후 3:25:50'], + ['ddd A h', '일 오후 3'], + ['M Mo MM MMMM MMM', '2 2일 02 2월 2월'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14일 14'], + ['d do dddd ddd dd', '0 0일 일요일 일 일'], + ['DDD DDDo DDDD', '45 45일 045'], + ['w wo ww', '8 8일 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '오후 오후'], + ['일년 중 DDDo째 되는 날', '일년 중 45일째 되는 날'], + ['L', '2010.02.14'], + ['LL', '2010년 2월 14일'], + ['LLL', '2010년 2월 14일 오후 3시 25분'], + ['LLLL', '2010년 2월 14일 일요일 오후 3시 25분'], + ['l', '2010.2.14'], + ['ll', '2010년 2월 14일'], + ['lll', '2010년 2월 14일 오후 3시 25분'], + ['llll', '2010년 2월 14일 일 오후 3시 25분'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1일', '1일'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2일', '2일'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3일', '3일'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4일', '4일'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5일', '5일'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6일', '6일'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7일', '7일'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8일', '8일'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9일', '9일'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10일', '10일'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11일', '11일'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12일', '12일'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13일', '13일'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14일', '14일'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15일', '15일'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16일', '16일'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17일', '17일'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18일', '18일'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19일', '19일'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20일', '20일'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21일', '21일'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22일', '22일'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23일', '23일'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24일', '24일'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25일', '25일'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26일', '26일'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27일', '27일'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28일', '28일'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29일', '29일'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30일', '30일'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31일', '31일'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = '1월 1월_2월 2월_3월 3월_4월 4월_5월 5월_6월 6월_7월 7월_8월 8월_9월 9월_10월 10월_11월 11월_12월 12월'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = '일요일 일 일_월요일 월 월_화요일 화 화_수요일 수 수_목요일 목 목_금요일 금 금_토요일 토 토'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "몇초", "44초 = 몇초"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "일분", "45초 = 일분"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "일분", "89초 = 일분"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2분", "90초 = 2분"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44분", "44분 = 44분"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "한시간", "45분 = 한시간"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "한시간", "89분 = 한시간"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2시간", "90분 = 2시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5시간", "5시간 = 5시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21시간", "21시간 = 21시간"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "하루", "22시간 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "하루", "35시간 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2일", "36시간 = 2일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "하루", "하루 = 하루"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5일", "5일 = 5일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25일", "25일 = 25일"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "한달", "26일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "한달", "30일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "한달", "45일 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2달", "46일 = 2달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2달", "75일 = 2달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3달", "76일 = 3달"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "한달", "1달 = 한달"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5달", "5달 = 5달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11달", "344일 = 11달"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "일년", "345일 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "일년", "547일 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2년", "548일 = 2년"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "일년", "일년 = 일년"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5년", "5년 = 5년"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "몇초 후", "prefix"); + test.equal(moment(0).from(30000), "몇초 전", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "몇초 전", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "몇초 후", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5일 후", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "오늘 오전 2시 00분", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "오늘 오전 2시 25분", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "오늘 오전 3시 00분", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "내일 오전 2시 00분", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "오늘 오전 1시 00분", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "어제 오전 2시 00분", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('지난주 dddd LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1일', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1일', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2일', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2일', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3일', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/lv.js b/node_modules/moment/test/lang/lv.js new file mode 100644 index 0000000..e256f81 --- /dev/null +++ b/node_modules/moment/test/lang/lv.js @@ -0,0 +1,362 @@ +var moment = require("../../moment"); + + + /************************************************** + Latvian + *************************************************/ + +exports["lang:lv"] = { + setUp : function (cb) { + moment.lang('lv'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'janvāris jan_februāris feb_marts mar_aprīlis apr_maijs mai_jūnijs jūn_jūlijs jūl_augusts aug_septembris sep_oktobris okt_novembris nov_decembris dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'svētdiena, 14. februāris 2010, 3:25:50 pm'], + ['ddd, hA', 'Sv, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 februāris feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. svētdiena Sv Sv'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '14.02.2010'], + ['LL', '2010. gada 14. februāris'], + ['LLL', '2010. gada 14. februāris, 15:25'], + ['LLLL', '2010. gada 14. februāris, svētdiena, 15:25'], + ['l', '14.2.2010'], + ['ll', '2010. gada 14. feb'], + ['lll', '2010. gada 14. feb, 15:25'], + ['llll', '2010. gada 14. feb, Sv, 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'janvāris jan_februāris feb_marts mar_aprīlis apr_maijs mai_jūnijs jūn_jūlijs jūl_augusts aug_septembris sep_oktobris okt_novembris nov_decembris dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'svētdiena Sv Sv_pirmdiena P P_otrdiena O O_trešdiena T T_ceturtdiena C C_piektdiena Pk Pk_sestdiena S S'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "dažas sekundes", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minūti", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minūti", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minūtes", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minūtes", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "stundu", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "stundu", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 stundas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 stundas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 stunda", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "dienu", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "dienu", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dienas", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "dienu", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dienas", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dienas", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "mēnesi", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "mēnesi", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "mēnesi", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mēneši", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mēneši", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mēneši", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "mēnesi", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mēneši", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mēneši", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "gadu", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "gadu", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 gadi", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "gadu", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 gadi", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "dažas sekundes vēlāk", "prefix"); + test.equal(moment(0).from(30000), "dažas sekundes agrāk", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "dažas sekundes agrāk", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "dažas sekundes vēlāk", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 dienas vēlāk", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Šodien pulksten 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Šodien pulksten 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Šodien pulksten 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Rīt pulksten 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Šodien pulksten 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Vakar pulksten 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [pulksten] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [pulksten] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [pulksten] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Pagājušā] dddd [pulksten] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Pagājušā] dddd [pulksten] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Pagājušā] dddd [pulksten] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ms-my.js b/node_modules/moment/test/lang/ms-my.js new file mode 100644 index 0000000..70f1a68 --- /dev/null +++ b/node_modules/moment/test/lang/ms-my.js @@ -0,0 +1,379 @@ +var moment = require("../../moment"); + + + /************************************************** + Bahasa Melayu + *************************************************/ + +exports["lang:ms-my"] = { + setUp : function (cb) { + moment.lang('ms-my'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'Januari Jan_Februari Feb_Mac Mac_April Apr_Mei Mei_Jun Jun_Julai Jul_Ogos Ogs_September Sep_Oktober Okt_November Nov_Disember Dis'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' sepatutnya bulan ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Ahad, Februari 14 2010, 3:25:50 petang'], + ['ddd, hA', 'Ahd, 3petang'], + ['M Mo MM MMMM MMM', '2 2 02 Februari Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 Ahad Ahd Ah'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '7 7 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'petang petang'], + ['[hari] [ke] DDDo [tahun] ini', 'hari ke 45 tahun ini'], + ['L', '14/02/2010'], + ['LL', '14 Februari 2010'], + ['LLL', '14 Februari 2010 pukul 15.25'], + ['LLLL', 'Ahad, 14 Februari 2010 pukul 15.25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 pukul 15.25'], + ['llll', 'Ahd, 14 Feb 2010 pukul 15.25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'Januari Jan_Februari Feb_Mac Mac_April Apr_Mei Mei_Jun Jun_Julai Jul_Ogos Ogs_September Sep_Oktober Okt_November Nov_Disember Dis'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'Ahad Ahd Ah_Isnin Isn Is_Selasa Sel Sl_Rabu Rab Rb_Khamis Kha Km_Jumaat Jum Jm_Sabtu Sab Sb'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "beberapa saat", "44 saat = beberapa saat"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "seminit", "45 saat = seminit"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "seminit", "89 saat = seminit"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minit", "90 saat = 2 minit"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minit", "44 minit = 44 minit"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "sejam", "45 minit = sejam"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "sejam", "89 minit = sejam"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 jam", "90 minit = 2 jam"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 jam", "5 jam = 5 jam"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 jam", "21 jam = 21 jam"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "sehari", "22 jam = sehari"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "sehari", "35 jam = sehari"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 hari", "36 jam = 2 hari"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "sehari", "1 hari = sehari"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 hari", "5 hari = 5 hari"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 hari", "25 hari = 25 hari"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "sebulan", "26 hari = sebulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "sebulan", "30 hari = sebulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "sebulan", "45 hari = sebulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 bulan", "46 hari = 2 bulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 bulan", "75 hari = 2 bulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 bulan", "76 hari = 3 bulan"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "sebulan", "1 bulan = sebulan"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 bulan", "5 bulan = 5 bulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 bulan", "344 hari = 11 bulan"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "setahun", "345 hari = setahun"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "setahun", "547 hari = setahun"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 tahun", "548 hari = 2 tahun"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "setahun", "1 tahun = setahun"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 tahun", "5 tahun = 5 tahun"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "dalam beberapa saat", "prefix"); + test.equal(moment(0).from(30000), "beberapa saat yang lepas", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "beberapa saat yang lepas", "waktu sekarang dari sekarang sepatutnya menunjukkan sebagai telah lepas"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "dalam beberapa saat", "dalam beberapa saat"); + test.equal(moment().add({d:5}).fromNow(), "dalam 5 hari", "dalam 5 hari"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hari ini pukul 02.00", "hari ini pada waktu yang sama"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hari ini pukul 02.25", "Sekarang tambah 25 minit"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hari ini pukul 03.00", "Sekarang tambah 1 jam"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Esok pukul 02.00", "esok pada waktu yang sama"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hari ini pukul 01.00", "Sekarang tolak 1 jam"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Kelmarin pukul 02.00", "kelmarin pada waktu yang sama"); + + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [pukul] LT'), "Hari ini + " + i + " hari waktu sekarang"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [pukul] LT'), "Hari ini + " + i + " hari permulaan hari"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [pukul] LT'), "Hari ini + " + i + " hari tamat hari"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [lepas] [pukul] LT'), "Hari ini - " + i + " hari waktu sekarang"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [lepas] [pukul] LT'), "Hari ini - " + i + " hari permulaan hari"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [lepas] [pukul] LT'), "Hari ini - " + i + " hari tamat hari"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }), + weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 minggu lepas"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "dalam 1 minggu"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 minggu lepas"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "dalam 2 minggu"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 sepatutnya minggu 1"); + test.equal(moment([2012, 0, 7]).week(), 2, "Jan 7 2012 sepatutnya minggu 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 sepatutnya minggu 2"); + test.equal(moment([2012, 0, 14]).week(), 3, "Jan 14 2012 sepatutnya minggu 3"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 sepatutnya minggu 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 53, "Dec 31 2006 sepatutnya minggu 53"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 sepatutnya minggu 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 sepatutnya minggu 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 sepatutnya minggu 1"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 sepatutnya minggu 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 sepatutnya minggu 2"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 52, "Dec 30 2007 sepatutnya minggu 52"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 sepatutnya minggu 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 sepatutnya minggu 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 sepatutnya minggu 1"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 sepatutnya minggu 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 sepatutnya minggu 2"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 52, "Dec 29 2002 sepatutnya minggu 52"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 sepatutnya minggu 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 sepatutnya minggu 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 sepatutnya minggu 1"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 sepatutnya minggu 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 sepatutnya minggu 2"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 52, "Dec 28 2008 sepatutnya minggu 52"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 sepatutnya minggu 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 sepatutnya minggu 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 sepatutnya minggu 1"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 sepatutnya minggu 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 sepatutnya minggu 2"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 52, "Dec 27 2009 sepatutnya minggu 52"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 sepatutnya minggu 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 sepatutnya minggu 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 sepatutnya minggu 1"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 sepatutnya minggu 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 sepatutnya minggu 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 52, "Dec 26 2010 sepatutnya minggu 52"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 sepatutnya minggu 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 sepatutnya minggu 1"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 sepatutnya minggu 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 sepatutnya minggu 2"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', "Jan 1 2012 sepatutnya minggu 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', "Jan 7 2012 sepatutnya minggu 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 sepatutnya minggu 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', "Jan 14 2012 sepatutnya minggu 3"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', "Jan 15 2012 sepatutnya minggu 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/nb.js b/node_modules/moment/test/lang/nb.js new file mode 100644 index 0000000..f53a1fc --- /dev/null +++ b/node_modules/moment/test/lang/nb.js @@ -0,0 +1,362 @@ +var moment = require("../../moment"); + + + /************************************************** + Norwegian bokmål + *************************************************/ + +exports["lang:nb"] = { + setUp : function (cb) { + moment.lang('nb'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'januar jan_februar feb_mars mar_april apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'søndag, februar 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'søn, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 februar feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. søndag søn sø'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '2010-02-14'], + ['LL', '14 februar 2010'], + ['LLL', '14 februar 2010 15:25'], + ['LLLL', 'søndag 14 februar 2010 15:25'], + ['l', '2010-2-14'], + ['ll', '14 feb 2010'], + ['lll', '14 feb 2010 15:25'], + ['llll', 'søn 14 feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'januar jan_februar feb_mars mar_april apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'søndag søn sø_mandag man ma_tirsdag tir ti_onsdag ons on_torsdag tor to_fredag fre fr_lørdag lør lø'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "noen sekunder", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ett minutt", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ett minutt", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutter", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutter", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "en time", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "en time", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timer", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timer", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timer", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dager", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dager", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dager", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en måned", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en måned", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en måned", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 måneder", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 måneder", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 måneder", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en måned", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 måneder", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 måneder", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ett år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ett år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ett år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "om noen sekunder", "prefix"); + test.equal(moment(0).from(30000), "for noen sekunder siden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "for noen sekunder siden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "om noen sekunder", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dager", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "I dag klokken 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "I dag klokken 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "I dag klokken 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "I morgen klokken 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "I dag klokken 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "I går klokken 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [klokken] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [klokken] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [klokken] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Forrige] dddd [klokken] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Forrige] dddd [klokken] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Forrige] dddd [klokken] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ne.js b/node_modules/moment/test/lang/ne.js new file mode 100644 index 0000000..ac5b290 --- /dev/null +++ b/node_modules/moment/test/lang/ne.js @@ -0,0 +1,382 @@ +var moment = require("../../moment"); + + + /************************************************** + Nepali + *************************************************/ + +exports["lang:ne"] = { + setUp : function (cb) { + moment.lang('ne'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'जनवरी जन._फेब्रुवरी फेब्रु._मार्च मार्च_अप्रिल अप्रि._मई मई_जुन जुन_जुलाई जुलाई._अगष्ट अग._सेप्टेम्बर सेप्ट._अक्टोबर अक्टो._नोभेम्बर नोभे._डिसेम्बर डिसे.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(21); + + var a = [ + ['dddd, Do MMMM YYYY, aको h:mm:ss बजे','आइतबार, १४ फेब्रुवरी २०१०, बेलुकाको ३:२५:५० बजे'], + ['ddd, aको h बजे', 'आइत., बेलुकाको ३ बजे'], + ['M Mo MM MMMM MMM', '२ २ ०२ फेब्रुवरी फेब्रु.'], + ['YYYY YY', '२०१० १०'], + ['D Do DD', '१४ १४ १४'], + ['d do dddd ddd dd', '० ० आइतबार आइत. आइ.'], + ['DDD DDDo DDDD', '४५ ४५ ०४५'], + ['w wo ww', '७ ७ ०७'], + ['h hh', '३ ०३'], + ['H HH', '१५ १५'], + ['m mm', '२५ २५'], + ['s ss', '५० ५०'], + ['a A', 'बेलुका बेलुका'], + ['L', '१४/०२/२०१०'], + ['LL', '१४ फेब्रुवरी २०१०'], + ['LLL', '१४ फेब्रुवरी २०१०, बेलुकाको ३:२५ बजे'], + ['LLLL', 'आइतबार, १४ फेब्रुवरी २०१०, बेलुकाको ३:२५ बजे'], + ['l', '१४/२/२०१०'], + ['ll', '१४ फेब्रु. २०१०'], + ['lll', '१४ फेब्रु. २०१०, बेलुकाको ३:२५ बजे'], + ['llll', 'आइत., १४ फेब्रु. २०१०, बेलुकाको ३:२५ बजे'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '१', '१'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '२', '२'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '३', '३'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '४', '४'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '५', '५'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '६', '६'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '७','७'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '८', '८'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '९', '९'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '१०', '१०'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '११', '११'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '१२', '१२'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '१३', '१३'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '१४', '१४'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '१५', '१५'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '१६', '१६'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '१७','१७'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '१८', '१८'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '१९', '१९'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '२०', '२०'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '२१', '२१'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '२२','२२'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '२३', '२३'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '२४','२४'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '२५','२५'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '२६','२६'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '२७','२७'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '२८','२८'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '२९','२९'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '३०', '३०'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '३१', '३१'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'जनवरी जन._फेब्रुवरी फेब्रु._मार्च मार्च_अप्रिल अप्रि._मई मई_जुन जुन_जुलाई जुलाई._अगष्ट अग._सेप्टेम्बर सेप्ट._अक्टोबर अक्टो._नोभेम्बर नोभे._डिसेम्बर डिसे.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'आइतबार आइत. आइ._सोमबार सोम. सो._मङ्गलबार मङ्गल. मङ्_बुधबार बुध. बु._बिहिबार बिहि. बि._शुक्रबार शुक्र. शु._शनिबार शनि. श.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "केही समय", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "एक मिनेट", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "एक मिनेट", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "२ मिनेट", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "४४ मिनेट", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "एक घण्टा", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "एक घण्टा", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "२ घण्टा", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "५ घण्टा", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "२१ घण्टा", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "एक दिन", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "एक दिन", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "२ दिन", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "एक दिन", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "५ दिन", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "२५ दिन", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "एक महिना", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "एक महिना", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "एक महिना", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "२ महिना", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "२ महिना", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "३ महिना", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "एक महिना", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "५ महिना", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "११ महिना", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "एक बर्ष", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "एक बर्ष", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "२ बर्ष", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "एक बर्ष", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "५ बर्ष", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "केही समयमा", "prefix"); + test.equal(moment(0).from(30000), "केही समय अगाडी", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "केही समय अगाडी", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "केही समयमा", "केही समयमा"); + test.equal(moment().add({d:5}).fromNow(), "५ दिनमा", "५ दिनमा"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "आज रातीको २:०० बजे", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "आज रातीको २:२५ बजे", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "आज बिहानको ३:०० बजे", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "भोली रातीको २:०० बजे", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "आज रातीको १:०० बजे", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "हिजो रातीको २:०० बजे", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[आउँदो] dddd[,] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[आउँदो] dddd[,] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[आउँदो] dddd[,] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[गएको] dddd[,] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[गएको] dddd[,] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[गएको] dddd[,] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + "meridiem" : function(test) { + test.expect(12); + + test.equal(moment([2011, 2, 23, 2, 30]).format('a'), "राती", "before dawn"); + test.equal(moment([2011, 2, 23, 9, 30]).format('a'), "बिहान", "morning"); + test.equal(moment([2011, 2, 23, 14, 30]).format('a'), "दिउँसो","during day"); + test.equal(moment([2011, 2, 23, 17, 30]).format('a'), "बेलुका", "evening"); + test.equal(moment([2011, 2, 23, 19, 30]).format('a'), "साँझ", "late evening"); + test.equal(moment([2011, 2, 23, 21, 20]).format('a'), "राती", "night"); + + test.equal(moment([2011, 2, 23, 2, 30]).format('A'), "राती", "before dawn"); + test.equal(moment([2011, 2, 23, 9, 30]).format('A'), "बिहान", "morning"); + test.equal(moment([2011, 2, 23, 14, 30]).format('A'), "दिउँसो","during day"); + test.equal(moment([2011, 2, 23, 17, 30]).format('A'), "बेलुका", "evening"); + test.equal(moment([2011, 2, 23, 19, 30]).format('A'), "साँझ", "late evening"); + test.equal(moment([2011, 2, 23, 21, 20]).format('A'), "राती", "night"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '१ ०१ १', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '१ ०१ १', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '२ ०२ २', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '२ ०२ २', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '३ ०३ ३', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/nl.js b/node_modules/moment/test/lang/nl.js new file mode 100644 index 0000000..935aa84 --- /dev/null +++ b/node_modules/moment/test/lang/nl.js @@ -0,0 +1,373 @@ +var moment = require("../../moment"); + + + /************************************************** + Dutch + *************************************************/ + +exports["lang:nl"] = { + setUp : function (cb) { + moment.lang('nl'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'januari jan._februari feb._maart mrt._april apr._mei mei._juni jun._juli jul._augustus aug._september sep._oktober okt._november nov._december dec.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'zondag, februari 14de 2010, 15:25:50'], + ['ddd, HH', 'zo., 15'], + ['M Mo MM MMMM MMM', '2 2de 02 februari feb.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14de 14'], + ['d do dddd ddd dd', '0 0de zondag zo. Zo'], + ['DDD DDDo DDDD', '45 45ste 045'], + ['w wo ww', '6 6de 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45ste day of the year'], + ['L', '14-02-2010'], + ['LL', '14 februari 2010'], + ['LLL', '14 februari 2010 15:25'], + ['LLLL', 'zondag 14 februari 2010 15:25'], + ['l', '14-2-2010'], + ['ll', '14 feb. 2010'], + ['lll', '14 feb. 2010 15:25'], + ['llll', 'zo. 14 feb. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1ste', '1ste'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2de', '2de'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3de', '3de'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4de', '4de'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5de', '5de'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6de', '6de'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7de', '7de'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8ste', '8ste'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9de', '9de'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10de', '10de'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11de', '11de'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12de', '12de'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13de', '13de'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14de', '14de'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15de', '15de'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16de', '16de'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17de', '17de'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18de', '18de'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19de', '19de'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20ste', '20ste'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21ste', '21ste'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22ste', '22ste'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23ste', '23ste'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24ste', '24ste'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25ste', '25ste'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26ste', '26ste'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27ste', '27ste'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28ste', '28ste'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29ste', '29ste'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30ste', '30ste'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31ste', '31ste'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'januari jan._februari feb._maart mrt._april apr._mei mei_juni jun._juli jul._augustus aug._september sep._oktober okt._november nov._december dec.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'zondag zo. Zo_maandag ma. Ma_dinsdag di. Di_woensdag wo. Wo_donderdag do. Do_vrijdag vr. Vr_zaterdag za. Za'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "een paar seconden", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "één minuut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "één minuut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuten", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuten", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "één uur", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "één uur", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 uur", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 uur", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 uur", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "één dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "één dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagen", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "één dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagen", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagen", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "één maand", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "één maand", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "één maand", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 maanden", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 maanden", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 maanden", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "één maand", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 maanden", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 maanden", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "één jaar", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "één jaar", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 jaar", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "één jaar", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 jaar", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "over een paar seconden", "prefix"); + test.equal(moment(0).from(30000), "een paar seconden geleden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "een paar seconden geleden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "over een paar seconden", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "over 5 dagen", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Vandaag om 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Vandaag om 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Vandaag om 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Morgen om 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Vandaag om 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Gisteren om 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [om] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [om] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [om] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + "month abbreviation" : function(test) { + test.expect(2); + + test.equal(moment([2012, 5, 23]).format('D-MMM-YYYY'), '23-jun-2012', 'format month abbreviation surrounded by dashes should not include a dot'); + test.equal(moment([2012, 5, 23]).format('D MMM YYYY'), '23 jun. 2012', 'format month abbreviation not surrounded by dashes should include a dot'); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52ste', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1ste' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1ste' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2de' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2de' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/nn.js b/node_modules/moment/test/lang/nn.js new file mode 100644 index 0000000..47f0c92 --- /dev/null +++ b/node_modules/moment/test/lang/nn.js @@ -0,0 +1,362 @@ +var moment = require("../../moment"); + + + /************************************************** + Norwegian nynorsk + *************************************************/ + +exports["lang:nn"] = { + setUp : function (cb) { + moment.lang('nn'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'januar jan_februar feb_mars mar_april apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'sundag, februar 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'sun, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 februar feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. sundag sun su'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '2010-02-14'], + ['LL', '14 februar 2010'], + ['LLL', '14 februar 2010 15:25'], + ['LLLL', 'sundag 14 februar 2010 15:25'], + ['l', '2010-2-14'], + ['ll', '14 feb 2010'], + ['lll', '14 feb 2010 15:25'], + ['llll', 'sun 14 feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'januar jan_februar feb_mars mar_april apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'sundag sun su_måndag mån må_tysdag tys ty_onsdag ons on_torsdag tor to_fredag fre fr_laurdag lau lø'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "noen sekund", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ett minutt", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ett minutt", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutt", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutt", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "en time", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "en time", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timar", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timar", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timar", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagar", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagar", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagar", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en månad", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en månad", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en månad", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 månader", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 månader", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 månader", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en månad", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 månader", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 månader", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ett år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ett år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ett år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "om noen sekund", "prefix"); + test.equal(moment(0).from(30000), "for noen sekund siden", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "for noen sekund siden", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "om noen sekund", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dagar", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "I dag klokka 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "I dag klokka 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "I dag klokka 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "I morgon klokka 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "I dag klokka 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "I går klokka 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [klokka] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [klokka] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [klokka] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Føregående] dddd [klokka] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Føregående] dddd [klokka] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Føregående] dddd [klokka] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/pl.js b/node_modules/moment/test/lang/pl.js new file mode 100644 index 0000000..df0b04b --- /dev/null +++ b/node_modules/moment/test/lang/pl.js @@ -0,0 +1,375 @@ +var moment = require("../../moment"); + + + /************************************************** + Polish + *************************************************/ + +exports["lang:pl"] = { + setUp : function (cb) { + moment.lang('pl'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'styczeń sty_luty lut_marzec mar_kwiecień kwi_maj maj_czerwiec cze_lipiec lip_sierpień sie_wrzesień wrz_październik paź_listopad lis_grudzień gru'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'niedziela, luty 14. 2010, 3:25:50 pm'], + ['ddd, hA', 'nie, 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 luty lut'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. niedziela nie N'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '14.02.2010'], + ['LL', '14 lutego 2010'], + ['LLL', '14 lutego 2010 15:25'], + ['LLLL', 'niedziela, 14 lutego 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14 lut 2010'], + ['lll', '14 lut 2010 15:25'], + ['llll', 'nie, 14 lut 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'styczeń sty_luty lut_marzec mar_kwiecień kwi_maj maj_czerwiec cze_lipiec lip_sierpień sie_wrzesień wrz_październik paź_listopad lis_grudzień gru'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'niedziela nie N_poniedziałek pon Pn_wtorek wt Wt_środa śr Śr_czwartek czw Cz_piątek pt Pt_sobota sb So'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "kilka sekund", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuty", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuty", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "godzina", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "godzina", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 godziny", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 godzin", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 godzin", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1 dzień", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1 dzień", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dni", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1 dzień", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dni", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dni", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "miesiąc", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "miesiąc", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "miesiąc", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 miesiące", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 miesiące", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 miesiące", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "miesiąc", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 miesięcy", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 miesięcy", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "rok", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "rok", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 lata", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "rok", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 lat", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "za kilka sekund", "prefix"); + test.equal(moment(0).from(30000), "kilka sekund temu", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "kilka sekund temu", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(3); + test.equal(moment().add({s:30}).fromNow(), "za kilka sekund", "in a few seconds"); + test.equal(moment().add({h:1}).fromNow(), "za godzinę", "in an hour"); + test.equal(moment().add({d:5}).fromNow(), "za 5 dni", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Dziś o 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Dziś o 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Dziś o 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Jutro o 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Dziś o 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Wczoraj o 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[W] dddd [o] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[W] dddd [o] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[W] dddd [o] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: return '[W zeszłą niedzielę o] LT' + case 3: return '[W zeszłą środę o] LT' + case 6: return '[W zeszłą sobotę o] LT' + default: return '[W zeszły] dddd [o] LT' + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/pt-br.js b/node_modules/moment/test/lang/pt-br.js new file mode 100644 index 0000000..7f5b9c0 --- /dev/null +++ b/node_modules/moment/test/lang/pt-br.js @@ -0,0 +1,364 @@ +var moment = require("../../moment"); + + + /************************************************** + Portuguese - Brazilian + *************************************************/ + +exports["lang:pt-br"] = { + setUp : function (cb) { + moment.lang('pt-br'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domingo, Fevereiro 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom, 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Fevereiro Fev'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd', '0 0º Domingo Dom'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '8 8º 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 de Fevereiro de 2010'], + ['LLL', '14 de Fevereiro de 2010 15:25'], + ['LLLL', 'Domingo, 14 de Fevereiro de 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 de Fev de 2010'], + ['lll', '14 de Fev de 2010 15:25'], + ['llll', 'Dom, 14 de Fev de 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'Domingo Dom_Segunda-feira Seg_Terça-feira Ter_Quarta-feira Qua_Quinta-feira Qui_Sexta-feira Sex_Sábado Sáb'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "segundos", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "um minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "um minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "uma hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "uma hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "um dia", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "um dia", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dias", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "um dia", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dias", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dias", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "um mês", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "um mês", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "um mês", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "um mês", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "um ano", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "um ano", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anos", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "um ano", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anos", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "em segundos", "prefix"); + test.equal(moment(0).from(30000), "segundos atrás", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "em segundos", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "em 5 dias", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hoje às 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hoje às 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hoje às 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Amanhã às 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hoje às 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ontem às 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1º', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1º', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2º', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2º', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3º', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/pt.js b/node_modules/moment/test/lang/pt.js new file mode 100644 index 0000000..9ee5d3c --- /dev/null +++ b/node_modules/moment/test/lang/pt.js @@ -0,0 +1,354 @@ +var moment = require("../../moment"); + + + /************************************************** + Portuguese + *************************************************/ + +exports["lang:pt"] = { + setUp : function (cb) { + moment.lang('pt'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domingo, Fevereiro 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom, 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Fevereiro Fev'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14º 14'], + ['d do dddd ddd dd', '0 0º Domingo Dom Dom'], + ['DDD DDDo DDDD', '45 45º 045'], + ['w wo ww', '6 6º 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45º day of the year'], + ['L', '14/02/2010'], + ['LL', '14 de Fevereiro de 2010'], + ['LLL', '14 de Fevereiro de 2010 15:25'], + ['LLLL', 'Domingo, 14 de Fevereiro de 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 de Fev de 2010'], + ['lll', '14 de Fev de 2010 15:25'], + ['llll', 'Dom, 14 de Fev de 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'Domingo Dom Dom_Segunda-feira Seg 2ª_Terça-feira Ter 3ª_Quarta-feira Qua 4ª_Quinta-feira Qui 5ª_Sexta-feira Sex 6ª_Sábado Sáb Sáb'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "segundos", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "um minuto", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "um minuto", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutos", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutos", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "uma hora", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "uma hora", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 horas", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 horas", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 horas", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "um dia", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "um dia", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dias", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "um dia", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dias", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dias", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "um mês", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "um mês", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "um mês", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meses", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meses", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 meses", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "um mês", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 meses", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 meses", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "um ano", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "um ano", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 anos", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "um ano", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 anos", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "em segundos", "prefix"); + test.equal(moment(0).from(30000), "segundos atrás", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "em segundos", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "em 5 dias", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Hoje às 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Hoje às 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Hoje às 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Amanhã às 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Hoje às 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Ontem às 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [às] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format((m.day() === 0 || m.day() === 6) ? '[Último] dddd [às] LT' : '[Última] dddd [às] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ro.js b/node_modules/moment/test/lang/ro.js new file mode 100644 index 0000000..8651104 --- /dev/null +++ b/node_modules/moment/test/lang/ro.js @@ -0,0 +1,363 @@ +var moment = require("../../moment"); + + + /************************************************** + Romanian + *************************************************/ + +exports["lang:ro"] = { + setUp : function (cb) { + moment.lang('ro'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'Ianuarie Ian_Februarie Feb_Martie Mar_Aprilie Apr_Mai Mai_Iunie Iun_Iulie Iul_August Aug_Septembrie Sep_Octombrie Oct_Noiembrie Noi_Decembrie Dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss A', 'Duminică, Februarie 14 2010, 3:25:50 PM'], + ['ddd, hA', 'Dum, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 Februarie Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 Duminică Dum Du'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '7 7 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[a] DDDo[a zi a anului]', 'a 45a zi a anului'], + ['L', '14/02/2010'], + ['LL', '14 Februarie 2010'], + ['LLL', '14 Februarie 2010 15:25'], + ['LLLL', 'Duminică, 14 Februarie 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 15:25'], + ['llll', 'Dum, 14 Feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'Ianuarie Ian_Februarie Feb_Martie Mar_Aprilie Apr_Mai Mai_Iunie Iun_Iulie Iul_August Aug_Septembrie Sep_Octombrie Oct_Noiembrie Noi_Decembrie Dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'Duminică Dum Du_Luni Lun Lu_Marţi Mar Ma_Miercuri Mie Mi_Joi Joi Jo_Vineri Vin Vi_Sâmbătă Sâm Sâ'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "câteva secunde", "44 secunde = câteva secunde"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "un minut", "45 secunde = un minut"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "un minut", "89 secunde = un minut"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minute", "90 secunde = 2 minute"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minute", "44 minute = 44 minute"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "o oră", "45 minute = o oră"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "o oră", "89 minute = o oră"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ore", "90 minute = 2 ore"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ore", "5 ore = 5 ore"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ore", "21 ore = 21 ore"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "o zi", "22 ore = o zi"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "o zi", "35 ore = o zi"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 zile", "36 ore = 2 zile"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "o zi", "1 zi = o zi"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 zile", "5 zile = 5 zile"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 zile", "25 zile = 25 zile"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "o lună", "26 zile = o lună"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "o lună", "30 zile = o lună"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "o lună", "45 zile = o lună"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 luni", "46 zile = 2 luni"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 luni", "75 zile = 2 luni"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 luni", "76 zile = 3 luni"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "o lună", "1 lună = o lună"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 luni", "5 luni = 5 luni"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 luni", "344 zile = 11 luni"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "un an", "345 zile = un an"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "un an", "547 zile = un an"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ani", "548 zile = 2 ani"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "un an", "1 an = un an"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ani", "5 ani = 5 ani"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "peste câteva secunde", "prefix"); + test.equal(moment(0).from(30000), "câteva secunde în urmă", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "câteva secunde în urmă", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "peste câteva secunde", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "peste 5 zile", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "azi la 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "azi la 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "azi la 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "mâine la 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "azi la 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "ieri la 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [la] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [la] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [la] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[fosta] dddd [la] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[fosta] dddd [la] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[fosta] dddd [la] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/ru.js b/node_modules/moment/test/lang/ru.js new file mode 100644 index 0000000..8e0ea75 --- /dev/null +++ b/node_modules/moment/test/lang/ru.js @@ -0,0 +1,393 @@ +var moment = require("../../moment"); + + + /************************************************** + Russian + *************************************************/ + +exports["lang:ru"] = { + setUp : function (cb) { + moment.lang('ru'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'январь янв_февраль фев_март мар_апрель апр_май май_июнь июн_июль июл_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'воскресенье, 14-го февраля 2010, 15:25:50'], + ['ddd, hA', 'вск, 3PM'], + ['M Mo MM MMMM MMM', '2 2-й 02 февраль фев'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-го 14'], + ['d do dddd ddd dd', '0 0-й воскресенье вск вс'], + ['DDD DDDo DDDD', '45 45-й 045'], + ['w wo ww', '7 7-я 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['DDDo [день года]', '45-й день года'], + ['L', '14.02.2010'], + ['LL', '14 февраля 2010 г.'], + ['LLL', '14 февраля 2010 г., 15:25'], + ['LLLL', 'воскресенье, 14 февраля 2010 г., 15:25'], + ['l', '14.2.2010'], + ['ll', '14 фев 2010 г.'], + ['lll', '14 фев 2010 г., 15:25'], + ['llll', 'вск, 14 фев 2010 г., 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1-й', '1-й'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2-й', '2-й'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3-й', '3-й'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4-й', '4-й'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5-й', '5-й'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6-й', '6-й'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7-й', '7-й'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8-й', '8-й'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9-й', '9-й'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10-й', '10-й'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11-й', '11-й'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12-й', '12-й'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13-й', '13-й'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14-й', '14-й'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15-й', '15-й'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16-й', '16-й'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17-й', '17-й'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18-й', '18-й'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19-й', '19-й'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20-й', '20-й'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21-й', '21-й'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22-й', '22-й'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23-й', '23-й'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24-й', '24-й'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25-й', '25-й'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26-й', '26-й'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27-й', '27-й'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28-й', '28-й'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29-й', '29-й'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30-й', '30-й'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31-й', '31-й'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'январь янв_февраль фев_март мар_апрель апр_май май_июнь июн_июль июл_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format month case" : function(test) { + test.expect(24); + + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }; + var i; + for (i = 0; i < 12; i++) { + test.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + test.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'воскресенье вск вс_понедельник пнд пн_вторник втр вт_среда срд ср_четверг чтв чт_пятница птн пт_суббота сбт сб'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(32); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "несколько секунд", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "минута", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "минута", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 минуты", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 минуты", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "час", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "час", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 часа", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 часов", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 час", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "день", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "день", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 дня", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "день", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 дней", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:11}), true), "11 дней", "11 days = 11 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:21}), true), "21 день", "21 days = 21 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 дней", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "месяц", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "месяц", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "месяц", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 месяца", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 месяца", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 месяца", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "месяц", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 месяцев", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 месяцев", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "год", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "год", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 года", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "год", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 лет", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "через несколько секунд", "prefix"); + test.equal(moment(0).from(30000), "несколько секунд назад", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "через несколько секунд", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "через 5 дней", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Сегодня в 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Сегодня в 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Сегодня в 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Завтра в 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Сегодня в 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Вчера в 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + function makeFormat(d) { + return d.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; + } + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-я', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-я', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-я', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-я', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-я', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/sk.js b/node_modules/moment/test/lang/sk.js new file mode 100644 index 0000000..863c655 --- /dev/null +++ b/node_modules/moment/test/lang/sk.js @@ -0,0 +1,413 @@ +var moment = require("../../moment"); + + + /************************************************** + Slovak + *************************************************/ + +exports["lang:sk"] = { + setUp : function (cb) { + moment.lang('sk'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'január jan._február feb._marec mar._apríl apr._máj máj_jún jún._júl júl._august aug._september sep._október okt._november nov._december dec.'.split("_"); + function equalTest(input, mmm, monthIndex) { + test.equal(moment(input, mmm).month(), monthIndex, input + ' should be month ' + (monthIndex + 1)); + } + for (var i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss', 'nedeľa, február 14. 2010, 3:25:50'], + ['ddd, h', 'ne, 3'], + ['M Mo MM MMMM MMM', '2 2. 02 február feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. nedeľa ne ne'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['DDDo [deň v roku]', '45. deň v roku'], + ['L', '14.02.2010'], + ['LL', '14. február 2010'], + ['LLL', '14. február 2010 15:25'], + ['LLLL', 'nedeľa 14. február 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14. feb 2010'], + ['lll', '14. feb 2010 15:25'], + ['llll', 'ne 14. feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'január jan_február feb_marec mar_apríl apr_máj máj_jún jún_júl júl_august aug_september sep_október okt_november nov_december dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'nedeľa ne ne_pondelok po po_utorok ut ut_streda st st_štvrtok št št_piatok pi pi_sobota so so'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "pár sekúnd", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minúta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minúta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minúty", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minút", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "hodina", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "hodina", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 hodiny", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 hodín", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 hodín", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "deň", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "deň", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dni", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "deň", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dní", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dní", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "mesiac", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "mesiac", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "mesiac", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 mesiace", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 mesiace", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mesiace", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "mesiac", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mesiacov", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mesiacov", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "rok", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "rok", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 roky", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "rok", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 rokov", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "za pár sekúnd", "prefix"); + test.equal(moment(0).from(30000), "pred pár sekundami", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "pred pár sekundami", "now from now should display as in the past"); + test.done(); + }, + + "fromNow (future)" : function(test) { + test.expect(16); + test.equal(moment().add({s:30}).fromNow(), "za pár sekúnd", "in a few seconds"); + test.equal(moment().add({m:1}).fromNow(), "za minútu", "in a minute"); + test.equal(moment().add({m:3}).fromNow(), "za 3 minúty", "in 3 minutes"); + test.equal(moment().add({m:10}).fromNow(), "za 10 minút", "in 10 minutes"); + test.equal(moment().add({h:1}).fromNow(), "za hodinu", "in an hour"); + test.equal(moment().add({h:3}).fromNow(), "za 3 hodiny", "in 3 hours"); + test.equal(moment().add({h:10}).fromNow(), "za 10 hodín", "in 10 hours"); + test.equal(moment().add({d:1}).fromNow(), "za deň", "in a day"); + test.equal(moment().add({d:3}).fromNow(), "za 3 dni", "in 3 days"); + test.equal(moment().add({d:10}).fromNow(), "za 10 dní", "in 10 days"); + test.equal(moment().add({M:1}).fromNow(), "za mesiac", "in a month"); + test.equal(moment().add({M:3}).fromNow(), "za 3 mesiace", "in 3 months"); + test.equal(moment().add({M:10}).fromNow(), "za 10 mesiacov", "in 10 months"); + test.equal(moment().add({y:1}).fromNow(), "za rok", "in a year"); + test.equal(moment().add({y:3}).fromNow(), "za 3 roky", "in 3 years"); + test.equal(moment().add({y:10}).fromNow(), "za 10 rokov", "in 10 years"); + test.done(); + }, + + "fromNow (past)" : function(test) { + test.expect(16); + test.equal(moment().subtract({s:30}).fromNow(), "pred pár sekundami", "a few seconds ago"); + test.equal(moment().subtract({m:1}).fromNow(), "pred minútou", "a minute ago"); + test.equal(moment().subtract({m:3}).fromNow(), "pred 3 minútami", "3 minutes ago"); + test.equal(moment().subtract({m:10}).fromNow(), "pred 10 minútami", "10 minutes ago"); + test.equal(moment().subtract({h:1}).fromNow(), "pred hodinou", "an hour ago"); + test.equal(moment().subtract({h:3}).fromNow(), "pred 3 hodinami", "3 hours ago"); + test.equal(moment().subtract({h:10}).fromNow(), "pred 10 hodinami", "10 hours ago"); + test.equal(moment().subtract({d:1}).fromNow(), "pred dňom", "a day ago"); + test.equal(moment().subtract({d:3}).fromNow(), "pred 3 dňami", "3 days ago"); + test.equal(moment().subtract({d:10}).fromNow(), "pred 10 dňami", "10 days ago"); + test.equal(moment().subtract({M:1}).fromNow(), "pred mesiacom", "a month ago"); + test.equal(moment().subtract({M:3}).fromNow(), "pred 3 mesiacmi", "3 months ago"); + test.equal(moment().subtract({M:10}).fromNow(), "pred 10 mesiacmi", "10 months ago"); + test.equal(moment().subtract({y:1}).fromNow(), "pred rokom", "a year ago"); + test.equal(moment().subtract({y:3}).fromNow(), "pred 3 rokmi", "3 years ago"); + test.equal(moment().subtract({y:10}).fromNow(), "pred 10 rokmi", "10 years ago"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "dnes o 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "dnes o 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "dnes o 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "zajtra o 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "dnes o 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "včera o 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + for (var i = 2; i < 7; i++) { + var m = moment().add({ d: i }); + var nextDay = ''; + switch (m.day()) { + case 0: nextDay = 'v nedeľu'; break; + case 1: nextDay = 'v pondelok'; break; + case 2: nextDay = 'v utorok'; break; + case 3: nextDay = 'v stredu'; break; + case 4: nextDay = 'vo štvrtok'; break; + case 5: nextDay = 'v piatok'; break; + case 6: nextDay = 'v sobotu'; break; + } + test.equal(m.calendar(), m.format('[' + nextDay + '] [o] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[' + nextDay + '] [o] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[' + nextDay + '] [o] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (var i = 2; i < 7; i++) { + var m = moment().subtract({ d: i }); + var lastDay = ''; + switch (m.day()) { + case 0: lastDay = 'minulú nedeľu'; break; + case 1: lastDay = 'minulý pondelok'; break; + case 2: lastDay = 'minulý utorok'; break; + case 3: lastDay = 'minulú stredu'; break; + case 4: lastDay = 'minulý štvrtok'; break; + case 5: lastDay = 'minulý piatok'; break; + case 6: lastDay = 'minulú sobotu'; break; + } + test.equal(m.calendar(), m.format('[' + lastDay + '] [o] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[' + lastDay + '] [o] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[' + lastDay + '] [o] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "humanize duration" : function(test) { + test.expect(4); + test.equal(moment.duration(1, "minutes").humanize(), "minúta", "a minute (future)"); + test.equal(moment.duration(1, "minutes").humanize(true), "za minútu", "in a minute"); + test.equal(moment.duration(-1, "minutes").humanize(), "minúta", "a minute (past)"); + test.equal(moment.duration(-1, "minutes").humanize(true), "pred minútou", "a minute ago"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/sl.js b/node_modules/moment/test/lang/sl.js new file mode 100644 index 0000000..8aa84a0 --- /dev/null +++ b/node_modules/moment/test/lang/sl.js @@ -0,0 +1,389 @@ +var moment = require("../../moment"); + + + /************************************************** + Slovenian + *************************************************/ + +exports["lang:sl"] = { + setUp : function (cb) { + moment.lang('sl'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'januar jan._februar feb._marec mar._april apr._maj maj_junij jun._julij jul._avgust avg._september sep._oktober okt._november nov._december dec.'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'nedelja, 14. februar 2010, 3:25:50 pm'], + ['ddd, hA', 'ned., 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 februar feb.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. nedelja ned. ne'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '7 7. 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '14. 02. 2010'], + ['LL', '14. februar 2010'], + ['LLL', '14. februar 2010 15:25'], + ['LLLL', 'nedelja, 14. februar 2010 15:25'], + ['l', '14. 2. 2010'], + ['ll', '14. feb. 2010'], + ['lll', '14. feb. 2010 15:25'], + ['llll', 'ned., 14. feb. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'januar jan._februar feb._marec mar._april apr._maj maj._junij jun._julij jul._avgust avg._september sep._oktober okt._november nov._december dec.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'nedelja ned. ne_ponedeljek pon. po_torek tor. to_sreda sre. sr_četrtek čet. če_petek pet. pe_sobota sob. so'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "nekaj sekund", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ena minuta", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ena minuta", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuti", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minut", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "ena ura", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "ena ura", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 uri", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ur", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ur", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dan", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dan", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dni", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dan", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dni", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dni", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en mesec", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en mesec", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en mesec", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 meseca", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 meseca", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 mesece", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en mesec", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 mesecev", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 mesecev", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "eno leto", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "eno leto", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 leti", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "eno leto", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 let", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "čez nekaj sekund", "prefix"); + test.equal(moment(0).from(30000), "nekaj sekund nazaj", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "nekaj sekund nazaj", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "čez nekaj sekund", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "čez 5 dni", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "danes ob 2:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "danes ob 2:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "danes ob 3:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "jutri ob 2:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "danes ob 1:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "včeraj ob 2:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + case 6: + return '[prejšnja] dddd [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/sq.js b/node_modules/moment/test/lang/sq.js new file mode 100644 index 0000000..36ed959 --- /dev/null +++ b/node_modules/moment/test/lang/sq.js @@ -0,0 +1,378 @@ +var moment = require("../../moment"); + + + /************************************************** + Albanian + *************************************************/ + +exports["lang:sq"] = { + setUp : function (cb) { + moment.lang('sq'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var i, + tests = 'Janar Jan_Shkurt Shk_Mars Mar_Prill Pri_Maj Maj_Qershor Qer_Korrik Kor_Gusht Gus_Shtator Sht_Tetor Tet_Nëntor Nën_Dhjetor Dhj'.split("_"); + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'E Diel, Shkurt 14. 2010, 15:25:50'], + ['ddd, HH', 'Die, 15'], + ['M Mo MM MMMM MMM', '2 2. 02 Shkurt Shk'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. E Diel Die D'], + ['DDD DDDo DDDD', '45 45. 045'], + ['w wo ww', '6 6. 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['L', '14/02/2010'], + ['LL', '14 Shkurt 2010'], + ['LLL', '14 Shkurt 2010 15:25'], + ['LLLL', 'E Diel, 14 Shkurt 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Shk 2010'], + ['lll', '14 Shk 2010 15:25'], + ['llll', 'Die, 14 Shk 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var i, + expected = 'Janar Jan_Shkurt Shk_Mars Mar_Prill Pri_Maj Maj_Qershor Qer_Korrik Kor_Gusht Gus_Shtator Sht_Tetor Tet_Nëntor Nën_Dhjetor Dhj'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var i, + expected = 'E Diel Die D_E Hënë Hën H_E Marte Mar Ma_E Mërkure Mër Më_E Enjte Enj E_E Premte Pre P_E Shtunë Sht Sh'.split("_"); + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "disa seconda", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "një minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "një minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minutea", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minutea", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "një orë", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "një orë", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 orë", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 orë", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 orë", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "një ditë", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "një ditë", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 ditë", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "një ditë", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 ditë", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 ditë", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "një muaj", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "një muaj", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "një muaj", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 muaj", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 muaj", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 muaj", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "një muaj", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 muaj", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 muaj", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "një vit", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "një vit", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 vite", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "një vit", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 vite", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "në disa seconda", "prefix"); + test.equal(moment(0).from(30000), "disa seconda me parë", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "disa seconda me parë", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "në disa seconda", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "në 5 ditë", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Sot në 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Sot në 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Sot në 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Neser në 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Sot në 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Dje në 02:00", "yesterday at the same time"); + + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [në] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [në] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [në] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [e kaluar në] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [e kaluar në] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [e kaluar në] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }), + weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/sv.js b/node_modules/moment/test/lang/sv.js new file mode 100644 index 0000000..377707e --- /dev/null +++ b/node_modules/moment/test/lang/sv.js @@ -0,0 +1,356 @@ +var moment = require("../../moment"); + +/************************************************** + Swedish + *************************************************/ + +exports["lang:sv"] = { + setUp : function (cb) { + moment.lang('sv'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'januari jan_februari feb_mars mar_april apr_maj maj_juni jun_juli jul_augusti aug_september sep_oktober okt_november nov_december dec'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'söndag, februari 14e 2010, 3:25:50 pm'], + ['ddd, hA', 'sön, 3PM'], + ['M Mo MM MMMM MMM', '2 2a 02 februari feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14e 14'], + ['d do dddd ddd dd', '0 0e söndag sön sö'], + ['DDD DDDo DDDD', '45 45e 045'], + ['w wo ww', '6 6e 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45e day of the year'], + ['L', '2010-02-14'], + ['LL', '14 februari 2010'], + ['LLL', '14 februari 2010 15:25'], + ['LLLL', 'söndag 14 februari 2010 15:25'], + ['l', '2010-2-14'], + ['ll', '14 feb 2010'], + ['lll', '14 feb 2010 15:25'], + ['llll', 'sön 14 feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1a', '1a'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2a', '2a'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3e', '3e'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4e', '4e'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5e', '5e'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6e', '6e'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7e', '7e'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8e', '8e'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9e', '9e'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10e', '10e'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11e', '11e'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12e', '12e'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13e', '13e'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14e', '14e'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15e', '15e'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16e', '16e'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17e', '17e'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18e', '18e'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19e', '19e'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20e', '20e'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21a', '21a'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22a', '22a'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23e', '23e'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24e', '24e'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25e', '25e'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26e', '26e'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27e', '27e'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28e', '28e'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29e', '29e'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30e', '30e'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31a', '31a'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'januari jan_februari feb_mars mar_april apr_maj maj_juni jun_juli jul_augusti aug_september sep_oktober okt_november nov_december dec'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'söndag sön sö_måndag mån må_tisdag tis ti_onsdag ons on_torsdag tor to_fredag fre fr_lördag lör lö'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "några sekunder", "44 sekunder = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "en minut", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "en minut", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuter", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuter", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "en timme", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "en timme", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 timmar", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 timmar", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 timmar", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "en dag", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "en dag", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 dagar", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "en dag", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 dagar", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 dagar", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "en månad", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "en månad", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "en månad", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 månader", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 månader", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 månader", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "en månad", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 månader", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 månader", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ett år", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ett år", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 år", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ett år", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 år", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "om några sekunder", "prefix"); + test.equal(moment(0).from(30000), "för några sekunder sedan", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "för några sekunder sedan", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "om några sekunder", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "om 5 dagar", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Idag 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Idag 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Idag 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Imorgon 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Idag 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Igår 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[Förra] dddd[en] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[Förra] dddd[en] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[Förra] dddd[en] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 4th is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 52, "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).week(), 1, "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 1, "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).week(), 2, "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 2, "Jan 15 2012 should be week 2"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 13]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 53, "Dec 28 2009 should be week 53"); + test.equal(moment([2010, 0, 1]).week(), 53, "Jan 1 2010 should be week 53"); + test.equal(moment([2010, 0, 3]).week(), 53, "Jan 3 2010 should be week 53"); + test.equal(moment([2010, 0, 4]).week(), 1, "Jan 4 2010 should be week 1"); + test.equal(moment([2010, 0, 10]).week(), 1, "Jan 10 2010 should be week 1"); + test.equal(moment([2010, 0, 11]).week(), 2, "Jan 11 2010 should be week 2"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 52, "Dec 27 2010 should be week 52"); + test.equal(moment([2011, 0, 1]).week(), 52, "Jan 1 2011 should be week 52"); + test.equal(moment([2011, 0, 2]).week(), 52, "Jan 2 2011 should be week 52"); + test.equal(moment([2011, 0, 3]).week(), 1, "Jan 3 2011 should be week 1"); + test.equal(moment([2011, 0, 9]).week(), 1, "Jan 9 2011 should be week 1"); + test.equal(moment([2011, 0, 10]).week(), 2, "Jan 10 2011 should be week 2"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52a', "Jan 1 2012 should be week 52"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1a' , "Jan 2 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1a' , "Jan 8 2012 should be week 1"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2a' , "Jan 9 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2a' , "Jan 15 2012 should be week 2"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/th.js b/node_modules/moment/test/lang/th.js new file mode 100644 index 0000000..a0cb4c4 --- /dev/null +++ b/node_modules/moment/test/lang/th.js @@ -0,0 +1,323 @@ +var moment = require("../../moment"); + + + /************************************************** + Thai + *************************************************/ + +exports["lang:th"] = { + setUp : function (cb) { + moment.lang('th'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'มกราคม มกรา_กุมภาพันธ์ กุมภา_มีนาคม มีนา_เมษายน เมษา_พฤษภาคม พฤษภา_มิถุนายน มิถุนา_กรกฎาคม กรกฎา_สิงหาคม สิงหา_กันยายน กันยา_ตุลาคม ตุลา_พฤศจิกายน พฤศจิกา_ธันวาคม ธันวา'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'อาทิตย์, 14 กุมภาพันธ์ 2010, 3:25:50 หลังเที่ยง'], + ['ddd, h A', 'อาทิตย์, 3 หลังเที่ยง'], + ['M Mo MM MMMM MMM', '2 2 02 กุมภาพันธ์ กุมภา'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 อาทิตย์ อาทิตย์ อา.'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'หลังเที่ยง หลังเที่ยง'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '2010/02/14'], + ['LL', '14 กุมภาพันธ์ 2010'], + ['LLL', '14 กุมภาพันธ์ 2010 เวลา 15 นาฬิกา 25 นาที'], + ['LLLL', 'วันอาทิตย์ที่ 14 กุมภาพันธ์ 2010 เวลา 15 นาฬิกา 25 นาที'], + ['l', '2010/2/14'], + ['ll', '14 กุมภา 2010'], + ['lll', '14 กุมภา 2010 เวลา 15 นาฬิกา 25 นาที'], + ['llll', 'วันอาทิตย์ที่ 14 กุมภา 2010 เวลา 15 นาฬิกา 25 นาที'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'มกราคม มกรา_กุมภาพันธ์ กุมภา_มีนาคม มีนา_เมษายน เมษา_พฤษภาคม พฤษภา_มิถุนายน มิถุนา_กรกฎาคม กรกฎา_สิงหาคม สิงหา_กันยายน กันยา_ตุลาคม ตุลา_พฤศจิกายน พฤศจิกา_ธันวาคม ธันวา'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'อาทิตย์ อาทิตย์ อา._จันทร์ จันทร์ จ._อังคาร อังคาร อ._พุธ พุธ พ._พฤหัสบดี พฤหัส พฤ._ศุกร์ ศุกร์ ศ._เสาร์ เสาร์ ส.'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "ไม่กี่วินาที", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "1 นาที", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "1 นาที", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 นาที", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 นาที", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "1 ชั่วโมง", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "1 ชั่วโมง", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ชั่วโมง", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ชั่วโมง", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ชั่วโมง", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1 วัน", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1 วัน", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 วัน", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1 วัน", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 วัน", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 วัน", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "1 เดือน", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "1 เดือน", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "1 เดือน", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 เดือน", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 เดือน", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 เดือน", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "1 เดือน", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 เดือน", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 เดือน", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "1 ปี", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "1 ปี", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ปี", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "1 ปี", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ปี", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "อีก ไม่กี่วินาที", "prefix"); + test.equal(moment(0).from(30000), "ไม่กี่วินาทีที่แล้ว", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "ไม่กี่วินาทีที่แล้ว", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "อีก ไม่กี่วินาที", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "อีก 5 วัน", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "วันนี้ เวลา 2 นาฬิกา 0 นาที", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "วันนี้ เวลา 2 นาฬิกา 25 นาที", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "วันนี้ เวลา 3 นาฬิกา 0 นาที", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "พรุ่งนี้ เวลา 2 นาฬิกา 0 นาที", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "วันนี้ เวลา 1 นาฬิกา 0 นาที", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "เมื่อวานนี้ เวลา 2 นาฬิกา 0 นาที", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd[หน้า เวลา] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd[หน้า เวลา] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd[หน้า เวลา] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[วัน]dddd[ที่แล้ว เวลา] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[วัน]dddd[ที่แล้ว เวลา] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[วัน]dddd[ที่แล้ว เวลา] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', "Jan 15 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/tr.js b/node_modules/moment/test/lang/tr.js new file mode 100644 index 0000000..4b5923f --- /dev/null +++ b/node_modules/moment/test/lang/tr.js @@ -0,0 +1,374 @@ +var moment = require("../../moment"); + + + /************************************************** + Turkish + *************************************************/ + +exports["lang:tr"] = { + setUp : function (cb) { + moment.lang('tr'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'Ocak Oca_Şubat Şub_Mart Mar_Nisan Nis_Mayıs May_Haziran Haz_Temmuz Tem_Ağustos Ağu_Eylül Eyl_Ekim Eki_Kasım Kas_Aralık Ara'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Pazar, Şubat 14\'üncü 2010, 3:25:50 pm'], + ['ddd, hA', 'Paz, 3PM'], + ['M Mo MM MMMM MMM', '2 2\'nci 02 Şubat Şub'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14\'üncü 14'], + ['d do dddd ddd dd', '0 0\'ıncı Pazar Paz Pz'], + ['DDD DDDo DDDD', '45 45\'inci 045'], + ['w wo ww', "7 7'nci 07"], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[yılın] DDDo [günü]', 'yılın 45\'inci günü'], + ['L', '14.02.2010'], + ['LL', '14 Şubat 2010'], + ['LLL', '14 Şubat 2010 15:25'], + ['LLLL', 'Pazar, 14 Şubat 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14 Şub 2010'], + ['lll', '14 Şub 2010 15:25'], + ['llll', 'Paz, 14 Şub 2010 15:25'] + ], + DDDo = [ + [359, '360\'ıncı'], + [199, '200\'üncü'], + [149, '150\'nci'] + ], + dt = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + DDDoDt, + i; + test.expect(a.length + DDDo.length); + + for (i = 0; i < a.length; i++) { + test.equal(dt.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + for (i = 0; i < DDDo.length; i++) { + DDDoDt = moment([2010]); + test.equal(DDDoDt.add('days', DDDo[i][0]).format('DDDo'), DDDo[i][1], DDDo[i][0] + ' ---> ' + DDDo[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1\'inci', '1st'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2\'nci', '2nd'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3\'üncü', '3rd'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4\'üncü', '4th'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5\'inci', '5th'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6\'ncı', '6th'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7\'nci', '7th'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8\'inci', '8th'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9\'uncu', '9th'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10\'uncu', '10th'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11\'inci', '11th'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12\'nci', '12th'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13\'üncü', '13th'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14\'üncü', '14th'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15\'inci', '15th'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16\'ncı', '16th'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17\'nci', '17th'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18\'inci', '18th'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19\'uncu', '19th'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20\'nci', '20th'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21\'inci', '21th'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22\'nci', '22th'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23\'üncü', '23th'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24\'üncü', '24th'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25\'inci', '25th'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26\'ncı', '26th'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27\'nci', '27th'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28\'inci', '28th'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29\'uncu', '29th'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30\'uncu', '30th'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31\'inci', '31st'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'Ocak Oca_Şubat Şub_Mart Mar_Nisan Nis_Mayıs May_Haziran Haz_Temmuz Tem_Ağustos Ağu_Eylül Eyl_Ekim Eki_Kasım Kas_Aralık Ara'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'Pazar Paz Pz_Pazartesi Pts Pt_Salı Sal Sa_Çarşamba Çar Ça_Perşembe Per Pe_Cuma Cum Cu_Cumartesi Cts Ct'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "birkaç saniye", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "bir dakika", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "bir dakika", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 dakika", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 dakika", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "bir saat", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "bir saat", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 saat", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 saat", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 saat", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "bir gün", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "bir gün", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 gün", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "bir gün", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 gün", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 gün", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "bir ay", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "bir ay", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "bir ay", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 ay", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 ay", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 ay", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "bir ay", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 ay", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 ay", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "bir yıl", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "bir yıl", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 yıl", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "bir yıl", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 yıl", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "birkaç saniye sonra", "prefix"); + test.equal(moment(0).from(30000), "birkaç saniye önce", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "birkaç saniye önce", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "birkaç saniye sonra", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5 gün sonra", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "bugün saat 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "bugün saat 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "bugün saat 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "yarın saat 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "bugün saat 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "dün 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), "1 01 1'inci", "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), "1 01 1'inci", "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), "2 02 2'nci", "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), "2 02 2'nci", "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), "3 03 3'üncü", "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/tzm-la.js b/node_modules/moment/test/lang/tzm-la.js new file mode 100644 index 0000000..7809772 --- /dev/null +++ b/node_modules/moment/test/lang/tzm-la.js @@ -0,0 +1,359 @@ +// moment.js Morocco Central Atlas Tamaziɣt in Latin (tzm-la) tests +// author : Abdel Said : https://github.com/abdelsaid +var moment = require("../../moment"); + + +exports["lang:tzm-la"] = { + setUp : function (cb) { + moment.lang('tzm-la'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = 'innayr innayr_brˤayrˤ brˤayrˤ_marˤsˤ marˤsˤ_ibrir ibrir_mayyw mayyw_ywnyw ywnyw_ywlywz ywlywz_ɣwšt ɣwšt_šwtanbir šwtanbir_ktˤwbrˤ ktˤwbrˤ_nwwanbir nwwanbir_dwjnbir dwjnbir'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'asamas, brˤayrˤ 14 2010, 3:25:50 pm'], + ['ddd, hA', 'asamas, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 brˤayrˤ brˤayrˤ'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 asamas asamas asamas'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 brˤayrˤ 2010'], + ['LLL', '14 brˤayrˤ 2010 15:25'], + ['LLLL', 'asamas 14 brˤayrˤ 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 brˤayrˤ 2010'], + ['lll', '14 brˤayrˤ 2010 15:25'], + ['llll', 'asamas 14 brˤayrˤ 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + + test.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = 'innayr innayr_brˤayrˤ brˤayrˤ_marˤsˤ marˤsˤ_ibrir ibrir_mayyw mayyw_ywnyw ywnyw_ywlywz ywlywz_ɣwšt ɣwšt_šwtanbir šwtanbir_ktˤwbrˤ ktˤwbrˤ_nwwanbir nwwanbir_dwjnbir dwjnbir'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = 'asamas asamas asamas_aynas aynas aynas_asinas asinas asinas_akras akras akras_akwas akwas akwas_asimwas asimwas asimwas_asiḍyas asiḍyas asiḍyas'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "imik", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "minuḍ", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "minuḍ", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 minuḍ", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 minuḍ", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "saɛa", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "saɛa", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 tassaɛin", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 tassaɛin", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 tassaɛin", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "ass", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "ass", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 ossan", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "ass", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 ossan", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 ossan", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "ayowr", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "ayowr", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "ayowr", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 iyyirn", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 iyyirn", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 iyyirn", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "ayowr", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 iyyirn", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 iyyirn", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "asgas", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "asgas", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 isgasn", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "asgas", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 isgasn", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "dadkh s yan imik", "prefix"); + test.equal(moment(0).from(30000), "yan imik", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "yan imik", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "dadkh s yan imik", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "dadkh s yan 5 ossan", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "asdkh g 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "asdkh g 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "asdkh g 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "aska g 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "asdkh g 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "assant g 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [g] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [g] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [g] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [g] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [g] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [g] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + + // Saturday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).week(), 1, "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).week(), 1, "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 2, "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).week(), 2, "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 3, "Jan 14 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2006, 11, 30]).week(), 1, "Dec 30 2006 should be week 1"); + test.equal(moment([2007, 0, 5]).week(), 1, "Jan 5 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 2, "Jan 6 2007 should be week 2"); + test.equal(moment([2007, 0, 12]).week(), 2, "Jan 12 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 3, "Jan 13 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 29]).week(), 1, "Dec 29 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 4]).week(), 1, "Jan 4 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 2, "Jan 5 2008 should be week 2"); + test.equal(moment([2008, 0, 11]).week(), 2, "Jan 11 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 3, "Jan 12 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 28]).week(), 1, "Dec 28 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 3]).week(), 1, "Jan 3 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 2, "Jan 4 2003 should be week 2"); + test.equal(moment([2003, 0, 10]).week(), 2, "Jan 10 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 3, "Jan 11 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 27]).week(), 1, "Dec 27 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 2]).week(), 1, "Jan 2 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 2, "Jan 3 2009 should be week 2"); + test.equal(moment([2009, 0, 9]).week(), 2, "Jan 9 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 3, "Jan 10 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(5); + + test.equal(moment([2009, 11, 26]).week(), 1, "Dec 26 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 2, "Jan 2 2010 should be week 2"); + test.equal(moment([2010, 0, 8]).week(), 2, "Jan 8 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 3, "Jan 9 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 7]).week(), 1, "Jan 7 2011 should be week 1"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 14]).week(), 2, "Jan 14 2011 should be week 2"); + test.equal(moment([2011, 0, 15]).week(), 3, "Jan 15 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', "Jan 14 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/tzm.js b/node_modules/moment/test/lang/tzm.js new file mode 100644 index 0000000..6675094 --- /dev/null +++ b/node_modules/moment/test/lang/tzm.js @@ -0,0 +1,351 @@ +// moment.js Morocco Central Atlas Tamaziɣt (tzm) tests +// author : Abdel Said : https://github.com/abdelsaid +var moment = require("../../moment"); + + +exports["lang:tzm"] = { + setUp : function (cb) { + moment.lang('tzm'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'ⵉⵏⵏⴰⵢⵔ ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ ⴷⵓⵊⵏⴱⵉⵔ'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'ⴰⵙⴰⵎⴰⵙ, ⴱⵕⴰⵢⵕ 14 2010, 3:25:50 pm'], + ['ddd, hA', 'ⴰⵙⴰⵎⴰⵙ, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 ⴱⵕⴰⵢⵕ ⴱⵕⴰⵢⵕ'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 ⴰⵙⴰⵎⴰⵙ ⴰⵙⴰⵎⴰⵙ ⴰⵙⴰⵎⴰⵙ'], + ['DDD DDDo DDDD', '45 45 045'], + ['w wo ww', '8 8 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['L', '14/02/2010'], + ['LL', '14 ⴱⵕⴰⵢⵕ 2010'], + ['LLL', '14 ⴱⵕⴰⵢⵕ 2010 15:25'], + ['LLLL', 'ⴰⵙⴰⵎⴰⵙ 14 ⴱⵕⴰⵢⵕ 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 ⴱⵕⴰⵢⵕ 2010'], + ['lll', '14 ⴱⵕⴰⵢⵕ 2010 15:25'], + ['llll', 'ⴰⵙⴰⵎⴰⵙ 14 ⴱⵕⴰⵢⵕ 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'ⵉⵏⵏⴰⵢⵔ ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ ⴷⵓⵊⵏⴱⵉⵔ'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'ⴰⵙⴰⵎⴰⵙ ⴰⵙⴰⵎⴰⵙ ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ ⴰⵢⵏⴰⵙ ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ ⴰⵙⵉⵏⴰⵙ ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ ⴰⴽⵔⴰⵙ ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ ⴰⴽⵡⴰⵙ ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ ⴰⵙⵉⵎⵡⴰⵙ ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ ⴰⵙⵉⴹⵢⴰⵙ ⴰⵙⵉⴹⵢⴰⵙ'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(30); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "ⵉⵎⵉⴽ", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "ⵎⵉⵏⵓⴺ", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "ⵎⵉⵏⵓⴺ", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 ⵎⵉⵏⵓⴺ", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 ⵎⵉⵏⵓⴺ", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "ⵙⴰⵄⴰ", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "ⵙⴰⵄⴰ", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 ⵜⴰⵙⵙⴰⵄⵉⵏ", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 ⵜⴰⵙⵙⴰⵄⵉⵏ", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 ⵜⴰⵙⵙⴰⵄⵉⵏ", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "ⴰⵙⵙ", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "ⴰⵙⵙ", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 oⵙⵙⴰⵏ", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "ⴰⵙⵙ", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 oⵙⵙⴰⵏ", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 oⵙⵙⴰⵏ", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "ⴰⵢoⵓⵔ", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "ⴰⵢoⵓⵔ", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "ⴰⵢoⵓⵔ", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 ⵉⵢⵢⵉⵔⵏ", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 ⵉⵢⵢⵉⵔⵏ", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 ⵉⵢⵢⵉⵔⵏ", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "ⴰⵢoⵓⵔ", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 ⵉⵢⵢⵉⵔⵏ", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 ⵉⵢⵢⵉⵔⵏ", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "ⴰⵙⴳⴰⵙ", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "ⴰⵙⴳⴰⵙ", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 ⵉⵙⴳⴰⵙⵏ", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "ⴰⵙⴳⴰⵙ", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 ⵉⵙⴳⴰⵙⵏ", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ ⵉⵎⵉⴽ", "prefix"); + test.equal(moment(0).from(30000), "ⵢⴰⵏ ⵉⵎⵉⴽ", "suffix"); + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + test.equal(moment().fromNow(), "ⵢⴰⵏ ⵉⵎⵉⴽ", "now from now should display as in the past"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ ⵉⵎⵉⴽ", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ 5 oⵙⵙⴰⵏ", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "ⴰⵙⴷⵅ ⴴ 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "ⴰⵙⴷⵅ ⴴ 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "ⴰⵙⴷⵅ ⴴ 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "ⴰⵙⴽⴰ ⴴ 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "ⴰⵙⴷⵅ ⴴ 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "ⴰⵚⴰⵏⵜ ⴴ 02:00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('dddd [ⴴ] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [ⴴ] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [ⴴ] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('dddd [ⴴ] LT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('dddd [ⴴ] LT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('dddd [ⴴ] LT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + + // Saturday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).week(), 1, "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).week(), 1, "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 2, "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).week(), 2, "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 3, "Jan 14 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2006, 11, 30]).week(), 1, "Dec 30 2006 should be week 1"); + test.equal(moment([2007, 0, 5]).week(), 1, "Jan 5 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 2, "Jan 6 2007 should be week 2"); + test.equal(moment([2007, 0, 12]).week(), 2, "Jan 12 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 3, "Jan 13 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 29]).week(), 1, "Dec 29 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 4]).week(), 1, "Jan 4 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 2, "Jan 5 2008 should be week 2"); + test.equal(moment([2008, 0, 11]).week(), 2, "Jan 11 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 3, "Jan 12 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 28]).week(), 1, "Dec 28 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 3]).week(), 1, "Jan 3 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 2, "Jan 4 2003 should be week 2"); + test.equal(moment([2003, 0, 10]).week(), 2, "Jan 10 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 3, "Jan 11 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 27]).week(), 1, "Dec 27 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 2]).week(), 1, "Jan 2 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 2, "Jan 3 2009 should be week 2"); + test.equal(moment([2009, 0, 9]).week(), 2, "Jan 9 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 3, "Jan 10 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(5); + + test.equal(moment([2009, 11, 26]).week(), 1, "Dec 26 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 2, "Jan 2 2010 should be week 2"); + test.equal(moment([2010, 0, 8]).week(), 2, "Jan 8 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 3, "Jan 9 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 7]).week(), 1, "Jan 7 2011 should be week 1"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 14]).week(), 2, "Jan 14 2011 should be week 2"); + test.equal(moment([2011, 0, 15]).week(), 3, "Jan 15 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', "Dec 31 2011 should be week 1"); + test.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', "Jan 6 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', "Jan 7 2012 should be week 2"); + test.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', "Jan 13 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', "Jan 14 2012 should be week 3"); + + test.done(); + } +}; + diff --git a/node_modules/moment/test/lang/uk.js b/node_modules/moment/test/lang/uk.js new file mode 100644 index 0000000..b82bee4 --- /dev/null +++ b/node_modules/moment/test/lang/uk.js @@ -0,0 +1,378 @@ +var moment = require("../../moment"); + + + /************************************************** + Ukrainian + *************************************************/ + +exports["lang:uk"] = { + setUp : function (cb) { + moment.lang('uk'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + var tests = 'січень січ_лютий лют_березень бер_квітень кві_травень тра_червень чер_липень лип_серпень сер_вересень вер_жовтень жов_листопад лис_грудень гру'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(18); + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'неділя, 14-го лютого 2010, 15:25:50'], + ['ddd, hA', 'нед, 3PM'], + ['M Mo MM MMMM MMM', '2 2-й 02 лютий лют'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-го 14'], + ['d do dddd ddd dd', '0 0-й неділя нед нд'], + ['DDD DDDo DDDD', '45 45-й 045'], + ['w wo ww', '7 7-й 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['DDDo [день року]', '45-й день року'], + ['L', '14.02.2010'], + ['LL', '14 лютого 2010 р.'], + ['LLL', '14 лютого 2010 р., 15:25'], + ['LLLL', 'неділя, 14 лютого 2010 р., 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "format ordinal" : function(test) { + test.expect(31); + test.equal(moment([2011, 0, 1]).format('DDDo'), '1-й', '1-й'); + test.equal(moment([2011, 0, 2]).format('DDDo'), '2-й', '2-й'); + test.equal(moment([2011, 0, 3]).format('DDDo'), '3-й', '3-й'); + test.equal(moment([2011, 0, 4]).format('DDDo'), '4-й', '4-й'); + test.equal(moment([2011, 0, 5]).format('DDDo'), '5-й', '5-й'); + test.equal(moment([2011, 0, 6]).format('DDDo'), '6-й', '6-й'); + test.equal(moment([2011, 0, 7]).format('DDDo'), '7-й', '7-й'); + test.equal(moment([2011, 0, 8]).format('DDDo'), '8-й', '8-й'); + test.equal(moment([2011, 0, 9]).format('DDDo'), '9-й', '9-й'); + test.equal(moment([2011, 0, 10]).format('DDDo'), '10-й', '10-й'); + + test.equal(moment([2011, 0, 11]).format('DDDo'), '11-й', '11-й'); + test.equal(moment([2011, 0, 12]).format('DDDo'), '12-й', '12-й'); + test.equal(moment([2011, 0, 13]).format('DDDo'), '13-й', '13-й'); + test.equal(moment([2011, 0, 14]).format('DDDo'), '14-й', '14-й'); + test.equal(moment([2011, 0, 15]).format('DDDo'), '15-й', '15-й'); + test.equal(moment([2011, 0, 16]).format('DDDo'), '16-й', '16-й'); + test.equal(moment([2011, 0, 17]).format('DDDo'), '17-й', '17-й'); + test.equal(moment([2011, 0, 18]).format('DDDo'), '18-й', '18-й'); + test.equal(moment([2011, 0, 19]).format('DDDo'), '19-й', '19-й'); + test.equal(moment([2011, 0, 20]).format('DDDo'), '20-й', '20-й'); + + test.equal(moment([2011, 0, 21]).format('DDDo'), '21-й', '21-й'); + test.equal(moment([2011, 0, 22]).format('DDDo'), '22-й', '22-й'); + test.equal(moment([2011, 0, 23]).format('DDDo'), '23-й', '23-й'); + test.equal(moment([2011, 0, 24]).format('DDDo'), '24-й', '24-й'); + test.equal(moment([2011, 0, 25]).format('DDDo'), '25-й', '25-й'); + test.equal(moment([2011, 0, 26]).format('DDDo'), '26-й', '26-й'); + test.equal(moment([2011, 0, 27]).format('DDDo'), '27-й', '27-й'); + test.equal(moment([2011, 0, 28]).format('DDDo'), '28-й', '28-й'); + test.equal(moment([2011, 0, 29]).format('DDDo'), '29-й', '29-й'); + test.equal(moment([2011, 0, 30]).format('DDDo'), '30-й', '30-й'); + + test.equal(moment([2011, 0, 31]).format('DDDo'), '31-й', '31-й'); + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + var expected = 'січень січ_лютий лют_березень бер_квітень кві_травень тра_червень чер_липень лип_серпень сер_вересень вер_жовтень жов_листопад лис_грудень гру'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + test.done(); + }, + + "format month case" : function(test) { + test.expect(24); + var months = { + 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), + 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') + }; + var i; + for (i = 0; i < 12; i++) { + test.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + test.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + var expected = 'неділя нед нд_понеділок пон пн_вівторок вів вт_середа срд ср_четвер чет чт_п’ятниця птн пт_субота суб сб'.split("_"); + var i; + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + test.done(); + }, + + "from" : function(test) { + test.expect(32); + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "декілька секунд", "44 seconds = seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "хвилина", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "хвилина", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2 хвилини", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44 хвилини", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "годину", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "годину", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2 години", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5 годин", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21 година", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "день", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "день", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2 дні", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "день", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5 днів", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:11}), true), "11 днів", "11 days = 11 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:21}), true), "21 день", "21 days = 21 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25 днів", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "місяць", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "місяць", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "місяць", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2 місяці", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2 місяці", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3 місяці", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "місяць", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5 місяців", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11 місяців", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "рік", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "рік", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2 роки", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "рік", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5 років", "5 years = 5 years"); + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + test.equal(moment(30000).from(0), "за декілька секунд", "prefix"); + test.equal(moment(0).from(30000), "декілька секунд тому", "suffix"); + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + test.equal(moment().add({s:30}).fromNow(), "за декілька секунд", "in seconds"); + test.equal(moment().add({d:5}).fromNow(), "за 5 днів", "in 5 days"); + test.done(); + }, + + "calendar day" : function(test) { + test.expect(7); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Сьогодні о 02:00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Сьогодні о 02:25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Сьогодні о 03:00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Завтра о 02:00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Сьогодні о 01:00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Вчора о 02:00", "yesterday at the same time"); + // A special case for Ukrainian since 11 hours have different preposition + test.equal(moment(a).add({ h: 9 }).calendar(), "Сьогодні об 11:00", "same day at 11 o'clock"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[У] dddd [о' + (m.hours() === 11 ? 'б' : '') + '] LT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[У] dddd [о] LT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[У] dddd [о] LT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + case 5: + case 6: + return '[Минулої] dddd [о' + (d.hours() === 11 ? 'б' : '') + '] LT'; + case 1: + case 2: + case 4: + return '[Минулого] dddd [о' + (d.hours() === 11 ? 'б' : '') + '] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format(makeFormat(m)), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).week(), 1, "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).week(), 2, "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).week(), 3, "Jan 9 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 1, "Jan 7 2007 should be week 1"); + test.equal(moment([2007, 0, 8]).week(), 2, "Jan 8 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 2, "Jan 14 2007 should be week 2"); + test.equal(moment([2007, 0, 15]).week(), 3, "Jan 15 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).week(), 1, "Dec 31 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 1, "Jan 6 2008 should be week 1"); + test.equal(moment([2008, 0, 7]).week(), 2, "Jan 7 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 2, "Jan 13 2008 should be week 2"); + test.equal(moment([2008, 0, 14]).week(), 3, "Jan 14 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).week(), 1, "Dec 30 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 1, "Jan 5 2003 should be week 1"); + test.equal(moment([2003, 0, 6]).week(), 2, "Jan 6 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 2, "Jan 12 2003 should be week 2"); + test.equal(moment([2003, 0, 13]).week(), 3, "Jan 13 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).week(), 1, "Dec 29 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 1, "Jan 4 2009 should be week 1"); + test.equal(moment([2009, 0, 5]).week(), 2, "Jan 5 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 2, "Jan 11 2009 should be week 2"); + test.equal(moment([2009, 0, 12]).week(), 3, "Jan 12 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).week(), 1, "Dec 28 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 1, "Jan 3 2010 should be week 1"); + test.equal(moment([2010, 0, 4]).week(), 2, "Jan 4 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 2, "Jan 10 2010 should be week 2"); + test.equal(moment([2010, 0, 11]).week(), 3, "Jan 11 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).week(), 1, "Dec 27 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 1, "Jan 2 2011 should be week 1"); + test.equal(moment([2011, 0, 3]).week(), 2, "Jan 3 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 2, "Jan 9 2011 should be week 2"); + test.equal(moment([2011, 0, 10]).week(), 3, "Jan 10 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-й', "Dec 26 2011 should be week 1"); + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-й', "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-й', "Jan 2 2012 should be week 2"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-й', "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-й', "Jan 9 2012 should be week 3"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/zh-cn.js b/node_modules/moment/test/lang/zh-cn.js new file mode 100644 index 0000000..7e2d4b7 --- /dev/null +++ b/node_modules/moment/test/lang/zh-cn.js @@ -0,0 +1,356 @@ +var moment = require("../../moment"); + + +/************************************************** + Simplified Chinese +**************************************************/ + +exports["lang:zh-cn"] = { + setUp : function (cb) { + moment.lang('zh-cn'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '星期日, 二月 14日 2010, 下午 3:25:50'], + ['ddd, Ah', '周日, 下午3'], + ['M Mo MM MMMM MMM', '2 2月 02 二月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14日 14'], + ['d do dddd ddd dd', '0 0日 星期日 周日 日'], + ['DDD DDDo DDDD', '45 45日 045'], + ['w wo ww', '8 8周 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '下午 下午'], + ['[这年的第] DDDo', '这年的第 45日'], + ['L', '2010年2月14日'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日下午3点25'], + ['LLLL', '2010年2月14日星期日下午3点25'], + ['l', '2010年2月14日'], + ['ll', '2010年2月14日'], + ['lll', '2010年2月14日下午3点25'], + ['llll', '2010年2月14日星期日下午3点25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = '星期日 周日 日_星期一 周一 一_星期二 周二 二_星期三 周三 三_星期四 周四 四_星期五 周五 五_星期六 周六 六'.split("_"); + var i; + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "几秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "1分钟", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "1分钟", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分钟", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分钟", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "1小时", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "1小时", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2小时", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5小时", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21小时", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "1天", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "1天", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2天", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "1天", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5天", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25天", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "1个月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "1个月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "1个月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2个月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2个月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3个月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "1个月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5个月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11个月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "1年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "1年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "1年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "几秒内", "prefix"); + test.equal(moment(0).from(30000), "几秒前", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "几秒前", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "几秒内", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5天内", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今天早上2点00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今天早上2点25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今天早上3点00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明天早上2点00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今天早上1点00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨天早上2点00", "yesterday at the same time"); + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days end of day"); + } + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days end of day"); + } + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + test.done(); + }, + + "meridiem" : function(test) { + test.expect(10); + + test.equal(moment([2011, 2, 23, 0, 0]).format('a'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('a'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('a'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('a'), "下午", "after noon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('a'), "晚上", "night"); + + test.equal(moment([2011, 2, 23, 0, 0]).format('A'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('A'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('A'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('A'), "下午", "afternoon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('A'), "晚上", "night"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1周', "Jan 1 2012 应该是第 1周"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1周', "Jan 7 2012 应该是第 1周"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2周', "Jan 8 2012 应该是第 2周"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2周', "Jan 14 2012 应该是第 2周"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3周', "Jan 15 2012 应该是第 3周"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/lang/zh-tw.js b/node_modules/moment/test/lang/zh-tw.js new file mode 100644 index 0000000..8990c5d --- /dev/null +++ b/node_modules/moment/test/lang/zh-tw.js @@ -0,0 +1,358 @@ +var moment = require("../../moment"); + + + /************************************************** + Traditional Chinese + *************************************************/ + +exports["lang:zh-tw"] = { + setUp : function (cb) { + moment.lang('zh-tw'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "parse" : function(test) { + test.expect(96); + + var tests = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + function equalTest(input, mmm, i) { + test.equal(moment(input, mmm).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMM', i); + equalTest(tests[i][1], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + } + test.done(); + }, + + "format" : function(test) { + test.expect(22); + + var a = [ + ['dddd, MMMM Do YYYY, a h:mm:ss', '星期日, 二月 14日 2010, 下午 3:25:50'], + ['ddd, Ah', '週日, 下午3'], + ['M Mo MM MMMM MMM', '2 2月 02 二月 2月'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14日 14'], + ['d do dddd ddd dd', '0 0日 星期日 週日 日'], + ['DDD DDDo DDDD', '45 45日 045'], + ['w wo ww', '8 8週 08'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '下午 下午'], + ['[這年的第] DDDo', '這年的第 45日'], + ['L', '2010年2月14日'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日下午3點25'], + ['LLLL', '2010年2月14日星期日下午3點25'], + ['l', '2010年2月14日'], + ['ll', '2010年2月14日'], + ['lll', '2010年2月14日下午3點25'], + ['llll', '2010年2月14日星期日下午3點25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + test.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "format month" : function(test) { + test.expect(12); + + var expected = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split("_"); + var i; + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + + test.done(); + }, + + "format week" : function(test) { + test.expect(7); + + var expected = '星期日 週日 日_星期一 週一 一_星期二 週二 二_星期三 週三 三_星期四 週四 四_星期五 週五 五_星期六 週六 六'.split("_"); + var i; + + for (i = 0; i < expected.length; i++) { + test.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + + test.done(); + }, + + "from" : function(test) { + test.expect(30); + + var start = moment([2007, 1, 28]); + test.equal(start.from(moment([2007, 1, 28]).add({s:44}), true), "幾秒", "44 seconds = a few seconds"); + test.equal(start.from(moment([2007, 1, 28]).add({s:45}), true), "一分鐘", "45 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:89}), true), "一分鐘", "89 seconds = a minute"); + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "2分鐘", "90 seconds = 2 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:44}), true), "44分鐘", "44 minutes = 44 minutes"); + test.equal(start.from(moment([2007, 1, 28]).add({m:45}), true), "一小時", "45 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:89}), true), "一小時", "89 minutes = an hour"); + test.equal(start.from(moment([2007, 1, 28]).add({m:90}), true), "2小時", "90 minutes = 2 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:5}), true), "5小時", "5 hours = 5 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:21}), true), "21小時", "21 hours = 21 hours"); + test.equal(start.from(moment([2007, 1, 28]).add({h:22}), true), "一天", "22 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:35}), true), "一天", "35 hours = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({h:36}), true), "2天", "36 hours = 2 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:1}), true), "一天", "1 day = a day"); + test.equal(start.from(moment([2007, 1, 28]).add({d:5}), true), "5天", "5 days = 5 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:25}), true), "25天", "25 days = 25 days"); + test.equal(start.from(moment([2007, 1, 28]).add({d:26}), true), "一個月", "26 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:30}), true), "一個月", "30 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:45}), true), "一個月", "45 days = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({d:46}), true), "2個月", "46 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:74}), true), "2個月", "75 days = 2 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:76}), true), "3個月", "76 days = 3 months"); + test.equal(start.from(moment([2007, 1, 28]).add({M:1}), true), "一個月", "1 month = a month"); + test.equal(start.from(moment([2007, 1, 28]).add({M:5}), true), "5個月", "5 months = 5 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:344}), true), "11個月", "344 days = 11 months"); + test.equal(start.from(moment([2007, 1, 28]).add({d:345}), true), "一年", "345 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:547}), true), "一年", "547 days = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({d:548}), true), "2年", "548 days = 2 years"); + test.equal(start.from(moment([2007, 1, 28]).add({y:1}), true), "一年", "1 year = a year"); + test.equal(start.from(moment([2007, 1, 28]).add({y:5}), true), "5年", "5 years = 5 years"); + + test.done(); + }, + + "suffix" : function(test) { + test.expect(2); + + test.equal(moment(30000).from(0), "幾秒內", "prefix"); + test.equal(moment(0).from(30000), "幾秒前", "suffix"); + + test.done(); + }, + + "now from now" : function(test) { + test.expect(1); + + test.equal(moment().fromNow(), "幾秒前", "now from now should display as in the past"); + + test.done(); + }, + + "fromNow" : function(test) { + test.expect(2); + + test.equal(moment().add({s:30}).fromNow(), "幾秒內", "in a few seconds"); + test.equal(moment().add({d:5}).fromNow(), "5天內", "in 5 days"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "今天早上2點00", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "今天早上2點25", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "今天早上3點00", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "明天早上2點00", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "今天早上1點00", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "昨天早上2點00", "yesterday at the same time"); + + test.done(); + }, + + "calendar next week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().add({ d: i }); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[下]ddddLT'), "Today + " + i + " days end of day"); + } + + test.done(); + }, + + "calendar last week" : function(test) { + test.expect(15); + + var i; + var m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ d: i }); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days current time"); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days beginning of day"); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + test.equal(m.calendar(), m.format('[上]ddddLT'), "Today - " + i + " days end of day"); + } + + test.done(); + }, + + "calendar all else" : function(test) { + test.expect(4); + + var weeksAgo = moment().subtract({ w: 1 }); + var weeksFromNow = moment().add({ w: 1 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "1 week ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 1 week"); + + weeksAgo = moment().subtract({ w: 2 }); + weeksFromNow = moment().add({ w: 2 }); + + test.equal(weeksAgo.calendar(), weeksAgo.format('L'), "2 weeks ago"); + test.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), "in 2 weeks"); + + test.done(); + }, + + "meridiem" : function(test) { + test.expect(10); + + test.equal(moment([2011, 2, 23, 0, 0]).format('a'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('a'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('a'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('a'), "下午", "after noon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('a'), "晚上", "night"); + + test.equal(moment([2011, 2, 23, 0, 0]).format('A'), "早上", "morning"); + test.equal(moment([2011, 2, 23, 9, 0]).format('A'), "上午", "before noon"); + test.equal(moment([2011, 2, 23, 12, 0]).format('A'), "中午", "noon"); + test.equal(moment([2011, 2, 23, 13, 0]).format('A'), "下午", "afternoon"); + test.equal(moment([2011, 2, 23, 18, 0]).format('A'), "晚上", "night"); + + test.done(); + }, + + // Sunday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + "weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).week(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).week(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).week(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).week(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "weeks year starting monday" : function(test) { + test.expect(6); + + test.equal(moment([2006, 11, 31]).week(), 1, "Dec 31 2006 should be week 1"); + test.equal(moment([2007, 0, 1]).week(), 1, "Jan 1 2007 should be week 1"); + test.equal(moment([2007, 0, 6]).week(), 1, "Jan 6 2007 should be week 1"); + test.equal(moment([2007, 0, 7]).week(), 2, "Jan 7 2007 should be week 2"); + test.equal(moment([2007, 0, 13]).week(), 2, "Jan 13 2007 should be week 2"); + test.equal(moment([2007, 0, 14]).week(), 3, "Jan 14 2007 should be week 3"); + + test.done(); + }, + + "weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 30]).week(), 1, "Dec 30 2007 should be week 1"); + test.equal(moment([2008, 0, 1]).week(), 1, "Jan 1 2008 should be week 1"); + test.equal(moment([2008, 0, 5]).week(), 1, "Jan 5 2008 should be week 1"); + test.equal(moment([2008, 0, 6]).week(), 2, "Jan 6 2008 should be week 2"); + test.equal(moment([2008, 0, 12]).week(), 2, "Jan 12 2008 should be week 2"); + test.equal(moment([2008, 0, 13]).week(), 3, "Jan 13 2008 should be week 3"); + + test.done(); + }, + + "weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 29]).week(), 1, "Dec 29 2002 should be week 1"); + test.equal(moment([2003, 0, 1]).week(), 1, "Jan 1 2003 should be week 1"); + test.equal(moment([2003, 0, 4]).week(), 1, "Jan 4 2003 should be week 1"); + test.equal(moment([2003, 0, 5]).week(), 2, "Jan 5 2003 should be week 2"); + test.equal(moment([2003, 0, 11]).week(), 2, "Jan 11 2003 should be week 2"); + test.equal(moment([2003, 0, 12]).week(), 3, "Jan 12 2003 should be week 3"); + + test.done(); + }, + + "weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 28]).week(), 1, "Dec 28 2008 should be week 1"); + test.equal(moment([2009, 0, 1]).week(), 1, "Jan 1 2009 should be week 1"); + test.equal(moment([2009, 0, 3]).week(), 1, "Jan 3 2009 should be week 1"); + test.equal(moment([2009, 0, 4]).week(), 2, "Jan 4 2009 should be week 2"); + test.equal(moment([2009, 0, 10]).week(), 2, "Jan 10 2009 should be week 2"); + test.equal(moment([2009, 0, 11]).week(), 3, "Jan 11 2009 should be week 3"); + + test.done(); + }, + + "weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 27]).week(), 1, "Dec 27 2009 should be week 1"); + test.equal(moment([2010, 0, 1]).week(), 1, "Jan 1 2010 should be week 1"); + test.equal(moment([2010, 0, 2]).week(), 1, "Jan 2 2010 should be week 1"); + test.equal(moment([2010, 0, 3]).week(), 2, "Jan 3 2010 should be week 2"); + test.equal(moment([2010, 0, 9]).week(), 2, "Jan 9 2010 should be week 2"); + test.equal(moment([2010, 0, 10]).week(), 3, "Jan 10 2010 should be week 3"); + + test.done(); + }, + + "weeks year starting saturday" : function(test) { + test.expect(5); + + test.equal(moment([2010, 11, 26]).week(), 1, "Dec 26 2010 should be week 1"); + test.equal(moment([2011, 0, 1]).week(), 1, "Jan 1 2011 should be week 1"); + test.equal(moment([2011, 0, 2]).week(), 2, "Jan 2 2011 should be week 2"); + test.equal(moment([2011, 0, 8]).week(), 2, "Jan 8 2011 should be week 2"); + test.equal(moment([2011, 0, 9]).week(), 3, "Jan 9 2011 should be week 3"); + + test.done(); + }, + + "weeks year starting sunday format" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1週', "Jan 1 2012 應該是第 1週"); + test.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1週', "Jan 7 2012 應該是第 1週"); + test.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2週', "Jan 8 2012 應該是第 2週"); + test.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2週', "Jan 14 2012 應該是第 2週"); + test.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3週', "Jan 15 2012 應該是第 3週"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/add_subtract.js b/node_modules/moment/test/moment/add_subtract.js new file mode 100644 index 0000000..0128b6a --- /dev/null +++ b/node_modules/moment/test/moment/add_subtract.js @@ -0,0 +1,246 @@ +var moment = require("../../moment"); + +exports.add = { + "add short" : function(test) { + test.expect(12); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add({ms:50}).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add({s:1}).seconds(), 9, 'Add seconds'); + test.equal(a.add({m:1}).minutes(), 8, 'Add minutes'); + test.equal(a.add({h:1}).hours(), 7, 'Add hours'); + test.equal(a.add({d:1}).date(), 13, 'Add date'); + test.equal(a.add({w:1}).date(), 20, 'Add week'); + test.equal(a.add({M:1}).month(), 10, 'Add month'); + test.equal(a.add({y:1}).year(), 2012, 'Add year'); + + var b = moment([2010, 0, 31]).add({M:1}); + var c = moment([2010, 1, 28]).subtract({M:1}); + + test.equal(b.month(), 1, 'add month, jan 31st to feb 28th'); + test.equal(b.date(), 28, 'add month, jan 31st to feb 28th'); + test.equal(c.month(), 0, 'subtract month, feb 28th to jan 28th'); + test.equal(c.date(), 28, 'subtract month, feb 28th to jan 28th'); + test.done(); + }, + + "add long" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add({milliseconds:50}).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add({seconds:1}).seconds(), 9, 'Add seconds'); + test.equal(a.add({minutes:1}).minutes(), 8, 'Add minutes'); + test.equal(a.add({hours:1}).hours(), 7, 'Add hours'); + test.equal(a.add({days:1}).date(), 13, 'Add date'); + test.equal(a.add({weeks:1}).date(), 20, 'Add week'); + test.equal(a.add({months:1}).month(), 10, 'Add month'); + test.equal(a.add({years:1}).year(), 2012, 'Add year'); + test.done(); + }, + + "add long singular" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add({millisecond:50}).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add({second:1}).seconds(), 9, 'Add seconds'); + test.equal(a.add({minute:1}).minutes(), 8, 'Add minutes'); + test.equal(a.add({hour:1}).hours(), 7, 'Add hours'); + test.equal(a.add({day:1}).date(), 13, 'Add date'); + test.equal(a.add({week:1}).date(), 20, 'Add week'); + test.equal(a.add({month:1}).month(), 10, 'Add month'); + test.equal(a.add({year:1}).year(), 2012, 'Add year'); + test.done(); + }, + + "add string long" : function(test) { + test.expect(9); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + var b = a.clone(); + + test.equal(a.add('millisecond', 50).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add('second', 1).seconds(), 9, 'Add seconds'); + test.equal(a.add('minute', 1).minutes(), 8, 'Add minutes'); + test.equal(a.add('hour', 1).hours(), 7, 'Add hours'); + test.equal(a.add('day', 1).date(), 13, 'Add date'); + test.equal(a.add('week', 1).date(), 20, 'Add week'); + test.equal(a.add('month', 1).month(), 10, 'Add month'); + test.equal(a.add('year', 1).year(), 2012, 'Add year'); + test.equal(b.add('day', '01').date(), 13, 'Add date'); + test.done(); + }, + + "add string long singular" : function(test) { + test.expect(9); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + var b = a.clone(); + + test.equal(a.add('milliseconds', 50).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add('seconds', 1).seconds(), 9, 'Add seconds'); + test.equal(a.add('minutes', 1).minutes(), 8, 'Add minutes'); + test.equal(a.add('hours', 1).hours(), 7, 'Add hours'); + test.equal(a.add('days', 1).date(), 13, 'Add date'); + test.equal(a.add('weeks', 1).date(), 20, 'Add week'); + test.equal(a.add('months', 1).month(), 10, 'Add month'); + test.equal(a.add('years', 1).year(), 2012, 'Add year'); + test.equal(b.add('days', '01').date(), 13, 'Add date'); + test.done(); + }, + + "add string short" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add('ms', 50).milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add('s', 1).seconds(), 9, 'Add seconds'); + test.equal(a.add('m', 1).minutes(), 8, 'Add minutes'); + test.equal(a.add('h', 1).hours(), 7, 'Add hours'); + test.equal(a.add('d', 1).date(), 13, 'Add date'); + test.equal(a.add('w', 1).date(), 20, 'Add week'); + test.equal(a.add('M', 1).month(), 10, 'Add month'); + test.equal(a.add('y', 1).year(), 2012, 'Add year'); + test.done(); + }, + + "add string long reverse args" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add(50, 'millisecond').milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add(1, 'second', 1).seconds(), 9, 'Add seconds'); + test.equal(a.add(1, 'minute', 1).minutes(), 8, 'Add minutes'); + test.equal(a.add(1, 'hour', 1).hours(), 7, 'Add hours'); + test.equal(a.add(1, 'day', 1).date(), 13, 'Add date'); + test.equal(a.add(1, 'week', 1).date(), 20, 'Add week'); + test.equal(a.add(1, 'month', 1).month(), 10, 'Add month'); + test.equal(a.add(1, 'year', 1).year(), 2012, 'Add year'); + test.done(); + }, + + "add string long singular reverse args" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add(50, 'milliseconds').milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add(1, 'seconds').seconds(), 9, 'Add seconds'); + test.equal(a.add(1, 'minutes').minutes(), 8, 'Add minutes'); + test.equal(a.add(1, 'hours').hours(), 7, 'Add hours'); + test.equal(a.add(1, 'days').date(), 13, 'Add date'); + test.equal(a.add(1, 'weeks').date(), 20, 'Add week'); + test.equal(a.add(1, 'months').month(), 10, 'Add month'); + test.equal(a.add(1, 'years').year(), 2012, 'Add year'); + test.done(); + }, + + "add string short reverse args" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + test.equal(a.add(50, 'ms').milliseconds(), 550, 'Add milliseconds'); + test.equal(a.add(1, 's').seconds(), 9, 'Add seconds'); + test.equal(a.add(1, 'm').minutes(), 8, 'Add minutes'); + test.equal(a.add(1, 'h').hours(), 7, 'Add hours'); + test.equal(a.add(1, 'd').date(), 13, 'Add date'); + test.equal(a.add(1, 'w').date(), 20, 'Add week'); + test.equal(a.add(1, 'M').month(), 10, 'Add month'); + test.equal(a.add(1, 'y').year(), 2012, 'Add year'); + test.done(); + }, + + "add across DST" : function(test) { + test.expect(3); + + var a = moment(new Date(2011, 2, 12, 5, 0, 0)); + var b = moment(new Date(2011, 2, 12, 5, 0, 0)); + var c = moment(new Date(2011, 2, 12, 5, 0, 0)); + var d = moment(new Date(2011, 2, 12, 5, 0, 0)); + a.add('days', 1); + b.add('hours', 24); + c.add('months', 1); + test.equal(a.hours(), 5, 'adding days over DST difference should result in the same hour'); + if (b.isDST() && !d.isDST()) { + test.equal(b.hours(), 6, 'adding hours over DST difference should result in a different hour'); + } else if (!b.isDST() && d.isDST()) { + test.equal(b.hours(), 4, 'adding hours over DST difference should result in a different hour'); + } else { + test.equal(b.hours(), 5, 'adding hours over DST difference should result in a same hour if the timezone does not have daylight savings time'); + } + test.equal(c.hours(), 5, 'adding months over DST difference should result in the same hour'); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/create.js b/node_modules/moment/test/moment/create.js new file mode 100644 index 0000000..2290fb4 --- /dev/null +++ b/node_modules/moment/test/moment/create.js @@ -0,0 +1,463 @@ +var moment = require("../../moment"); + +exports.create = { + "array" : function(test) { + test.expect(8); + test.ok(moment([2010]).toDate() instanceof Date, "[2010]"); + test.ok(moment([2010, 1]).toDate() instanceof Date, "[2010, 1]"); + test.ok(moment([2010, 1, 12]).toDate() instanceof Date, "[2010, 1, 12]"); + test.ok(moment([2010, 1, 12, 1]).toDate() instanceof Date, "[2010, 1, 12, 1]"); + test.ok(moment([2010, 1, 12, 1, 1]).toDate() instanceof Date, "[2010, 1, 12, 1, 1]"); + test.ok(moment([2010, 1, 12, 1, 1, 1]).toDate() instanceof Date, "[2010, 1, 12, 1, 1, 1]"); + test.ok(moment([2010, 1, 12, 1, 1, 1, 1]).toDate() instanceof Date, "[2010, 1, 12, 1, 1, 1, 1]"); + test.equal(+moment(new Date(2010, 1, 14, 15, 25, 50, 125)), +moment([2010, 1, 14, 15, 25, 50, 125]), "constructing with array === constructing with new Date()"); + test.done(); + }, + + "array copying": function(test) { + var importantArray = [2009, 11]; + test.expect(1); + moment(importantArray); + test.deepEqual(importantArray, [2009, 11], "initializer should not mutate the original array"); + test.done(); + }, + + "multi format array copying": function(test) { + var importantArray = ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY']; + test.expect(1); + moment('1999-02-13', importantArray); + test.deepEqual(importantArray, ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY'], "initializer should not mutate the original array"); + test.done(); + }, + + "number" : function(test) { + test.expect(3); + test.ok(moment(1000).toDate() instanceof Date, "1000"); + test.ok((moment(1000).valueOf() === 1000), "testing valueOf"); + test.ok((moment.utc(1000).valueOf() === 1000), "testing valueOf"); + test.done(); + }, + + "unix" : function(test) { + test.expect(8); + test.equal(moment.unix(1).valueOf(), 1000, "1 unix timestamp == 1000 Date.valueOf"); + test.equal(moment(1000).unix(), 1, "1000 Date.valueOf == 1 unix timestamp"); + test.equal(moment.unix(1000).valueOf(), 1000000, "1000 unix timestamp == 1000000 Date.valueOf"); + test.equal(moment(1500).unix(), 1, "1500 Date.valueOf == 1 unix timestamp"); + test.equal(moment(1900).unix(), 1, "1900 Date.valueOf == 1 unix timestamp"); + test.equal(moment(2100).unix(), 2, "2100 Date.valueOf == 2 unix timestamp"); + test.equal(moment(1333129333524).unix(), 1333129333, "1333129333524 Date.valueOf == 1333129333 unix timestamp"); + test.equal(moment(1333129333524000).unix(), 1333129333524, "1333129333524000 Date.valueOf == 1333129333524 unix timestamp"); + test.done(); + }, + + "date" : function(test) { + test.expect(1); + test.ok(moment(new Date()).toDate() instanceof Date, "new Date()"); + test.done(); + }, + + "date mutation" : function(test) { + test.expect(1); + var a = new Date(); + test.ok(moment(a).toDate() !== a, "the date moment uses should not be the date passed in"); + test.done(); + }, + + "moment" : function(test) { + test.expect(2); + test.ok(moment(moment()).toDate() instanceof Date, "moment(moment())"); + test.ok(moment(moment(moment())).toDate() instanceof Date, "moment(moment(moment()))"); + test.done(); + }, + + "cloning moment should only copy own properties" : function(test) { + test.expect(2); + test.ok(!moment().clone().hasOwnProperty('month'), "Should not clone prototype methods"); + test.ok(!moment().clone().hasOwnProperty('_lang'), "Should not clone prototype objects"); + test.done(); + }, + + "undefined" : function(test) { + test.expect(1); + test.ok(moment().toDate() instanceof Date, "undefined"); + test.done(); + }, + + "string without format" : function(test) { + test.expect(2); + test.ok(moment("Aug 9, 1995").toDate() instanceof Date, "Aug 9, 1995"); + test.ok(moment("Mon, 25 Dec 1995 13:30:00 GMT").toDate() instanceof Date, "Mon, 25 Dec 1995 13:30:00 GMT"); + test.done(); + }, + + "string without format - json" : function(test) { + test.expect(5); + test.equal(moment("Date(1325132654000)").valueOf(), 1325132654000, "Date(1325132654000)"); + test.equal(moment("Date(-1325132654000)").valueOf(), -1325132654000, "Date(-1325132654000)"); + test.equal(moment("/Date(1325132654000)/").valueOf(), 1325132654000, "/Date(1325132654000)/"); + test.equal(moment("/Date(1325132654000+0700)/").valueOf(), 1325132654000, "/Date(1325132654000+0700)/"); + test.equal(moment("/Date(1325132654000-0700)/").valueOf(), 1325132654000, "/Date(1325132654000-0700)/"); + test.done(); + }, + + "string with format dropped am/pm bug" : function(test) { + moment.lang('en'); + test.expect(3); + + test.equal(moment('05/1/2012', 'MM/DD/YYYY h:m:s a').format('MM/DD/YYYY'), '05/01/2012', 'should not break if am/pm is left off from the parsing tokens'); + test.equal(moment('05/1/2012 12:25:00 am', 'MM/DD/YYYY h:m:s a').format('MM/DD/YYYY'), '05/01/2012', 'should not break if am/pm is left off from the parsing tokens'); + test.equal(moment('05/1/2012 12:25:00 pm', 'MM/DD/YYYY h:m:s a').format('MM/DD/YYYY'), '05/01/2012', 'should not break if am/pm is left off from the parsing tokens'); + + test.done(); + }, + + "empty string with formats" : function(test) { + test.expect(3); + + test.equal(moment(' ', 'MM').format('YYYY-MM-DD HH:mm:ss'), '0000-01-01 00:00:00', 'should not break if input is an empty string'); + test.equal(moment(' ', 'DD').format('YYYY-MM-DD HH:mm:ss'), '0000-01-01 00:00:00', 'should not break if input is an empty string'); + test.equal(moment(' ', ['MM', "DD"]).format('YYYY-MM-DD HH:mm:ss'), '0000-01-01 00:00:00', 'should not break if input is an empty string'); + + test.done(); + }, + + "matching am/pm" : function(test) { + test.expect(13); + + test.equal(moment('2012-09-03T03:00PM', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00PM', 'am/pm should parse correctly for PM'); + test.equal(moment('2012-09-03T03:00P.M.', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00PM', 'am/pm should parse correctly for P.M.'); + test.equal(moment('2012-09-03T03:00P', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00PM', 'am/pm should parse correctly for P'); + test.equal(moment('2012-09-03T03:00pm', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00PM', 'am/pm should parse correctly for pm'); + test.equal(moment('2012-09-03T03:00p.m.', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00PM', 'am/pm should parse correctly for p.m.'); + test.equal(moment('2012-09-03T03:00p', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00PM', 'am/pm should parse correctly for p'); + + test.equal(moment('2012-09-03T03:00AM', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00AM', 'am/pm should parse correctly for AM'); + test.equal(moment('2012-09-03T03:00A.M.', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00AM', 'am/pm should parse correctly for A.M.'); + test.equal(moment('2012-09-03T03:00A', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00AM', 'am/pm should parse correctly for A'); + test.equal(moment('2012-09-03T03:00am', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00AM', 'am/pm should parse correctly for am'); + test.equal(moment('2012-09-03T03:00a.m.', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00AM', 'am/pm should parse correctly for a.m.'); + test.equal(moment('2012-09-03T03:00a', 'YYYY-MM-DDThh:mmA').format('YYYY-MM-DDThh:mmA'), '2012-09-03T03:00AM', 'am/pm should parse correctly for a'); + + test.equal(moment('5:00p.m.March 4 2012', 'h:mmAMMMM D YYYY').format('YYYY-MM-DDThh:mmA'), '2012-03-04T05:00PM', 'am/pm should parse correctly before month names'); + + test.done(); + }, + + "string with format" : function(test) { + moment.lang('en'); + var a = [ + ['MM-DD-YYYY', '12-02-1999'], + ['DD-MM-YYYY', '12-02-1999'], + ['DD/MM/YYYY', '12/02/1999'], + ['DD_MM_YYYY', '12_02_1999'], + ['DD:MM:YYYY', '12:02:1999'], + ['D-M-YY', '2-2-99'], + ['YY', '99'], + ['DDD-YYYY', '300-1999'], + ['DD-MM-YYYY h:m:s', '12-02-1999 2:45:10'], + ['DD-MM-YYYY h:m:s a', '12-02-1999 2:45:10 am'], + ['DD-MM-YYYY h:m:s a', '12-02-1999 2:45:10 pm'], + ['h:mm a', '12:00 pm'], + ['h:mm a', '12:30 pm'], + ['h:mm a', '12:00 am'], + ['h:mm a', '12:30 am'], + ['HH:mm', '12:00'], + ['YYYY-MM-DDTHH:mm:ss', '2011-11-11T11:11:11'], + ['MM-DD-YYYY [M]', '12-02-1999 M'], + ['ddd MMM DD HH:mm:ss YYYY', 'Tue Apr 07 22:52:51 2009'], + ['HH:mm:ss', '12:00:00'], + ['HH:mm:ss', '12:30:00'], + ['HH:mm:ss', '00:00:00'], + ['HH:mm:ss S', '00:30:00 1'], + ['HH:mm:ss SS', '00:30:00 12'], + ['HH:mm:ss SSS', '00:30:00 123'], + ['HH:mm:ss S', '00:30:00 7'], + ['HH:mm:ss SS', '00:30:00 78'], + ['HH:mm:ss SSS', '00:30:00 789'], + ['X.SSS', '1234567890.123'] + ], + i; + + test.expect(a.length); + for (i = 0; i < a.length; i++) { + test.equal(moment(a[i][1], a[i][0]).format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + test.done(); + }, + + "unix timestamp format" : function(test) { + var formats = ['X', 'X.S', 'X.SS', 'X.SSS']; + + test.expect(formats.length * 4); + for (var i = 0; i < formats.length; i++) { + var format = formats[i]; + test.equal(moment('1234567890', format).valueOf(), 1234567890 * 1000, format + " matches timestamp without milliseconds"); + test.equal(moment('1234567890.1', format).valueOf(), 1234567890 * 1000 + 100, format + " matches timestamp with deciseconds"); + test.equal(moment('1234567890.12', format).valueOf(), 1234567890 * 1000 + 120, format + " matches timestamp with centiseconds"); + test.equal(moment('1234567890.123', format).valueOf(), 1234567890 * 1000 + 123, format + " matches timestamp with milliseconds"); + } + + test.done(); + }, + + "string with format no separators" : function(test) { + moment.lang('en'); + var a = [ + ['MMDDYYYY', '12021999'], + ['DDMMYYYY', '12021999'], + ['YYYYMMDD', '19991202'], + ['DDMMMYYYY', '10Sep2001'] + ],i; + + test.expect(a.length); + + for (i = 0; i < a.length; i++) { + test.equal(moment(a[i][1], a[i][0]).format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + + test.done(); + }, + + "string with format (timezone)" : function(test) { + test.expect(8); + test.equal(moment('5 -0700', 'H ZZ').toDate().getUTCHours(), 12, 'parse hours "5 -0700" ---> "H ZZ"'); + test.equal(moment('5 -07:00', 'H Z').toDate().getUTCHours(), 12, 'parse hours "5 -07:00" ---> "H Z"'); + test.equal(moment('5 -0730', 'H ZZ').toDate().getUTCMinutes(), 30, 'parse hours "5 -0730" ---> "H ZZ"'); + test.equal(moment('5 -07:30', 'H Z').toDate().getUTCMinutes(), 30, 'parse hours "5 -07:30" ---> "H Z"'); + test.equal(moment('5 +0100', 'H ZZ').toDate().getUTCHours(), 4, 'parse hours "5 +0100" ---> "H ZZ"'); + test.equal(moment('5 +01:00', 'H Z').toDate().getUTCHours(), 4, 'parse hours "5 +01:00" ---> "H Z"'); + test.equal(moment('5 +0130', 'H ZZ').toDate().getUTCMinutes(), 30, 'parse hours "5 +0130" ---> "H ZZ"'); + test.equal(moment('5 +01:30', 'H Z').toDate().getUTCMinutes(), 30, 'parse hours "5 +01:30" ---> "H Z"'); + test.done(); + }, + + "string with format (timezone offset)" : function(test) { + test.expect(4); + var a = new Date(Date.UTC(2011, 0, 1, 1)); + var b = moment('2011 1 1 0 -01:00', 'YYYY MM DD HH Z'); + test.equal(a.getHours(), b.hours(), 'date created with utc == parsed string with timezone offset'); + test.equal(+a, +b, 'date created with utc == parsed string with timezone offset'); + var c = moment('2011 2 1 10 -05:00', 'YYYY MM DD HH Z'); + var d = moment('2011 2 1 8 -07:00', 'YYYY MM DD HH Z'); + test.equal(c.hours(), d.hours(), '10 am central time == 8 am pacific time'); + var e = moment.utc('Fri, 20 Jul 2012 17:15:00', 'ddd, DD MMM YYYY HH:mm:ss'); + var f = moment.utc('Fri, 20 Jul 2012 10:15:00 -0700', 'ddd, DD MMM YYYY HH:mm:ss ZZ'); + test.equal(e.hours(), f.hours(), 'parse timezone offset in utc'); + test.done(); + }, + + "string with array of formats" : function(test) { + test.expect(14); + + test.equal(moment('11-02-1999', ['MM-DD-YYYY', 'DD-MM-YYYY']).format('MM DD YYYY'), '11 02 1999', 'switching month and day'); + test.equal(moment('02-11-1999', ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY']).format('MM DD YYYY'), '02 11 1999', 'year last'); + test.equal(moment('1999-02-11', ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY']).format('MM DD YYYY'), '02 11 1999', 'year first'); + + test.equal(moment('02-11-1999', ['MM/DD/YYYY', 'YYYY-MM-DD']).format('MM DD YYYY'), '02 11 1999', 'year last'); + test.equal(moment('1999-02-11', ['MM/DD/YYYY', 'YYYY-MM-DD']).format('MM DD YYYY'), '02 11 1999', 'year first'); + test.equal(moment('02-11-1999', ['YYYY-MM-DD', 'MM/DD/YYYY']).format('MM DD YYYY'), '02 11 1999', 'year last'); + test.equal(moment('1999-02-11', ['YYYY-MM-DD', 'MM/DD/YYYY']).format('MM DD YYYY'), '02 11 1999', 'year first'); + + test.equal(moment('13-11-1999', ['MM/DD/YYYY', 'DD/MM/YYYY']).format('MM DD YYYY'), '11 13 1999', 'second must be month'); + test.equal(moment('11-13-1999', ['MM/DD/YYYY', 'DD/MM/YYYY']).format('MM DD YYYY'), '11 13 1999', 'first must be month'); + test.equal(moment('13-14-1999', ['MM/DD/YYYY', 'DD/MM/YYYY']).format('MM DD YYYY'), '01 14 2000', 'either can be a month, month first format'); + test.equal(moment('13-14-1999', ['DD/MM/YYYY', 'MM/DD/YYYY']).format('MM DD YYYY'), '02 13 2000', 'either can be a month, day first format'); + + test.equal(moment('13-14-98', ['DD MM YY', 'DD MM YYYY'])._f, 'DD MM YY', 'use two digit year'); + test.equal(moment('13-14-1998', ['DD MM YY', 'DD MM YYYY'])._f, 'DD MM YYYY', 'use four digit year'); + + test.equal(moment('01', ["MM", "DD"])._f, "MM", "Should use first valid format"); + + test.done(); + }, + + "string with format - years" : function(test) { + test.expect(4); + test.equal(moment('67', 'YY').format('YYYY'), '2067', '67 > 2067'); + test.equal(moment('68', 'YY').format('YYYY'), '2068', '68 > 2068'); + test.equal(moment('69', 'YY').format('YYYY'), '1969', '69 > 1969'); + test.equal(moment('70', 'YY').format('YYYY'), '1970', '70 > 1970'); + test.done(); + }, + + "implicit cloning" : function(test) { + test.expect(2); + var momentA = moment([2011, 10, 10]); + var momentB = moment(momentA); + momentA.month(5); + test.equal(momentB.month(), 10, "Calling moment() on a moment will create a clone"); + test.equal(momentA.month(), 5, "Calling moment() on a moment will create a clone"); + test.done(); + }, + + "explicit cloning" : function(test) { + test.expect(2); + var momentA = moment([2011, 10, 10]); + var momentB = momentA.clone(); + momentA.month(5); + test.equal(momentB.month(), 10, "Calling moment() on a moment will create a clone"); + test.equal(momentA.month(), 5, "Calling moment() on a moment will create a clone"); + test.done(); + }, + + "cloning carrying over utc mode" : function(test) { + test.expect(8); + + test.equal(moment().local().clone()._isUTC, false, "An explicit cloned local moment should have _isUTC == false"); + test.equal(moment().utc().clone()._isUTC, true, "An cloned utc moment should have _isUTC == true"); + test.equal(moment().clone()._isUTC, false, "An explicit cloned local moment should have _isUTC == false"); + test.equal(moment.utc().clone()._isUTC, true, "An explicit cloned utc moment should have _isUTC == true"); + test.equal(moment(moment().local())._isUTC, false, "An implicit cloned local moment should have _isUTC == false"); + test.equal(moment(moment().utc())._isUTC, true, "An implicit cloned utc moment should have _isUTC == true"); + test.equal(moment(moment())._isUTC, false, "An implicit cloned local moment should have _isUTC == false"); + test.equal(moment(moment.utc())._isUTC, true, "An implicit cloned utc moment should have _isUTC == true"); + + test.done(); + }, + + "parsing iso" : function(test) { + var offset = moment([2011, 9, 08]).zone(); + var pad = function(input) { + if (input < 10) { + return '0' + input; + } + return '' + input; + } + var hourOffset = (offset > 0) ? Math.floor(offset / 60) : Math.ceil(offset / 60); + var minOffset = offset - (hourOffset * 60); + var tz = (offset > 0) ? '-' + pad(hourOffset) + ':' + pad(minOffset) : '+' + pad(-hourOffset) + ':' + pad(-minOffset); + var tz2 = tz.replace(':', ''); + var formats = [ + ['2011-10-08', '2011-10-08T00:00:00.000' + tz], + ['2011-10-08T18', '2011-10-08T18:00:00.000' + tz], + ['2011-10-08T18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-10-08T18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-10-08T18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-10-08T18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-10-08T18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-10-08T18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011-10-08 18', '2011-10-08T18:00:00.000' + tz], + ['2011-10-08 18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-10-08 18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-10-08 18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08 18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-10-08 18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08 18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-10-08 18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-10-08 18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-10-08 18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz] + ]; + test.expect(formats.length); + for (var i = 0; i < formats.length; i++) { + test.equal(formats[i][1], moment(formats[i][0]).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), "moment should be able to parse ISO " + formats[i][0]); + } + test.done(); + }, + + "parsing iso with T" : function(test) { + test.expect(9); + + test.equal(moment('2011-10-08T18')._f, "YYYY-MM-DDTHH", "should include 'T' in the format"); + test.equal(moment('2011-10-08T18:20')._f, "YYYY-MM-DDTHH:mm", "should include 'T' in the format"); + test.equal(moment('2011-10-08T18:20:13')._f, "YYYY-MM-DDTHH:mm:ss", "should include 'T' in the format"); + test.equal(moment('2011-10-08T18:20:13.321')._f, "YYYY-MM-DDTHH:mm:ss.S", "should include 'T' in the format"); + + test.equal(moment('2011-10-08 18')._f, "YYYY-MM-DD HH", "should not include 'T' in the format"); + test.equal(moment('2011-10-08 18:20')._f, "YYYY-MM-DD HH:mm", "should not include 'T' in the format"); + test.equal(moment('2011-10-08 18:20:13')._f, "YYYY-MM-DD HH:mm:ss", "should not include 'T' in the format"); + test.equal(moment('2011-10-08 18:20:13.321')._f, "YYYY-MM-DD HH:mm:ss.S", "should not include 'T' in the format"); + + test.ok(moment("2013-04-23 15:23:47 UTC").isValid(), "including a trailing UTC in the input should work"); + + test.done(); + }, + + "parsing iso Z timezone" : function(test) { + var i, + formats = [ + ['2011-10-08T18:04Z', '2011-10-08T18:04:00.000+00:00'], + ['2011-10-08T18:04:20Z', '2011-10-08T18:04:20.000+00:00'], + ['2011-10-08T18:04:20.111Z', '2011-10-08T18:04:20.111+00:00'] + ]; + test.expect(formats.length); + for (i = 0; i < formats.length; i++) { + test.equal(moment.utc(formats[i][0]).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), formats[i][1], "moment should be able to parse ISO " + formats[i][0]); + } + test.done(); + }, + + "parsing iso Z timezone into local" : function(test) { + test.expect(1); + + var m = moment('2011-10-08T18:04:20.111Z'); + + test.equal(m.utc().format('YYYY-MM-DDTHH:mm:ss.SSS'), '2011-10-08T18:04:20.111', "moment should be able to parse ISO 2011-10-08T18:04:20.111Z"); + + test.done(); + }, + + "null" : function(test) { + test.expect(3); + test.equal(moment(''), null, "Calling moment('')"); + test.equal(moment(null), null, "Calling moment(null)"); + test.equal(moment('', 'YYYY-MM-DD'), null, "Calling moment('', 'YYYY-MM-DD')"); + test.done(); + }, + + "first century" : function(test) { + test.expect(9); + test.equal(moment([0, 0, 1]).format("YYYY-MM-DD"), "0000-01-01", "Year AD 0"); + test.equal(moment([99, 0, 1]).format("YYYY-MM-DD"), "0099-01-01", "Year AD 99"); + test.equal(moment([999, 0, 1]).format("YYYY-MM-DD"), "0999-01-01", "Year AD 999"); + test.equal(moment('0 1 1', 'YYYY MM DD').format("YYYY-MM-DD"), "0000-01-01", "Year AD 0"); + test.equal(moment('99 1 1', 'YYYY MM DD').format("YYYY-MM-DD"), "0099-01-01", "Year AD 99"); + test.equal(moment('999 1 1', 'YYYY MM DD').format("YYYY-MM-DD"), "0999-01-01", "Year AD 999"); + test.equal(moment('0 1 1', 'YYYYY MM DD').format("YYYYY-MM-DD"), "00000-01-01", "Year AD 0"); + test.equal(moment('99 1 1', 'YYYYY MM DD').format("YYYYY-MM-DD"), "00099-01-01", "Year AD 99"); + test.equal(moment('999 1 1', 'YYYYY MM DD').format("YYYYY-MM-DD"), "00999-01-01", "Year AD 999"); + test.done(); + }, + + "six digit years" : function(test) { + test.expect(8); + test.equal(moment([-270000, 0, 1]).format("YYYYY-MM-DD"), "-270000-01-01", "format BC 270,001"); + test.equal(moment([ 270000, 0, 1]).format("YYYYY-MM-DD"), "270000-01-01", "format AD 270,000"); + test.equal(moment("-270000-01-01", "YYYYY-MM-DD").toDate().getFullYear(), -270000, "parse BC 270,001"); + test.equal(moment("270000-01-01", "YYYYY-MM-DD").toDate().getFullYear(), 270000, "parse AD 270,000"); + test.equal(moment("+270000-01-01", "YYYYY-MM-DD").toDate().getFullYear(), 270000, "parse AD +270,000"); + test.equal(moment.utc("-270000-01-01", "YYYYY-MM-DD").toDate().getUTCFullYear(), -270000, "parse utc BC 270,001"); + test.equal(moment.utc("270000-01-01", "YYYYY-MM-DD").toDate().getUTCFullYear(), 270000, "parse utc AD 270,000"); + test.equal(moment.utc("+270000-01-01", "YYYYY-MM-DD").toDate().getUTCFullYear(), 270000, "parse utc AD +270,000"); + test.done(); + }, + + "negative four digit years" : function(test) { + test.expect(2); + test.equal(moment("-1000-01-01", "YYYYY-MM-DD").toDate().getFullYear(), -1000, "parse BC 1,001"); + test.equal(moment.utc("-1000-01-01", "YYYYY-MM-DD").toDate().getUTCFullYear(), -1000, "parse utc BC 1,001"); + test.done(); + }, + + "parsing into a language" : function (test) { + test.expect(2); + + moment.lang('parselang', { + months : "one_two_three_four_five_six_seven_eight_nine_ten_eleven_twelve".split('_'), + monthsShort : "one_two_three_four_five_six_seven_eight_nine_ten_eleven_twelve".split("_") + }); + + moment.lang('en'); + + test.equal(moment('2012 seven', 'YYYY MMM', 'parselang').month(), 6, "should be able to parse in a specific language"); + + moment.lang('parselang'); + + test.equal(moment('2012 july', 'YYYY MMM', 'en').month(), 6, "should be able to parse in a specific language"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/days_in_month.js b/node_modules/moment/test/moment/days_in_month.js new file mode 100644 index 0000000..ffa2546 --- /dev/null +++ b/node_modules/moment/test/moment/days_in_month.js @@ -0,0 +1,28 @@ +var moment = require("../../moment"); + +exports.days_in_month = { + "days in month" : function(test) { + test.expect(24); + var months = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + for (var i = 0; i < 12; i++) { + test.equal(moment([2012, i]).daysInMonth(), + months[i], + moment([2012, i]).format('L') + " should have " + months[i] + " days. (beginning of month " + i + ')') + } + for (var i = 0; i < 12; i++) { + test.equal(moment([2012, i, months[i]]).daysInMonth(), + months[i], + moment([2012, i, months[i]]).format('L') + " should have " + months[i] + " days. (end of month " + i + ')') + } + test.done(); + }, + + "days in month leap years" : function(test) { + test.expect(4); + test.equal(moment([2010, 1]).daysInMonth(), 28, "Feb 2010 should have 28 days"); + test.equal(moment([2100, 1]).daysInMonth(), 28, "Feb 2100 should have 28 days"); + test.equal(moment([2008, 1]).daysInMonth(), 29, "Feb 2008 should have 29 days"); + test.equal(moment([2000, 1]).daysInMonth(), 29, "Feb 2000 should have 29 days"); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/diff.js b/node_modules/moment/test/moment/diff.js new file mode 100644 index 0000000..997d812 --- /dev/null +++ b/node_modules/moment/test/moment/diff.js @@ -0,0 +1,239 @@ +var moment = require("../../moment"); + +function equal(test, a, b, message) { + test.ok(Math.abs(a - b) < 0.00000001, "(" + a + " === " + b + ") " + message); +} + +function dstForYear(year) { + var start = moment([year]), + end = moment([year + 1]), + current = start.clone(), + last; + + while (current < end) { + last = current.clone(); + current.add(24, 'hour'); + if (last.zone() !== current.zone()) { + end = current.clone(); + current = last.clone(); + break; + } + } + + while (current < end) { + last = current.clone(); + current.add(1, 'hour'); + if (last.zone() !== current.zone()) { + return { + moment : last, + diff : (current.zone() - last.zone()) / 60 + }; + } + } +} + +exports.diff = { + "diff" : function(test) { + test.expect(5); + + test.equal(moment(1000).diff(0), 1000, "1 second - 0 = 1000"); + test.equal(moment(1000).diff(500), 500, "1 second - 0.5 seconds = 500"); + test.equal(moment(0).diff(1000), -1000, "0 - 1 second = -1000"); + test.equal(moment(new Date(1000)).diff(1000), 0, "1 second - 1 second = 0"); + var oneHourDate = new Date(), + nowDate = new Date(+oneHourDate); + oneHourDate.setHours(oneHourDate.getHours() + 1); + test.equal(moment(oneHourDate).diff(nowDate), 60 * 60 * 1000, "1 hour from now = 3600000"); + test.done(); + }, + + "diff key after" : function(test) { + test.expect(10); + + test.equal(moment([2010]).diff([2011], 'years'), -1, "year diff"); + test.equal(moment([2010]).diff([2010, 2], 'months'), -2, "month diff"); + test.equal(moment([2010]).diff([2010, 0, 7], 'weeks'), 0, "week diff"); + test.equal(moment([2010]).diff([2010, 0, 8], 'weeks'), -1, "week diff"); + test.equal(moment([2010]).diff([2010, 0, 21], 'weeks'), -2, "week diff"); + test.equal(moment([2010]).diff([2010, 0, 22], 'weeks'), -3, "week diff"); + test.equal(moment([2010]).diff([2010, 0, 4], 'days'), -3, "day diff"); + test.equal(moment([2010]).diff([2010, 0, 1, 4], 'hours'), -4, "hour diff"); + test.equal(moment([2010]).diff([2010, 0, 1, 0, 5], 'minutes'), -5, "minute diff"); + test.equal(moment([2010]).diff([2010, 0, 1, 0, 0, 6], 'seconds'), -6, "second diff"); + test.done(); + }, + + "diff key before" : function(test) { + test.expect(10); + + test.equal(moment([2011]).diff([2010], 'years'), 1, "year diff"); + test.equal(moment([2010, 2]).diff([2010], 'months'), 2, "month diff"); + test.equal(moment([2010, 0, 4]).diff([2010], 'days'), 3, "day diff"); + test.equal(moment([2010, 0, 7]).diff([2010], 'weeks'), 0, "week diff"); + test.equal(moment([2010, 0, 8]).diff([2010], 'weeks'), 1, "week diff"); + test.equal(moment([2010, 0, 21]).diff([2010], 'weeks'), 2, "week diff"); + test.equal(moment([2010, 0, 22]).diff([2010], 'weeks'), 3, "week diff"); + test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hours'), 4, "hour diff"); + test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minutes'), 5, "minute diff"); + test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'seconds'), 6, "second diff"); + test.done(); + }, + + "diff key before singular" : function(test) { + test.expect(10); + + test.equal(moment([2011]).diff([2010], 'year'), 1, "year diff singular"); + test.equal(moment([2010, 2]).diff([2010], 'month'), 2, "month diff singular"); + test.equal(moment([2010, 0, 4]).diff([2010], 'day'), 3, "day diff singular"); + test.equal(moment([2010, 0, 7]).diff([2010], 'week'), 0, "week diff singular"); + test.equal(moment([2010, 0, 8]).diff([2010], 'week'), 1, "week diff singular"); + test.equal(moment([2010, 0, 21]).diff([2010], 'week'), 2, "week diff singular"); + test.equal(moment([2010, 0, 22]).diff([2010], 'week'), 3, "week diff singular"); + test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hour'), 4, "hour diff singular"); + test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minute'), 5, "minute diff singular"); + test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'second'), 6, "second diff singular"); + test.done(); + }, + + "diff key before abbreviated" : function(test) { + test.expect(10); + + test.equal(moment([2011]).diff([2010], 'y'), 1, "year diff abbreviated"); + test.equal(moment([2010, 2]).diff([2010], 'M'), 2, "month diff abbreviated"); + test.equal(moment([2010, 0, 4]).diff([2010], 'd'), 3, "day diff abbreviated"); + test.equal(moment([2010, 0, 7]).diff([2010], 'w'), 0, "week diff abbreviated"); + test.equal(moment([2010, 0, 8]).diff([2010], 'w'), 1, "week diff abbreviated"); + test.equal(moment([2010, 0, 21]).diff([2010], 'w'), 2, "week diff abbreviated"); + test.equal(moment([2010, 0, 22]).diff([2010], 'w'), 3, "week diff abbreviated"); + test.equal(moment([2010, 0, 1, 4]).diff([2010], 'h'), 4, "hour diff abbreviated"); + test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'm'), 5, "minute diff abbreviated"); + test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 's'), 6, "second diff abbreviated"); + test.done(); + }, + + "diff month" : function(test) { + test.expect(1); + + test.equal(moment([2011, 0, 31]).diff([2011, 2, 1], 'months'), -1, "month diff"); + test.done(); + }, + + "diff across DST" : function(test) { + var dst = dstForYear(2012), a, b, daysInMonth; + if (!dst) { + console.log("No DST?"); + test.done(); + return; + } + + test.expect(16); + + a = dst.moment; + b = a.clone().utc().add(12, 'hours').local(); + daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2; + equal(test, b.diff(a, 'ms', true), 12 * 60 * 60 * 1000, "ms diff across DST"); + equal(test, b.diff(a, 's', true), 12 * 60 * 60, "second diff across DST"); + equal(test, b.diff(a, 'm', true), 12 * 60, "minute diff across DST"); + equal(test, b.diff(a, 'h', true), 12, "hour diff across DST"); + equal(test, b.diff(a, 'd', true), (12 - dst.diff) / 24, "day diff across DST"); + equal(test, b.diff(a, 'w', true), (12 - dst.diff) / 24 / 7, "week diff across DST"); + equal(test, b.diff(a, 'M', true), (12 - dst.diff) / 24 / daysInMonth, "month diff across DST"); + equal(test, b.diff(a, 'y', true), (12 - dst.diff) / 24 / daysInMonth / 12, "year diff across DST"); + + + a = dst.moment; + b = a.clone().utc().add(12 + dst.diff, 'hours').local(); + daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2; + + equal(test, b.diff(a, 'ms', true), (12 + dst.diff) * 60 * 60 * 1000, "ms diff across DST"); + equal(test, b.diff(a, 's', true), (12 + dst.diff) * 60 * 60, "second diff across DST"); + equal(test, b.diff(a, 'm', true), (12 + dst.diff) * 60, "minute diff across DST"); + equal(test, b.diff(a, 'h', true), (12 + dst.diff), "hour diff across DST"); + equal(test, b.diff(a, 'd', true), 12 / 24, "day diff across DST"); + equal(test, b.diff(a, 'w', true), 12 / 24 / 7, "week diff across DST"); + equal(test, b.diff(a, 'M', true), 12 / 24 / daysInMonth, "month diff across DST"); + equal(test, b.diff(a, 'y', true), 12 / 24 / daysInMonth / 12, "year diff across DST"); + + test.done(); + }, + + "diff overflow" : function(test) { + test.expect(4); + + test.equal(moment([2011]).diff([2010], 'months'), 12, "month diff"); + test.equal(moment([2010, 0, 2]).diff([2010], 'hours'), 24, "hour diff"); + test.equal(moment([2010, 0, 1, 2]).diff([2010], 'minutes'), 120, "minute diff"); + test.equal(moment([2010, 0, 1, 0, 4]).diff([2010], 'seconds'), 240, "second diff"); + test.done(); + }, + + "diff between utc and local" : function(test) { + test.expect(7); + + test.equal(moment([2011]).utc().diff([2010], 'years'), 1, "year diff"); + test.equal(moment([2010, 2, 2]).utc().diff([2010, 0, 2], 'months'), 2, "month diff"); + test.equal(moment([2010, 0, 4]).utc().diff([2010], 'days'), 3, "day diff"); + test.equal(moment([2010, 0, 22]).utc().diff([2010], 'weeks'), 3, "week diff"); + test.equal(moment([2010, 0, 1, 4]).utc().diff([2010], 'hours'), 4, "hour diff"); + test.equal(moment([2010, 0, 1, 0, 5]).utc().diff([2010], 'minutes'), 5, "minute diff"); + test.equal(moment([2010, 0, 1, 0, 0, 6]).utc().diff([2010], 'seconds'), 6, "second diff"); + + test.done(); + }, + + "diff floored" : function(test) { + test.expect(7); + + test.equal(moment([2010, 0, 1, 23]).diff([2010], 'day'), 0, "23 hours = 0 days"); + test.equal(moment([2010, 0, 1, 23, 59]).diff([2010], 'day'), 0, "23:59 hours = 0 days"); + test.equal(moment([2010, 0, 1, 24]).diff([2010], 'day'), 1, "24 hours = 1 day"); + test.equal(moment([2010, 0, 2]).diff([2011, 0, 1], 'year'), 0, "year rounded down"); + test.equal(moment([2011, 0, 1]).diff([2010, 0, 2], 'year'), 0, "year rounded down"); + test.equal(moment([2010, 0, 2]).diff([2011, 0, 2], 'year'), -1, "year rounded down"); + test.equal(moment([2011, 0, 2]).diff([2010, 0, 2], 'year'), 1, "year rounded down"); + + test.done(); + }, + + "year diffs include dates" : function(test) { + test.expect(1); + + test.ok(moment([2012, 1, 19]).diff(moment([2002, 1, 20]), 'years', true) < 10, "year diff should include date of month"); + + test.done(); + }, + + "month diffs" : function (test) { + test.expect(8); + + // due to floating point math errors, these tests just need to be accurate within 0.00000001 + equal(test, moment([2012, 0, 1]).diff([2012, 1, 1], 'months', true), -1, 'Jan 1 to Feb 1 should be 1 month'); + equal(test, moment([2012, 0, 1]).diff([2012, 0, 1, 12], 'months', true), -0.5/31, 'Jan 1 to Jan 1 noon should be 0.5/31 months'); + equal(test, moment([2012, 0, 15]).diff([2012, 1, 15], 'months', true), -1, 'Jan 15 to Feb 15 should be 1 month'); + equal(test, moment([2012, 0, 28]).diff([2012, 1, 28], 'months', true), -1, 'Jan 28 to Feb 28 should be 1 month'); + equal(test, moment([2012, 0, 31]).diff([2012, 1, 29], 'months', true), -1 + (2/30), 'Jan 31 to Feb 29 should be 1 - (2/30) months'); + equal(test, moment([2012, 0, 31]).diff([2012, 2, 1], 'months', true), -2 + (30/31), 'Jan 31 to Mar 1 should be 2 - (30/31) months'); + equal(test, moment([2012, 0, 31]).diff([2012, 2, 1, 12], 'months', true), -2 + (29.5/31), 'Jan 31 to Mar 1 should be 2 - (29.5/31) months'); + equal(test, moment([2012, 0, 1]).diff([2012, 0, 31], 'months', true), -(30 / 31), 'Jan 1 to Jan 31 should be 30/31 months'); + + test.done(); + }, + + "year diffs" : function (test) { + test.expect(10); + + // due to floating point math errors, these tests just need to be accurate within 0.00000001 + equal(test, moment([2012, 0, 1]).diff([2013, 0, 1], 'years', true), -1, 'Jan 1 2012 to Jan 1 2013 should be 1 year'); + equal(test, moment([2012, 1, 28]).diff([2013, 1, 28], 'years', true), -1, 'Feb 28 2012 to Feb 28 2013 should be 1 year'); + equal(test, moment([2012, 2, 1]).diff([2013, 2, 1], 'years', true), -1, 'Mar 1 2012 to Mar 1 2013 should be 1 year'); + equal(test, moment([2012, 11, 1]).diff([2013, 11, 1], 'years', true), -1, 'Dec 1 2012 to Dec 1 2013 should be 1 year'); + equal(test, moment([2012, 11, 31]).diff([2013, 11, 31], 'years', true), -1, 'Dec 31 2012 to Dec 31 2013 should be 1 year'); + equal(test, moment([2012, 0, 1]).diff([2013, 6, 1], 'years', true), -1.5, 'Jan 1 2012 to Jul 1 2013 should be 1.5 years'); + equal(test, moment([2012, 0, 31]).diff([2013, 6, 31], 'years', true), -1.5, 'Jan 31 2012 to Jul 31 2013 should be 1.5 years'); + equal(test, moment([2012, 0, 1]).diff([2013, 0, 1, 12], 'years', true), -1-(0.5/31)/12, 'Jan 1 2012 to Jan 1 2013 noon should be 1+(0.5/31)/12 years'); + equal(test, moment([2012, 0, 1]).diff([2013, 6, 1, 12], 'years', true), -1.5-(0.5/31)/12, 'Jan 1 2012 to Jul 1 2013 noon should be 1.5+(0.5/31)/12 years'); + equal(test, moment([2012, 1, 29]).diff([2013, 1, 28], 'years', true), -1 + (1/28.5)/12, 'Feb 29 2012 to Feb 28 2013 should be 1-(1/28.5)/12 years'); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/duration.js b/node_modules/moment/test/moment/duration.js new file mode 100644 index 0000000..8b4b0e4 --- /dev/null +++ b/node_modules/moment/test/moment/duration.js @@ -0,0 +1,409 @@ +var moment = require("../../moment"); + +exports.duration = { + "object instantiation" : function(test) { + var d = moment.duration({ + years: 2, + months: 3, + weeks: 2, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(8); + test.equal(d.years(), 2, "years"); + test.equal(d.months(), 3, "months"); + test.equal(d.weeks(), 2, "weeks"); + test.equal(d.days(), 15, "days"); // two weeks + 1 day + test.equal(d.hours(), 8, "hours"); + test.equal(d.minutes(), 9, "minutes"); + test.equal(d.seconds(), 20, "seconds"); + test.equal(d.milliseconds(), 12, "milliseconds"); + test.done(); + }, + + "milliseconds instantiation" : function(test) { + test.expect(1); + test.equal(moment.duration(72).milliseconds(), 72, "milliseconds"); + test.done(); + }, + + "instantiation by type" : function(test) { + test.expect(16); + test.equal(moment.duration(1, "years").years(), 1, "years"); + test.equal(moment.duration(1, "y").years(), 1, "y"); + test.equal(moment.duration(2, "months").months(), 2, "months"); + test.equal(moment.duration(2, "M").months(), 2, "M"); + test.equal(moment.duration(3, "weeks").weeks(), 3, "weeks"); + test.equal(moment.duration(3, "w").weeks(), 3, "weeks"); + test.equal(moment.duration(4, "days").days(), 4, "days"); + test.equal(moment.duration(4, "d").days(), 4, "d"); + test.equal(moment.duration(5, "hours").hours(), 5, "hours"); + test.equal(moment.duration(5, "h").hours(), 5, "h"); + test.equal(moment.duration(6, "minutes").minutes(), 6, "minutes"); + test.equal(moment.duration(6, "m").minutes(), 6, "m"); + test.equal(moment.duration(7, "seconds").seconds(), 7, "seconds"); + test.equal(moment.duration(7, "s").seconds(), 7, "s"); + test.equal(moment.duration(8, "milliseconds").milliseconds(), 8, "milliseconds"); + test.equal(moment.duration(8, "ms").milliseconds(), 8, "ms"); + test.done(); + }, + + "shortcuts" : function(test) { + test.expect(8); + test.equal(moment.duration({y: 1}).years(), 1, "years = y"); + test.equal(moment.duration({M: 2}).months(), 2, "months = M"); + test.equal(moment.duration({w: 3}).weeks(), 3, "weeks = w"); + test.equal(moment.duration({d: 4}).days(), 4, "days = d"); + test.equal(moment.duration({h: 5}).hours(), 5, "hours = h"); + test.equal(moment.duration({m: 6}).minutes(), 6, "minutes = m"); + test.equal(moment.duration({s: 7}).seconds(), 7, "seconds = s"); + test.equal(moment.duration({ms: 8}).milliseconds(), 8, "milliseconds = ms"); + test.done(); + }, + + "generic getter" : function(test) { + test.expect(24); + test.equal(moment.duration(1, "years").get("years"), 1, "years"); + test.equal(moment.duration(1, "years").get("year"), 1, "years = year"); + test.equal(moment.duration(1, "years").get("y"), 1, "years = y"); + test.equal(moment.duration(2, "months").get("months"), 2, "months"); + test.equal(moment.duration(2, "months").get("month"), 2, "months = month"); + test.equal(moment.duration(2, "months").get("M"), 2, "months = M"); + test.equal(moment.duration(3, "weeks").get("weeks"), 3, "weeks"); + test.equal(moment.duration(3, "weeks").get("week"), 3, "weeks = week"); + test.equal(moment.duration(3, "weeks").get("w"), 3, "weeks = w"); + test.equal(moment.duration(4, "days").get("days"), 4, "days"); + test.equal(moment.duration(4, "days").get("day"), 4, "days = day"); + test.equal(moment.duration(4, "days").get("d"), 4, "days = d"); + test.equal(moment.duration(5, "hours").get("hours"), 5, "hours"); + test.equal(moment.duration(5, "hours").get("hour"), 5, "hours = hour"); + test.equal(moment.duration(5, "hours").get("h"), 5, "hours = h"); + test.equal(moment.duration(6, "minutes").get("minutes"), 6, "minutes"); + test.equal(moment.duration(6, "minutes").get("minute"), 6, "minutes = minute"); + test.equal(moment.duration(6, "minutes").get("m"), 6, "minutes = m"); + test.equal(moment.duration(7, "seconds").get("seconds"), 7, "seconds"); + test.equal(moment.duration(7, "seconds").get("second"), 7, "seconds = second"); + test.equal(moment.duration(7, "seconds").get("s"), 7, "seconds = s"); + test.equal(moment.duration(8, "milliseconds").get("milliseconds"), 8, "milliseconds"); + test.equal(moment.duration(8, "milliseconds").get("millisecond"), 8, "milliseconds = millisecond"); + test.equal(moment.duration(8, "milliseconds").get("ms"), 8, "milliseconds = ms"); + test.done(); + }, + + "instantiation from another duration" : function(test) { + var simple = moment.duration(1234), + lengthy = moment.duration(60 * 60 * 24 * 360 * 1e3), + complicated = moment.duration({ + years: 2, + months: 3, + weeks: 4, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(3); + test.deepEqual(moment.duration(simple), simple, "simple clones are equal"); + test.deepEqual(moment.duration(lengthy), lengthy, "lengthy clones are equal"); + test.deepEqual(moment.duration(complicated), complicated, "complicated clones are equal"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan zero" : function(test) { + test.expect(6); + test.equal(moment.duration("00:00:00").years(), 0, "0 years"); + test.equal(moment.duration("00:00:00").days(), 0, "0 days"); + test.equal(moment.duration("00:00:00").hours(), 0, "0 hours"); + test.equal(moment.duration("00:00:00").minutes(), 0, "0 minutes"); + test.equal(moment.duration("00:00:00").seconds(), 0, "0 seconds"); + test.equal(moment.duration("00:00:00").milliseconds(), 0, "0 milliseconds"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan with days" : function(test) { + test.expect(6); + test.equal(moment.duration("1.02:03:04.9999999").years(), 0, "0 years"); + test.equal(moment.duration("1.02:03:04.9999999").days(), 1, "1 day"); + test.equal(moment.duration("1.02:03:04.9999999").hours(), 2, "2 hours"); + test.equal(moment.duration("1.02:03:04.9999999").minutes(), 3, "3 minutes"); + test.equal(moment.duration("1.02:03:04.9999999").seconds(), 4, "4 seconds"); + test.equal(moment.duration("1.02:03:04.9999999").milliseconds(), 999, "999 milliseconds"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan without days" : function(test) { + test.expect(6); + test.equal(moment.duration("01:02:03.9999999").years(), 0, "0 years"); + test.equal(moment.duration("01:02:03.9999999").days(), 0, "0 days"); + test.equal(moment.duration("01:02:03.9999999").hours(), 1, "1 hour"); + test.equal(moment.duration("01:02:03.9999999").minutes(), 2, "2 minutes"); + test.equal(moment.duration("01:02:03.9999999").seconds(), 3, "3 seconds"); + test.equal(moment.duration("01:02:03.9999999").milliseconds(), 999, "999 milliseconds"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan without days or milliseconds" : function(test) { + test.expect(6); + test.equal(moment.duration("01:02:03").years(), 0, "0 years"); + test.equal(moment.duration("01:02:03").days(), 0, "0 days"); + test.equal(moment.duration("01:02:03").hours(), 1, "1 hour"); + test.equal(moment.duration("01:02:03").minutes(), 2, "2 minutes"); + test.equal(moment.duration("01:02:03").seconds(), 3, "3 seconds"); + test.equal(moment.duration("01:02:03").milliseconds(), 0, "0 milliseconds"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan without milliseconds" : function(test) { + test.expect(6); + test.equal(moment.duration("1.02:03:04").years(), 0, "0 years"); + test.equal(moment.duration("1.02:03:04").days(), 1, "1 day"); + test.equal(moment.duration("1.02:03:04").hours(), 2, "2 hours"); + test.equal(moment.duration("1.02:03:04").minutes(), 3, "3 minutes"); + test.equal(moment.duration("1.02:03:04").seconds(), 4, "4 seconds"); + test.equal(moment.duration("1.02:03:04").milliseconds(), 0, "0 milliseconds"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan maxValue" : function(test) { + test.expect(6); + test.equal(moment.duration("10675199.02:48:05.4775807").years(), 29653, "29653 years"); + test.equal(moment.duration("10675199.02:48:05.4775807").days(), 29, "29 day"); + test.equal(moment.duration("10675199.02:48:05.4775807").hours(), 2, "2 hours"); + test.equal(moment.duration("10675199.02:48:05.4775807").minutes(), 48, "48 minutes"); + test.equal(moment.duration("10675199.02:48:05.4775807").seconds(), 5, "5 seconds"); + test.equal(moment.duration("10675199.02:48:05.4775807").milliseconds(), 477, "477 milliseconds"); + test.done(); + }, + + "instatiation from serialized C# TimeSpan minValue" : function(test) { + test.expect(6); + test.equal(moment.duration("-10675199.02:48:05.4775808").years(), -29653, "29653 years"); + test.equal(moment.duration("-10675199.02:48:05.4775808").days(), -29, "29 day"); + test.equal(moment.duration("-10675199.02:48:05.4775808").hours(), -2, "2 hours"); + test.equal(moment.duration("-10675199.02:48:05.4775808").minutes(), -48, "48 minutes"); + test.equal(moment.duration("-10675199.02:48:05.4775808").seconds(), -5, "5 seconds"); + test.equal(moment.duration("-10675199.02:48:05.4775808").milliseconds(), -477, "477 milliseconds"); + test.done(); + }, + + "humanize" : function(test) { + test.expect(32); + moment.lang('en'); + test.equal(moment.duration({seconds: 44}).humanize(), "a few seconds", "44 seconds = a few seconds"); + test.equal(moment.duration({seconds: 45}).humanize(), "a minute", "45 seconds = a minute"); + test.equal(moment.duration({seconds: 89}).humanize(), "a minute", "89 seconds = a minute"); + test.equal(moment.duration({seconds: 90}).humanize(), "2 minutes", "90 seconds = 2 minutes"); + test.equal(moment.duration({minutes: 44}).humanize(), "44 minutes", "44 minutes = 44 minutes"); + test.equal(moment.duration({minutes: 45}).humanize(), "an hour", "45 minutes = an hour"); + test.equal(moment.duration({minutes: 89}).humanize(), "an hour", "89 minutes = an hour"); + test.equal(moment.duration({minutes: 90}).humanize(), "2 hours", "90 minutes = 2 hours"); + test.equal(moment.duration({hours: 5}).humanize(), "5 hours", "5 hours = 5 hours"); + test.equal(moment.duration({hours: 21}).humanize(), "21 hours", "21 hours = 21 hours"); + test.equal(moment.duration({hours: 22}).humanize(), "a day", "22 hours = a day"); + test.equal(moment.duration({hours: 35}).humanize(), "a day", "35 hours = a day"); + test.equal(moment.duration({hours: 36}).humanize(), "2 days", "36 hours = 2 days"); + test.equal(moment.duration({days: 1}).humanize(), "a day", "1 day = a day"); + test.equal(moment.duration({days: 5}).humanize(), "5 days", "5 days = 5 days"); + test.equal(moment.duration({weeks: 1}).humanize(), "7 days", "1 week = 7 days"); + test.equal(moment.duration({days: 25}).humanize(), "25 days", "25 days = 25 days"); + test.equal(moment.duration({days: 26}).humanize(), "a month", "26 days = a month"); + test.equal(moment.duration({days: 30}).humanize(), "a month", "30 days = a month"); + test.equal(moment.duration({days: 45}).humanize(), "a month", "45 days = a month"); + test.equal(moment.duration({days: 46}).humanize(), "2 months", "46 days = 2 months"); + test.equal(moment.duration({days: 74}).humanize(), "2 months", "75 days = 2 months"); + test.equal(moment.duration({days: 76}).humanize(), "3 months", "76 days = 3 months"); + test.equal(moment.duration({months: 1}).humanize(), "a month", "1 month = a month"); + test.equal(moment.duration({months: 5}).humanize(), "5 months", "5 months = 5 months"); + test.equal(moment.duration({days: 344}).humanize(), "11 months", "344 days = 11 months"); + test.equal(moment.duration({days: 345}).humanize(), "a year", "345 days = a year"); + test.equal(moment.duration({days: 547}).humanize(), "a year", "547 days = a year"); + test.equal(moment.duration({days: 548}).humanize(), "2 years", "548 days = 2 years"); + test.equal(moment.duration({years: 1}).humanize(), "a year", "1 year = a year"); + test.equal(moment.duration({years: 5}).humanize(), "5 years", "5 years = 5 years"); + test.equal(moment.duration(7200000).humanize(), "2 hours", "7200000 = 2 minutes"); + test.done(); + }, + + "humanize duration with suffix" : function(test) { + test.expect(2); + moment.lang('en'); + test.equal(moment.duration({seconds: 44}).humanize(true), "in a few seconds", "44 seconds = a few seconds"); + test.equal(moment.duration({seconds: -44}).humanize(true), "a few seconds ago", "44 seconds = a few seconds"); + test.done(); + }, + + "bubble value up" : function(test) { + test.expect(5); + test.equal(moment.duration({milliseconds: 61001}).milliseconds(), 1, "61001 milliseconds has 1 millisecond left over"); + test.equal(moment.duration({milliseconds: 61001}).seconds(), 1, "61001 milliseconds has 1 second left over"); + test.equal(moment.duration({milliseconds: 61001}).minutes(), 1, "61001 milliseconds has 1 minute left over"); + + test.equal(moment.duration({minutes: 350}).minutes(), 50, "350 minutes has 50 minutes left over"); + test.equal(moment.duration({minutes: 350}).hours(), 5, "350 minutes has 5 hours left over"); + test.done(); + }, + + "clipping" : function(test) { + test.expect(18); + test.equal(moment.duration({months: 11}).months(), 11, "11 months is 11 months"); + test.equal(moment.duration({months: 11}).years(), 0, "11 months makes no year"); + test.equal(moment.duration({months: 12}).months(), 0, "12 months is 0 months left over"); + test.equal(moment.duration({months: 12}).years(), 1, "12 months makes 1 year"); + test.equal(moment.duration({months: 13}).months(), 1, "13 months is 1 month left over"); + test.equal(moment.duration({months: 13}).years(), 1, "13 months makes 1 year"); + + test.equal(moment.duration({days: 29}).days(), 29, "29 days is 29 days"); + test.equal(moment.duration({days: 29}).months(), 0, "29 days makes no month"); + test.equal(moment.duration({days: 30}).days(), 0, "30 days is 0 days left over"); + test.equal(moment.duration({days: 30}).months(), 1, "30 days is a month"); + test.equal(moment.duration({days: 31}).days(), 1, "31 days is 1 day left over"); + test.equal(moment.duration({days: 31}).months(), 1, "31 days is a month"); + + test.equal(moment.duration({hours: 23}).hours(), 23, "23 hours is 23 hours"); + test.equal(moment.duration({hours: 23}).days(), 0, "23 hours makes no day"); + test.equal(moment.duration({hours: 24}).hours(), 0, "24 hours is 0 hours left over"); + test.equal(moment.duration({hours: 24}).days(), 1, "24 hours makes 1 day"); + test.equal(moment.duration({hours: 25}).hours(), 1, "25 hours is 1 hour left over"); + test.equal(moment.duration({hours: 25}).days(), 1, "25 hours makes 1 day"); + test.done(); + }, + + "effective equivalency" : function(test) { + test.expect(7); + test.deepEqual(moment.duration({seconds: 1})._data, moment.duration({milliseconds: 1000})._data, "1 second is the same as 1000 milliseconds"); + test.deepEqual(moment.duration({seconds: 60})._data, moment.duration({minutes: 1})._data, "1 minute is the same as 60 seconds"); + test.deepEqual(moment.duration({minutes: 60})._data, moment.duration({hours: 1})._data, "1 hour is the same as 60 minutes"); + test.deepEqual(moment.duration({hours: 24})._data, moment.duration({days: 1})._data, "1 day is the same as 24 hours"); + test.deepEqual(moment.duration({days: 7})._data, moment.duration({weeks: 1})._data, "1 week is the same as 7 days"); + test.deepEqual(moment.duration({days: 30})._data, moment.duration({months: 1})._data, "1 month is the same as 30 days"); + test.deepEqual(moment.duration({months: 12})._data, moment.duration({years: 1})._data, "1 years is the same as 12 months"); + test.done(); + }, + + "asGetters" : function(test) { + var d = moment.duration({ + years: 2, + months: 3, + weeks: 2, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(8); + test.equal(d.asYears().toFixed(2), "2.29", "years"); + test.equal(d.asMonths().toFixed(2), "27.51", "months"); + test.equal(d.asWeeks().toFixed(2), "119.33", "weeks"); + test.equal(d.asDays().toFixed(2), "835.34", "days"); + test.equal(d.asHours().toFixed(2), "20048.16", "hours"); + test.equal(d.asMinutes().toFixed(2), "1202889.33", "minutes"); + test.equal(d.asSeconds().toFixed(2), "72173360.01", "seconds"); + test.equal(d.asMilliseconds(), 72173360012, "milliseconds"); + test.done(); + }, + + "generic as getter" : function(test) { + var d = moment.duration({ + years: 2, + months: 3, + weeks: 2, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + test.expect(24); + test.equal(d.as("years").toFixed(2), "2.29", "years"); + test.equal(d.as("year").toFixed(2), "2.29", "years = year"); + test.equal(d.as("y").toFixed(2), "2.29", "years = y"); + test.equal(d.as("months").toFixed(2), "27.51", "months"); + test.equal(d.as("month").toFixed(2), "27.51", "months = month"); + test.equal(d.as("M").toFixed(2), "27.51", "months = M"); + test.equal(d.as("weeks").toFixed(2), "119.33", "weeks"); + test.equal(d.as("week").toFixed(2), "119.33", "weeks = week"); + test.equal(d.as("w").toFixed(2), "119.33", "weeks = w"); + test.equal(d.as("days").toFixed(2), "835.34", "days"); + test.equal(d.as("day").toFixed(2), "835.34", "days = day"); + test.equal(d.as("d").toFixed(2), "835.34", "days = d"); + test.equal(d.as("hours").toFixed(2), "20048.16", "hours"); + test.equal(d.as("hour").toFixed(2), "20048.16", "hours = hour"); + test.equal(d.as("h").toFixed(2), "20048.16", "hours = h"); + test.equal(d.as("minutes").toFixed(2), "1202889.33", "minutes"); + test.equal(d.as("minute").toFixed(2), "1202889.33", "minutes = minute"); + test.equal(d.as("m").toFixed(2), "1202889.33", "minutes = m"); + test.equal(d.as("seconds").toFixed(2), "72173360.01", "seconds"); + test.equal(d.as("second").toFixed(2), "72173360.01", "seconds = second"); + test.equal(d.as("s").toFixed(2), "72173360.01", "seconds = s"); + test.equal(d.as("milliseconds"), 72173360012, "milliseconds"); + test.equal(d.as("millisecond"), 72173360012, "milliseconds = millisecond"); + test.equal(d.as("ms"), 72173360012, "milliseconds = ms"); + test.done(); + }, + + "isDuration" : function(test) { + test.expect(3); + test.ok(moment.isDuration(moment.duration(12345678)), "correctly says true"); + test.ok(!moment.isDuration(moment()), "moment object is not a duration"); + test.ok(!moment.isDuration({milliseconds: 1}), "plain object is not a duration"); + test.done(); + }, + + "add" : function(test) { + test.expect(4); + + var d = moment.duration({months: 4, weeks: 3, days: 2}); + // for some reason, d._data._months does not get updated; use d._months instead. + test.equal(d.add(1, 'month')._months, 5, 'Add months'); + test.equal(d.add(5, 'days')._days, 28, 'Add days'); + test.equal(d.add(10000)._milliseconds, 10000, 'Add milliseconds'); + test.equal(d.add({h: 23, m: 59})._milliseconds, 23*60*60*1000 + 59*60*1000 + 10000, 'Add hour:minute'); + + test.done(); + }, + + "add and bubble" : function(test) { + test.expect(4); + + test.equal(moment.duration(1, 'second').add(1000, 'milliseconds').seconds(), 2, 'Adding milliseconds should bubble up to seconds'); + test.equal(moment.duration(1, 'minute').add(60, 'second').minutes(), 2, 'Adding seconds should bubble up to minutes'); + test.equal(moment.duration(1, 'hour').add(60, 'minutes').hours(), 2, 'Adding minutes should bubble up to hours'); + test.equal(moment.duration(1, 'day').add(24, 'hours').days(), 2, 'Adding hours should bubble up to days'); + + test.done(); + }, + + "subtract and bubble" : function(test) { + test.expect(4); + + test.equal(moment.duration(2, 'second').subtract(1000, 'milliseconds').seconds(), 1, 'Subtracting milliseconds should bubble up to seconds'); + test.equal(moment.duration(2, 'minute').subtract(60, 'second').minutes(), 1, 'Subtracting seconds should bubble up to minutes'); + test.equal(moment.duration(2, 'hour').subtract(60, 'minutes').hours(), 1, 'Subtracting minutes should bubble up to hours'); + test.equal(moment.duration(2, 'day').subtract(24, 'hours').days(), 1, 'Subtracting hours should bubble up to days'); + + test.done(); + }, + + "subtract" : function(test) { + test.expect(4); + + var d = moment.duration({months: 2, weeks: 2, days: 0, hours: 5}); + // for some reason, d._data._months does not get updated; use d._months instead. + test.equal(d.subtract(1, 'months')._months, 1, 'Subtract months'); + test.equal(d.subtract(14, 'days')._days, 0, 'Subtract days'); + test.equal(d.subtract(10000)._milliseconds, 5*60*60*1000 - 10000, 'Subtract milliseconds'); + test.equal(d.subtract({h: 1, m: 59})._milliseconds, 3*60*60*1000 + 1*60*1000 - 10000, 'Subtract hour:minute'); + + test.done(); + } + +}; diff --git a/node_modules/moment/test/moment/format.js b/node_modules/moment/test/moment/format.js new file mode 100644 index 0000000..1534c06 --- /dev/null +++ b/node_modules/moment/test/moment/format.js @@ -0,0 +1,308 @@ +var moment = require("../../moment"); + +exports.format = { + "format YY" : function(test) { + test.expect(1); + + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 125)); + test.equal(b.format('YY'), '09', 'YY ---> 09'); + test.done(); + }, + + "format escape brackets" : function(test) { + test.expect(9); + + moment.lang('en'); + + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 125)); + test.equal(b.format('[day]'), 'day', 'Single bracket'); + test.equal(b.format('[day] YY [YY]'), 'day 09 YY', 'Double bracket'); + test.equal(b.format('[YY'), '[09', 'Un-ended bracket'); + test.equal(b.format('[[YY]]'), '[YY]', 'Double nested brackets'); + test.equal(b.format('[[]'), '[', 'Escape open bracket'); + test.equal(b.format('[Last]'), 'Last', 'localized tokens'); + test.equal(b.format('[L] L'), 'L 02/14/2009', 'localized tokens with escaped localized tokens'); + test.equal(b.format('[L LL LLL LLLL aLa]'), 'L LL LLL LLLL aLa', 'localized tokens with escaped localized tokens'); + test.equal(b.format('[LLL] LLL'), 'LLL February 14 2009 3:25 PM', 'localized tokens with escaped localized tokens (recursion)'); + test.done(); + }, + + "format milliseconds" : function(test) { + test.expect(6); + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 123)); + test.equal(b.format('S'), '1', 'Deciseconds'); + test.equal(b.format('SS'), '12', 'Centiseconds'); + test.equal(b.format('SSS'), '123', 'Milliseconds'); + b.milliseconds(789); + test.equal(b.format('S'), '7', 'Deciseconds'); + test.equal(b.format('SS'), '78', 'Centiseconds'); + test.equal(b.format('SSS'), '789', 'Milliseconds'); + test.done(); + }, + + "format timezone" : function(test) { + test.expect(2); + + var b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)); + var explanation = 'moment().format("z") = ' + b.format('z') + ' It should be something like "PST"' + if (moment().zone() === -60) { + explanation += "For UTC+1 this is a known issue, see https://github.com/timrwood/moment/issues/162"; + } + test.ok(b.format('Z').match(/^[\+\-]\d\d:\d\d$/), b.format('Z') + ' should be something like "+07:30"'); + test.ok(b.format('ZZ').match(/^[\+\-]\d{4}$/), b.format('ZZ') + ' should be something like "+0700"'); + test.done(); + }, + + "format multiple with zone" : function(test) { + test.expect(1); + + var b = moment('2012-10-08 -1200', ['YYYY-MM-DD HH:mm ZZ', 'YYYY-MM-DD ZZ', 'YYYY-MM-DD']); + test.equals(b.format('YYYY-MM'), '2012-10', 'Parsing multiple formats should not crash with different sized formats'); + test.done(); + }, + + "isDST" : function(test) { + test.expect(2); + + var janOffset = new Date(2011, 0, 1).getTimezoneOffset(), + julOffset = new Date(2011, 6, 1).getTimezoneOffset(), + janIsDst = janOffset < julOffset, + julIsDst = julOffset < janOffset, + jan1 = moment([2011]), + jul1 = moment([2011, 6]); + + if (janIsDst && julIsDst) { + test.ok(0, 'January and July cannot both be in DST'); + test.ok(0, 'January and July cannot both be in DST'); + } else if (janIsDst) { + test.ok(jan1.isDST(), 'January 1 is DST'); + test.ok(!jul1.isDST(), 'July 1 is not DST'); + } else if (julIsDst) { + test.ok(!jan1.isDST(), 'January 1 is not DST'); + test.ok(jul1.isDST(), 'July 1 is DST'); + } else { + test.ok(!jan1.isDST(), 'January 1 is not DST'); + test.ok(!jul1.isDST(), 'July 1 is not DST'); + } + test.done(); + }, + + "unix timestamp" : function(test) { + test.expect(4); + + var m = moment('1234567890.123', 'X'); + test.equals(m.format('X'), '1234567890', 'unix timestamp without milliseconds'); + test.equals(m.format('X.S'), '1234567890.1', 'unix timestamp with deciseconds'); + test.equals(m.format('X.SS'), '1234567890.12', 'unix timestamp with centiseconds'); + test.equals(m.format('X.SSS'), '1234567890.123', 'unix timestamp with milliseconds'); + + test.done(); + }, + + "zone" : function(test) { + test.expect(3); + + if (moment().zone() > 0) { + test.ok(moment().format('ZZ').indexOf('-') > -1, 'When the zone() offset is greater than 0, the ISO offset should be less than zero'); + } + if (moment().zone() < 0) { + test.ok(moment().format('ZZ').indexOf('+') > -1, 'When the zone() offset is less than 0, the ISO offset should be greater than zero'); + } + if (moment().zone() == 0) { + test.ok(moment().format('ZZ').indexOf('+') > -1, 'When the zone() offset is equal to 0, the ISO offset should be positive zero'); + } + if (moment().zone() === 0) { + test.equal(moment().zone(), 0, 'moment.fn.zone should be a multiple of 15 (was ' + moment().zone() + ')'); + } else { + test.equal(moment().zone() % 15, 0, 'moment.fn.zone should be a multiple of 15 (was ' + moment().zone() + ')'); + } + test.equal(moment().zone(), new Date().getTimezoneOffset(), 'zone should equal getTimezoneOffset'); + test.done(); + }, + + "default format" : function(test) { + test.expect(1); + var isoRegex = /\d{4}.\d\d.\d\dT\d\d.\d\d.\d\d[\+\-]\d\d:\d\d/; + test.ok(isoRegex.exec(moment().format()), "default format (" + moment().format() + ") should match ISO"); + test.done(); + }, + + "escaping quotes" : function(test) { + test.expect(4); + moment.lang('en'); + var date = moment([2012, 0]); + test.equal(date.format('MMM \'YY'), "Jan '12", "Should be able to format with single parenthesis"); + test.equal(date.format('MMM "YY'), 'Jan "12', "Should be able to format with double parenthesis"); + test.equal(date.format("MMM 'YY"), "Jan '12", "Should be able to format with single parenthesis"); + test.equal(date.format("MMM \"YY"), 'Jan "12', "Should be able to format with double parenthesis"); + test.done(); + }, + + "toJSON" : function(test) { + var supportsJson = typeof JSON !== "undefined" && JSON.stringify && JSON.stringify.call, + date = moment("2012-10-09T21:30:40.678+0100"); + + test.expect(supportsJson ? 2 : 1); + + test.equal(date.toJSON(), "2012-10-09T20:30:40.678Z", "should output ISO8601 on moment.fn.toJSON"); + + if (supportsJson) { + test.equal(JSON.stringify({ + date : date + }), '{"date":"2012-10-09T20:30:40.678Z"}', "should output ISO8601 on JSON.stringify"); + } + + test.done(); + }, + + "toISOString" : function(test) { + var date = moment.utc("2012-10-09T20:30:40.678"); + + test.equal(date.toISOString(), "2012-10-09T20:30:40.678Z", "should output ISO8601 on moment.fn.toISOString"); + test.done(); + }, + + "weeks format" : function(test) { + + // http://en.wikipedia.org/wiki/ISO_week_date + var cases = { + "2005-01-02": "2004-53", + "2005-12-31": "2005-52", + "2007-01-01": "2007-01", + "2007-12-30": "2007-52", + "2007-12-31": "2008-01", + "2008-01-01": "2008-01", + "2008-12-28": "2008-52", + "2008-12-29": "2009-01", + "2008-12-30": "2009-01", + "2008-12-31": "2009-01", + "2009-01-01": "2009-01", + "2009-12-31": "2009-53", + "2010-01-01": "2009-53", + "2010-01-02": "2009-53", + "2010-01-03": "2009-53" + }; + + for (var i in cases) { + var iso = cases[i].split('-').pop(); + var the = moment(i).format('WW'); + test.equal(iso, the, i + ": should be " + iso + ", but " + the); + } + + test.done(); + }, + + "iso week year formats" : function(test) { + + // http://en.wikipedia.org/wiki/ISO_week + var cases = { + "2005-01-02": "2004-53", + "2005-12-31": "2005-52", + "2007-01-01": "2007-01", + "2007-12-30": "2007-52", + "2007-12-31": "2008-01", + "2008-01-01": "2008-01", + "2008-12-28": "2008-52", + "2008-12-29": "2009-01", + "2008-12-30": "2009-01", + "2008-12-31": "2009-01", + "2009-01-01": "2009-01", + "2009-12-31": "2009-53", + "2010-01-01": "2009-53", + "2010-01-02": "2009-53", + "2010-01-03": "2009-53" + }; + + for (var i in cases) { + var isoWeekYear = cases[i].split('-')[0]; + var formatted5 = moment(i).format('GGGGG'); + test.equal('0' + isoWeekYear, formatted5, i + ": should be " + isoWeekYear + ", but " + formatted4); + var formatted4 = moment(i).format('GGGG'); + test.equal(isoWeekYear, formatted4, i + ": should be " + isoWeekYear + ", but " + formatted4); + var formatted2 = moment(i).format('GG'); + test.equal(isoWeekYear.slice(2, 4), formatted2, i + ": should be " + isoWeekYear + ", but " + formatted2); + } + + test.done(); + }, + + "week year formats" : function(test) { + + // http://en.wikipedia.org/wiki/ISO_week + var cases = { + "2005-01-02": "2004-53", + "2005-12-31": "2005-52", + "2007-01-01": "2007-01", + "2007-12-30": "2007-52", + "2007-12-31": "2008-01", + "2008-01-01": "2008-01", + "2008-12-28": "2008-52", + "2008-12-29": "2009-01", + "2008-12-30": "2009-01", + "2008-12-31": "2009-01", + "2009-01-01": "2009-01", + "2009-12-31": "2009-53", + "2010-01-01": "2009-53", + "2010-01-02": "2009-53", + "2010-01-03": "2009-53" + }; + + moment.lang('en-gb'); // 1, 4 + for (var i in cases) { + var isoWeekYear = cases[i].split('-')[0]; + var formatted5 = moment(i).format('ggggg'); + test.equal('0' + isoWeekYear, formatted5, i + ": should be " + isoWeekYear + ", but " + formatted4); + var formatted4 = moment(i).format('gggg'); + test.equal(isoWeekYear, formatted4, i + ": should be " + isoWeekYear + ", but " + formatted4); + var formatted2 = moment(i).format('gg'); + test.equal(isoWeekYear.slice(2, 4), formatted2, i + ": should be " + isoWeekYear + ", but " + formatted2); + } + + test.done(); + }, + + "iso weekday formats" : function(test) { + test.expect(7); + + test.equal(moment([1985, 1, 4]).format('E'), '1', "Feb 4 1985 is Monday -- 1st day"); + test.equal(moment([2029, 8, 18]).format('E'), '2', "Sep 18 2029 is Tuesday -- 2nd day"); + test.equal(moment([2013, 3, 24]).format('E'), '3', "Apr 24 2013 is Wednesday -- 3rd day"); + test.equal(moment([2015, 2, 5]).format('E'), '4', "Mar 5 2015 is Thursday -- 4th day"); + test.equal(moment([1970, 0, 2]).format('E'), '5', "Jan 2 1970 is Friday -- 5th day"); + test.equal(moment([2001, 4, 12]).format('E'), '6', "May 12 2001 is Saturday -- 6th day"); + test.equal(moment([2000, 0, 2]).format('E'), '7', "Jan 2 2000 is Sunday -- 7th day"); + + test.done(); + }, + + "weekday formats" : function(test) { + test.expect(7); + + moment.lang('dow:3,doy:5', {week: {dow: 3, doy: 5}}); + test.equal(moment([1985, 1, 6]).format('e'), '0', "Feb 6 1985 is Wednesday -- 0th day"); + test.equal(moment([2029, 8, 20]).format('e'), '1', "Sep 20 2029 is Thursday -- 1st day"); + test.equal(moment([2013, 3, 26]).format('e'), '2', "Apr 26 2013 is Friday -- 2nd day"); + test.equal(moment([2015, 2, 7]).format('e'), '3', "Mar 7 2015 is Saturday -- 3nd day"); + test.equal(moment([1970, 0, 4]).format('e'), '4', "Jan 4 1970 is Sunday -- 4th day"); + test.equal(moment([2001, 4, 14]).format('e'), '5', "May 14 2001 is Monday -- 5th day"); + test.equal(moment([2000, 0, 4]).format('e'), '6', "Jan 4 2000 is Tuesday -- 6th day"); + + test.done(); + }, + + "toString is just human readable format" : function(test) { + test.expect(1); + + var b = moment(new Date(2009, 1, 5, 15, 25, 50, 125)); + test.equal(b.toString(), b.format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ')); + test.done(); + }, + + "toJSON skips postformat" : function(test) { + test.expect(1); + + moment.lang('postformat', {postformat: function(s) { s.replace(/./g, 'X') }}); + test.equal(moment.utc([2000, 0, 1]).toJSON(), "2000-01-01T00:00:00.000Z", "toJSON doesn't postformat"); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/getters_setters.js b/node_modules/moment/test/moment/getters_setters.js new file mode 100644 index 0000000..2e79deb --- /dev/null +++ b/node_modules/moment/test/moment/getters_setters.js @@ -0,0 +1,167 @@ +var moment = require("../../moment"); + +exports.getters_setters = { + "getters" : function(test) { + test.expect(8); + + var a = moment([2011, 9, 12, 6, 7, 8, 9]); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hours(), 6, 'hour'); + test.equal(a.minutes(), 7, 'minute'); + test.equal(a.seconds(), 8, 'second'); + test.equal(a.milliseconds(), 9, 'milliseconds'); + test.done(); + }, + + "setters plural" : function(test) { + test.expect(8); + + var a = moment(); + a.years(2011); + a.months(9); + a.dates(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(9); + test.equal(a.years(), 2011, 'years'); + test.equal(a.months(), 9, 'months'); + test.equal(a.dates(), 12, 'dates'); + test.equal(a.days(), 3, 'days'); + test.equal(a.hours(), 6, 'hours'); + test.equal(a.minutes(), 7, 'minutes'); + test.equal(a.seconds(), 8, 'seconds'); + test.equal(a.milliseconds(), 9, 'milliseconds'); + test.done(); + }, + + "setters singular" : function(test) { + test.expect(8); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hour(6); + a.minute(7); + a.second(8); + a.millisecond(9); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hour(), 6, 'hour'); + test.equal(a.minute(), 7, 'minute'); + test.equal(a.second(), 8, 'second'); + test.equal(a.millisecond(), 9, 'milliseconds'); + test.done(); + }, + + "setters" : function(test) { + test.expect(9); + + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(9); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hours(), 6, 'hour'); + test.equal(a.minutes(), 7, 'minute'); + test.equal(a.seconds(), 8, 'second'); + test.equal(a.milliseconds(), 9, 'milliseconds'); + + // Test month() behavior. See https://github.com/timrwood/moment/pull/822 + a = moment('20130531', 'YYYYMMDD'); + a.month(3); + test.equal(a.month(), 3, 'month edge case'); + + test.done(); + }, + + "setters strings" : function(test) { + test.expect(7); + + var a = moment([2012]).lang('en'); + test.equal(a.clone().day(0).day('Wednesday').day(), 3, 'day full name'); + test.equal(a.clone().day(0).day('Wed').day(), 3, 'day short name'); + test.equal(a.clone().day(0).day('We').day(), 3, 'day minimal name'); + test.equal(a.clone().day(0).day('invalid').day(), 0, 'invalid day name'); + test.equal(a.clone().month(0).month('April').month(), 3, 'month full name'); + test.equal(a.clone().month(0).month('Apr').month(), 3, 'month short name'); + test.equal(a.clone().month(0).month('invalid').month(), 0, 'invalid month name'); + test.done(); + }, + + "setters - falsey values" : function(test) { + test.expect(1); + + var a = moment(); + // ensure minutes wasn't coincidentally 0 already + a.minutes(1); + a.minutes(0); + test.equal(a.minutes(), 0, 'falsey value'); + test.done(); + }, + + "chaining setters" : function(test) { + test.expect(7); + + var a = moment(); + a.year(2011) + .month(9) + .date(12) + .hours(6) + .minutes(7) + .seconds(8); + test.equal(a.year(), 2011, 'year'); + test.equal(a.month(), 9, 'month'); + test.equal(a.date(), 12, 'date'); + test.equal(a.day(), 3, 'day'); + test.equal(a.hours(), 6, 'hour'); + test.equal(a.minutes(), 7, 'minute'); + test.equal(a.seconds(), 8, 'second'); + test.done(); + }, + + "day setter" : function(test) { + test.expect(18); + + var a = moment([2011, 0, 15]); + test.equal(moment(a).day(0).date(), 9, 'set from saturday to sunday'); + test.equal(moment(a).day(6).date(), 15, 'set from saturday to saturday'); + test.equal(moment(a).day(3).date(), 12, 'set from saturday to wednesday'); + + a = moment([2011, 0, 9]); + test.equal(moment(a).day(0).date(), 9, 'set from sunday to sunday'); + test.equal(moment(a).day(6).date(), 15, 'set from sunday to saturday'); + test.equal(moment(a).day(3).date(), 12, 'set from sunday to wednesday'); + + a = moment([2011, 0, 12]); + test.equal(moment(a).day(0).date(), 9, 'set from wednesday to sunday'); + test.equal(moment(a).day(6).date(), 15, 'set from wednesday to saturday'); + test.equal(moment(a).day(3).date(), 12, 'set from wednesday to wednesday'); + + test.equal(moment(a).day(-7).date(), 2, 'set from wednesday to last sunday'); + test.equal(moment(a).day(-1).date(), 8, 'set from wednesday to last saturday'); + test.equal(moment(a).day(-4).date(), 5, 'set from wednesday to last wednesday'); + + test.equal(moment(a).day(7).date(), 16, 'set from wednesday to next sunday'); + test.equal(moment(a).day(13).date(), 22, 'set from wednesday to next saturday'); + test.equal(moment(a).day(10).date(), 19, 'set from wednesday to next wednesday'); + + test.equal(moment(a).day(14).date(), 23, 'set from wednesday to second next sunday'); + test.equal(moment(a).day(20).date(), 29, 'set from wednesday to second next saturday'); + test.equal(moment(a).day(17).date(), 26, 'set from wednesday to second next wednesday'); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/is_after.js b/node_modules/moment/test/moment/is_after.js new file mode 100644 index 0000000..59c02e3 --- /dev/null +++ b/node_modules/moment/test/moment/is_after.js @@ -0,0 +1,188 @@ +var moment = require("../../moment"); + +exports.is_after = { + "is after without units" : function(test) { + test.expect(17); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 5, 5, 10))), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 3, 5, 10))), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 5, 10))), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 5, 10))), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 5, 10))), false, "day is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 3, 4, 5, 10))), true, "day is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 5, 10))), false, "hour is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 2, 4, 5, 10))), true, "hour is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 5, 10))), false, "minute is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 5, 10))), true, "minute is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 10))), false, "second is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 11))), true, "second is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, "millisecond match"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 11))), false, "millisecond is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 9))), true, "millisecond is earlier"); + test.equal(m.isAfter(m), false, "moments are not after themselves"); + test.equal(+m, +mCopy, "isAfter second should not change moment"); + test.done(); + }, + + "is after year" : function(test) { + test.expect(11); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), false, "year match"); + test.equal(m.isAfter(moment(new Date(2010, 5, 6, 7, 8, 9, 10)), 'years'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2013, 5, 6, 7, 8, 9, 10)), 'year'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 5, 6, 7, 8, 9, 10)), 'year'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 0, 1, 0, 0, 0, 0)), 'year'), false, "exact start of year"); + test.equal(m.isAfter(moment(new Date(2011, 11, 31, 23, 59, 59, 999)), 'year'), false, "exact end of year"); + test.equal(m.isAfter(moment(new Date(2012, 0, 1, 0, 0, 0, 0)), 'year'), false, "start of next year"); + test.equal(m.isAfter(moment(new Date(2010, 11, 31, 23, 59, 59, 999)), 'year'), true, "end of previous year"); + test.equal(m.isAfter(moment(new Date(1980, 11, 31, 23, 59, 59, 999)), 'year'), true, "end of year far before"); + test.equal(m.isAfter(m, 'year'), false, "same moments are not after the same year"); + test.equal(+m, +mCopy, "isAfter year should not change moment"); + test.done(); + }, + + "is after month" : function(test) { + test.expect(13); + + var m = moment(new Date(2011, 2, 3, 4, 5, 6, 7)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), false, "month match"); + test.equal(m.isAfter(moment(new Date(2010, 2, 6, 7, 8, 9, 10)), 'months'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'month'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 2, 6, 7, 8, 9, 10)), 'month'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'month'), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 1, 6, 7, 8, 9, 10)), 'month'), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), false, "exact start of month"); + test.equal(m.isAfter(moment(new Date(2011, 2, 31, 23, 59, 59, 999)), 'month'), false, "exact end of month"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 0, 0, 0, 0)), 'month'), false, "start of next month"); + test.equal(m.isAfter(moment(new Date(2011, 1, 27, 23, 59, 59, 999)), 'month'), true, "end of previous month"); + test.equal(m.isAfter(moment(new Date(2010, 12, 31, 23, 59, 59, 999)), 'month'), true, "later month but earlier year"); + test.equal(m.isAfter(m, 'month'), false, "same moments are not after the same month"); + test.equal(+m, +mCopy, "isAfter month should not change moment"); + test.done(); + }, + + "is after day" : function(test) { + test.expect(15); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 7, 8, 9, 10)), 'day'), false, "day match"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 7, 8, 9, 10)), 'days'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2012, 3, 2, 7, 8, 9, 10)), 'day'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 7, 8, 9, 10)), 'day'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 4, 2, 7, 8, 9, 10)), 'day'), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 2, 2, 7, 8, 9, 10)), 'day'), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 7, 8, 9, 10)), 'day'), false, "day is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 7, 8, 9, 10)), 'day'), true, "day is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 0, 0, 0, 0)), 'day'), false, "exact start of day"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 23, 59, 59, 999)), 'day'), false, "exact end of day"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 0, 0, 0, 0)), 'day'), false, "start of next day"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 23, 59, 59, 999)), 'day'), true, "end of previous day"); + test.equal(m.isAfter(moment(new Date(2010, 3, 10, 0, 0, 0, 0)), 'day'), true, "later day but earlier year"); + test.equal(m.isAfter(m, 'day'), false, "same moments are not after the same day"); + test.equal(+m, +mCopy, "isAfter day should not change moment"); + test.done(); + }, + + "is after hour" : function(test) { + test.expect(16); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, "hour match"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 8, 9, 10)), 'hours'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 8, 9, 10)), 'hour'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 8, 9, 10)), 'hour'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 8, 9, 10)), 'hour'), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hour'), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 8, 9, 10)), 'hour'), false, "day is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 3, 8, 9, 10)), 'hour'), true, "day is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 8, 9, 10)), 'hour'), false, "hour is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, "hour is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 0, 0, 0)), 'hour'), false, "exact start of hour"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 59, 59, 999)), 'hour'), false, "exact end of hour"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 0, 0, 0)), 'hour'), false, "start of next hour"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 2, 59, 59, 999)), 'hour'), true, "end of previous hour"); + test.equal(m.isAfter(m, 'hour'), false, "same moments are not after the same hour"); + test.equal(+m, +mCopy, "isAfter hour should not change moment"); + test.done(); + }, + + "is after minute" : function(test) { + test.expect(18); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 9, 10)), 'minute'), false, "minute match"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 9, 10)), 'minutes'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 4, 9, 10)), 'minute'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 9, 10)), 'minute'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 9, 10)), 'minute'), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 9, 10)), 'minute'), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 9, 10)), 'minute'), false, "day is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 3, 4, 9, 10)), 'minute'), true, "day is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 9, 10)), 'minute'), false, "hour is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 2, 4, 9, 10)), 'minute'), true, "hour is earler"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 9, 10)), 'minute'), false, "minute is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 9, 10)), 'minute'), true, "minute is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 0, 0)), 'minute'), false, "exact start of minute"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 59, 999)), 'minute'), false, "exact end of minute"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 0, 0)), 'minute'), false, "start of next minute"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 59, 999)), 'minute'), true, "end of previous minute"); + test.equal(m.isAfter(m, 'minute'), false, "same moments are not after the same minute"); + test.equal(+m, +mCopy, "isAfter minute should not change moment"); + test.done(); + }, + + "is after second" : function(test) { + test.expect(20); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'second'), false, "second match"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'seconds'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'second'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'second'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'second'), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'second'), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'second'), false, "day is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'second'), true, "day is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'second'), false, "hour is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'second'), true, "hour is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'second'), false, "minute is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'second'), true, "minute is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'second'), false, "second is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'second'), true, "second is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 0)), 'second'), false, "exact start of second"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 999)), 'second'), false, "exact end of second"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 0)), 'second'), false, "start of next second"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 999)), 'second'), true, "end of previous second"); + test.equal(m.isAfter(m, 'second'), false, "same moments are not after the same second"); + test.equal(+m, +mCopy, "isAfter second should not change moment"); + test.done(); + }, + + "is after millisecond" : function(test) { + test.expect(18); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, "millisecond match"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'milliseconds'), true, "plural should work"); + test.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, "year is later"); + test.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'millisecond'), true, "year is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'millisecond'), false, "month is later"); + test.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'millisecond'), true, "month is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'millisecond'), false, "day is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'millisecond'), true, "day is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'millisecond'), false, "hour is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'millisecond'), true, "hour is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'millisecond'), false, "minute is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'millisecond'), true, "minute is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'millisecond'), false, "second is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'millisecond'), true, "second is earlier"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 11)), 'millisecond'), false, "millisecond is later"); + test.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 9)), 'millisecond'), true, "millisecond is earlier"); + test.equal(m.isAfter(m, 'millisecond'), false, "same moments are not after the same millisecond"); + test.equal(+m, +mCopy, "isAfter millisecond should not change moment"); + test.done(); + } + +}; diff --git a/node_modules/moment/test/moment/is_before.js b/node_modules/moment/test/moment/is_before.js new file mode 100644 index 0000000..0e0efb5 --- /dev/null +++ b/node_modules/moment/test/moment/is_before.js @@ -0,0 +1,187 @@ +var moment = require("../../moment"); + +exports.is_before = { + "is after without units" : function(test) { + test.expect(17); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 5, 5, 10))), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 3, 5, 10))), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 5, 10))), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 5, 10))), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 5, 10))), true, "day is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 3, 4, 5, 10))), false, "day is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 5, 10))), true, "hour is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 2, 4, 5, 10))), false, "hour is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 5, 10))), true, "minute is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 5, 10))), false, "minute is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 10))), true, "second is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 11))), false, "second is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, "millisecond match"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 11))), true, "millisecond is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 9))), false, "millisecond is earlier"); + test.equal(m.isBefore(m), false, "moments are not before themselves"); + test.equal(+m, +mCopy, "isBefore second should not change moment"); + test.done(); + }, + + "is before year" : function(test) { + test.expect(11); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), false, "year match"); + test.equal(m.isBefore(moment(new Date(2012, 5, 6, 7, 8, 9, 10)), 'years'), true, "plural should work"); + test.equal(m.isBefore(moment(new Date(2013, 5, 6, 7, 8, 9, 10)), 'year'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 5, 6, 7, 8, 9, 10)), 'year'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 0, 1, 0, 0, 0, 0)), 'year'), false, "exact start of year"); + test.equal(m.isBefore(moment(new Date(2011, 11, 31, 23, 59, 59, 999)), 'year'), false, "exact end of year"); + test.equal(m.isBefore(moment(new Date(2012, 0, 1, 0, 0, 0, 0)), 'year'), true, "start of next year"); + test.equal(m.isBefore(moment(new Date(2010, 11, 31, 23, 59, 59, 999)), 'year'), false, "end of previous year"); + test.equal(m.isBefore(moment(new Date(1980, 11, 31, 23, 59, 59, 999)), 'year'), false, "end of year far before"); + test.equal(m.isBefore(m, 'year'), false, "same moments are not before the same year"); + test.equal(+m, +mCopy, "isBefore year should not change moment"); + test.done(); + }, + + "is before month" : function(test) { + test.expect(13); + + var m = moment(new Date(2011, 2, 3, 4, 5, 6, 7)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), false, "month match"); + test.equal(m.isBefore(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'months'), true, "plural should work"); + test.equal(m.isBefore(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'month'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 2, 6, 7, 8, 9, 10)), 'month'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'month'), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 1, 6, 7, 8, 9, 10)), 'month'), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), false, "exact start of month"); + test.equal(m.isBefore(moment(new Date(2011, 2, 31, 23, 59, 59, 999)), 'month'), false, "exact end of month"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 0, 0, 0, 0)), 'month'), true, "start of next month"); + test.equal(m.isBefore(moment(new Date(2011, 1, 27, 23, 59, 59, 999)), 'month'), false, "end of previous month"); + test.equal(m.isBefore(moment(new Date(2010, 12, 31, 23, 59, 59, 999)), 'month'), false, "later month but earlier year"); + test.equal(m.isBefore(m, 'month'), false, "same moments are not before the same month"); + test.equal(+m, +mCopy, "isBefore month should not change moment"); + test.done(); + }, + + "is before day" : function(test) { + test.expect(15); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 7, 8, 9, 10)), 'day'), false, "day match"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 7, 8, 9, 10)), 'days'), true, "plural should work"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 7, 8, 9, 10)), 'day'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 7, 8, 9, 10)), 'day'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 4, 2, 7, 8, 9, 10)), 'day'), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 2, 2, 7, 8, 9, 10)), 'day'), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 7, 8, 9, 10)), 'day'), true, "day is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 7, 8, 9, 10)), 'day'), false, "day is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 0, 0, 0, 0)), 'day'), false, "exact start of day"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 23, 59, 59, 999)), 'day'), false, "exact end of day"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 0, 0, 0, 0)), 'day'), true, "start of next day"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 23, 59, 59, 999)), 'day'), false, "end of previous day"); + test.equal(m.isBefore(moment(new Date(2010, 3, 10, 0, 0, 0, 0)), 'day'), false, "later day but earlier year"); + test.equal(m.isBefore(m, 'day'), false, "same moments are not before the same day"); + test.equal(+m, +mCopy, "isBefore day should not change moment"); + test.done(); + }, + + "is before hour" : function(test) { + test.expect(16); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, "hour match"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 8, 9, 10)), 'hours'), true, "plural should work"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 8, 9, 10)), 'hour'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 8, 9, 10)), 'hour'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 8, 9, 10)), 'hour'), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hour'), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 8, 9, 10)), 'hour'), true, "day is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 3, 8, 9, 10)), 'hour'), false, "day is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 8, 9, 10)), 'hour'), true, "hour is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, "hour is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 0, 0, 0)), 'hour'), false, "exact start of hour"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 59, 59, 999)), 'hour'), false, "exact end of hour"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 0, 0, 0)), 'hour'), true, "start of next hour"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 2, 59, 59, 999)), 'hour'), false, "end of previous hour"); + test.equal(m.isBefore(m, 'hour'), false, "same moments are not before the same hour"); + test.equal(+m, +mCopy, "isBefore hour should not change moment"); + test.done(); + }, + + "is before minute" : function(test) { + test.expect(18); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 9, 10)), 'minute'), false, "minute match"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 9, 10)), 'minutes'), true, "plural should work"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 9, 10)), 'minute'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 9, 10)), 'minute'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 9, 10)), 'minute'), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 9, 10)), 'minute'), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 9, 10)), 'minute'), true, "day is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 3, 4, 9, 10)), 'minute'), false, "day is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 9, 10)), 'minute'), true, "hour is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 2, 4, 9, 10)), 'minute'), false, "hour is earler"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 9, 10)), 'minute'), true, "minute is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 9, 10)), 'minute'), false, "minute is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 0, 0)), 'minute'), false, "exact start of minute"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 59, 999)), 'minute'), false, "exact end of minute"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 0, 0)), 'minute'), true, "start of next minute"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 59, 999)), 'minute'), false, "end of previous minute"); + test.equal(m.isBefore(m, 'minute'), false, "same moments are not before the same minute"); + test.equal(+m, +mCopy, "isBefore minute should not change moment"); + test.done(); + }, + + "is before second" : function(test) { + test.expect(20); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'second'), false, "second match"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'seconds'), true, "plural should work"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'second'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'second'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'second'), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'second'), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'second'), true, "day is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'second'), false, "day is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'second'), true, "hour is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'second'), false, "hour is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'second'), true, "minute is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'second'), false, "minute is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'second'), true, "second is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'second'), false, "second is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 0)), 'second'), false, "exact start of second"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 999)), 'second'), false, "exact end of second"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 0)), 'second'), true, "start of next second"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 999)), 'second'), false, "end of previous second"); + test.equal(m.isBefore(m, 'second'), false, "same moments are not before the same second"); + test.equal(+m, +mCopy, "isBefore second should not change moment"); + test.done(); + }, + + "is before millisecond" : function(test) { + test.expect(18); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, "millisecond match"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'milliseconds'), false, "plural should work"); + test.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'millisecond'), true, "year is later"); + test.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, "year is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'millisecond'), true, "month is later"); + test.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'millisecond'), false, "month is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'millisecond'), true, "day is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'millisecond'), false, "day is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'millisecond'), true, "hour is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'millisecond'), false, "hour is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'millisecond'), true, "minute is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'millisecond'), false, "minute is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'millisecond'), true, "second is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'millisecond'), false, "second is earlier"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 11)), 'millisecond'), true, "millisecond is later"); + test.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 9)), 'millisecond'), false, "millisecond is earlier"); + test.equal(m.isBefore(m, 'millisecond'), false, "same moments are not before the same millisecond"); + test.equal(+m, +mCopy, "isBefore millisecond should not change moment"); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/is_moment.js b/node_modules/moment/test/moment/is_moment.js new file mode 100644 index 0000000..9b085cc --- /dev/null +++ b/node_modules/moment/test/moment/is_moment.js @@ -0,0 +1,27 @@ +var moment = require('../../moment'); + +exports.is_moment = { + "is moment object": function(test) { + test.expect(11); + + var MyObj = function() {}; + MyObj.prototype.toDate = function() { + return new Date(); + } + + test.ok(moment.isMoment(moment()), 'simple moment object'); + test.ok(moment.isMoment(moment('invalid date')), 'invalid moment object'); + + test.ok(!moment.isMoment(new MyObj()), 'myObj is not moment object'); + test.ok(!moment.isMoment(moment), 'moment function is not moment object'); + test.ok(!moment.isMoment(new Date()), 'date object is not moment object'); + test.ok(!moment.isMoment(Object), 'Object is not moment object'); + test.ok(!moment.isMoment('foo'), 'string is not moment object'); + test.ok(!moment.isMoment(1), 'number is not moment object'); + test.ok(!moment.isMoment(NaN), 'NaN is not moment object'); + test.ok(!moment.isMoment(null), 'null is not moment object'); + test.ok(!moment.isMoment(undefined), 'undefined is not moment object'); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/is_same.js b/node_modules/moment/test/moment/is_same.js new file mode 100644 index 0000000..bd9a792 --- /dev/null +++ b/node_modules/moment/test/moment/is_same.js @@ -0,0 +1,163 @@ +var moment = require("../../moment"); + +exports.is_same = { + "is same without units" : function(test) { + test.expect(17); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2012, 3, 2, 3, 5, 5, 10))), false, "year is later"); + test.equal(m.isSame(moment(new Date(2010, 3, 2, 3, 3, 5, 10))), false, "year is earlier"); + test.equal(m.isSame(moment(new Date(2011, 4, 2, 3, 4, 5, 10))), false, "month is later"); + test.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 5, 10))), false, "month is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 3, 3, 4, 5, 10))), false, "day is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 1, 3, 4, 5, 10))), false, "day is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 4, 4, 5, 10))), false, "hour is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 2, 4, 5, 10))), false, "hour is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 5, 5, 10))), false, "minute is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 3, 5, 10))), false, "minute is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 6, 10))), false, "second is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 4, 11))), false, "second is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 10))), true, "millisecond match"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 11))), false, "millisecond is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 9))), false, "millisecond is earlier"); + test.equal(m.isSame(m), true, "moments are the same as themselves"); + test.equal(+m, +mCopy, "isSame second should not change moment"); + test.done(); + }, + + "is same year" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), true, "year match"); + test.equal(m.isSame(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'years'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 5, 6, 7, 8, 9, 10)), 'year'), false, "year mismatch"); + test.equal(m.isSame(moment(new Date(2011, 0, 1, 0, 0, 0, 0)), 'year'), true, "exact start of year"); + test.equal(m.isSame(moment(new Date(2011, 11, 31, 23, 59, 59, 999)), 'year'), true, "exact end of year"); + test.equal(m.isSame(moment(new Date(2012, 0, 1, 0, 0, 0, 0)), 'year'), false, "start of next year"); + test.equal(m.isSame(moment(new Date(2010, 11, 31, 23, 59, 59, 999)), 'year'), false, "end of previous year"); + test.equal(m.isSame(m, 'year'), true, "same moments are in the same year"); + test.equal(+m, +mCopy, "isSame year should not change moment"); + test.done(); + }, + + "is same month" : function(test) { + test.expect(10); + + var m = moment(new Date(2011, 2, 3, 4, 5, 6, 7)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), true, "month match"); + test.equal(m.isSame(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'months'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'month'), false, "year mismatch"); + test.equal(m.isSame(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'month'), false, "month mismatch"); + test.equal(m.isSame(moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), true, "exact start of month"); + test.equal(m.isSame(moment(new Date(2011, 2, 31, 23, 59, 59, 999)), 'month'), true, "exact end of month"); + test.equal(m.isSame(moment(new Date(2011, 3, 1, 0, 0, 0, 0)), 'month'), false, "start of next month"); + test.equal(m.isSame(moment(new Date(2011, 1, 27, 23, 59, 59, 999)), 'month'), false, "end of previous month"); + test.equal(m.isSame(m, 'month'), true, "same moments are in the same month"); + test.equal(+m, +mCopy, "isSame month should not change moment"); + test.done(); + }, + + "is same day" : function(test) { + test.expect(11); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'day'), true, "day match"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'days'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 1, 2, 7, 8, 9, 10)), 'day'), false, "year mismatch"); + test.equal(m.isSame(moment(new Date(2011, 2, 2, 7, 8, 9, 10)), 'day'), false, "month mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 3, 7, 8, 9, 10)), 'day'), false, "day mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 0, 0, 0, 0)), 'day'), true, "exact start of day"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 23, 59, 59, 999)), 'day'), true, "exact end of day"); + test.equal(m.isSame(moment(new Date(2011, 1, 3, 0, 0, 0, 0)), 'day'), false, "start of next day"); + test.equal(m.isSame(moment(new Date(2011, 1, 1, 23, 59, 59, 999)), 'day'), false, "end of previous day"); + test.equal(m.isSame(m, 'day'), true, "same moments are in the same day"); + test.equal(+m, +mCopy, "isSame day should not change moment"); + test.done(); + }, + + "is same hour" : function(test) { + test.expect(12); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hour'), true, "hour match"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hours'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 1, 2, 3, 8, 9, 10)), 'hour'), false, "year mismatch"); + test.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 8, 9, 10)), 'hour'), false, "month mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 3, 3, 8, 9, 10)), 'hour'), false, "day mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 8, 9, 10)), 'hour'), false, "hour mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 0, 0, 0)), 'hour'), true, "exact start of hour"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 59, 59, 999)), 'hour'), true, "exact end of hour"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 0, 0, 0)), 'hour'), false, "start of next hour"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 2, 59, 59, 999)), 'hour'), false, "end of previous hour"); + test.equal(m.isSame(m, 'hour'), true, "same moments are in the same hour"); + test.equal(+m, +mCopy, "isSame hour should not change moment"); + test.done(); + }, + + "is same minute" : function(test) { + test.expect(13); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 9, 10)), 'minute'), true, "minute match"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 9, 10)), 'minutes'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 1, 2, 3, 4, 9, 10)), 'minute'), false, "year mismatch"); + test.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 9, 10)), 'minute'), false, "month mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 3, 3, 4, 9, 10)), 'minute'), false, "day mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 4, 9, 10)), 'minute'), false, "hour mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 5, 9, 10)), 'minute'), false, "minute mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 0, 0)), 'minute'), true, "exact start of minute"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 59, 999)), 'minute'), true, "exact end of minute"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 5, 0, 0)), 'minute'), false, "start of next minute"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 3, 59, 999)), 'minute'), false, "end of previous minute"); + test.equal(m.isSame(m, 'minute'), true, "same moments are in the same minute"); + test.equal(+m, +mCopy, "isSame minute should not change moment"); + test.done(); + }, + + "is same second" : function(test) { + test.expect(14); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 10)), 'second'), true, "second match"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 10)), 'seconds'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 1, 2, 3, 4, 5, 10)), 'second'), false, "year mismatch"); + test.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'second'), false, "month mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 3, 3, 4, 5, 10)), 'second'), false, "day mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 4, 5, 10)), 'second'), false, "hour mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 5, 5, 10)), 'second'), false, "minute mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 6, 10)), 'second'), false, "second mismatch"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 0)), 'second'), true, "exact start of second"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 999)), 'second'), true, "exact end of second"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 6, 0)), 'second'), false, "start of next second"); + test.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 4, 999)), 'second'), false, "end of previous second"); + test.equal(m.isSame(m, 'second'), true, "same moments are in the same second"); + test.equal(+m, +mCopy, "isSame second should not change moment"); + test.done(); + }, + + "is same millisecond" : function(test) { + test.expect(18); + + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'millisecond'), true, "millisecond match"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'milliseconds'), true, "plural should work"); + test.equal(m.isSame(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, "year is later"); + test.equal(m.isSame(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, "year is earlier"); + test.equal(m.isSame(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'millisecond'), false, "month is later"); + test.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'millisecond'), false, "month is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'millisecond'), false, "day is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'millisecond'), false, "day is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'millisecond'), false, "hour is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'millisecond'), false, "hour is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'millisecond'), false, "minute is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'millisecond'), false, "minute is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'millisecond'), false, "second is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'millisecond'), false, "second is earlier"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 6, 11)), 'millisecond'), false, "millisecond is later"); + test.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 4, 9)), 'millisecond'), false, "millisecond is earlier"); + test.equal(m.isSame(m, 'millisecond'), true, "same moments are in the same millisecond"); + test.equal(+m, +mCopy, "isSame millisecond should not change moment"); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/is_valid.js b/node_modules/moment/test/moment/is_valid.js new file mode 100644 index 0000000..a0e2b60 --- /dev/null +++ b/node_modules/moment/test/moment/is_valid.js @@ -0,0 +1,164 @@ +var moment = require("../../moment"); + +exports.is_valid = { + "array bad month" : function (test) { + test.expect(2); + + test.equal(moment([2010, -1]).isValid(), false, 'month -1'); + test.equal(moment([2100, 12]).isValid(), false, 'month 12'); + + test.done(); + }, + + "array good month" : function (test) { + test.expect(24); + + for (var i = 0; i < 12; i++) { + test.equal(moment([2010, i]).isValid(), true, 'month ' + i); + test.equal(moment.utc([2010, i]).isValid(), true, 'month ' + i); + } + + test.done(); + }, + + "array bad date" : function (test) { + test.expect(4); + + test.equal(moment([2010, 0, 0]).isValid(), false, 'date 0'); + test.equal(moment([2100, 0, 32]).isValid(), false, 'date 32'); + + test.equal(moment.utc([2010, 0, 0]).isValid(), false, 'utc date 0'); + test.equal(moment.utc([2100, 0, 32]).isValid(), false, 'utc date 32'); + + test.done(); + }, + + "array bad date leap year" : function (test) { + test.expect(8); + + test.equal(moment([2010, 1, 29]).isValid(), false, '2010 feb 29'); + test.equal(moment([2100, 1, 29]).isValid(), false, '2100 feb 29'); + test.equal(moment([2008, 1, 30]).isValid(), false, '2008 feb 30'); + test.equal(moment([2000, 1, 30]).isValid(), false, '2000 feb 30'); + + test.equal(moment.utc([2010, 1, 29]).isValid(), false, 'utc 2010 feb 29'); + test.equal(moment.utc([2100, 1, 29]).isValid(), false, 'utc 2100 feb 29'); + test.equal(moment.utc([2008, 1, 30]).isValid(), false, 'utc 2008 feb 30'); + test.equal(moment.utc([2000, 1, 30]).isValid(), false, 'utc 2000 feb 30'); + + test.done(); + }, + + "string + formats bad date" : function (test) { + test.expect(9); + + test.equal(moment('2020-00-00', ['YYYY-MM-DD', 'DD-MM-YYYY']).isValid(), false, 'invalid on all in array'); + test.equal(moment('2020-00-00', ['DD-MM-YYYY', 'YYYY-MM-DD']).isValid(), false, 'invalid on all in array'); + test.equal(moment('2020-01-01', ['YYYY-MM-DD', 'DD-MM-YYYY']).isValid(), true, 'valid on first'); + test.equal(moment('2020-01-01', ['DD-MM-YYYY', 'YYYY-MM-DD']).isValid(), true, 'valid on last'); + test.equal(moment('2020-01-01', ['YYYY-MM-DD', 'YYYY-DD-MM']).isValid(), true, 'valid on both'); + test.equal(moment('2020-13-01', ['YYYY-MM-DD', 'YYYY-DD-MM']).isValid(), true, 'valid on last'); + + test.equal(moment('12-13-2012', ['DD-MM-YYYY', 'YYYY-MM-DD']).isValid(), false, 'month rollover'); + test.equal(moment('12-13-2012', ['DD-MM-YYYY', 'DD-MM-YYYY']).isValid(), false, 'month rollover'); + test.equal(moment('38-12-2012', ['DD-MM-YYYY']).isValid(), false, 'day rollover'); + + test.done(); + }, + + "string nonsensical" : function (test) { + test.expect(1); + + test.equal(moment('fail').isValid(), false, 'string "fail"'); + test.done(); + }, + + "string nonsensical with format" : function (test) { + test.expect(2); + + test.equal(moment('fail', "MM-DD-YYYY").isValid(), false, 'string "fail" with format "MM-DD-YYYY"'); + test.equal(moment("xx-xx-2001", 'DD-MM-YYY').isValid(), false, 'string "xx-xx-2001" with format "MM-DD-YYYY"'); + test.done(); + }, + + "string with bad month name" : function (test) { + test.expect(2); + + moment.lang('en'); + + test.equal(moment('01-Nam-2012', 'DD-MMM-YYYY').isValid(), false, '"Nam" is an invalid month'); + test.equal(moment('01-Aug-2012', 'DD-MMM-YYYY').isValid(), true, '"Aug" is a valid month'); + + test.done(); + }, + + "string with spaceless format" : function (test) { + test.expect(1); + + test.equal(moment('10Sep2001', 'DDMMMYYYY').isValid(), true, "Parsing 10Sep2001 should result in a valid date"); + + test.done(); + }, + + "invalid string iso 8601" : function (test) { + + var tests = [ + '2010-00-00', + '2010-01-00', + '2010-01-40', + '2010-01-01T24', + '2010-01-01T23:60', + '2010-01-01T23:59:60' + ]; + + test.expect(tests.length * 2); + + for (var i = 0; i < tests.length; i++) { + test.equal(moment(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + test.equal(moment.utc(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + } + test.done(); + }, + + "invalid string iso 8601 + timezone" : function (test) { + + var tests = [ + '2010-00-00+00:00', + '2010-01-00+00:00', + '2010-01-40+00:00', + '2010-01-40T24+00:00', + '2010-01-40T23:60+00:00', + '2010-01-40T23:59:60+00:00', + '2010-01-40T23:59:59.9999+00:00' + ]; + + test.expect(tests.length * 2); + + for (var i = 0; i < tests.length; i++) { + test.equal(moment(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + test.equal(moment.utc(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + } + test.done(); + }, + + "valid string iso 8601 + timezone" : function (test) { + var tests = [ + '2010-01-01', + '2010-01-30', + '2010-01-30T23+00:00', + '2010-01-30T23:59+00:00', + '2010-01-30T23:59:59+00:00', + '2010-01-30T23:59:59.999+00:00', + '2010-01-30T23:59:59.999-07:00', + '2010-01-30T00:00:00.000+07:00' + ]; + + test.expect(tests.length * 2); + + for (var i = 0; i < tests.length; i++) { + test.equal(moment(tests[i]).isValid(), true, tests[i] + ' should be valid'); + test.equal(moment.utc(tests[i]).isValid(), true, tests[i] + ' should be valid'); + } + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/lang.js b/node_modules/moment/test/moment/lang.js new file mode 100644 index 0000000..ee0cb5e --- /dev/null +++ b/node_modules/moment/test/moment/lang.js @@ -0,0 +1,236 @@ +var moment = require("../../moment"); + +exports.lang = { + "library getter" : function (test) { + test.expect(5); + + moment.lang('en'); + test.equal(moment.lang(), 'en', 'Lang should return en by default'); + + moment.lang('fr'); + test.equal(moment.lang(), 'fr', 'Lang should return the changed language'); + + moment.lang('en-gb'); + test.equal(moment.lang(), 'en-gb', 'Lang should return the changed language'); + + moment.lang('en'); + test.equal(moment.lang(), 'en', 'Lang should reset'); + + moment.lang('does-not-exist'); + test.equal(moment.lang(), 'en', 'Lang should reset'); + + test.done(); + }, + + "library ensure inheritance" : function (test) { + test.expect(2); + + moment.lang('made-up', { + // I put them out of order + months : "February_March_April_May_June_July_August_September_October_November_December_January".split("_") + // the rest of the properties should be inherited. + }); + + test.equal(moment([2012, 5, 6]).format('MMMM'), 'July', 'Override some of the configs'); + test.equal(moment([2012, 5, 6]).format('MMM'), 'Jun', 'But not all of them'); + + test.done(); + }, + + "library ensure inheritance LT L LL LLL LLLL" : function (test) { + test.expect(5); + + var lang = 'test-inherit-lt'; + + moment.lang(lang, { + longDateFormat : { + LT : "-[LT]-", + L : "-[L]-", + LL : "-[LL]-", + LLL : "-[LLL]-", + LLLL : "-[LLLL]-" + }, + calendar : { + sameDay : '[sameDay] LT', + nextDay : '[nextDay] L', + nextWeek : '[nextWeek] LL', + lastDay : '[lastDay] LLL', + lastWeek : '[lastWeek] LLLL', + sameElse : 'L' + } + }); + + moment.lang('es'); + + test.equal(moment().lang(lang).calendar(), "sameDay -LT-", "Should use instance lang in LT formatting"); + test.equal(moment().add('days', 1).lang(lang).calendar(), "nextDay -L-", "Should use instance lang in L formatting"); + test.equal(moment().add('days', -1).lang(lang).calendar(), "lastDay -LLL-", "Should use instance lang in LL formatting"); + test.equal(moment().add('days', 4).lang(lang).calendar(), "nextWeek -LL-", "Should use instance lang in LLL formatting"); + test.equal(moment().add('days', -4).lang(lang).calendar(), "lastWeek -LLLL-", "Should use instance lang in LLLL formatting"); + + test.done(); + }, + + "library langData" : function (test) { + test.expect(3); + moment.lang('en'); + + var jan = moment([2000, 0]); + + test.equal(moment.langData().months(jan), 'January', 'no arguments returns global'); + test.equal(moment.langData('zh-cn').months(jan), '一月', 'a string returns the language based on key'); + test.equal(moment.langData(moment().lang('es')).months(jan), 'enero', "if you pass in a moment it uses the moment's language"); + + test.done(); + }, + + "instance lang method" : function (test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment([2012, 5, 6]).format('MMMM'), 'June', 'Normally default to global'); + test.equal(moment([2012, 5, 6]).lang('es').format('MMMM'), 'junio', 'Use the instance specific language'); + test.equal(moment([2012, 5, 6]).format('MMMM'), 'June', 'Using an instance specific language does not affect other moments'); + + test.done(); + }, + + "instance lang persists with manipulation" : function (test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment([2012, 5, 6]).lang('es').add({days: 1}).format('MMMM'), 'junio', 'With addition'); + test.equal(moment([2012, 5, 6]).lang('es').day(0).format('MMMM'), 'junio', 'With day getter'); + test.equal(moment([2012, 5, 6]).lang('es').endOf('day').format('MMMM'), 'junio', 'With endOf'); + + test.done(); + }, + + "instance lang persists with cloning" : function (test) { + test.expect(2); + moment.lang('en'); + + var a = moment([2012, 5, 6]).lang('es'), + b = a.clone(), + c = moment(a); + + test.equal(b.format('MMMM'), 'junio', 'using moment.fn.clone()'); + test.equal(b.format('MMMM'), 'junio', 'using moment()'); + + test.done(); + }, + + "duration lang method" : function (test) { + test.expect(3); + moment.lang('en'); + + test.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', 'Normally default to global'); + test.equal(moment.duration({seconds: 44}).lang('es').humanize(), 'unos segundos', 'Use the instance specific language'); + test.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', 'Using an instance specific language does not affect other durations'); + + test.done(); + }, + + "duration lang persists with cloning" : function (test) { + test.expect(1); + moment.lang('en'); + + var a = moment.duration({seconds: 44}).lang('es'), + b = moment.duration(a); + + test.equal(b.humanize(), 'unos segundos', 'using moment.duration()'); + test.done(); + }, + + "instance lang used with from" : function (test) { + test.expect(2); + moment.lang('en'); + + var a = moment([2012, 5, 6]).lang('es'), + b = moment([2012, 5, 7]); + + test.equal(a.from(b), 'hace un día', 'preserve language of first moment'); + test.equal(b.from(a), 'in a day', 'do not preserve language of second moment'); + + test.done(); + }, + + "month name callback function" : function (test) { + test.expect(3); + + function fakeReplace(m, format) { + if (/test/.test(format)) { + return "test"; + } + if (m.date() === 1) { + return "date"; + } + return 'default'; + } + + moment.lang('made-up-2', { + months : fakeReplace, + monthsShort : fakeReplace, + weekdays : fakeReplace, + weekdaysShort : fakeReplace, + weekdaysMin : fakeReplace + }); + + test.equal(moment().format('[test] dd ddd dddd MMM MMMM'), 'test test test test test test', 'format month name function should be able to access the format string'); + test.equal(moment([2011, 0, 1]).format('dd ddd dddd MMM MMMM'), 'date date date date date', 'format month name function should be able to access the moment object'); + test.equal(moment([2011, 0, 2]).format('dd ddd dddd MMM MMMM'), 'default default default default default', 'format month name function should be able to access the moment object'); + + test.done(); + }, + + "changing parts of a language config" : function (test) { + test.expect(2); + + moment.lang('partial-lang', { + months : 'a b c d e f g h i j k l'.split(' ') + }); + + test.equal(moment([2011, 0, 1]).format('MMMM'), 'a', 'should be able to set language values when creating the language'); + + moment.lang('partial-lang', { + monthsShort : 'A B C D E F G H I J K L'.split(' ') + }); + + test.equal(moment([2011, 0, 1]).format('MMMM MMM'), 'a A', 'should be able to set language values after creating the language'); + + test.done(); + }, + + "start/endOf week feature for first-day-is-monday langs" : function (test) { + test.expect(2); + + moment.lang('monday-lang', { + week : { + dow : 1 // Monday is the first day of the week + } + }); + + moment.lang('monday-lang'); + test.equal(moment([2013, 0, 1]).startOf('week').day(), 1, 'for lang monday-lang first day of the week should be monday'); + test.equal(moment([2013, 0, 1]).endOf('week').day(), 0, 'for lang monday-lang last day of the week should be sunday'); + + test.done(); + }, + + "meridiem parsing" : function (test) { + test.expect(2); + + moment.lang('meridiem-parsing', { + meridiemParse : /[bd]/i, + isPM : function (input) { + return input === 'b'; + } + }); + + moment.lang('meridiem-parsing'); + test.equal(moment('2012-01-01 3b', 'YYYY-MM-DD ha').hour(), 15, 'Custom parsing of meridiem should work'); + test.equal(moment('2012-01-01 3d', 'YYYY-MM-DD ha').hour(), 3, 'Custom parsing of meridiem should work'); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/leapyear.js b/node_modules/moment/test/moment/leapyear.js new file mode 100644 index 0000000..7a3dd26 --- /dev/null +++ b/node_modules/moment/test/moment/leapyear.js @@ -0,0 +1,13 @@ +var moment = require("../../moment"); + +exports.leapyear = { + "leap year" : function(test) { + test.expect(4); + + test.equal(moment([2010, 0, 1]).isLeapYear(), false, '2010'); + test.equal(moment([2100, 0, 1]).isLeapYear(), false, '2100'); + test.equal(moment([2008, 0, 1]).isLeapYear(), true, '2008'); + test.equal(moment([2000, 0, 1]).isLeapYear(), true, '2000'); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/min_max.js b/node_modules/moment/test/moment/min_max.js new file mode 100644 index 0000000..da75c48 --- /dev/null +++ b/node_modules/moment/test/moment/min_max.js @@ -0,0 +1,62 @@ +var moment = require("../../moment"); + +exports.min_max = { + setUp : function (cb) { + moment.lang('en'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "min" : function (test) { + test.expect(8); + + var now = moment(), + future = now.clone().add(1, 'month'), + past = now.clone().subtract(1, 'month'); + + // we use Math.abs(a.diff(b)) < 2 to prevent issues where + // two moments are off by a millisecond. + + test.ok(Math.abs(past.min(now).diff(now)) < 2, "A past date with the minimum of now should be now"); + test.ok(Math.abs(past.min().diff(now)) < 2, "A past date with the minimum of implied now should be now"); + test.ok(Math.abs(past.min(future).diff(future)) < 2, "A past date with the minimum of the future should be the future date"); + + test.ok(Math.abs(future.min(now).diff(future)) < 2, "A future date with the minimum of now should be the future"); + test.ok(Math.abs(future.min().diff(future)) < 2, "A future date with the minimum of implied now should be the future"); + test.ok(Math.abs(future.min(past).diff(future)) < 2, "A future date with the minimum of the past should be the future"); + + test.ok(Math.abs(now.min(past).diff(now)) < 2, "Now with the minimum of the past should be now"); + test.ok(Math.abs(now.min(future).diff(future)) < 2, "Now with the minimum of the future should be the future"); + + test.done(); + }, + + "max" : function (test) { + test.expect(8); + + var now = moment(), + future = now.clone().add(1, 'month'), + past = now.clone().subtract(1, 'month'); + + // we use Math.abs(a.diff(b)) < 2 to prevent issues where + // two moments are off by a millisecond. + + test.ok(Math.abs(past.max(now).diff(past)) < 2, "A past date with the maximum of now should be the past"); + test.ok(Math.abs(past.max().diff(past)) < 2, "A past date with the maximum of implied now should be the past"); + test.ok(Math.abs(past.max(future).diff(past)) < 2, "A past date with the maximum of the future should be the past"); + + test.ok(Math.abs(future.max(now).diff(now)) < 2, "A future date with the maximum of now should be now"); + test.ok(Math.abs(future.max().diff(now)) < 2, "A future date with the maximum of implied now should be now"); + test.ok(Math.abs(future.max(past).diff(past)) < 2, "A future date with the maximum of the past should be the past"); + + test.ok(Math.abs(now.max(past).diff(past)) < 2, "Now with the maximum of the past should be the past"); + test.ok(Math.abs(now.max(future).diff(now)) < 2, "Now with the maximum of the future should be now"); + + test.done(); + } + +}; diff --git a/node_modules/moment/test/moment/mutable.js b/node_modules/moment/test/moment/mutable.js new file mode 100644 index 0000000..fdc7673 --- /dev/null +++ b/node_modules/moment/test/moment/mutable.js @@ -0,0 +1,55 @@ +var moment = require("../../moment"); + +exports.mutable = { + "manipulation methods" : function (test) { + + var mutableMethods = { + 'year': function (m){ return m.year(2011); }, + 'month': function (m){ return m.month(1); }, + 'date': function (m){ return m.date(9); }, + 'hours': function (m){ return m.hours(7); }, + 'minutes': function (m){ return m.minutes(33); }, + 'seconds': function (m){ return m.seconds(44); }, + 'milliseconds': function (m){ return m.milliseconds(55); }, + 'day': function (m){ return m.day(2); }, + 'startOf': function (m){ return m.startOf('week') }, + 'endOf': function (m){ return m.endOf('week') }, + 'add': function (m){ return m.add('days', 1) }, + 'subtract': function (m){ return m.subtract('years', 2) }, + 'local': function (m){ return m.local() }, + 'utc': function (m){ return m.utc() } + }; + + test.expect(14); + + for (method in mutableMethods) { + if (mutableMethods.hasOwnProperty(method)) { + var d = moment(); + var d2 = mutableMethods[method](d); + test.equal(d, d2, method + "() should be mutable"); + } + } + + test.done(); + }, + + "non mutable methods" : function (test) { + + var nonMutableMethods = { + 'clone': function (m){ return m.clone() } + }; + + test.expect(1); + + for (method in nonMutableMethods){ + if (nonMutableMethods.hasOwnProperty(method)) { + var d = new Date(); + var d2 = nonMutableMethods[method](moment(d)).toDate(); + test.notEqual(d, d2, method + "() should not be mutable"); + } + } + + test.done(); + } + +}; diff --git a/node_modules/moment/test/moment/preparse_postformat.js b/node_modules/moment/test/moment/preparse_postformat.js new file mode 100644 index 0000000..d3dcc2d --- /dev/null +++ b/node_modules/moment/test/moment/preparse_postformat.js @@ -0,0 +1,91 @@ +var moment = require("../../moment"); + + +var symbolMap = { + '1': '!', + '2': '@', + '3': '#', + '4': '$', + '5': '%', + '6': '^', + '7': '&', + '8': '*', + '9': '(', + '0': ')' +}; + +var numberMap = { + '!': '1', + '@': '2', + '#': '3', + '$': '4', + '%': '5', + '^': '6', + '&': '7', + '*': '8', + '(': '9', + ')': '0' +}; + +var symbolLang = { + preparse: function(string) { + return string.replace(/[!@#$%\^&*()]/g, function(match) { + return numberMap[match]; + }); + }, + + postformat: function(string) { + return string.replace(/\d/g, function(match) { + return symbolMap[match]; + }); + } +}; + +exports.preparse_postformat = { + setUp: function(cb) { + moment.lang('symbol', symbolLang); + cb(); + }, + + tearDown: function(cb) { + moment.lang('en-gb'); + cb(); + }, + + "transform": function(test) { + test.expect(3); + + test.equal(moment.utc('@)!@-)*-@&', 'YYYY-MM-DD').unix(), 1346025600, "preparse string + format"); + test.equal(moment.utc('@)!@-)*-@&').unix(), 1346025600, "preparse ISO8601 string"); + test.equal(moment.unix(1346025600).utc().format('YYYY-MM-DD'), '@)!@-)*-@&', "postformat"); + + test.done(); + }, + + "transform from": function(test) { + test.expect(3); + + var start = moment([2007, 1, 28]); + + test.equal(start.from(moment([2007, 1, 28]).add({s:90}), true), "@ minutes", "postformat should work on moment.fn.from"); + test.equal(moment().add('d', 6).fromNow(true), "^ days", "postformat should work on moment.fn.fromNow"); + test.equal(moment.duration(10, "h").humanize(), "!) hours", "postformat should work on moment.duration.fn.humanize"); + + test.done(); + }, + + "calendar day" : function(test) { + test.expect(6); + + var a = moment().hours(2).minutes(0).seconds(0); + + test.equal(moment(a).calendar(), "Today at @:)) AM", "today at the same time"); + test.equal(moment(a).add({ m: 25 }).calendar(), "Today at @:@% AM", "Now plus 25 min"); + test.equal(moment(a).add({ h: 1 }).calendar(), "Today at #:)) AM", "Now plus 1 hour"); + test.equal(moment(a).add({ d: 1 }).calendar(), "Tomorrow at @:)) AM", "tomorrow at the same time"); + test.equal(moment(a).subtract({ h: 1 }).calendar(), "Today at !:)) AM", "Now minus 1 hour"); + test.equal(moment(a).subtract({ d: 1 }).calendar(), "Yesterday at @:)) AM", "yesterday at the same time"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/sod_eod.js b/node_modules/moment/test/moment/sod_eod.js new file mode 100644 index 0000000..98338b9 --- /dev/null +++ b/node_modules/moment/test/moment/sod_eod.js @@ -0,0 +1,267 @@ +var moment = require("../../moment"); + +exports.end_start_of = { + setUp : function (cb) { + moment.lang('en'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "start of year" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('year'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('years'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('y'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 0, "strip out the month"); + test.equal(m.date(), 1, "strip out the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of year" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('year'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('years'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('y'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 11, "set the month"); + test.equal(m.date(), 31, "set the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of month" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('month'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('months'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('M'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 1, "strip out the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of month" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('month'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('months'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('M'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 28, "set the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of week" : function(test) { + test.expect(10); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('week'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('weeks'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('w'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 0, "rolls back to January"); + test.equal(m.day(), 0, "set day of week"); + test.equal(m.date(), 30, "set correct date"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of week" : function(test) { + test.expect(10); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('week'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('weeks'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('weeks'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.day(), 6, "set the day of the week"); + test.equal(m.date(), 5, "set the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of day" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('day'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('days'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('d'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 0, "strip out the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of day" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('day'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('days'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('d'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 23, "set the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of hour" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('hour'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('hours'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('h'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 0, "strip out the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of hour" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('hour'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('hours'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('h'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 59, "set the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of minute" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('minute'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('minutes'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('m'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 0, "strip out the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of minute" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('minute'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('minutes'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('m'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 59, "set the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + }, + + "start of second" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('second'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('seconds'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('s'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 5, "keep the the seconds"); + test.equal(m.milliseconds(), 0, "strip out the milliseconds"); + test.done(); + }, + + "end of second" : function(test) { + test.expect(9); + + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('second'); + var ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('seconds'); + var ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('s'); + test.equal(+m, +ms, "Plural or singular should work"); + test.equal(+m, +ma, "Full or abbreviated should work"); + test.equal(m.year(), 2011, "keep the year"); + test.equal(m.month(), 1, "keep the month"); + test.equal(m.date(), 2, "keep the day"); + test.equal(m.hours(), 3, "keep the hours"); + test.equal(m.minutes(), 4, "keep the minutes"); + test.equal(m.seconds(), 5, "keep the seconds"); + test.equal(m.milliseconds(), 999, "set the seconds"); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/string_prototype.js b/node_modules/moment/test/moment/string_prototype.js new file mode 100644 index 0000000..d4712d1 --- /dev/null +++ b/node_modules/moment/test/moment/string_prototype.js @@ -0,0 +1,17 @@ +var moment = require("../../moment"); + +exports.add = { + "string prototype overrides call" : function(test) { + test.expect(1); + + var prior = String.prototype.call; + String.prototype.call = function() { return null;}; + + var b = moment(new Date(2011, 7, 28, 15, 25, 50, 125)); + test.equal(b.format('MMMM Do YYYY, h:mm a'), 'August 28th 2011, 3:25 pm'); + + String.prototype.call = prior; + test.done(); + } + +}; diff --git a/node_modules/moment/test/moment/utc.js b/node_modules/moment/test/moment/utc.js new file mode 100644 index 0000000..a064ee0 --- /dev/null +++ b/node_modules/moment/test/moment/utc.js @@ -0,0 +1,77 @@ +var moment = require("../../moment"); + +exports.utc = { + setUp : function (cb) { + moment.lang('en'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "utc and local" : function(test) { + test.expect(7); + + var m = moment(Date.UTC(2011, 1, 2, 3, 4, 5, 6)); + m.utc(); + // utc + test.equal(m.date(), 2, "the day should be correct for utc"); + test.equal(m.day(), 3, "the date should be correct for utc"); + test.equal(m.hours(), 3, "the hours should be correct for utc"); + + // local + m.local(); + if (m.zone() > 180) { + test.equal(m.date(), 1, "the date should be correct for local"); + test.equal(m.day(), 2, "the day should be correct for local"); + } else { + test.equal(m.date(), 2, "the date should be correct for local"); + test.equal(m.day(), 3, "the day should be correct for local"); + } + var zone = Math.ceil(m.zone() / 60); + var expected = (24 + 3 - zone) % 24; + test.equal(m.hours(), expected, "the hours (" + m.hours() + ") should be correct for local"); + test.equal(moment().utc().zone(), 0, "timezone in utc should always be zero"); + test.done(); + }, + + "creating with utc" : function(test) { + test.expect(7); + + var diff = moment.utc().valueOf() - moment().valueOf(); + diff = Math.abs(diff); + // we check the diff rather than equality because sometimes they are off by a millisecond + + test.ok(diff < 5, "Calling moment.utc() should default to the current time"); + + var m = moment.utc([2011, 1, 2, 3, 4, 5, 6]); + test.equal(m.date(), 2, "the day should be correct for utc array"); + test.equal(m.hours(), 3, "the hours should be correct for utc array"); + + m = moment.utc("2011-02-02 3:04:05", "YYYY-MM-DD HH:mm:ss"); + test.equal(m.date(), 2, "the day should be correct for utc parsing format"); + test.equal(m.hours(), 3, "the hours should be correct for utc parsing format"); + + m = moment.utc("2011-02-02T03:04:05+00:00"); + test.equal(m.date(), 2, "the day should be correct for utc parsing iso"); + test.equal(m.hours(), 3, "the hours should be correct for utc parsing iso"); + + test.done(); + }, + + "creating with utc without timezone" : function(test) { + test.expect(4); + + var m = moment.utc("2012-01-02T08:20:00"); + test.equal(m.date(), 2, "the day should be correct for utc parse without timezone"); + test.equal(m.hours(), 8, "the hours should be correct for utc parse without timezone"); + + m = moment.utc("2012-01-02T08:20:00+09:00"); + test.equal(m.date(), 1, "the day should be correct for utc parse with timezone"); + test.equal(m.hours(), 23, "the hours should be correct for utc parse with timezone"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/week_year.js b/node_modules/moment/test/moment/week_year.js new file mode 100644 index 0000000..185e524 --- /dev/null +++ b/node_modules/moment/test/moment/week_year.js @@ -0,0 +1,72 @@ +var moment = require("../../moment"); + +exports.week_year = { + "iso week year": function(test) { + test.expect(19); + + // Some examples taken from http://en.wikipedia.org/wiki/ISO_week + test.equal(moment([2005, 0, 1]).isoWeekYear(), 2004); + test.equal(moment([2005, 0, 2]).isoWeekYear(), 2004); + test.equal(moment([2005, 0, 3]).isoWeekYear(), 2005); + test.equal(moment([2005, 11, 31]).isoWeekYear(), 2005); + test.equal(moment([2006, 0, 1]).isoWeekYear(), 2005); + test.equal(moment([2006, 0, 2]).isoWeekYear(), 2006); + test.equal(moment([2007, 0, 1]).isoWeekYear(), 2007); + test.equal(moment([2007, 11, 30]).isoWeekYear(), 2007); + test.equal(moment([2007, 11, 31]).isoWeekYear(), 2008); + test.equal(moment([2008, 0, 1]).isoWeekYear(), 2008); + test.equal(moment([2008, 11, 28]).isoWeekYear(), 2008); + test.equal(moment([2008, 11, 29]).isoWeekYear(), 2009); + test.equal(moment([2008, 11, 30]).isoWeekYear(), 2009); + test.equal(moment([2008, 11, 31]).isoWeekYear(), 2009); + test.equal(moment([2009, 0, 1]).isoWeekYear(), 2009); + test.equal(moment([2010, 0, 1]).isoWeekYear(), 2009); + test.equal(moment([2010, 0, 2]).isoWeekYear(), 2009); + test.equal(moment([2010, 0, 3]).isoWeekYear(), 2009); + test.equal(moment([2010, 0, 4]).isoWeekYear(), 2010); + + test.done(); + }, + + "week year": function(test) { + test.expect(31); + + // Some examples taken from http://en.wikipedia.org/wiki/ISO_week + moment.lang('dow:1,doy:4', {week: {dow: 1, doy: 4}}); // like iso + test.equal(moment([2005, 0, 1]).weekYear(), 2004); + test.equal(moment([2005, 0, 2]).weekYear(), 2004); + test.equal(moment([2005, 0, 3]).weekYear(), 2005); + test.equal(moment([2005, 11, 31]).weekYear(), 2005); + test.equal(moment([2006, 0, 1]).weekYear(), 2005); + test.equal(moment([2006, 0, 2]).weekYear(), 2006); + test.equal(moment([2007, 0, 1]).weekYear(), 2007); + test.equal(moment([2007, 11, 30]).weekYear(), 2007); + test.equal(moment([2007, 11, 31]).weekYear(), 2008); + test.equal(moment([2008, 0, 1]).weekYear(), 2008); + test.equal(moment([2008, 11, 28]).weekYear(), 2008); + test.equal(moment([2008, 11, 29]).weekYear(), 2009); + test.equal(moment([2008, 11, 30]).weekYear(), 2009); + test.equal(moment([2008, 11, 31]).weekYear(), 2009); + test.equal(moment([2009, 0, 1]).weekYear(), 2009); + test.equal(moment([2010, 0, 1]).weekYear(), 2009); + test.equal(moment([2010, 0, 2]).weekYear(), 2009); + test.equal(moment([2010, 0, 3]).weekYear(), 2009); + test.equal(moment([2010, 0, 4]).weekYear(), 2010); + + moment.lang('dow:1,doy:7', {week: {dow: 1, doy: 7}}); + test.equal(moment([2004, 11, 26]).weekYear(), 2004); + test.equal(moment([2004, 11, 27]).weekYear(), 2005); + test.equal(moment([2005, 11, 25]).weekYear(), 2005); + test.equal(moment([2005, 11, 26]).weekYear(), 2006); + test.equal(moment([2006, 11, 31]).weekYear(), 2006); + test.equal(moment([2007, 0, 1]).weekYear(), 2007); + test.equal(moment([2007, 11, 30]).weekYear(), 2007); + test.equal(moment([2007, 11, 31]).weekYear(), 2008); + test.equal(moment([2008, 11, 28]).weekYear(), 2008); + test.equal(moment([2008, 11, 29]).weekYear(), 2009); + test.equal(moment([2009, 11, 27]).weekYear(), 2009); + test.equal(moment([2009, 11, 28]).weekYear(), 2010); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/weekday.js b/node_modules/moment/test/moment/weekday.js new file mode 100644 index 0000000..ef1571e --- /dev/null +++ b/node_modules/moment/test/moment/weekday.js @@ -0,0 +1,158 @@ +var moment = require("../../moment"); + +exports.week_year = { + "iso weekday": function(test) { + var i; + test.expect(7 * 7); + + for (i = 0; i < 7; ++i) { + moment.lang('dow:' + i + ',doy:6', {week: {dow: i, doy: 6}}); + test.equal(moment([1985, 1, 4]).isoWeekday(), 1, "Feb 4 1985 is Monday -- 1st day"); + test.equal(moment([2029, 8, 18]).isoWeekday(), 2, "Sep 18 2029 is Tuesday -- 2nd day"); + test.equal(moment([2013, 3, 24]).isoWeekday(), 3, "Apr 24 2013 is Wednesday -- 3rd day"); + test.equal(moment([2015, 2, 5]).isoWeekday(), 4, "Mar 5 2015 is Thursday -- 4th day"); + test.equal(moment([1970, 0, 2]).isoWeekday(), 5, "Jan 2 1970 is Friday -- 5th day"); + test.equal(moment([2001, 4, 12]).isoWeekday(), 6, "May 12 2001 is Saturday -- 6th day"); + test.equal(moment([2000, 0, 2]).isoWeekday(), 7, "Jan 2 2000 is Sunday -- 7th day"); + } + test.done(); + }, + + "iso weekday setter" : function(test) { + test.expect(27); + + var a = moment([2011, 0, 10]); + test.equal(moment(a).isoWeekday(1).date(), 10, 'set from mon to mon'); + test.equal(moment(a).isoWeekday(4).date(), 13, 'set from mon to thu'); + test.equal(moment(a).isoWeekday(7).date(), 16, 'set from mon to sun'); + test.equal(moment(a).isoWeekday(-6).date(), 3, 'set from mon to last mon'); + test.equal(moment(a).isoWeekday(-3).date(), 6, 'set from mon to last thu'); + test.equal(moment(a).isoWeekday(0).date(), 9, 'set from mon to last sun'); + test.equal(moment(a).isoWeekday(8).date(), 17, 'set from mon to next mon'); + test.equal(moment(a).isoWeekday(11).date(), 20, 'set from mon to next thu'); + test.equal(moment(a).isoWeekday(14).date(), 23, 'set from mon to next sun'); + + a = moment([2011, 0, 13]); + test.equal(moment(a).isoWeekday(1).date(), 10, 'set from thu to mon'); + test.equal(moment(a).isoWeekday(4).date(), 13, 'set from thu to thu'); + test.equal(moment(a).isoWeekday(7).date(), 16, 'set from thu to sun'); + test.equal(moment(a).isoWeekday(-6).date(), 3, 'set from thu to last mon'); + test.equal(moment(a).isoWeekday(-3).date(), 6, 'set from thu to last thu'); + test.equal(moment(a).isoWeekday(0).date(), 9, 'set from thu to last sun'); + test.equal(moment(a).isoWeekday(8).date(), 17, 'set from thu to next mon'); + test.equal(moment(a).isoWeekday(11).date(), 20, 'set from thu to next thu'); + test.equal(moment(a).isoWeekday(14).date(), 23, 'set from thu to next sun'); + + a = moment([2011, 0, 16]); + test.equal(moment(a).isoWeekday(1).date(), 10, 'set from sun to mon'); + test.equal(moment(a).isoWeekday(4).date(), 13, 'set from sun to thu'); + test.equal(moment(a).isoWeekday(7).date(), 16, 'set from sun to sun'); + test.equal(moment(a).isoWeekday(-6).date(), 3, 'set from sun to last mon'); + test.equal(moment(a).isoWeekday(-3).date(), 6, 'set from sun to last thu'); + test.equal(moment(a).isoWeekday(0).date(), 9, 'set from sun to last sun'); + test.equal(moment(a).isoWeekday(8).date(), 17, 'set from sun to next mon'); + test.equal(moment(a).isoWeekday(11).date(), 20, 'set from sun to next thu'); + test.equal(moment(a).isoWeekday(14).date(), 23, 'set from sun to next sun'); + + test.done(); + }, + + "weekday first day of week Sunday (dow 0)": function(test) { + test.expect(7); + + moment.lang('dow:0,doy:6', {week: {dow: 0, doy: 6}}); + test.equal(moment([1985, 1, 3]).weekday(), 0, "Feb 3 1985 is Sunday -- 0th day"); + test.equal(moment([2029, 8, 17]).weekday(), 1, "Sep 17 2029 is Monday -- 1st day"); + test.equal(moment([2013, 3, 23]).weekday(), 2, "Apr 23 2013 is Tuesday -- 2nd day"); + test.equal(moment([2015, 2, 4]).weekday(), 3, "Mar 4 2015 is Wednesday -- 3nd day"); + test.equal(moment([1970, 0, 1]).weekday(), 4, "Jan 1 1970 is Thursday -- 4th day"); + test.equal(moment([2001, 4, 11]).weekday(), 5, "May 11 2001 is Friday -- 5th day"); + test.equal(moment([2000, 0, 1]).weekday(), 6, "Jan 1 2000 is Saturday -- 6th day"); + test.done(); + }, + + "weekday first day of week Monday (dow 1)": function(test) { + test.expect(7); + + moment.lang('dow:1,doy:6', {week: {dow: 1, doy: 6}}); + test.equal(moment([1985, 1, 4]).weekday(), 0, "Feb 4 1985 is Monday -- 0th day"); + test.equal(moment([2029, 8, 18]).weekday(), 1, "Sep 18 2029 is Tuesday -- 1st day"); + test.equal(moment([2013, 3, 24]).weekday(), 2, "Apr 24 2013 is Wednesday -- 2nd day"); + test.equal(moment([2015, 2, 5]).weekday(), 3, "Mar 5 2015 is Thursday -- 3nd day"); + test.equal(moment([1970, 0, 2]).weekday(), 4, "Jan 2 1970 is Friday -- 4th day"); + test.equal(moment([2001, 4, 12]).weekday(), 5, "May 12 2001 is Saturday -- 5th day"); + test.equal(moment([2000, 0, 2]).weekday(), 6, "Jan 2 2000 is Sunday -- 6th day"); + test.done(); + }, + + "weekday first day of week Tuesday (dow 2)": function(test) { + test.expect(7); + + moment.lang('dow:2,doy:6', {week: {dow: 2, doy: 6}}); + test.equal(moment([1985, 1, 5]).weekday(), 0, "Feb 5 1985 is Tuesday -- 0th day"); + test.equal(moment([2029, 8, 19]).weekday(), 1, "Sep 19 2029 is Wednesday -- 1st day"); + test.equal(moment([2013, 3, 25]).weekday(), 2, "Apr 25 2013 is Thursday -- 2nd day"); + test.equal(moment([2015, 2, 6]).weekday(), 3, "Mar 6 2015 is Friday -- 3nd day"); + test.equal(moment([1970, 0, 3]).weekday(), 4, "Jan 3 1970 is Staturday -- 4th day"); + test.equal(moment([2001, 4, 13]).weekday(), 5, "May 13 2001 is Sunday -- 5th day"); + test.equal(moment([2000, 0, 3]).weekday(), 6, "Jan 3 2000 is Monday -- 6th day"); + test.done(); + }, + + "weekday first day of week Wednesday (dow 3)": function(test) { + test.expect(7); + + moment.lang('dow:3,doy:6', {week: {dow: 3, doy: 6}}); + test.equal(moment([1985, 1, 6]).weekday(), 0, "Feb 6 1985 is Wednesday -- 0th day"); + test.equal(moment([2029, 8, 20]).weekday(), 1, "Sep 20 2029 is Thursday -- 1st day"); + test.equal(moment([2013, 3, 26]).weekday(), 2, "Apr 26 2013 is Friday -- 2nd day"); + test.equal(moment([2015, 2, 7]).weekday(), 3, "Mar 7 2015 is Saturday -- 3nd day"); + test.equal(moment([1970, 0, 4]).weekday(), 4, "Jan 4 1970 is Sunday -- 4th day"); + test.equal(moment([2001, 4, 14]).weekday(), 5, "May 14 2001 is Monday -- 5th day"); + test.equal(moment([2000, 0, 4]).weekday(), 6, "Jan 4 2000 is Tuesday -- 6th day"); + test.done(); + }, + + "weekday first day of week Thursday (dow 4)": function(test) { + test.expect(7); + + moment.lang('dow:4,doy:6', {week: {dow: 4, doy: 6}}); + + test.equal(moment([1985, 1, 7]).weekday(), 0, "Feb 7 1985 is Thursday -- 0th day"); + test.equal(moment([2029, 8, 21]).weekday(), 1, "Sep 21 2029 is Friday -- 1st day"); + test.equal(moment([2013, 3, 27]).weekday(), 2, "Apr 27 2013 is Saturday -- 2nd day"); + test.equal(moment([2015, 2, 8]).weekday(), 3, "Mar 8 2015 is Sunday -- 3nd day"); + test.equal(moment([1970, 0, 5]).weekday(), 4, "Jan 5 1970 is Monday -- 4th day"); + test.equal(moment([2001, 4, 15]).weekday(), 5, "May 15 2001 is Tuesday -- 5th day"); + test.equal(moment([2000, 0, 5]).weekday(), 6, "Jan 5 2000 is Wednesday -- 6th day"); + test.done(); + }, + + "weekday first day of week Friday (dow 5)": function(test) { + test.expect(7); + + moment.lang('dow:5,doy:6', {week: {dow: 5, doy: 6}}); + test.equal(moment([1985, 1, 8]).weekday(), 0, "Feb 8 1985 is Friday -- 0th day"); + test.equal(moment([2029, 8, 22]).weekday(), 1, "Sep 22 2029 is Staturday -- 1st day"); + test.equal(moment([2013, 3, 28]).weekday(), 2, "Apr 28 2013 is Sunday -- 2nd day"); + test.equal(moment([2015, 2, 9]).weekday(), 3, "Mar 9 2015 is Monday -- 3nd day"); + test.equal(moment([1970, 0, 6]).weekday(), 4, "Jan 6 1970 is Tuesday -- 4th day"); + test.equal(moment([2001, 4, 16]).weekday(), 5, "May 16 2001 is Wednesday -- 5th day"); + test.equal(moment([2000, 0, 6]).weekday(), 6, "Jan 6 2000 is Thursday -- 6th day"); + test.done(); + }, + + "weekday first day of week Saturday (dow 6)": function(test) { + test.expect(7); + + moment.lang('dow:6,doy:6', {week: {dow: 6, doy: 6}}); + test.equal(moment([1985, 1, 9]).weekday(), 0, "Feb 9 1985 is Staturday -- 0th day"); + test.equal(moment([2029, 8, 23]).weekday(), 1, "Sep 23 2029 is Sunday -- 1st day"); + test.equal(moment([2013, 3, 29]).weekday(), 2, "Apr 29 2013 is Monday -- 2nd day"); + test.equal(moment([2015, 2, 10]).weekday(), 3, "Mar 10 2015 is Tuesday -- 3nd day"); + test.equal(moment([1970, 0, 7]).weekday(), 4, "Jan 7 1970 is Wednesday -- 4th day"); + test.equal(moment([2001, 4, 17]).weekday(), 5, "May 17 2001 is Thursday -- 5th day"); + test.equal(moment([2000, 0, 7]).weekday(), 6, "Jan 7 2000 is Friday -- 6th day"); + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/weeks.js b/node_modules/moment/test/moment/weeks.js new file mode 100644 index 0000000..1b8b383 --- /dev/null +++ b/node_modules/moment/test/moment/weeks.js @@ -0,0 +1,205 @@ +var moment = require("../../moment"); + +exports.weeks = { + setUp : function (cb) { + moment.lang('en'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "day of year" : function (test) { + test.expect(8); + + test.equal(moment([2000, 0, 1]).dayOfYear(), 1, "Jan 1 2000 should be day 1 of the year"); + test.equal(moment([2000, 1, 28]).dayOfYear(), 59, "Feb 28 2000 should be day 59 of the year"); + test.equal(moment([2000, 1, 29]).dayOfYear(), 60, "Feb 28 2000 should be day 60 of the year"); + test.equal(moment([2000, 11, 31]).dayOfYear(), 366, "Dec 31 2000 should be day 366 of the year"); + test.equal(moment([2001, 0, 1]).dayOfYear(), 1, "Jan 1 2001 should be day 1 of the year"); + test.equal(moment([2001, 1, 28]).dayOfYear(), 59, "Feb 28 2001 should be day 59 of the year"); + test.equal(moment([2001, 2, 1]).dayOfYear(), 60, "Mar 1 2001 should be day 60 of the year"); + test.equal(moment([2001, 11, 31]).dayOfYear(), 365, "Dec 31 2001 should be day 365 of the year"); + + test.done(); + }, + + "day of year setters" : function (test) { + test.expect(8); + + test.equal(moment([2000, 0, 1]).dayOfYear(200).dayOfYear(), 200, "Setting Jan 1 2000 day of the year to 200 should work"); + test.equal(moment([2000, 1, 28]).dayOfYear(200).dayOfYear(), 200, "Setting Feb 28 2000 day of the year to 200 should work"); + test.equal(moment([2000, 1, 29]).dayOfYear(200).dayOfYear(), 200, "Setting Feb 28 2000 day of the year to 200 should work"); + test.equal(moment([2000, 11, 31]).dayOfYear(200).dayOfYear(), 200, "Setting Dec 31 2000 day of the year to 200 should work"); + test.equal(moment().dayOfYear( 1).dayOfYear(), 1, "Setting day of the year to 1 should work"); + test.equal(moment().dayOfYear( 59).dayOfYear(), 59, "Setting day of the year to 59 should work"); + test.equal(moment().dayOfYear( 60).dayOfYear(), 60, "Setting day of the year to 60 should work"); + test.equal(moment().dayOfYear(365).dayOfYear(), 365, "Setting day of the year to 365 should work"); + + test.done(); + }, + + "iso weeks year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).isoWeek(), 52, "Jan 1 2012 should be iso week 52"); + test.equal(moment([2012, 0, 2]).isoWeek(), 1, "Jan 2 2012 should be iso week 1"); + test.equal(moment([2012, 0, 8]).isoWeek(), 1, "Jan 8 2012 should be iso week 1"); + test.equal(moment([2012, 0, 9]).isoWeek(), 2, "Jan 9 2012 should be iso week 2"); + test.equal(moment([2012, 0, 15]).isoWeek(), 2, "Jan 15 2012 should be iso week 2"); + + test.done(); + }, + + "iso weeks year starting monday" : function(test) { + test.expect(5); + + test.equal(moment([2007, 0, 1]).isoWeek(), 1, "Jan 1 2007 should be iso week 1"); + test.equal(moment([2007, 0, 7]).isoWeek(), 1, "Jan 7 2007 should be iso week 1"); + test.equal(moment([2007, 0, 8]).isoWeek(), 2, "Jan 8 2007 should be iso week 2"); + test.equal(moment([2007, 0, 14]).isoWeek(), 2, "Jan 14 2007 should be iso week 2"); + test.equal(moment([2007, 0, 15]).isoWeek(), 3, "Jan 15 2007 should be iso week 3"); + + test.done(); + }, + + "iso weeks year starting tuesday" : function(test) { + test.expect(6); + + test.equal(moment([2007, 11, 31]).isoWeek(), 1, "Dec 31 2007 should be iso week 1"); + test.equal(moment([2008, 0, 1]).isoWeek(), 1, "Jan 1 2008 should be iso week 1"); + test.equal(moment([2008, 0, 6]).isoWeek(), 1, "Jan 6 2008 should be iso week 1"); + test.equal(moment([2008, 0, 7]).isoWeek(), 2, "Jan 7 2008 should be iso week 2"); + test.equal(moment([2008, 0, 13]).isoWeek(), 2, "Jan 13 2008 should be iso week 2"); + test.equal(moment([2008, 0, 14]).isoWeek(), 3, "Jan 14 2008 should be iso week 3"); + + test.done(); + }, + + "iso weeks year starting wednesday" : function(test) { + test.expect(6); + + test.equal(moment([2002, 11, 30]).isoWeek(), 1, "Dec 30 2002 should be iso week 1"); + test.equal(moment([2003, 0, 1]).isoWeek(), 1, "Jan 1 2003 should be iso week 1"); + test.equal(moment([2003, 0, 5]).isoWeek(), 1, "Jan 5 2003 should be iso week 1"); + test.equal(moment([2003, 0, 6]).isoWeek(), 2, "Jan 6 2003 should be iso week 2"); + test.equal(moment([2003, 0, 12]).isoWeek(), 2, "Jan 12 2003 should be iso week 2"); + test.equal(moment([2003, 0, 13]).isoWeek(), 3, "Jan 13 2003 should be iso week 3"); + + test.done(); + }, + + "iso weeks year starting thursday" : function(test) { + test.expect(6); + + test.equal(moment([2008, 11, 29]).isoWeek(), 1, "Dec 29 2008 should be iso week 1"); + test.equal(moment([2009, 0, 1]).isoWeek(), 1, "Jan 1 2009 should be iso week 1"); + test.equal(moment([2009, 0, 4]).isoWeek(), 1, "Jan 4 2009 should be iso week 1"); + test.equal(moment([2009, 0, 5]).isoWeek(), 2, "Jan 5 2009 should be iso week 2"); + test.equal(moment([2009, 0, 11]).isoWeek(), 2, "Jan 11 2009 should be iso week 2"); + test.equal(moment([2009, 0, 13]).isoWeek(), 3, "Jan 12 2009 should be iso week 3"); + + test.done(); + }, + + "iso weeks year starting friday" : function(test) { + test.expect(6); + + test.equal(moment([2009, 11, 28]).isoWeek(), 53, "Dec 28 2009 should be iso week 53"); + test.equal(moment([2010, 0, 1]).isoWeek(), 53, "Jan 1 2010 should be iso week 53"); + test.equal(moment([2010, 0, 3]).isoWeek(), 53, "Jan 3 2010 should be iso week 53"); + test.equal(moment([2010, 0, 4]).isoWeek(), 1, "Jan 4 2010 should be iso week 1"); + test.equal(moment([2010, 0, 10]).isoWeek(), 1, "Jan 10 2010 should be iso week 1"); + test.equal(moment([2010, 0, 11]).isoWeek(), 2, "Jan 11 2010 should be iso week 2"); + + test.done(); + }, + + "iso weeks year starting saturday" : function(test) { + test.expect(6); + + test.equal(moment([2010, 11, 27]).isoWeek(), 52, "Dec 27 2010 should be iso week 52"); + test.equal(moment([2011, 0, 1]).isoWeek(), 52, "Jan 1 2011 should be iso week 52"); + test.equal(moment([2011, 0, 2]).isoWeek(), 52, "Jan 2 2011 should be iso week 52"); + test.equal(moment([2011, 0, 3]).isoWeek(), 1, "Jan 3 2011 should be iso week 1"); + test.equal(moment([2011, 0, 9]).isoWeek(), 1, "Jan 9 2011 should be iso week 1"); + test.equal(moment([2011, 0, 10]).isoWeek(), 2, "Jan 10 2011 should be iso week 2"); + + test.done(); + }, + + "iso weeks year starting sunday formatted" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).format('W WW Wo'), '52 52 52nd', "Jan 1 2012 should be iso week 52"); + test.equal(moment([2012, 0, 2]).format('W WW Wo'), '1 01 1st' , "Jan 2 2012 should be iso week 1"); + test.equal(moment([2012, 0, 8]).format('W WW Wo'), '1 01 1st' , "Jan 8 2012 should be iso week 1"); + test.equal(moment([2012, 0, 9]).format('W WW Wo'), '2 02 2nd' , "Jan 9 2012 should be iso week 2"); + test.equal(moment([2012, 0, 15]).format('W WW Wo'), '2 02 2nd' , "Jan 15 2012 should be iso week 2"); + + test.done(); + }, + + "weeks plural year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).weeks(), 1, "Jan 1 2012 should be week 1"); + test.equal(moment([2012, 0, 7]).weeks(), 1, "Jan 7 2012 should be week 1"); + test.equal(moment([2012, 0, 8]).weeks(), 2, "Jan 8 2012 should be week 2"); + test.equal(moment([2012, 0, 14]).weeks(), 2, "Jan 14 2012 should be week 2"); + test.equal(moment([2012, 0, 15]).weeks(), 3, "Jan 15 2012 should be week 3"); + + test.done(); + }, + + "iso weeks plural year starting sunday" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).isoWeeks(), 52, "Jan 1 2012 should be iso week 52"); + test.equal(moment([2012, 0, 2]).isoWeeks(), 1, "Jan 2 2012 should be iso week 1"); + test.equal(moment([2012, 0, 8]).isoWeeks(), 1, "Jan 8 2012 should be iso week 1"); + test.equal(moment([2012, 0, 9]).isoWeeks(), 2, "Jan 9 2012 should be iso week 2"); + test.equal(moment([2012, 0, 15]).isoWeeks(), 2, "Jan 15 2012 should be iso week 2"); + + test.done(); + }, + + "weeks setter" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).week(30).week(), 30, "Setting Jan 1 2012 to week 30 should work"); + test.equal(moment([2012, 0, 7]).week(30).week(), 30, "Setting Jan 7 2012 to week 30 should work"); + test.equal(moment([2012, 0, 8]).week(30).week(), 30, "Setting Jan 8 2012 to week 30 should work"); + test.equal(moment([2012, 0, 14]).week(30).week(), 30, "Setting Jan 14 2012 to week 30 should work"); + test.equal(moment([2012, 0, 15]).week(30).week(), 30, "Setting Jan 15 2012 to week 30 should work"); + + test.done(); + }, + + "iso weeks setter" : function(test) { + test.expect(5); + + test.equal(moment([2012, 0, 1]).isoWeeks(25).isoWeeks(), 25, "Setting Jan 1 2012 to week 25 should work"); + test.equal(moment([2012, 0, 2]).isoWeeks(24).isoWeeks(), 24, "Setting Jan 2 2012 to week 24 should work"); + test.equal(moment([2012, 0, 8]).isoWeeks(23).isoWeeks(), 23, "Setting Jan 8 2012 to week 23 should work"); + test.equal(moment([2012, 0, 9]).isoWeeks(22).isoWeeks(), 22, "Setting Jan 9 2012 to week 22 should work"); + test.equal(moment([2012, 0, 15]).isoWeeks(21).isoWeeks(), 21, "Setting Jan 15 2012 to week 21 should work"); + + test.done(); + }, + + "iso weeks setter day of year" : function(test) { + test.expect(6); + + test.equal(moment([2012, 0, 1]).isoWeek(1).dayOfYear(), 9, "Setting Jan 1 2012 to week 1 should be day of year 8"); + test.equal(moment([2012, 0, 1]).isoWeek(1).year(), 2011, "Setting Jan 1 2012 to week 1 should be year 2011"); + test.equal(moment([2012, 0, 2]).isoWeek(1).dayOfYear(), 2, "Setting Jan 2 2012 to week 1 should be day of year 2"); + test.equal(moment([2012, 0, 8]).isoWeek(1).dayOfYear(), 8, "Setting Jan 8 2012 to week 1 should be day of year 8"); + test.equal(moment([2012, 0, 9]).isoWeek(1).dayOfYear(), 2, "Setting Jan 9 2012 to week 1 should be day of year 2"); + test.equal(moment([2012, 0, 15]).isoWeek(1).dayOfYear(), 8, "Setting Jan 15 2012 to week 1 should be day of year 8"); + + test.done(); + } +}; diff --git a/node_modules/moment/test/moment/zones.js b/node_modules/moment/test/moment/zones.js new file mode 100644 index 0000000..133de2e --- /dev/null +++ b/node_modules/moment/test/moment/zones.js @@ -0,0 +1,420 @@ +var moment = require("../../moment"); + +exports.zones = { + setUp : function (cb) { + moment.lang('en'); + cb(); + }, + + tearDown : function (cb) { + moment.lang('en'); + cb(); + }, + + "set zone" : function (test) { + var zone = moment(); + + zone.zone(0); + test.equal(zone.zone(), 0, "should be able to set the zone to 0"); + + zone.zone(60); + test.equal(zone.zone(), 60, "should be able to set the zone to 60"); + + zone.zone(-60); + test.equal(zone.zone(), -60, "should be able to set the zone to -60"); + + test.done(); + }, + + "set zone shorthand" : function (test) { + var zone = moment(); + + zone.zone(1); + test.equal(zone.zone(), 60, "setting the zone to 1 should imply hours and convert to 60"); + + zone.zone(-1); + test.equal(zone.zone(), -60, "setting the zone to -1 should imply hours and convert to -60"); + + zone.zone(15); + test.equal(zone.zone(), 900, "setting the zone to 15 should imply hours and convert to 900"); + + zone.zone(-15); + test.equal(zone.zone(), -900, "setting the zone to -15 should imply hours and convert to -900"); + + zone.zone(16); + test.equal(zone.zone(), 16, "setting the zone to 16 should imply minutes"); + + zone.zone(-16); + test.equal(zone.zone(), -16, "setting the zone to -16 should imply minutes"); + + test.done(); + }, + + "set zone with string" : function (test) { + var zone = moment(); + + zone.zone("+00:00"); + test.equal(zone.zone(), 0, "set the zone with a timezone string"); + + zone.zone("2013-03-07T07:00:00-08:00"); + test.equal(zone.zone(), 480, "set the zone with a string that does not begin with the timezone"); + + zone.zone("2013-03-07T07:00:00+0100"); + test.equal(zone.zone(), -60, "set the zone with a string that uses the +0000 syntax"); + + test.done(); + }, + + "change hours when changing the zone" : function (test) { + var zone = moment.utc([2000, 0, 1, 6]); + + zone.zone(0); + test.equal(zone.hour(), 6, "UTC 6AM should be 6AM at +0000"); + + zone.zone(60); + test.equal(zone.hour(), 5, "UTC 6AM should be 5AM at -0100"); + + zone.zone(-60); + test.equal(zone.hour(), 7, "UTC 6AM should be 7AM at +0100"); + + test.done(); + }, + + "change minutes when changing the zone" : function (test) { + var zone = moment.utc([2000, 0, 1, 6, 31]); + + zone.zone(0); + test.equal(zone.format("HH:mm"), "06:31", "UTC 6:31AM should be 6:31AM at +0000"); + + zone.zone(30); + test.equal(zone.format("HH:mm"), "06:01", "UTC 6:31AM should be 6:01AM at -0030"); + + zone.zone(-30); + test.equal(zone.format("HH:mm"), "07:01", "UTC 6:31AM should be 7:01AM at +0030"); + + zone.zone(1380); + test.equal(zone.format("HH:mm"), "07:31", "UTC 6:31AM should be 7:31AM at +1380"); + + test.done(); + }, + + "distance from the unix epoch" : function (test) { + var zoneA = moment(), + zoneB = moment(zoneA), + zoneC = moment(zoneA), + zoneD = moment(zoneA), + zoneE = moment(zoneA); + + zoneB.utc(); + test.equal(+zoneA, +zoneB, "moment should equal moment.utc"); + + zoneC.zone(-60); + test.equal(+zoneA, +zoneC, "moment should equal moment.zone(-60)"); + + zoneD.zone(480); + test.equal(+zoneA, +zoneD, "moment should equal moment.zone(480)"); + + zoneE.zone(1000); + test.equal(+zoneA, +zoneE, "moment should equal moment.zone(1000)"); + + test.done(); + }, + + "update offset after changing any values" : function (test) { + var oldOffset = moment.updateOffset, + m = moment.utc([2000, 6, 1]); + + moment.updateOffset = function (mom) { + if (mom.__doChange) { + if (+mom > 962409600000) { + mom.zone(120); + } else { + mom.zone(60); + } + } + }; + + test.equal(m.format("ZZ"), "+0000", "should be at +0000"); + test.equal(m.format("HH:mm"), "00:00", "should start 12AM at +0000 timezone"); + + m.__doChange = true; + m.add('h', 1); + + test.equal(m.format("ZZ"), "-0200", "should be at -0200"); + test.equal(m.format("HH:mm"), "23:00", "1AM at +0000 should be 11PM at -0200 timezone"); + + m.subtract('h', 1); + + test.equal(m.format("ZZ"), "-0100", "should be at -0100"); + test.equal(m.format("HH:mm"), "23:00", "12AM at +0000 should be 11PM at -0100 timezone"); + + moment.updateOffset = oldOffset; + + test.done(); + }, + + "getters and setters" : function (test) { + var a = moment([2011, 5, 20]); + + test.equal(a.clone().zone(120).year(2012).year(), 2012, "should get and set year correctly"); + test.equal(a.clone().zone(120).month(1).month(), 1, "should get and set month correctly"); + test.equal(a.clone().zone(120).date(2).date(), 2, "should get and set date correctly"); + test.equal(a.clone().zone(120).day(1).day(), 1, "should get and set day correctly"); + test.equal(a.clone().zone(120).hour(1).hour(), 1, "should get and set hour correctly"); + test.equal(a.clone().zone(120).minute(1).minute(), 1, "should get and set minute correctly"); + + test.done(); + }, + + "getters" : function (test) { + var a = moment.utc([2012, 0, 1, 0, 0, 0]); + + test.equal(a.clone().zone(120).year(), 2011, "should get year correctly"); + test.equal(a.clone().zone(120).month(), 11, "should get month correctly"); + test.equal(a.clone().zone(120).date(), 31, "should get date correctly"); + test.equal(a.clone().zone(120).hour(), 22, "should get hour correctly"); + test.equal(a.clone().zone(120).minute(), 0, "should get minute correctly"); + + test.equal(a.clone().zone(-120).year(), 2012, "should get year correctly"); + test.equal(a.clone().zone(-120).month(), 0, "should get month correctly"); + test.equal(a.clone().zone(-120).date(), 1, "should get date correctly"); + test.equal(a.clone().zone(-120).hour(), 2, "should get hour correctly"); + test.equal(a.clone().zone(-120).minute(), 0, "should get minute correctly"); + + test.equal(a.clone().zone(-90).year(), 2012, "should get year correctly"); + test.equal(a.clone().zone(-90).month(), 0, "should get month correctly"); + test.equal(a.clone().zone(-90).date(), 1, "should get date correctly"); + test.equal(a.clone().zone(-90).hour(), 1, "should get hour correctly"); + test.equal(a.clone().zone(-90).minute(), 30, "should get minute correctly"); + + test.done(); + }, + + "from" : function (test) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(720), + zoneC = moment(zoneA).zone(360), + zoneD = moment(zoneA).zone(-690), + other = moment(zoneA).add('m', 35); + + test.equal(zoneA.from(other), zoneB.from(other), "moment#from should be the same in all zones"); + test.equal(zoneA.from(other), zoneC.from(other), "moment#from should be the same in all zones"); + test.equal(zoneA.from(other), zoneD.from(other), "moment#from should be the same in all zones"); + + test.done(); + }, + + "diff" : function (test) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(720), + zoneC = moment(zoneA).zone(360), + zoneD = moment(zoneA).zone(-690), + other = moment(zoneA).add('m', 35); + + test.equal(zoneA.diff(other), zoneB.diff(other), "moment#diff should be the same in all zones"); + test.equal(zoneA.diff(other), zoneC.diff(other), "moment#diff should be the same in all zones"); + test.equal(zoneA.diff(other), zoneD.diff(other), "moment#diff should be the same in all zones"); + + test.equal(zoneA.diff(other, 'minute', true), zoneB.diff(other, 'minute', true), "moment#diff should be the same in all zones"); + test.equal(zoneA.diff(other, 'minute', true), zoneC.diff(other, 'minute', true), "moment#diff should be the same in all zones"); + test.equal(zoneA.diff(other, 'minute', true), zoneD.diff(other, 'minute', true), "moment#diff should be the same in all zones"); + + test.equal(zoneA.diff(other, 'hour', true), zoneB.diff(other, 'hour', true), "moment#diff should be the same in all zones"); + test.equal(zoneA.diff(other, 'hour', true), zoneC.diff(other, 'hour', true), "moment#diff should be the same in all zones"); + test.equal(zoneA.diff(other, 'hour', true), zoneD.diff(other, 'hour', true), "moment#diff should be the same in all zones"); + + test.done(); + }, + + "unix offset and timestamp" : function (test) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(720), + zoneC = moment(zoneA).zone(360), + zoneD = moment(zoneA).zone(-690); + + test.equal(zoneA.unix(), zoneB.unix(), "moment#unix should be the same in all zones"); + test.equal(zoneA.unix(), zoneC.unix(), "moment#unix should be the same in all zones"); + test.equal(zoneA.unix(), zoneD.unix(), "moment#unix should be the same in all zones"); + + test.equal(+zoneA, +zoneB, "moment#valueOf should be the same in all zones"); + test.equal(+zoneA, +zoneC, "moment#valueOf should be the same in all zones"); + test.equal(+zoneA, +zoneD, "moment#valueOf should be the same in all zones"); + + test.done(); + }, + + "cloning" : function (test) { + test.equal(moment().zone(120).clone().zone(), 120, "explicit cloning should retain the zone"); + test.equal(moment().zone(-120).clone().zone(), -120, "explicit cloning should retain the zone"); + test.equal(moment(moment().zone(120)).zone(), 120, "implicit cloning should retain the zone"); + test.equal(moment(moment().zone(-120)).zone(), -120, "implicit cloning should retain the zone"); + + test.done(); + }, + + "start of / end of" : function (test) { + var a = moment.utc([2010, 1, 2, 0, 0, 0]).zone(450); + + test.equal(a.clone().startOf('day').hour(), 0, "start of day should work on moments with a zone"); + test.equal(a.clone().startOf('day').minute(), 0, "start of day should work on moments with a zone"); + test.equal(a.clone().startOf('hour').minute(), 0, "start of hour should work on moments with a zone"); + + test.equal(a.clone().endOf('day').hour(), 23, "end of day should work on moments with a zone"); + test.equal(a.clone().endOf('day').minute(), 59, "end of day should work on moments with a zone"); + test.equal(a.clone().endOf('hour').minute(), 59, "end of hour should work on moments with a zone"); + + test.done(); + }, + + "reset zone with moment#utc" : function (test) { + var a = moment.utc([2012]).zone(480); + + test.equal(a.clone().hour(), 16, "different zone should have different hour"); + test.equal(a.clone().utc().hour(), 0, "calling moment#utc should reset the offset"); + + test.done(); + }, + + "reset zone with moment#local" : function (test) { + var a = moment([2012]).zone(480); + + test.equal(a.clone().local().hour(), 0, "calling moment#local should reset the offset"); + + test.done(); + }, + + "toDate" : function (test) { + var zoneA = new Date(), + zoneB = moment(zoneA).zone(720).toDate(), + zoneC = moment(zoneA).zone(360).toDate(), + zoneD = moment(zoneA).zone(-690).toDate(); + + test.equal(+zoneA, +zoneB, "moment#toDate should output a date with the right unix timestamp"); + test.equal(+zoneA, +zoneC, "moment#toDate should output a date with the right unix timestamp"); + test.equal(+zoneA, +zoneD, "moment#toDate should output a date with the right unix timestamp"); + + test.done(); + }, + + "same / before / after" : function (test) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(120), + zoneC = moment(zoneA).zone(-120); + + test.ok(zoneA.isSame(zoneB), "two moments with different offsets should be the same"); + test.ok(zoneA.isSame(zoneC), "two moments with different offsets should be the same"); + + test.ok(zoneA.isSame(zoneB, 'hour'), "two moments with different offsets should be the same hour"); + test.ok(zoneA.isSame(zoneC, 'hour'), "two moments with different offsets should be the same hour"); + + zoneA.add('hour', 1); + + test.ok(zoneA.isAfter(zoneB), "isAfter should work with two moments with different offsets"); + test.ok(zoneA.isAfter(zoneC), "isAfter should work with two moments with different offsets"); + + test.ok(zoneA.isAfter(zoneB, 'hour'), "isAfter:hour should work with two moments with different offsets"); + test.ok(zoneA.isAfter(zoneC, 'hour'), "isAfter:hour should work with two moments with different offsets"); + + zoneA.subtract('hour', 2); + + test.ok(zoneA.isBefore(zoneB), "isBefore should work with two moments with different offsets"); + test.ok(zoneA.isBefore(zoneC), "isBefore should work with two moments with different offsets"); + + test.ok(zoneA.isBefore(zoneB, 'hour'), "isBefore:hour should work with two moments with different offsets"); + test.ok(zoneA.isBefore(zoneC, 'hour'), "isBefore:hour should work with two moments with different offsets"); + + test.done(); + }, + + "add / subtract over dst" : function (test) { + var oldOffset = moment.updateOffset, + m = moment.utc([2000, 2, 31, 3]); + + moment.updateOffset = function (mom) { + if (mom.clone().utc().month() > 2) { + mom.zone(-60); + } else { + mom.zone(0); + } + }; + + test.equal(m.hour(), 3, "should start at 00:00"); + + m.add('hour', 24); + + test.equal(m.hour(), 4, "adding 24 hours should disregard dst"); + + m.subtract('hour', 24); + + test.equal(m.hour(), 3, "subtracting 24 hours should disregard dst"); + + m.add('day', 1); + + test.equal(m.hour(), 3, "adding 1 day should have the same hour"); + + m.subtract('day', 1); + + test.equal(m.hour(), 3, "subtracting 1 day should have the same hour"); + + m.add('month', 1); + + test.equal(m.hour(), 3, "adding 1 month should have the same hour"); + + m.subtract('month', 1); + + test.equal(m.hour(), 3, "subtracting 1 month should have the same hour"); + + moment.updateOffset = oldOffset; + + test.done(); + }, + + "isDST" : function (test) { + var oldOffset = moment.updateOffset; + + moment.updateOffset = function (mom) { + if (mom.month() > 2 && mom.month() < 9) { + mom.zone(-60); + } else { + mom.zone(0); + } + }; + + test.ok(!moment().month(0).isDST(), "Jan should not be summer dst"); + test.ok(moment().month(6).isDST(), "Jul should be summer dst"); + test.ok(!moment().month(11).isDST(), "Dec should not be summer dst"); + + moment.updateOffset = function (mom) { + if (mom.month() > 2 && mom.month() < 9) { + mom.zone(0); + } else { + mom.zone(-60); + } + }; + + test.ok(moment().month(0).isDST(), "Jan should be winter dst"); + test.ok(!moment().month(6).isDST(), "Jul should not be winter dst"); + test.ok(moment().month(11).isDST(), "Dec should be winter dst"); + + moment.updateOffset = oldOffset; + + test.done(); + }, + + "zone names" : function (test) { + test.expect(8); + + test.equal(moment().zoneAbbr(), "", "Local zone abbr should be empty"); + test.equal(moment().format('z'), "", "Local zone formatted abbr should be empty"); + test.equal(moment().zoneName(), "", "Local zone name should be empty"); + test.equal(moment().format('zz'), "", "Local zone formatted name should be empty"); + + test.equal(moment.utc().zoneAbbr(), "UTC", "UTC zone abbr should be UTC"); + test.equal(moment.utc().format('z'), "UTC", "UTC zone formatted abbr should be UTC"); + test.equal(moment.utc().zoneName(), "Coordinated Universal Time", "UTC zone abbr should be Coordinated Universal Time"); + test.equal(moment.utc().format('zz'), "Coordinated Universal Time", "UTC zone formatted abbr should be Coordinated Universal Time"); + + test.done(); + } + +}; diff --git a/node_modules/mongoose-pureautoinc/.npmignore b/node_modules/mongoose-pureautoinc/.npmignore new file mode 100644 index 0000000..55efcbe --- /dev/null +++ b/node_modules/mongoose-pureautoinc/.npmignore @@ -0,0 +1,2 @@ +node_modules +pre-commit \ No newline at end of file diff --git a/node_modules/mongoose-pureautoinc/README.md b/node_modules/mongoose-pureautoinc/README.md new file mode 100644 index 0000000..cc1bd90 --- /dev/null +++ b/node_modules/mongoose-pureautoinc/README.md @@ -0,0 +1,73 @@ +mongoose-pureautoinc +==================== + +This plugin let you add an `auto increment` field to your schema. + + +## Requirements + +- [Node.js](http://nodejs.org/), a server-side JavaScript implementation, +- [MongoDB](http://www.mongodb.org), a NoSQL database, +- [Mongoose](http://mongoosejs.com), an elegant Object Document Mapper for MongoDB. + + +## Installation + +Install it from NPM as you always do it with other packages. +~~~ +npm install mongoose-pureautoinc +~~~ + + +## Available options + +- `model` - required parameter, name of your Mongoose model +- `field` - name of your field +- `start` - first value of your field which will be used + + +## How to use + +You can run example using this command: +~~~ +$ node examples/example.js +~~~ + +Firstly, you need to `require` Mongoose and the plugin. +~~~ +var mongoose = require('../node_modules/mongoose'), + Schema = mongoose.Schema, + db = mongoose.createConnection('127.0.0.1', 'yourDatabaseName'), + pureautoinc = require('pureautoinc'); +~~~ + +Secondly, you need to initialize the plugin, define your schema and connect the plugin to it. +~~~ +pureautoinc.init(db); + +var schema = new Schema({ + email: String, + text: String +}); + +schema.plugin(pureautoinc, { + model: 'Subscriber', + field: 'recordNum' +}); +~~~ + +After that you can create your model and use it as you wish. +~~~ +var Subscriber = db.model('Subscriber', schema); +~~~ + + +## For developers +You should use Git pre-hook to validate your changes. Just copy `pre-commit` file into `./git/hooks/` directory. +In order to run tests manually execute `$ vows --spec tests/*` +In order to test performance of the plugin execute `$ node benchmarks/benchmark.js` + + +## Copyright + +© 2012 [MyLove Company, LLC](http://www.mylovecompany.com). Source code is distributed under [CDDL 1.0](http://opensource.org/licenses/CDDL-1.0) open source license. \ No newline at end of file diff --git a/node_modules/mongoose-pureautoinc/benchmarks/benchmark.js b/node_modules/mongoose-pureautoinc/benchmarks/benchmark.js new file mode 100644 index 0000000..5de1c31 --- /dev/null +++ b/node_modules/mongoose-pureautoinc/benchmarks/benchmark.js @@ -0,0 +1,86 @@ +/** + * @author Dmitry Ilin @ MyLove Company, LLC + */ + +var mongoose = require('../node_modules/mongoose'), + Schema = mongoose.Schema, + db = mongoose.createConnection('127.0.0.1', 'pureautoinc_benchmark'), + pureautoinc = require('../index'); + +pureautoinc.init(db); + + +var schema = new Schema({ + email: String, + text: String +}); + +schema.plugin(pureautoinc.plugin, { + model: 'Subscriber', + field: 'subscriberId' +}); +var Subscriber = db.model('Subscriber', schema); + +var time, + i = 0, + j = 0, + tests = 5, + iterations = 10000, + results = []; + +console.log('\nIterations per test: ' + iterations + '\n'); + + +function testsCompleted () { + + mongoose.disconnect(); + + var sum = 0; + for (var k = 0; k < results.length; k++) + sum += results[k]; + + console.log('Average time: ' + (sum / tests).toFixed(0) + ' ms\n'); +} + +function subscriberSaved (err, res) { + + i++; + if (i < iterations) { + addSubscriber(); + } else { + results.push(new Date().getTime() - time); + + console.log((j + 1) + '. Time: ' + results[results.length - 1] + ' ms'); + + j++; + if (j < tests) + runTest(); + else + Subscriber.collection.drop(testsCompleted); + } +} + +function addSubscriber () { + + var subscriber = new Subscriber({ + email: 'email@mail.ru', + text: 'text' + }); + + subscriber.save(subscriberSaved); +} + +function dataRemoved () { + + time = new Date().getTime(); + i = 0; + addSubscriber(); +} + +function runTest () { + + // Removing all subscribers before next test + Subscriber.remove({}, dataRemoved); +} + +runTest(); \ No newline at end of file diff --git a/node_modules/mongoose-pureautoinc/examples/example.js b/node_modules/mongoose-pureautoinc/examples/example.js new file mode 100644 index 0000000..fa85fe5 --- /dev/null +++ b/node_modules/mongoose-pureautoinc/examples/example.js @@ -0,0 +1,40 @@ +/** + * @author Dmitry Ilin @ MyLove Company, LLC + */ + +var dbName = 'pureautoinc_example', + mongoose = require('../node_modules/mongoose'), + Schema = mongoose.Schema, + db = mongoose.createConnection('127.0.0.1', dbName), + pureautoinc = require('../index'); + +pureautoinc.init(db); + + +var schema = new Schema({ + name: String, + address: String +}); + +schema.plugin(pureautoinc.plugin, { + model: 'Person', + field: 'filingNumber', + start: 100 +}); + +var Person = db.model('Person', schema); + +console.log('Database: ' + dbName); +console.log('Collection: ' + Person.collection.name); + +var person = new Person({ + name: 'Sherlock Holmes', + address: '221b Baker St, Marylebone, London W1' +}); + +person.save(function (err, res) { + + console.log('New record added:'); + console.log(res); + mongoose.disconnect(); +}); \ No newline at end of file diff --git a/node_modules/mongoose-pureautoinc/index.js b/node_modules/mongoose-pureautoinc/index.js new file mode 100644 index 0000000..b28f31b --- /dev/null +++ b/node_modules/mongoose-pureautoinc/index.js @@ -0,0 +1,5 @@ +/** + * @author Dmitry Ilin @ MyLove Company, LLC + */ + +module.exports = require('./lib/pureautoinc.js'); \ No newline at end of file diff --git a/node_modules/mongoose-pureautoinc/lib/pureautoinc.js b/node_modules/mongoose-pureautoinc/lib/pureautoinc.js new file mode 100644 index 0000000..2d567bf --- /dev/null +++ b/node_modules/mongoose-pureautoinc/lib/pureautoinc.js @@ -0,0 +1,105 @@ +/** + * @author Dmitry Ilin @ MyLove Company, LLC + */ + +module.exports = new (function () { + + var db, + Counter, + mongoose, + counterName; + + this.plugin = function(schema, options) { + + if (!options.model) + throw new Error('Missing required parameter: model'); + + options.model = options.model.toLowerCase(); + options.field = options.field || 'sequenceNumber'; + options.start = (!isNaN(options.start)) ? options.start : 0; + + var fields = {}, + ready = false; + + // Adding new field into schema + fields[options.field] = { + type: Number, + unique: true, + require: true + }; + schema.add(fields); + + // Initializing of plugin + Counter.findOne({ + model: options.model, + field: options.field + }, function (err, res) { + if (!res) + (new Counter({ + model: options.model, + field: options.field, + c: options.start + })).save(function () { + ready = true; + }); + else + ready = true; + }); + + schema.pre('save', function (next) { + + var doc = this; + + // Delay before plugin will be sucessfully initialized + function save () { + + if (ready) + Counter.collection.findAndModify({ + model: options.model, + field: options.field + }, [], { + $inc: { + c: 1 + } + }, { + 'new': true, + upsert: true + }, function (err, res) { + + if (!err) + doc[options.field] = res.c - 1; + next(err); + }); + else + setTimeout(save, 5); + } + save(); + }); + }; + + this.init = function (database, counter) { + + db = database; + mongoose = require('mongoose'); + counterName = counter || 'counter'; + + var schema = new mongoose.Schema({ + model: { + type: String, + require: true + }, + field: { + type: String, + require: true + }, + c: { + type: Number, + 'default': 0 + } + }); + schema.index({ field: 1, model: 1 }, { unique: true, required: true, index: -1 }); + + Counter = db.model(counterName, schema); + }; + +})(); \ No newline at end of file diff --git a/node_modules/mongoose-pureautoinc/package.json b/node_modules/mongoose-pureautoinc/package.json new file mode 100644 index 0000000..a0e694f --- /dev/null +++ b/node_modules/mongoose-pureautoinc/package.json @@ -0,0 +1,37 @@ +{ + "name": "mongoose-pureautoinc", + "description": "Creating of auto increment fields", + "version": "2012.1.0", + "author": { + "name": "MyLove Company, LLC" + }, + "dependencies": {}, + "devDependencies": { + "mongoose": ">=3.0.0", + "vows": "0.5.13" + }, + "keywords": [ + "mongoose", + "mongo", + "mongodb", + "auto-increment", + "increment", + "field" + ], + "engines": { + "node": ">=0.8.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/mylovecompany/mongoose-pureautoinc.git" + }, + "main": "./index.js", + "readme": "mongoose-pureautoinc\n====================\n\nThis plugin let you add an `auto increment` field to your schema.\n\n\n## Requirements\n\n- [Node.js](http://nodejs.org/), a server-side JavaScript implementation,\n- [MongoDB](http://www.mongodb.org), a NoSQL database,\n- [Mongoose](http://mongoosejs.com), an elegant Object Document Mapper for MongoDB.\n\n\n## Installation\n\nInstall it from NPM as you always do it with other packages.\n~~~\nnpm install mongoose-pureautoinc\n~~~\n\n\n## Available options\n\n- `model` - required parameter, name of your Mongoose model\n- `field` - name of your field\n- `start` - first value of your field which will be used\n\n\n## How to use\n\nYou can run example using this command:\n~~~\n$ node examples/example.js\n~~~\n\nFirstly, you need to `require` Mongoose and the plugin.\n~~~\nvar mongoose = require('../node_modules/mongoose'),\n Schema = mongoose.Schema,\n db = mongoose.createConnection('127.0.0.1', 'yourDatabaseName'),\n pureautoinc = require('pureautoinc');\n~~~\n\nSecondly, you need to initialize the plugin, define your schema and connect the plugin to it.\n~~~\npureautoinc.init(db);\n\nvar schema = new Schema({\n email: String,\n text: String\n});\n\nschema.plugin(pureautoinc, {\n model: 'Subscriber',\n field: 'recordNum'\n});\n~~~\n\nAfter that you can create your model and use it as you wish.\n~~~\nvar Subscriber = db.model('Subscriber', schema);\n~~~\n\n\n## For developers\nYou should use Git pre-hook to validate your changes. Just copy `pre-commit` file into `./git/hooks/` directory. \nIn order to run tests manually execute `$ vows --spec tests/*` \nIn order to test performance of the plugin execute `$ node benchmarks/benchmark.js`\n\n\n## Copyright\n\n© 2012 [MyLove Company, LLC](http://www.mylovecompany.com). Source code is distributed under [CDDL 1.0](http://opensource.org/licenses/CDDL-1.0) open source license.", + "readmeFilename": "README.md", + "_id": "mongoose-pureautoinc@2012.1.0", + "dist": { + "shasum": "97c7346dcbfbe08f4b27efe688ad75cdbf65d850" + }, + "_from": "mongoose-pureautoinc@", + "_resolved": "https://registry.npmjs.org/mongoose-pureautoinc/-/mongoose-pureautoinc-2012.1.0.tgz" +} diff --git a/node_modules/mongoose-pureautoinc/tests/test.js b/node_modules/mongoose-pureautoinc/tests/test.js new file mode 100644 index 0000000..581ceb4 --- /dev/null +++ b/node_modules/mongoose-pureautoinc/tests/test.js @@ -0,0 +1,138 @@ +/** + * @author Dmitry Ilin @ MyLove Company, LLC + */ + +var vows = require('vows'), + assert = require('assert'), + events = require('events'), + mongoose = require('../node_modules/mongoose'), + pureautoinc = require('../index'), + Schema = mongoose.Schema, + db = mongoose.createConnection('127.0.0.1', 'pureautoinc_test'); + +pureautoinc.init(db); + + +var suite = vows.describe('Testing Schema creation and auto incrementing'); + +suite.addBatch({ + + 'After schema creation and plugin application': { + + topic: function () { + + var schema = new Schema({ + email: String, + text: String + }); + + var pluginParameters = { + model: 'Subscriber', + field: 'sequenceNumber' + }; + + schema.plugin(pureautoinc.plugin, pluginParameters); + + var Subscriber = db.model('Subscriber', schema); + + var Test = { + model: db.model('Subscriber'), + pluginParameters: pluginParameters + }; + + return Test; + }, + + 'schema gained auto increment field': function (topic) { + + assert.ok(topic.model.schema.paths[topic.pluginParameters.field]); + }, + + 'and model created': { + + topic: function (Model) { + + var promise = new (events.EventEmitter); + + var subscriber; + var count = 5; + + function save (counter) { + + subscriber = new Model.model({ + email: 'useremail@emailserver.com', + text: 'some text' + }); + + subscriber.save(function (err, res) { + + if (err) + promise.emit('error', err, Model); + else if (counter < count) + save(++counter); + else + promise.emit('success', res, Model); + }); + } + save(1); + + return promise; + }, + + 'data saved successfully': function (err, res, Model) { + + assert.ok(res); + }, + + 'and if we look at indexes': { + + topic: function (promise, Model) { + + var promise = new (events.EventEmitter); + + Model.model.collection.getIndexes(function (err, res) { + if (err) + promise.emit('error', err, Model); + else + promise.emit('success', res, Model); + }); + + return promise; + }, + + 'index created successfully': function (err, res, Model) { + + assert.ok(res[Model.pluginParameters.field + '_1']); + }, + + 'and after documents created': { + + topic: function (promise, Model) { + + var promise = new (events.EventEmitter); + + Model.model.find({}, function (err, res) { + + Model.model.collection.drop(function (err) { }); + + var counter = Model.pluginParameters.start; + for (var i = 0; i < res.length; i++) { + if (res[i][Model.pluginParameters.field] != counter) + promise.emit('error', err, Model); + counter++; + } + promise.emit('success', res, Model); + }); + + return promise; + }, + + 'data contains right sequence numbers': function (err, res, Model) { + + assert.ok(res); + } + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/mongoose/.npmignore b/node_modules/mongoose/.npmignore new file mode 100644 index 0000000..df5ea94 --- /dev/null +++ b/node_modules/mongoose/.npmignore @@ -0,0 +1,13 @@ +lib-cov +**.swp +*.sw* +*.orig +.DS_Store +node_modules/ +benchmarks/ +docs/ +test/ +Makefile +CNAME +index.html +index.jade diff --git a/node_modules/mongoose/.travis.yml b/node_modules/mongoose/.travis.yml new file mode 100644 index 0000000..ab51641 --- /dev/null +++ b/node_modules/mongoose/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.10 +services: + - mongodb diff --git a/node_modules/mongoose/CONTRIBUTING.md b/node_modules/mongoose/CONTRIBUTING.md new file mode 100644 index 0000000..daddb4a --- /dev/null +++ b/node_modules/mongoose/CONTRIBUTING.md @@ -0,0 +1,60 @@ +## Contributing to Mongoose + +### STOP! + +If you have a question about Mongoose (not a bug report) please post it to either [StackOverflow](http://stackoverflow.com/questions/tagged/mongoose), our [Google Group](http://groups.google.com/group/mongoose-orm), or on the #mongoosejs irc channel on freenode. + +### Reporting bugs + +- Before opening a new issue, look for existing [issues](https://github.com/learnboost/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/learnboost/mongoose/issues/new). + - Please describe the issue you are experiencing, along with any associated stack trace. + - Please post code that reproduces the issue, the version of mongoose, node version, and mongodb version. + - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. + - In general, adding a "+1" comment to an existing issue does little to help get it resolved. A better way is to submit a well documented pull request with clean code and passing tests. + +### Requesting new features + +- Before opening a new issue, look for existing [issues](https://github.com/learnboost/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/learnboost/mongoose/issues/new). +- Please describe a use case for it +- it would be ideal to include test cases as well +- In general, adding a "+1" comment to an existing issue does little to help get it resolved. A better way is to submit a well documented pull request with clean code and passing tests. + +### Fixing bugs / Adding features + +- Before starting to write code, look for existing [issues](https://github.com/learnboost/mongoose/issues). That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. You can create a new issue [here](https://github.com/learnboost/mongoose/issues/new). + - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. +- Fork the [repo](https://github.com/learnboost/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. +- Follow the general coding style of the rest of the project: + - 2 space tabs + - no trailing whitespace + - comma first + - inline documentation for new methods, class members, etc + - 1 space between conditionals/functions, and their parenthesis and curly braces + - `if (..) {` + - `for (..) {` + - `while (..) {` + - `function (err) {` +- Write tests and make sure they pass (tests are in the [test](https://github.com/LearnBoost/mongoose/tree/master/test) directory). + +### Running the tests +- Open a terminal and navigate to the root of the project +- execute `npm install` to install the necessary dependencies +- execute `make test` to run the tests (we're using [mocha](http://visionmedia.github.com/mocha/)) + - or to execute a single test `T="-g 'some regexp that matches the test description'" make test` + - any mocha flags can be specified with T="..." + +### Documentation + +To contribute to the [API documentation](http://mongoosejs.com/docs/api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/LearnBoost/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + +To contribute to the [guide](http://mongoosejs.com/docs/guide.html) or [quick start](http://mongoosejs.com/docs/index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/LearnBoost/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. + +If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make docs` from the project root, which switches to the gh-pages branch, merges from master, and builds all the static pages for you. Now execute `node server.js` from the project root which will launch a local webserver where you can browse the documentation site locally. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes. + +### Plugins website + +The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! + +### Sharing your projects + +All are welcome to share their creations which use mongoose on our [tumbler](http://mongoosejs.tumblr.com/). Just fill out the [simple submission form](http://mongoosejs.tumblr.com/submit). diff --git a/node_modules/mongoose/History.md b/node_modules/mongoose/History.md new file mode 100644 index 0000000..2e3b58c --- /dev/null +++ b/node_modules/mongoose/History.md @@ -0,0 +1,1673 @@ + +3.6.15 / 2013-07-16 +================== + + * added; mongos failover support #1037 + * updated; make schematype return vals return self #1580 + * docs; add note to model.update #571 + * docs; document third param to document.save callback #1536 + * tests; tweek mongos test timeout + +3.6.14 / 2013-07-05 +=================== + + * updated; driver to 1.3.11 + * fixed; issue with findOneAndUpdate not returning null on upserts #1533 [ebensing](https://github.com/ebensing) + * fixed; missing return statement in SchemaArray#$geoIntersects() #1498 [bsrykt](https://github.com/bsrykt) + * fixed; wrong isSelected() behavior #1521 [kyano](https://github.com/kyano) + * docs; note about toObject behavior during save() + * docs; add callbacks details #1547 [nikmartin](https://github.com/nikmartin) + +3.6.13 / 2013-06-27 +=================== + + * fixed; calling model.distinct without conditions #1541 + * fixed; regression in Query#count() #1542 + * now working on 3.6.13 + +3.6.12 / 2013-06-25 +=================== + + * updated; driver to 1.3.10 + * updated; clearer capped collection error message #1509 [bitmage](https://github.com/bitmage) + * fixed; MongooseBuffer subtype loss during casting #1517 [zedgu](https://github.com/zedgu) + * fixed; docArray#id when doc.id is disabled #1492 + * fixed; docArray#id now supports matches on populated arrays #1492 [pgherveou](https://github.com/pgherveou) + * website; fix example + * website; improve _id disabling example + * website; fix typo #1494 [dejj](https://github.com/dejj) + * docs; added a 'Requesting new features' section #1504 [shovon](https://github.com/shovon) + * docs; improve subtypes description + * docs; clarify _id disabling + * docs: display by alphabetical order the methods list #1508 [nicolasleger](https://github.com/nicolasleger) + * tests; refactor isSelected checks + * tests; remove pointless test + * tests; fixed timeouts + +3.6.11 / 2013-05-15 +=================== + + * updated; driver to 1.3.5 + * fixed; compat w/ Object.create(null) #1484 #1485 + * fixed; cloning objects w/ missing constructors + * fixed; prevent multiple min number validators #1481 [nrako](https://github.com/nrako) + * docs; add doc.increment() example + * docs; add $size example + * docs; add "distinct" example + +3.6.10 / 2013-05-09 +================== + + * update driver to 1.3.3 + * fixed; increment() works without other changes #1475 + * website; fix links to posterous + * docs; fix link #1472 + +3.6.9 / 2013-05-02 +================== + + * fixed; depopulation of mixed documents #1471 + * fixed; use of $options in array #1462 + * tests; fix race condition + * docs; fix default example + +3.6.8 / 2013-04-25 +================== + + * updated; driver to 1.3.0 + * fixed; connection.model should retain options #1458 [vedmalex](https://github.com/vedmalex) + * tests; 4-5 seconds faster + +3.6.7 / 2013-04-19 +================== + + * fixed; population regression in 3.6.6 #1444 + +3.6.6 / 2013-04-18 +================== + + * fixed; saving populated new documents #1442 + * fixed; population regession in 3.6.5 #1441 + * website; fix copyright #1439 + +3.6.5 / 2013-04-15 +================== + + * fixed; strict:throw edge case using .set(path, val) + * fixed; schema.pathType() on some numbericAlpha paths + * fixed; numbericAlpha path versioning + * fixed; setting nested mixed paths #1418 + * fixed; setting nested objects with null prop #1326 + * fixed; regression in v3.6 population performance #1426 [vedmalex](https://github.com/vedmalex) + * fixed; read pref typos #1422 [kyano](https://github.com/kyano) + * docs; fix method example + * website; update faq + * website; add more deep links + * website; update poolSize docs + * website; add 3.6 release notes + * website; note about keepAlive + +3.6.4 / 2013-04-03 +================== + + * fixed; +field conflict with $slice #1370 + * fixed; nested deselection conflict #1333 + * fixed; RangeError in ValidationError.toString() #1296 + * fixed; do not save user defined transforms #1415 + * tests; fix race condition + +3.6.3 / 2013-04-02 +================== + + * fixed; setting subdocuments deeply nested fields #1394 + * fixed; regression: populated streams #1411 + * docs; mention hooks/validation with findAndModify + * docs; mention auth + * docs; add more links + * examples; add document methods example + * website; display "see" links for properties + * website; clean up homepage + +3.6.2 / 2013-03-29 +================== + + * fixed; corrupted sub-doc array #1408 + * fixed; document#update returns a Query #1397 + * docs; readpref strategy + +3.6.1 / 2013-03-27 +================== + + * added; populate support to findAndModify varients #1395 + * added; text index type to schematypes + * expose allowed index types as Schema.indexTypes + * fixed; use of `setMaxListeners` as path + * fixed; regression in node 0.6 on docs with > 10 arrays + * fixed; do not alter schema arguments #1364 + * fixed; subdoc#ownerDocument() #1385 + * website; change search id + * website; add search from google [jackdbernier](https://github.com/jackdbernier) + * website; fix link + * website; add 3.5.x docs release + * website; fix link + * docs; fix geometry + * docs; hide internal constructor + * docs; aggregation does not cast arguments #1399 + * docs; querystream options + * examples; added for population + +3.6.0 / 2013-03-18 +================== + + * changed; cast 'true'/'false' to boolean #1282 [mgrach](https://github.com/mgrach) + * changed; Buffer arrays can now contain nulls + * added; QueryStream transform option + * added; support for authSource driver option + * added; {mongoose,db}.modelNames() + * added; $push w/ $slice,$sort support (MongoDB 2.4) + * added; hashed index type (MongoDB 2.4) + * added; support for mongodb 2.4 geojson (MongoDB 2.4) + * added; value at time of validation error + * added; support for object literal schemas + * added; bufferCommands schema option + * added; allow auth option in connections #1360 [geoah](https://github.com/geoah) + * added; performance improvements to populate() [263ece9](https://github.com/LearnBoost/mongoose/commit/263ece9) + * added; allow adding uncasted docs to populated arrays and properties #570 + * added; doc#populated(path) stores original populated _ids + * added; lean population #1260 + * added; query.populate() now accepts an options object + * added; document#populate(opts, callback) + * added; Model.populate(docs, opts, callback) + * added; support for rich nested path population + * added; doc.array.remove(value) subdoc with _id value support #1278 + * added; optionally allow non-strict sets and updates + * added; promises/A+ comformancy with [mpromise](https://github.com/aheckmann/mpromise) + * added; promise#then + * added; promise#end + * fixed; use of `model` as doc property + * fixed; lean population #1382 + * fixed; empty object mixed defaults #1380 + * fixed; populate w/ deselected _id using string syntax + * fixed; attempted save of divergent populated arrays #1334 related + * fixed; better error msg when attempting toObject as property name + * fixed; non population buffer casting from doc + * fixed; setting populated paths #570 + * fixed; casting when added docs to populated arrays #570 + * fixed; prohibit updating arrays selected with $elemMatch #1334 + * fixed; pull / set subdoc combination #1303 + * fixed; multiple bg index creation #1365 + * fixed; manual reconnection to single mongod + * fixed; Constructor / version exposure #1124 + * fixed; CastError race condition + * fixed; no longer swallowing misuse of subdoc#invalidate() + * fixed; utils.clone retains RegExp opts + * fixed; population of non-schema property + * fixed; allow updating versionKey #1265 + * fixed; add EventEmitter props to reserved paths #1338 + * fixed; can now deselect populated doc _ids #1331 + * fixed; properly pass subtype to Binary in MongooseBuffer + * fixed; casting _id from document with non-ObjectId _id + * fixed; specifying schema type edge case { path: [{type: "String" }] } + * fixed; typo in schemdate #1329 [jplock](https://github.com/jplock) + * updated; driver to 1.2.14 + * updated; muri to 0.3.1 + * updated; mpromise to 0.2.1 + * updated; mocha 1.8.1 + * updated; mpath to 0.1.1 + * deprecated; pluralization will die in 4.x + * refactor; rename private methods to something unusable as doc properties + * refactor MongooseArray#remove + * refactor; move expires index to SchemaDate #1328 + * refactor; internal document properties #1171 #1184 + * tests; added + * docs; indexes + * docs; validation + * docs; populate + * docs; populate + * docs; add note about stream compatibility with node 0.8 + * docs; fix for private names + * docs; Buffer -> mongodb.Binary #1363 + * docs; auth options + * docs; improved + * website; update FAQ + * website; add more api links + * website; add 3.5.x docs to prior releases + * website; Change mongoose-types to an active repo [jackdbernier](https://github.com/jackdbernier) + * website; compat with node 0.10 + * website; add news section + * website; use T for generic type + * benchmark; make adjustable + +3.6.0rc1 / 2013-03-12 +====================== + + * refactor; rename private methods to something unusable as doc properties + * added; {mongoose,db}.modelNames() + * added; $push w/ $slice,$sort support (MongoDB 2.4) + * added; hashed index type (MongoDB 2.4) + * added; support for mongodb 2.4 geojson (MongoDB 2.4) + * added; value at time of validation error + * added; support for object literal schemas + * added; bufferCommands schema option + * added; allow auth option in connections #1360 [geoah](https://github.com/geoah) + * fixed; lean population #1382 + * fixed; empty object mixed defaults #1380 + * fixed; populate w/ deselected _id using string syntax + * fixed; attempted save of divergent populated arrays #1334 related + * fixed; better error msg when attempting toObject as property name + * fixed; non population buffer casting from doc + * fixed; setting populated paths #570 + * fixed; casting when added docs to populated arrays #570 + * fixed; prohibit updating arrays selected with $elemMatch #1334 + * fixed; pull / set subdoc combination #1303 + * fixed; multiple bg index creation #1365 + * fixed; manual reconnection to single mongod + * fixed; Constructor / version exposure #1124 + * fixed; CastError race condition + * fixed; no longer swallowing misuse of subdoc#invalidate() + * fixed; utils.clone retains RegExp opts + * fixed; population of non-schema property + * fixed; allow updating versionKey #1265 + * fixed; add EventEmitter props to reserved paths #1338 + * fixed; can now deselect populated doc _ids #1331 + * updated; muri to 0.3.1 + * updated; driver to 1.2.12 + * updated; mpromise to 0.2.1 + * deprecated; pluralization will die in 4.x + * docs; Buffer -> mongodb.Binary #1363 + * docs; auth options + * docs; improved + * website; add news section + * benchmark; make adjustable + +3.6.0rc0 / 2013-02-03 +====================== + + * changed; cast 'true'/'false' to boolean #1282 [mgrach](https://github.com/mgrach) + * changed; Buffer arrays can now contain nulls + * fixed; properly pass subtype to Binary in MongooseBuffer + * fixed; casting _id from document with non-ObjectId _id + * fixed; specifying schema type edge case { path: [{type: "String" }] } + * fixed; typo in schemdate #1329 [jplock](https://github.com/jplock) + * refactor; move expires index to SchemaDate #1328 + * refactor; internal document properties #1171 #1184 + * added; performance improvements to populate() [263ece9](https://github.com/LearnBoost/mongoose/commit/263ece9) + * added; allow adding uncasted docs to populated arrays and properties #570 + * added; doc#populated(path) stores original populated _ids + * added; lean population #1260 + * added; query.populate() now accepts an options object + * added; document#populate(opts, callback) + * added; Model.populate(docs, opts, callback) + * added; support for rich nested path population + * added; doc.array.remove(value) subdoc with _id value support #1278 + * added; optionally allow non-strict sets and updates + * added; promises/A+ comformancy with [mpromise](https://github.com/aheckmann/mpromise) + * added; promise#then + * added; promise#end + * updated; mocha 1.8.1 + * updated; muri to 0.3.0 + * updated; mpath to 0.1.1 + * updated; docs + +3.5.14 / 2013-05-15 +=================== + + * updated; driver to 1.3.5 + * fixed; compat w/ Object.create(null) #1484 #1485 + * fixed; cloning objects missing constructors + * fixed; prevent multiple min number validators #1481 [nrako](https://github.com/nrako) + +3.5.13 / 2013-05-09 +================== + + * update driver to 1.3.3 + * fixed; use of $options in array #1462 + +3.5.12 / 2013-04-25 +=================== + + * updated; driver to 1.3.0 + * fixed; connection.model should retain options #1458 [vedmalex](https://github.com/vedmalex) + * fixed; read pref typos #1422 [kyano](https://github.com/kyano) + +3.5.11 / 2013-04-03 +================== + + * fixed; +field conflict with $slice #1370 + * fixed; RangeError in ValidationError.toString() #1296 + * fixed; nested deselection conflict #1333 + * remove time from Makefile + +3.5.10 / 2013-04-02 +================== + + * fixed; setting subdocuments deeply nested fields #1394 + * fixed; do not alter schema arguments #1364 + +3.5.9 / 2013-03-15 +================== + + * updated; driver to 1.2.14 + * added; support for authSource driver option (mongodb 2.4) + * added; QueryStream transform option (node 0.10 helper) + * fixed; backport for saving required populated buffers + * fixed; pull / set subdoc combination #1303 + * fixed; multiple bg index creation #1365 + * test; added for saveable required populated buffers + * test; added for #1365 + * test; add authSource test + +3.5.8 / 2013-03-12 +================== + + * added; auth option in connection [geoah](https://github.com/geoah) + * fixed; CastError race condition + * docs; add note about stream compatibility with node 0.8 + +3.5.7 / 2013-02-22 +================== + + * updated; driver to 1.2.13 + * updated; muri to 0.3.1 #1347 + * fixed; utils.clone retains RegExp opts #1355 + * fixed; deepEquals RegExp support + * tests; fix a connection test + * website; clean up docs [afshinm](https://github.com/afshinm) + * website; update homepage + * website; migragtion: emphasize impact of strict docs #1264 + +3.5.6 / 2013-02-14 +================== + + * updated; driver to 1.2.12 + * fixed; properly pass Binary subtype + * fixed; add EventEmitter props to reserved paths #1338 + * fixed; use correct node engine version + * fixed; display empty docs as {} in log output #953 follow up + * improved; "bad $within $box argument" error message + * populate; add unscientific benchmark + * website; add stack overflow to help section + * website; use better code font #1336 [risseraka](https://github.com/risseraka) + * website; clarify where help is available + * website; fix source code links #1272 [floatingLomas](https://github.com/floatingLomas) + * docs; be specific about _id schema option #1103 + * docs; add ensureIndex error handling example + * docs; README + * docs; CONTRIBUTING.md + +3.5.5 / 2013-01-29 +================== + + * updated; driver to 1.2.11 + * removed; old node < 0.6x shims + * fixed; documents with Buffer _ids equality + * fixed; MongooseBuffer properly casts numbers + * fixed; reopening closed connection on alt host/port #1287 + * docs; fixed typo in Readme #1298 [rened](https://github.com/rened) + * docs; fixed typo in migration docs [Prinzhorn](https://github.com/Prinzhorn) + * docs; fixed incorrect annotation in SchemaNumber#min [bilalq](https://github.com/bilalq) + * docs; updated + +3.5.4 / 2013-01-07 +================== + + * changed; "_pres" & "_posts" are now reserved pathnames #1261 + * updated; driver to 1.2.8 + * fixed; exception when reopening a replica set. #1263 [ethankan](https://github.com/ethankan) + * website; updated + +3.5.3 / 2012-12-26 +================== + + * added; support for geo object notation #1257 + * fixed; $within query casting with arrays + * fixed; unix domain socket support #1254 + * updated; driver to 1.2.7 + * updated; muri to 0.0.5 + +3.5.2 / 2012-12-17 +================== + + * fixed; using auth with replica sets #1253 + +3.5.1 / 2012-12-12 +================== + + * fixed; regression when using subdoc with `path` as pathname #1245 [daeq](https://github.com/daeq) + * fixed; safer db option checks + * updated; driver to 1.2.5 + * website; add more examples + * website; clean up old docs + * website; fix prev release urls + * docs; clarify streaming with HTTP responses + +3.5.0 / 2012-12-10 +================== + + * added; paths to CastErrors #1239 + * added; support for mongodb connection string spec #1187 + * added; post validate event + * added; Schema#get (to retrieve schema options) + * added; VersionError #1071 + * added; npmignore [hidekiy](https://github.com/hidekiy) + * update; driver to 1.2.3 + * fixed; stackoverflow in setter #1234 + * fixed; utils.isObject() + * fixed; do not clobber user specified driver writeConcern #1227 + * fixed; always pass current document to post hooks + * fixed; throw error when user attempts to overwrite a model + * fixed; connection.model only caches on connection #1209 + * fixed; respect conn.model() creation when matching global model exists #1209 + * fixed; passing model name + collection name now always honors collection name + * fixed; setting virtual field to an empty object #1154 + * fixed; subclassed MongooseErrors exposure, now available in mongoose.Error.xxxx + * fixed; model.remove() ignoring callback when executed twice [daeq](https://github.com/daeq) #1210 + * docs; add collection option to schema api docs #1222 + * docs; NOTE about db safe options + * docs; add post hooks docs + * docs; connection string options + * docs; middleware is not executed with Model.remove #1241 + * docs; {g,s}etter introspection #777 + * docs; update validation docs + * docs; add link to plugins page + * docs; clarify error returned by unique indexes #1225 + * docs; more detail about disabling autoIndex behavior + * docs; add homepage section to package (npm docs mongoose) + * docs; more detail around collection name pluralization #1193 + * website; add .important css + * website; update models page + * website; update getting started + * website; update quick start + +3.4.0 / 2012-11-10 +================== + + * added; support for generic toJSON/toObject transforms #1160 #1020 #1197 + * added; doc.set() merge support #1148 [NuORDER](https://github.com/NuORDER) + * added; query#add support #1188 [aleclofabbro](https://github.com/aleclofabbro) + * changed; adding invalid nested paths to non-objects throws 4216f14 + * changed; fixed; stop invalid function cloning (internal fix) + * fixed; add query $and casting support #1180 [anotheri](https://github.com/anotheri) + * fixed; overwriting of query arguments #1176 + * docs; fix expires examples + * docs; transforms + * docs; schema `collection` option docs [hermanjunge](https://github.com/hermanjunge) + * website; updated + * tests; added + +3.3.1 / 2012-10-11 +================== + + * fixed; allow goose.connect(uris, dbname, opts) #1144 + * docs; persist API private checked state across page loads + +3.3.0 / 2012-10-10 +================== + + * fixed; passing options as 2nd arg to connect() #1144 + * fixed; race condition after no-op save #1139 + * fixed; schema field selection application in findAndModify #1150 + * fixed; directly setting arrays #1126 + * updated; driver to 1.1.11 + * updated; collection pluralization rules [mrickard](https://github.com/mrickard) + * tests; added + * docs; updated + +3.2.2 / 2012-10-08 +================== + + * updated; driver to 1.1.10 #1143 + * updated; use sliced 0.0.3 + * fixed; do not recast embedded docs unnecessarily + * fixed; expires schema option helper #1132 + * fixed; built in string setters #1131 + * fixed; debug output for Dates/ObjectId properties #1129 + * docs; fixed Javascript syntax error in example [olalonde](https://github.com/olalonde) + * docs; fix toJSON example #1137 + * docs; add ensureIndex production notes + * docs; fix spelling + * docs; add blogposts about v3 + * website; updated + * removed; undocumented inGroupsOf util + * tests; added + +3.2.1 / 2012-09-28 +================== + + * fixed; remove query batchSize option default of 1000 https://github.com/learnboost/mongoose/commit/3edaa8651 + * docs; updated + * website; updated + +3.2.0 / 2012-09-27 +================== + + * added; direct array index assignment with casting support `doc.array.set(index, value)` + * fixed; QueryStream#resume within same tick as pause() #1116 + * fixed; default value validatation #1109 + * fixed; array splice() not casting #1123 + * fixed; default array construction edge case #1108 + * fixed; query casting for inequalities in arrays #1101 [dpatti](https://github.com/dpatti) + * tests; added + * website; more documentation + * website; fixed layout issue #1111 [SlashmanX](https://github.com/SlashmanX) + * website; refactored [guille](https://github.com/guille) + +3.1.2 / 2012-09-10 +================== + + * added; ReadPreferrence schema option #1097 + * updated; driver to 1.1.7 + * updated; default query batchSize to 1000 + * fixed; we now cast the mapReduce query option #1095 + * fixed; $elemMatch+$in with field selection #1091 + * fixed; properly cast $elemMatch+$in conditions #1100 + * fixed; default field application of subdocs #1027 + * fixed; querystream prematurely dying #1092 + * fixed; querystream never resumes when paused at getMore boundries #1092 + * fixed; querystream occasionally emits data events after destroy #1092 + * fixed; remove unnecessary ObjectId creation in querystream + * fixed; allow ne(boolean) again #1093 + * docs; add populate/field selection syntax notes + * docs; add toObject/toJSON options detail + * docs; `read` schema option + +3.1.1 / 2012-08-31 +================== + + * updated; driver to 1.1.6 + +3.1.0 / 2012-08-29 +================== + + * changed; fixed; directly setting nested objects now overwrites entire object (previously incorrectly merged them) + * added; read pref support (mongodb 2.2) 205a709c + * added; aggregate support (mongodb 2.2) f3a5bd3d + * added; virtual {g,s}etter introspection (#1070) + * updated; docs [brettz9](https://github.com/brettz9) + * updated; driver to 1.1.5 + * fixed; retain virtual setter return values (#1069) + +3.0.3 / 2012-08-23 +================== + + * fixed; use of nested paths beginning w/ numbers #1062 + * fixed; query population edge case #1053 #1055 [jfremy](https://github.com/jfremy) + * fixed; simultaneous top and sub level array modifications #1073 + * added; id and _id schema option aliases + tests + * improve debug formatting to allow copy/paste logged queries into mongo shell [eknkc](https://github.com/eknkc) + * docs + +3.0.2 / 2012-08-17 +================== + + * added; missing support for v3 sort/select syntax to findAndModify helpers (#1058) + * fixed; replset fullsetup event emission + * fixed; reconnected event for replsets + * fixed; server reconnection setting discovery + * fixed; compat with non-schema path props using positional notation (#1048) + * fixed; setter/casting order (#665) + * docs; updated + +3.0.1 / 2012-08-11 +================== + + * fixed; throw Error on bad validators (1044) + * fixed; typo in EmbeddedDocument#parentArray [lackac] + * fixed; repair mongoose.SchemaTypes alias + * updated; docs + +3.0.0 / 2012-08-07 +================== + + * removed; old subdocument#commit method + * fixed; setting arrays of matching docs [6924cbc2] + * fixed; doc!remove event now emits in save order as save for consistency + * fixed; pre-save hooks no longer fire on subdocuments when validation fails + * added; subdoc#parent() and subdoc#parentArray() to access subdocument parent objects + * added; query#lean() helper + +3.0.0rc0 / 2012-08-01 +===================== + + * fixed; allow subdoc literal declarations containing "type" pathname (#993) + * fixed; unsetting a default array (#758) + * fixed; boolean $in queries (#998) + * fixed; allow use of `options` as a pathname (#529) + * fixed; `model` is again a permitted schema path name + * fixed; field selection option on subdocs (#1022) + * fixed; handle another edge case with subdoc saving (#975) + * added; emit save err on model if listening + * added; MongoDB TTL collection support (#1006) + * added; $center options support + * added; $nearSphere and $polygon support + * updated; driver version to 1.1.2 + +3.0.0alpha2 / 2012-07-18 +========================= + + * changed; index errors are now emitted on their model and passed to an optional callback (#984) + * fixed; specifying index along with sparse/unique option no longer overwrites (#1004) + * fixed; never swallow connection errors (#618) + * fixed; creating object from model with emded object no longer overwrites defaults [achurkin] (#859) + * fixed; stop needless validation of unchanged/unselected fields (#891) + * fixed; document#equals behavior of objectids (#974) + * fixed; honor the minimize schema option (#978) + * fixed; provide helpful error msgs when reserved schema path is used (#928) + * fixed; callback to conn#disconnect is optional (#875) + * fixed; handle missing protocols in connection urls (#987) + * fixed; validate args to query#where (#969) + * fixed; saving modified/removed subdocs (#975) + * fixed; update with $pull from Mixed array (#735) + * fixed; error with null shard key value + * fixed; allow unsetting enums (#967) + * added; support for manual index creation (#984) + * added; support for disabled auto-indexing (#984) + * added; support for preserving MongooseArray#sort changes (#752) + * added; emit state change events on connection + * added; support for specifying BSON subtype in MongooseBuffer#toObject [jcrugzz] + * added; support for disabled versioning (#977) + * added; implicit "new" support for models and Schemas + +3.0.0alpha1 / 2012-06-15 +========================= + + * removed; doc#commit (use doc#markModified) + * removed; doc.modified getter (#950) + * removed; mongoose{connectSet,createSetConnection}. use connect,createConnection instead + * removed; query alias methods 1149804c + * removed; MongooseNumber + * changed; now creating indexes in background by default + * changed; strict mode now enabled by default (#952) + * changed; doc#modifiedPaths is now a method (#950) + * changed; getters no longer cast (#820); casting happens during set + * fixed; no need to pass updateArg to findOneAndUpdate (#931) + * fixed: utils.merge bug when merging nested non-objects. [treygriffith] + * fixed; strict:throw should produce errors in findAndModify (#963) + * fixed; findAndUpdate no longer overwrites document (#962) + * fixed; setting default DocumentArrays (#953) + * fixed; selection of _id with schema deselection (#954) + * fixed; ensure promise#error emits instanceof Error + * fixed; CursorStream: No stack overflow on any size result (#929) + * fixed; doc#remove now passes safe options + * fixed; invalid use of $set during $pop + * fixed; array#{$pop,$shift} mirror MongoDB behavior + * fixed; no longer test non-required vals in string match (#934) + * fixed; edge case with doc#inspect + * fixed; setter order (#665) + * fixed; setting invalid paths in strict mode (#916) + * fixed; handle docs without id in DocumentArray#id method (#897) + * fixed; do not save virtuals during model.update (#894) + * fixed; sub doc toObject virtuals application (#889) + * fixed; MongooseArray#pull of ObjectId (#881) + * fixed; handle passing db name with any repl set string + * fixed; default application of selected fields (#870) + * fixed; subdoc paths reported in validation errors (#725) + * fixed; incorrect reported num of affected docs in update ops (#862) + * fixed; connection assignment in Model#model (#853) + * fixed; stringifying arrays of docs (#852) + * fixed; modifying subdoc and parent array works (#842) + * fixed; passing undefined to next hook (#785) + * fixed; Query#{update,remove}() works without callbacks (#788) + * fixed; set/updating nested objects by parent pathname (#843) + * fixed; allow null in number arrays (#840) + * fixed; isNew on sub doc after insertion error (#837) + * fixed; if an insert fails, set isNew back to false [boutell] + * fixed; isSelected when only _id is selected (#730) + * fixed; setting an unset default value (#742) + * fixed; query#sort error messaging (#671) + * fixed; support for passing $options with $regex + * added; array of object literal notation in schema creates DocumentArrays + * added; gt,gte,lt,lte query support for arrays (#902) + * added; capped collection support (#938) + * added; document versioning support + * added; inclusion of deselected schema path (#786) + * added; non-atomic array#pop + * added; EmbeddedDocument constructor is now exposed in DocArray#create 7cf8beec + * added; mapReduce support (#678) + * added; support for a configurable minimize option #to{Object,JSON}(option) (#848) + * added; support for strict: `throws` [regality] + * added; support for named schema types (#795) + * added; to{Object,JSON} schema options (#805) + * added; findByIdAnd{Update,Remove}() + * added; findOneAnd{Update,Remove}() + * added; query.setOptions() + * added; instance.update() (#794) + * added; support specifying model in populate() [DanielBaulig] + * added; `lean` query option [gitfy] + * added; multi-atomic support to MongooseArray#nonAtomicPush + * added; support for $set + other $atomic ops on single array + * added; tests + * updated; driver to 1.0.2 + * updated; query.sort() syntax to mirror query.select() + * updated; clearer cast error msg for array numbers + * updated; docs + * updated; doc.clone 3x faster (#950) + * updated; only create _id if necessary (#950) + +2.7.3 / 2012-08-01 +================== + + * fixed; boolean $in queries (#998) + * fixed field selection option on subdocs (#1022) + +2.7.2 / 2012-07-18 +================== + + * fixed; callback to conn#disconnect is optional (#875) + * fixed; handle missing protocols in connection urls (#987) + * fixed; saving modified/removed subdocs (#975) + * updated; tests + +2.7.1 / 2012-06-26 +=================== + + * fixed; sharding: when a document holds a null as a value of the shard key + * fixed; update() using $pull on an array of Mixed (gh-735) + * deprecated; MongooseNumber#{inc, increment, decrement} methods + * tests; now using mocha + +2.7.0 / 2012-06-14 +=================== + + * added; deprecation warnings to methods being removed in 3.x + +2.6.8 / 2012-06-14 +=================== + + * fixed; edge case when using 'options' as a path name (#961) + +2.6.7 / 2012-06-08 +=================== + + * fixed; ensure promise#error always emits instanceof Error + * fixed; selection of _id w/ another excluded path (#954) + * fixed; setting default DocumentArrays (#953) + +2.6.6 / 2012-06-06 +=================== + + * fixed; stack overflow in query stream with large result sets (#929) + * added; $gt, $gte, $lt, $lte support to arrays (#902) + * fixed; pass option `safe` along to doc#remove() calls + +2.6.5 / 2012-05-24 +=================== + + * fixed; do not save virtuals in Model.update (#894) + * added; missing $ prefixed query aliases (going away in 3.x) (#884) [timoxley] + * fixed; setting invalid paths in strict mode (#916) + * fixed; resetting isNew after insert failure (#837) [boutell] + +2.6.4 / 2012-05-15 +=================== + + * updated; backport string regex $options to 2.x + * updated; use driver 1.0.2 (performance improvements) (#914) + * fixed; calling MongooseDocumentArray#id when the doc has no _id (#897) + +2.6.3 / 2012-05-03 +=================== + + * fixed; repl-set connectivity issues during failover on MongoDB 2.0.1 + * updated; driver to 1.0.0 + * fixed; virtuals application of subdocs when using toObject({ virtuals: true }) (#889) + * fixed; MongooseArray#pull of ObjectId correctly updates the array itself (#881) + +2.6.2 / 2012-04-30 +=================== + + * fixed; default field application of selected fields (#870) + +2.6.1 / 2012-04-30 +=================== + + * fixed; connection assignment in mongoose#model (#853, #877) + * fixed; incorrect reported num of affected docs in update ops (#862) + +2.6.0 / 2012-04-19 +=================== + + * updated; hooks.js to 0.2.1 + * fixed; issue with passing undefined to a hook callback. thanks to [chrisleishman] for reporting. + * fixed; updating/setting nested objects in strict schemas (#843) as reported by [kof] + * fixed; Query#{update,remove}() work without callbacks again (#788) + * fixed; modifying subdoc along with parent array $atomic op (#842) + +2.5.14 / 2012-04-13 +=================== + + * fixed; setting an unset default value (#742) + * fixed; doc.isSelected(otherpath) when only _id is selected (#730) + * updated; docs + +2.5.13 / 2012-03-22 +=================== + + * fixed; failing validation of unselected required paths (#730,#713) + * fixed; emitting connection error when only one listener (#759) + * fixed; MongooseArray#splice was not returning values (#784) [chrisleishman] + +2.5.12 / 2012-03-21 +=================== + + * fixed; honor the `safe` option in all ensureIndex calls + * updated; node-mongodb-native driver to 0.9.9-7 + +2.5.11 / 2012-03-15 +=================== + + * added; introspection for getters/setters (#745) + * updated; node-mongodb-driver to 0.9.9-5 + * added; tailable method to Query (#769) [holic] + * fixed; Number min/max validation of null (#764) [btamas] + * added; more flexible user/password connection options (#738) [KarneAsada] + +2.5.10 / 2012-03-06 +=================== + + * updated; node-mongodb-native driver to 0.9.9-4 + * added; Query#comment() + * fixed; allow unsetting arrays + * fixed; hooking the set method of subdocuments (#746) + * fixed; edge case in hooks + * fixed; allow $id and $ref in queries (fixes compatibility with mongoose-dbref) (#749) [richtera] + * added; default path selection to SchemaTypes + +2.5.9 / 2012-02-22 +=================== + + * fixed; properly cast nested atomic update operators for sub-documents + +2.5.8 / 2012-02-21 +=================== + + * added; post 'remove' middleware includes model that was removed (#729) [timoxley] + +2.5.7 / 2012-02-09 +=================== + + * fixed; RegExp validators on node >= v0.6.x + +2.5.6 / 2012-02-09 +=================== + + * fixed; emit errors returned from db.collection() on the connection (were being swallowed) + * added; can add multiple validators in your schema at once (#718) [diogogmt] + * fixed; strict embedded documents (#717) + * updated; docs [niemyjski] + * added; pass number of affected docs back in model.update/save + +2.5.5 / 2012-02-03 +=================== + + * fixed; RangeError: maximum call stack exceed error when removing docs with Number _id (#714) + +2.5.4 / 2012-02-03 +=================== + + * fixed; RangeError: maximum call stack exceed error (#714) + +2.5.3 / 2012-02-02 +=================== + + * added; doc#isSelected(path) + * added; query#equals() + * added; beta sharding support + * added; more descript error msgs (#700) [obeleh] + * added; document.modifiedPaths (#709) [ljharb] + * fixed; only functions can be added as getters/setters (#707,704) [ljharb] + +2.5.2 / 2012-01-30 +=================== + + * fixed; rollback -native driver to 0.9.7-3-5 (was causing timeouts and other replica set weirdness) + * deprecated; MongooseNumber (will be moved to a separate repo for 3.x) + * added; init event is emitted on schemas + +2.5.1 / 2012-01-27 +=================== + + * fixed; honor strict schemas in Model.update (#699) + +2.5.0 / 2012-01-26 +=================== + + * added; doc.toJSON calls toJSON on embedded docs when exists [jerem] + * added; populate support for refs of type Buffer (#686) [jerem] + * added; $all support for ObjectIds and Dates (#690) + * fixed; virtual setter calling on instantiation when strict: true (#682) [hunterloftis] + * fixed; doc construction triggering getters (#685) + * fixed; MongooseBuffer check in deepEquals (#688) + * fixed; range error when using Number _ids with `instance.save()` (#691) + * fixed; isNew on embedded docs edge case (#680) + * updated; driver to 0.9.8-3 + * updated; expose `model()` method within static methods + +2.4.10 / 2012-01-10 +=================== + + * added; optional getter application in .toObject()/.toJSON() (#412) + * fixed; nested $operators in $all queries (#670) + * added; $nor support (#674) + * fixed; bug when adding nested schema (#662) [paulwe] + +2.4.9 / 2012-01-04 +=================== + + * updated; driver to 0.9.7-3-5 to fix Linux performance degradation on some boxes + +2.4.8 / 2011-12-22 +=================== + + * updated; bump -native to 0.9.7.2-5 + * fixed; compatibility with date.js (#646) [chrisleishman] + * changed; undocumented schema "lax" option to "strict" + * fixed; default value population for strict schemas + * updated; the nextTick helper for small performance gain. 1bee2a2 + +2.4.7 / 2011-12-16 +=================== + + * fixed; bug in 2.4.6 with path setting + * updated; bump -native to 0.9.7.2-1 + * added; strict schema option [nw] + +2.4.6 / 2011-12-16 +=================== + + * fixed; conflicting mods on update bug [sirlantis] + * improved; doc.id getter performance + +2.4.5 / 2011-12-14 +=================== + + * fixed; bad MongooseArray behavior in 2.4.2 - 2.4.4 + +2.4.4 / 2011-12-14 +=================== + + * fixed; MongooseArray#doAtomics throwing after sliced + +2.4.3 / 2011-12-14 +=================== + + * updated; system.profile schema for MongoDB 2x + +2.4.2 / 2011-12-12 +=================== + + * fixed; partially populating multiple children of subdocs (#639) [kenpratt] + * fixed; allow Update of numbers to null (#640) [jerem] + +2.4.1 / 2011-12-02 +=================== + + * added; options support for populate() queries + * updated; -native driver to 0.9.7-1.4 + +2.4.0 / 2011-11-29 +=================== + + * added; QueryStreams (#614) + * added; debug print mode for development + * added; $within support to Array queries (#586) [ggoodale] + * added; $centerSphere query support + * fixed; $within support + * added; $unset is now used when setting a path to undefined (#519) + * added; query#batchSize support + * updated; docs + * updated; -native driver to 0.9.7-1.3 (provides Windows support) + +2.3.13 / 2011-11-15 +=================== + + * fixed; required validation for Refs (#612) [ded] + * added; $nearSphere support for Arrays (#610) + +2.3.12 / 2011-11-09 +=================== + + * fixed; regression, objects passed to Model.update should not be changed (#605) + * fixed; regression, empty Model.update should not be executed + +2.3.11 / 2011-11-08 +=================== + + * fixed; using $elemMatch on arrays of Mixed types (#591) + * fixed; allow using $regex when querying Arrays (#599) + * fixed; calling Model.update with no atomic keys (#602) + +2.3.10 / 2011-11-05 +=================== + + * fixed; model.update casting for nested paths works (#542) + +2.3.9 / 2011-11-04 +================== + + * fixed; deepEquals check for MongooseArray returned false + * fixed; reset modified flags of embedded docs after save [gitfy] + * fixed; setting embedded doc with identical values no longer marks modified [gitfy] + * updated; -native driver to 0.9.6.23 [mlazarov] + * fixed; Model.update casting (#542, #545, #479) + * fixed; populated refs no longer fail required validators (#577) + * fixed; populating refs of objects with custom ids works + * fixed; $pop & $unset work with Model.update (#574) + * added; more helpful debugging message for Schema#add (#578) + * fixed; accessing .id when no _id exists now returns null (#590) + +2.3.8 / 2011-10-26 +================== + + * added; callback to query#findOne is now optional (#581) + +2.3.7 / 2011-10-24 +================== + + * fixed; wrapped save/remove callbacks in nextTick to mitigate -native swallowing thrown errors + +2.3.6 / 2011-10-21 +================== + + * fixed; exclusion of embedded doc _id from query results (#541) + +2.3.5 / 2011-10-19 +================== + + * fixed; calling queries without passing a callback works (#569) + * fixed; populate() works with String and Number _ids too (#568) + +2.3.4 / 2011-10-18 +================== + + * added; Model.create now accepts an array as a first arg + * fixed; calling toObject on a DocumentArray with nulls no longer throws + * fixed; calling inspect on a DocumentArray with nulls no longer throws + * added; MongooseArray#unshift support + * fixed; save hooks now fire on embedded documents [gitfy] (#456) + * updated; -native driver to 0.9.6-22 + * fixed; correctly pass $addToSet op instead of $push + * fixed; $addToSet properly detects dates + * fixed; $addToSet with multiple items works + * updated; better node 0.6 Buffer support + +2.3.3 / 2011-10-12 +================== + + * fixed; population conditions in multi-query settings [vedmalex] (#563) + * fixed; now compatible with Node v0.5.x + +2.3.2 / 2011-10-11 +================== + + * fixed; population of null subdoc properties no longer hangs (#561) + +2.3.1 / 2011-10-10 +================== + + * added; support for Query filters to populate() [eneko] + * fixed; querying with number no longer crashes mongodb (#555) [jlbyrey] + * updated; version of -native driver to 0.9.6-21 + * fixed; prevent query callbacks that throw errors from corrupting -native connection state + +2.3.0 / 2011-10-04 +================== + + * fixed; nulls as default values for Boolean now works as expected + * updated; version of -native driver to 0.9.6-20 + +2.2.4 / 2011-10-03 +================== + + * fixed; populate() works when returned array contains undefined/nulls + +2.2.3 / 2011-09-29 +================== + + * updated; version of -native driver to 0.9.6-19 + +2.2.2 / 2011-09-28 +================== + + * added; $regex support to String [davidandrewcope] + * added; support for other contexts like repl etc (#535) + * fixed; clear modified state properly after saving + * added; $addToSet support to Array + +2.2.1 / 2011-09-22 +================== + + * more descript error when casting undefined to string + * updated; version of -native driver to 0.9.6-18 + +2.2.0 / 2011-09-22 +================== + + * fixed; maxListeners warning on schemas with many arrays (#530) + * changed; return / apply defaults based on fields selected in query (#423) + * fixed; correctly detect Mixed types within schema arrays (#532) + +2.1.4 / 2011-09-20 +================== + + * fixed; new private methods that stomped on users code + * changed; finished removing old "compat" support which did nothing + +2.1.3 / 2011-09-16 +================== + + * updated; version of -native driver to 0.9.6-15 + * added; emit `error` on connection when open fails [edwardhotchkiss] + * added; index support to Buffers (thanks justmoon for helping track this down) + * fixed; passing collection name via schema in conn.model() now works (thanks vedmalex for reporting) + +2.1.2 / 2011-09-07 +================== + + * fixed; Query#find with no args no longer throws + +2.1.1 / 2011-09-07 +================== + + * added; support Model.count(fn) + * fixed; compatibility with node >=0.4.0 < 0.4.3 + * added; pass model.options.safe through with .save() so w:2, wtimeout:5000 options work [andrewjstone] + * added; support for $type queries + * added; support for Query#or + * added; more tests + * optimized populate queries + +2.1.0 / 2011-09-01 +================== + + * changed; document#validate is a public method + * fixed; setting number to same value no longer marks modified (#476) [gitfy] + * fixed; Buffers shouldn't have default vals + * added; allow specifying collection name in schema (#470) [ixti] + * fixed; reset modified paths and atomics after saved (#459) + * fixed; set isNew on embedded docs to false after save + * fixed; use self to ensure proper scope of options in doOpenSet (#483) [andrewjstone] + +2.0.4 / 2011-08-29 +================== + + * Fixed; Only send the depopulated ObjectId instead of the entire doc on save (DBRefs) + * Fixed; Properly cast nested array values in Model.update (the data was stored in Mongo incorrectly but recast on document fetch was "fixing" it) + +2.0.3 / 2011-08-28 +================== + + * Fixed; manipulating a populated array no longer causes infinite loop in BSON serializer during save (#477) + * Fixed; populating an empty array no longer hangs foreeeeeeeever (#481) + +2.0.2 / 2011-08-25 +================== + + * Fixed; Maintain query option key order (fixes 'bad hint' error from compound query hints) + +2.0.1 / 2011-08-25 +================== + + * Fixed; do not over-write the doc when no valide props exist in Model.update (#473) + +2.0.0 / 2011-08-24 +=================== + + * Added; support for Buffers [justmoon] + * Changed; improved error handling [maelstrom] + * Removed: unused utils.erase + * Fixed; support for passing other context object into Schemas (#234) [Sija] + * Fixed; getters are no longer circular refs to themselves (#366) + * Removed; unused compat.js + * Fixed; getter/setter scopes are set properly + * Changed; made several private properties more obvious by prefixing _ + * Added; DBRef support [guille] + * Changed; removed support for multiple collection names per model + * Fixed; no longer applying setters when document returned from db + * Changed; default auto_reconnect to true + * Changed; Query#bind no longer clones the query + * Fixed; Model.update now accepts $pull, $inc and friends (#404) + * Added; virtual type option support [nw] + +1.8.4 / 2011-08-21 +=================== + + * Fixed; validation bug when instantiated with non-schema properties (#464) [jmreidy] + +1.8.3 / 2011-08-19 +=================== + + * Fixed; regression in connection#open [jshaw86] + +1.8.2 / 2011-08-17 +=================== + + * fixed; reset connection.readyState after failure [tomseago] + * fixed; can now query positionally for non-embedded docs (arrays of numbers/strings etc) + * fixed; embedded document query casting + * added; support for passing options to node-mongo-native db, server, and replsetserver [tomseago] + +1.8.1 / 2011-08-10 +=================== + + * fixed; ObjectIds were always marked modified + * fixed; can now query using document instances + * fixed; can now query/update using documents with subdocs + +1.8.0 / 2011-08-04 +=================== + + * fixed; can now use $all with String and Number + * fixed; can query subdoc array with $ne: null + * fixed; instance.subdocs#id now works with custom _ids + * fixed; do not apply setters when doc returned from db (change in bad behavior) + +1.7.4 / 2011-07-25 +=================== + + * fixed; sparse now a valid seperate schema option + * fixed; now catching cast errors in queries + * fixed; calling new Schema with object created in vm.runInNewContext now works (#384) [Sija] + * fixed; String enum was disallowing null + * fixed; Find by nested document _id now works (#389) + +1.7.3 / 2011-07-16 +=================== + + * fixed; MongooseArray#indexOf now works with ObjectIds + * fixed; validation scope now set properly (#418) + * fixed; added missing colors dependency (#398) + +1.7.2 / 2011-07-13 +=================== + + * changed; node-mongodb-native driver to v0.9.6.7 + +1.7.1 / 2011-07-12 +=================== + + * changed; roll back node-mongodb-native driver to v0.9.6.4 + +1.7.0 / 2011-07-12 +=================== + + * fixed; collection name misspelling [mathrawka] + * fixed; 2nd param is required for ReplSetServers [kevinmarvin] + * fixed; MongooseArray behaves properly with Object.keys + * changed; node-mongodb-native driver to v0.9.6.6 + * fixed/changed; Mongodb segfault when passed invalid ObjectId (#407) + - This means invalid data passed to the ObjectId constructor will now error + +1.6.0 / 2011-07-07 +=================== + + * changed; .save() errors are now emitted on the instances db instead of the instance 9782463fc + * fixed; errors occurring when creating indexes now properly emit on db + * added; $maxDistance support to MongooseArrays + * fixed; RegExps now work with $all + * changed; node-mongodb-native driver to v0.9.6.4 + * fixed; model names are now accessible via .modelName + * added; Query#slaveOk support + +1.5.0 / 2011-06-27 +=================== + + * changed; saving without a callback no longer ignores the error (@bnoguchi) + * changed; hook-js version bump to 0.1.9 + * changed; node-mongodb-native version bumped to 0.9.6.1 - When .remove() doesn't + return an error, null is no longer passed. + * fixed; two memory leaks (@justmoon) + * added; sparse index support + * added; more ObjectId conditionals (gt, lt, gte, lte) (@phillyqueso) + * added; options are now passed in model#remote (@JerryLuke) + +1.4.0 / 2011-06-10 +=================== + + * bumped hooks-js dependency (fixes issue passing null as first arg to next()) + * fixed; document#inspect now works properly with nested docs + * fixed; 'set' now works as a schema attribute (GH-365) + * fixed; _id is now set properly within pre-init hooks (GH-289) + * added; Query#distinct / Model#distinct support (GH-155) + * fixed; embedded docs now can use instance methods (GH-249) + * fixed; can now overwrite strings conflicting with schema type + +1.3.7 / 2011-06-03 +=================== + + * added MongooseArray#splice support + * fixed; 'path' is now a valid Schema pathname + * improved hooks (utilizing https://github.com/bnoguchi/hooks-js) + * fixed; MongooseArray#$shift now works (never did) + * fixed; Document.modified no longer throws + * fixed; modifying subdoc property sets modified paths for subdoc and parent doc + * fixed; marking subdoc path as modified properly persists the value to the db + * fixed; RexExps can again be saved ( #357 ) + +1.3.6 / 2011-05-18 +=================== + + * fixed; corrected casting for queries against array types + * added; Document#set now accepts Document instances + +1.3.5 / 2011-05-17 +=================== + + * fixed; $ne queries work properly with single vals + * added; #inspect() methods to improve console.log output + +1.3.4 / 2011-05-17 +=================== + + * fixed; find by Date works as expected (#336) + * added; geospatial 2d index support + * added; support for $near (#309) + * updated; node-mongodb-native driver + * fixed; updating numbers work (#342) + * added; better error msg when try to remove an embedded doc without an _id (#307) + * added; support for 'on-the-fly' schemas (#227) + * changed; virtual id getters can now be skipped + * fixed; .index() called on subdoc schema now works as expected + * fixed; db.setProfile() now buffers until the db is open (#340) + +1.3.3 / 2011-04-27 +=================== + + * fixed; corrected query casting on nested mixed types + +1.3.2 / 2011-04-27 +=================== + + * fixed; query hints now retain key order + +1.3.1 / 2011-04-27 +=================== + + * fixed; setting a property on an embedded array no longer overwrites entire array (GH-310) + * fixed; setting nested properties works when sibling prop is named "type" + * fixed; isModified is now much finer grained when .set() is used (GH-323) + * fixed; mongoose.model() and connection.model() now return the Model (GH-308, GH-305) + * fixed; can now use $gt, $lt, $gte, $lte with String schema types (GH-317) + * fixed; .lowercase() -> .toLowerCase() in pluralize() + * fixed; updating an embedded document by index works (GH-334) + * changed; .save() now passes the instance to the callback (GH-294, GH-264) + * added; can now query system.profile and system.indexes collections + * added; db.model('system.profile') is now included as a default Schema + * added; db.setProfiling(level, ms, callback) + * added; Query#hint() support + * added; more tests + * updated node-mongodb-native to 0.9.3 + +1.3.0 / 2011-04-19 +=================== + + * changed; save() callbacks now fire only once on failed validation + * changed; Errors returned from save() callbacks now instances of ValidationError + * fixed; MongooseArray#indexOf now works properly + +1.2.0 / 2011-04-11 +=================== + + * changed; MongooseNumber now casts empty string to null + +1.1.25 / 2011-04-08 +=================== + + * fixed; post init now fires at proper time + +1.1.24 / 2011-04-03 +=================== + + * fixed; pushing an array onto an Array works on existing docs + +1.1.23 / 2011-04-01 +=================== + + * Added Model#model + +1.1.22 / 2011-03-31 +=================== + + * Fixed; $in queries on mixed types now work + +1.1.21 / 2011-03-31 +=================== + + * Fixed; setting object root to null/undefined works + +1.1.20 / 2011-03-31 +=================== + + * Fixed; setting multiple props on null field works + +1.1.19 / 2011-03-31 +=================== + + * Fixed; no longer using $set on paths to an unexisting fields + +1.1.18 / 2011-03-30 +=================== + + * Fixed; non-mixed type object setters work after initd from null + +1.1.17 / 2011-03-30 +=================== + + * Fixed; nested object property access works when root initd with null value + +1.1.16 / 2011-03-28 +=================== + + * Fixed; empty arrays are now saved + +1.1.15 / 2011-03-28 +=================== + + * Fixed; `null` and `undefined` are set atomically. + +1.1.14 / 2011-03-28 +=================== + + * Changed; more forgiving date casting, accepting '' as null. + +1.1.13 / 2011-03-26 +=================== + + * Fixed setting values as `undefined`. + +1.1.12 / 2011-03-26 +=================== + + * Fixed; nested objects now convert to JSON properly + * Fixed; setting nested objects directly now works + * Update node-mongodb-native + +1.1.11 / 2011-03-25 +=================== + + * Fixed for use of `type` as a key. + +1.1.10 / 2011-03-23 +=================== + + * Changed; Make sure to only ensure indexes while connected + +1.1.9 / 2011-03-2 +================== + + * Fixed; Mixed can now default to empty arrays + * Fixed; keys by the name 'type' are now valid + * Fixed; null values retrieved from the database are hydrated as null values. + * Fixed repeated atomic operations when saving a same document twice. + +1.1.8 / 2011-03-23 +================== + + * Fixed 'id' overriding. [bnoguchi] + +1.1.7 / 2011-03-22 +================== + + * Fixed RegExp query casting when querying against an Array of Strings [bnoguchi] + * Fixed getters/setters for nested virtualsl. [bnoguchi] + +1.1.6 / 2011-03-22 +================== + + * Only doValidate when path exists in Schema [aheckmann] + * Allow function defaults for Array types [aheckmann] + * Fix validation hang [aheckmann] + * Fix setting of isRequired of SchemaType [aheckmann] + * Fix SchemaType#required(false) filter [aheckmann] + * More backwards compatibility [aheckmann] + * More tests [aheckmann] + +1.1.5 / 2011-03-14 +================== + + * Added support for `uri, db, fn` and `uri, fn` signatures for replica sets. + * Improved/extended replica set tests. + +1.1.4 / 2011-03-09 +================== + + * Fixed; running an empty Query doesn't throw. [aheckmann] + * Changed; Promise#addBack returns promise. [aheckmann] + * Added streaming cursor support. [aheckmann] + * Changed; Query#update defaults to use$SetOnSave now. [brian] + * Added more docs. + +1.1.3 / 2011-03-04 +================== + + * Added Promise#resolve [aheckmann] + * Fixed backward compatibility with nulls [aheckmann] + * Changed; Query#{run,exec} return promises [aheckmann] + +1.1.2 / 2011-03-03 +================== + + * Restored Query#exec and added notion of default operation [brian] + * Fixed ValidatorError messages [brian] + +1.1.1 / 2011-03-01 +================== + + * Added SchemaType String `lowercase`, `uppercase`, `trim`. + * Public exports (`Model`, `Document`) and tests. + * Added ObjectId casting support for `Document`s. + +1.1.0 / 2011-02-25 +================== + + * Added support for replica sets. + +1.0.16 / 2011-02-18 +=================== + + * Added $nin as another whitelisted $conditional for SchemaArray [brian] + * Changed #with to #where [brian] + * Added ability to use $in conditional with Array types [brian] + +1.0.15 / 2011-02-18 +=================== + + * Added `id` virtual getter for documents to easily access the hexString of + the `_id`. + +1.0.14 / 2011-02-17 +=================== + + * Fix for arrays within subdocuments [brian] + +1.0.13 / 2011-02-16 +=================== + + * Fixed embedded documents saving. + +1.0.12 / 2011-02-14 +=================== + + * Minor refactorings [brian] + +1.0.11 / 2011-02-14 +=================== + + * Query refactor and $ne, $slice, $or, $size, $elemMatch, $nin, $exists support [brian] + * Named scopes sugar [brian] + +1.0.10 / 2011-02-11 +=================== + + * Updated node-mongodb-native driver [thanks John Allen] + +1.0.9 / 2011-02-09 +================== + + * Fixed single member arrays as defaults [brian] + +1.0.8 / 2011-02-09 +================== + + * Fixed for collection-level buffering of commands [gitfy] + * Fixed `Document#toJSON` [dalejefferson] + * Fixed `Connection` authentication [robrighter] + * Fixed clash of accessors in getters/setters [eirikurn] + * Improved `Model#save` promise handling + +1.0.7 / 2011-02-05 +================== + + * Fixed memory leak warnings for test suite on 0.3 + * Fixed querying documents that have an array that contain at least one + specified member. [brian] + * Fixed default value for Array types (fixes GH-210). [brian] + * Fixed example code. + +1.0.6 / 2011-02-03 +================== + + * Fixed `post` middleware + * Fixed; it's now possible to instantiate a model even when one of the paths maps + to an undefined value [brian] + +1.0.5 / 2011-02-02 +================== + + * Fixed; combo $push and $pushAll auto-converts into a $pushAll [brian] + * Fixed; combo $pull and $pullAll auto-converts to a single $pullAll [brian] + * Fixed; $pullAll now removes said members from array before save (so it acts just + like pushAll) [brian] + * Fixed; multiple $pulls and $pushes become a single $pullAll and $pushAll. + Moreover, $pull now modifies the array before save to reflect the immediate + change [brian] + * Added tests for nested shortcut getters [brian] + * Added tests that show that Schemas with nested Arrays don't apply defaults + [brian] + +1.0.4 / 2011-02-02 +================== + + * Added MongooseNumber#toString + * Added MongooseNumber unit tests + +1.0.3 / 2011-02-02 +================== + + * Make sure safe mode works with Model#save + * Changed Schema options: safe mode is now the default + * Updated node-mongodb-native to HEAD + +1.0.2 / 2011-02-02 +================== + + * Added a Model.create shortcut for creating documents. [brian] + * Fixed; we can now instantiate models with hashes that map to at least one + null value. [brian] + * Fixed Schema with more than 2 nested levels. [brian] + +1.0.1 / 2011-02-02 +================== + + * Improved `MongooseNumber`, works almost like the native except for `typeof` + not being `'number'`. diff --git a/node_modules/mongoose/README.md b/node_modules/mongoose/README.md new file mode 100644 index 0000000..71af427 --- /dev/null +++ b/node_modules/mongoose/README.md @@ -0,0 +1,269 @@ +## What's Mongoose? + +Mongoose is a [MongoDB](http://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. + +## Documentation + +[mongoosejs.com](http://mongoosejs.com/) + +## Try it live + + +## Support + + - [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose) + - [bug reports](https://github.com/learnboost/mongoose/issues/) + - [help forum](http://groups.google.com/group/mongoose-orm) + - [10gen support](http://www.mongodb.org/display/DOCS/Technical+Support) + - (irc) #mongoosejs on freenode + +## Installation + +First install [node.js](http://nodejs.org/) and [mongodb](http://www.mongodb.org/downloads). + + $ npm install mongoose + +## Plugins + +Check out the [plugins search site](http://plugins.mongoosejs.com/) to see hundreds of related modules from the community. + +## Contributors + +View all 90+ [contributors](https://github.com/learnboost/mongoose/graphs/contributors). + +## Get Involved + +Stand up and be counted as a [contributor](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md) too! + +## Overview + +### Connecting to MongoDB + +First, we need to define a connection. If your app uses only one database, you should use `mongose.connect`. If you need to create additional connections, use `mongoose.createConnection`. + +Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters `host, database, port, options`. + + var mongoose = require('mongoose'); + + mongoose.connect('mongodb://localhost/my_database'); + +Once connected, the `open` event is fired on the `Connection` instance. If you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. Otherwise, `mongoose.createConnection` return value is a `Connection`. + +**Important!** Mongoose buffers all the commands until it's connected to the database. This means that you don't have to wait until it connects to MongoDB in order to define models, run queries, etc. + +### Defining a Model + +Models are defined through the `Schema` interface. + + var Schema = mongoose.Schema + , ObjectId = Schema.ObjectId; + + var BlogPost = new Schema({ + author : ObjectId + , title : String + , body : String + , date : Date + }); + +Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of: + +* [Validators](http://mongoosejs.com/docs/validation.html) (async and sync) +* [Defaults](http://mongoosejs.com/docs/api.html#schematype_SchemaType-default) +* [Getters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-get) +* [Setters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set) +* [Indexes](http://mongoosejs.com/docs/guide.html#indexes) +* [Middleware](http://mongoosejs.com/docs/middleware.html) +* [Methods](http://mongoosejs.com/docs/guide.html#methods) definition +* [Statics](http://mongoosejs.com/docs/guide.html#statics) definition +* [Plugins](http://mongoosejs.com/docs/plugins.html) +* [pseudo-JOINs](http://mongoosejs.com/docs/populate.html) + +The following example shows some of these features: + + var Comment = new Schema({ + name : { type: String, default: 'hahaha' } + , age : { type: Number, min: 18, index: true } + , bio : { type: String, match: /[a-z]/ } + , date : { type: Date, default: Date.now } + , buff : Buffer + }); + + // a setter + Comment.path('name').set(function (v) { + return capitalize(v); + }); + + // middleware + Comment.pre('save', function (next) { + notify(this.get('email')); + next(); + }); + +Take a look at the example in `examples/schema.js` for an end-to-end example of a typical setup. + +### Accessing a Model + +Once we define a model through `mongoose.model('ModelName', mySchema)`, we can access it through the same function + + var myModel = mongoose.model('ModelName'); + +Or just do it all at once + + var MyModel = mongoose.model('ModelName', mySchema); + +We can then instantiate it, and save it: + + var instance = new MyModel(); + instance.my.key = 'hello'; + instance.save(function (err) { + // + }); + +Or we can find documents from the same collection + + MyModel.find({}, function (err, docs) { + // docs.forEach + }); + +You can also `findOne`, `findById`, `update`, etc. For more details check out [the docs](http://mongoosejs.com/docs/queries.html). + +**Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created: + + var conn = mongoose.createConnection('your connection string'); + var MyModel = conn.model('ModelName', schema); + var m = new MyModel; + m.save() // works + + vs + + var conn = mongoose.createConnection('your connection string'); + var MyModel = mongoose.model('ModelName', schema); + var m = new MyModel; + m.save() // does not work b/c the default connection object was never connected + +### Embedded Documents + +In the first example snippet, we defined a key in the Schema that looks like: + + comments: [Comments] + +Where `Comments` is a `Schema` we created. This means that creating embedded documents is as simple as: + + // retrieve my model + var BlogPost = mongoose.model('BlogPost'); + + // create a blog post + var post = new BlogPost(); + + // create a comment + post.comments.push({ title: 'My comment' }); + + post.save(function (err) { + if (!err) console.log('Success!'); + }); + +The same goes for removing them: + + BlogPost.findById(myId, function (err, post) { + if (!err) { + post.comments[0].remove(); + post.save(function (err) { + // do something + }); + } + }); + +Embedded documents enjoy all the same features as your models. Defaults, validators, middleware. Whenever an error occurs, it's bubbled to the `save()` error callback, so error handling is a snap! + +Mongoose interacts with your embedded documents in arrays _atomically_, out of the box. + +### Middleware + +See the [docs](http://mongoosejs.com/docs/middleware.html) page. + +#### Intercepting and mutating method arguments + +You can intercept method arguments via middleware. + +For example, this would allow you to broadcast changes about your Documents every time someone `set`s a path in your Document to a new value: + + schema.pre('set', function (next, path, val, typel) { + // `this` is the current Document + this.emit('set', path, val); + + // Pass control to the next pre + next(); + }); + +Moreover, you can mutate the incoming `method` arguments so that subsequent middleware see different values for those arguments. To do so, just pass the new values to `next`: + + .pre(method, function firstPre (next, methodArg1, methodArg2) { + // Mutate methodArg1 + next("altered-" + methodArg1.toString(), methodArg2); + }) + + // pre declaration is chainable + .pre(method, function secondPre (next, methodArg1, methodArg2) { + console.log(methodArg1); + // => 'altered-originalValOfMethodArg1' + + console.log(methodArg2); + // => 'originalValOfMethodArg2' + + // Passing no arguments to `next` automatically passes along the current argument values + // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)` + // and also equivalent to, with the example method arg + // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')` + next(); + }) + +#### Schema gotcha + +`type`, when used in a schema has special meaning within Mongoose. If your schema requires using `type` as a nested property you must use object notation: + + new Schema({ + broken: { type: Boolean } + , asset : { + name: String + , type: String // uh oh, it broke. asset will be interpreted as String + } + }); + + new Schema({ + works: { type: Boolean } + , asset : { + name: String + , type: { type: String } // works. asset is an object with a type property + } + }); + +### Driver access + +The driver being used defaults to [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) and is directly accessible through `YourModel.collection`. **Note**: using the driver directly bypasses all Mongoose power-tools like validation, getters, setters, hooks, etc. + +## API Docs + +Find the API docs [here](http://mongoosejs.com/docs/api.html), generated by [dox](http://github.com/visionmedia/dox). + +## License + +Copyright (c) 2010 LearnBoost <dev@learnboost.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/mongoose/examples/README.md b/node_modules/mongoose/examples/README.md new file mode 100644 index 0000000..89728d9 --- /dev/null +++ b/node_modules/mongoose/examples/README.md @@ -0,0 +1,42 @@ + +This directory contains runnable sample mongoose programs. + +To run: + + - first install [Node.js](http://nodejs.org/) + - from the command line, execute: `node example.js`, replacing "example.js" with the name of a program. + + +Goal is to show: + +- global schemas +- GeoJSON schemas / use (with crs) +- text search +- storing schemas as json +- lean querires +- statics +- methods and statics on subdocs +- custom types +- querybuilder +- promises +- express + mongoose +- accessing driver collection, db +- connecting to replica sets +- connecting to sharded clusters +- enabling a fail fast mode +- on the fly schemas +- storing files +- map reduce +- aggregation +- advanced hooks +- using $elemMatch to return a subset of an array +- query casting +- upserts +- pagination +- express + mongoose session handling +- group by (use aggregation) +- authentication +- schema migration techniques +- converting documents to plain objects (show transforms) +- how to $unset + diff --git a/node_modules/mongoose/examples/doc-methods.js b/node_modules/mongoose/examples/doc-methods.js new file mode 100644 index 0000000..373a46b --- /dev/null +++ b/node_modules/mongoose/examples/doc-methods.js @@ -0,0 +1,70 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +console.log('Running mongoose version %s', mongoose.version); + +/** + * Schema + */ + +var CharacterSchema = Schema({ + name: { type: String, required: true } + , health: { type: Number, min: 0, max: 100 } +}) + +/** + * Methods + */ + +CharacterSchema.methods.attack = function () { + console.log('%s is attacking', this.name); +} + +/** + * Character model + */ + +var Character = mongoose.model('Character', CharacterSchema); + +/** + * Connect to the database on localhost with + * the default port (27017) + */ + +var dbname = 'mongoose-example-doc-methods-' + ((Math.random()*10000)|0); +var uri = 'mongodb://localhost/' + dbname; + +console.log('connecting to %s', uri); + +mongoose.connect(uri, function (err) { + // if we failed to connect, abort + if (err) throw err; + + // we connected ok + example(); +}) + +/** + * Use case + */ + +function example () { + Character.create({ name: 'Link', health: 100 }, function (err, link) { + if (err) return done(err); + console.log('found', link); + link.attack(); // 'Link is attacking' + done(); + }) +} + +/** + * Clean up + */ + +function done (err) { + if (err) console.error(err); + mongoose.connection.db.dropDatabase(function () { + mongoose.disconnect(); + }) +} diff --git a/node_modules/mongoose/examples/hooks.js b/node_modules/mongoose/examples/hooks.js new file mode 100644 index 0000000..01b2bb1 --- /dev/null +++ b/node_modules/mongoose/examples/hooks.js @@ -0,0 +1,42 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +mongoose.connect('mongodb://localhost/example-hooks'); + +var schema = Schema({ name: String }); +schema.post('save', function () { + console.log('post save hook', arguments); +}) + +schema.pre('save', function (next) { + console.log('pre save'); + next(); +}) + +var M = mongoose.model('Hooks', schema); + +var doc = new M({ name: 'hooooks' }); +doc.save(function (err) { + console.log('save callback'); + mongoose.disconnect(); +}) + + +//// + +Model.on('init', cb); +Model.on('remove', cb); +Model.on('update', cb); + // Model.update() and doc.save() +Model.on('insert', cb); +Model.on('save', cb); + +var promise = Model.save(doc, options, callback); + +// + +var schema = new Schema(..); +schema.pre('save', function (next, done) { + +}) diff --git a/node_modules/mongoose/examples/population-across-three-collections.js b/node_modules/mongoose/examples/population-across-three-collections.js new file mode 100644 index 0000000..4bec928 --- /dev/null +++ b/node_modules/mongoose/examples/population-across-three-collections.js @@ -0,0 +1,135 @@ + +var assert = require('assert') +var mongoose = require('../'); +var Schema = mongoose.Schema; +var ObjectId = mongoose.Types.ObjectId; + +/** + * Connect to the db + */ + +var dbname = 'testing_populateAdInfinitum_' + require('../lib/utils').random() +mongoose.connect('localhost', dbname); +mongoose.connection.on('error', function() { + console.error('connection error', arguments); +}); + +/** + * Schemas + */ + +var user = new Schema({ + name: String, + friends: [{ + type: Schema.ObjectId, + ref: 'User' + }] +}); +var User = mongoose.model('User', user); + +var blogpost = Schema({ + title: String, + tags: [String], + author: { + type: Schema.ObjectId, + ref: 'User' + } +}) +var BlogPost = mongoose.model('BlogPost', blogpost); + +/** + * example + */ + +mongoose.connection.on('open', function() { + + /** + * Generate data + */ + + var userIds = [new ObjectId, new ObjectId, new ObjectId, new ObjectId]; + var users = []; + + users.push({ + _id: userIds[0], + name: 'mary', + friends: [userIds[1], userIds[2], userIds[3]] + }); + users.push({ + _id: userIds[1], + name: 'bob', + friends: [userIds[0], userIds[2], userIds[3]] + }); + users.push({ + _id: userIds[2], + name: 'joe', + friends: [userIds[0], userIds[1], userIds[3]] + }); + users.push({ + _id: userIds[3], + name: 'sally', + friends: [userIds[0], userIds[1], userIds[2]] + }); + + User.create(users, function(err, docs) { + assert.ifError(err); + + var blogposts = []; + blogposts.push({ + title: 'blog 1', + tags: ['fun', 'cool'], + author: userIds[3] + }) + blogposts.push({ + title: 'blog 2', + tags: ['cool'], + author: userIds[1] + }) + blogposts.push({ + title: 'blog 3', + tags: ['fun', 'odd'], + author: userIds[2] + }) + + BlogPost.create(blogposts, function(err, docs) { + assert.ifError(err); + + /** + * Population + */ + + BlogPost + .find({ tags: 'fun' }) + .lean() + .populate('author') + .exec(function(err, docs) { + assert.ifError(err); + + /** + * Populate the populated documents + */ + + var opts = { + path: 'author.friends', + select: 'name', + options: { limit: 2 } + } + + BlogPost.populate(docs, opts, function(err, docs) { + assert.ifError(err); + console.log('populated'); + var s = require('util').inspect(docs, { depth: null }) + console.log(s); + done(); + }) + }) + }) + }) +}); + +function done(err) { + if (err) console.error(err.stack); + mongoose.connection.db.dropDatabase(function() { + mongoose.connection.close(); + }); +} diff --git a/node_modules/mongoose/examples/population-basic.js b/node_modules/mongoose/examples/population-basic.js new file mode 100644 index 0000000..c1d6a70 --- /dev/null +++ b/node_modules/mongoose/examples/population-basic.js @@ -0,0 +1,95 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +console.log('Running mongoose version %s', mongoose.version); + +/** + * Console schema + */ + +var consoleSchema = Schema({ + name: String + , manufacturer: String + , released: Date +}) +var Console = mongoose.model('Console', consoleSchema); + +/** + * Game schema + */ + +var gameSchema = Schema({ + name: String + , developer: String + , released: Date + , consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }] +}) +var Game = mongoose.model('Game', gameSchema); + +/** + * Connect to the console database on localhost with + * the default port (27017) + */ + +mongoose.connect('mongodb://localhost/console', function (err) { + // if we failed to connect, abort + if (err) throw err; + + // we connected ok + createData(); +}) + +/** + * Data generation + */ + +function createData () { + Console.create({ + name: 'Nintendo 64' + , manufacturer: 'Nintendo' + , released: 'September 29, 1996' + }, function (err, nintendo64) { + if (err) return done(err); + + Game.create({ + name: 'Legend of Zelda: Ocarina of Time' + , developer: 'Nintendo' + , released: new Date('November 21, 1998') + , consoles: [nintendo64] + }, function (err) { + if (err) return done(err); + example(); + }) + }) +} + +/** + * Population + */ + +function example () { + Game + .findOne({ name: /^Legend of Zelda/ }) + .populate('consoles') + .exec(function (err, ocinara) { + if (err) return done(err); + + console.log( + '"%s" was released for the %s on %s' + , ocinara.name + , ocinara.consoles[0].name + , ocinara.released.toLocaleDateString()); + + done(); + }) +} + +function done (err) { + if (err) console.error(err); + Console.remove(function () { + Game.remove(function () { + mongoose.disconnect(); + }) + }) +} diff --git a/node_modules/mongoose/examples/population-of-existing-doc.js b/node_modules/mongoose/examples/population-of-existing-doc.js new file mode 100644 index 0000000..6d48fdc --- /dev/null +++ b/node_modules/mongoose/examples/population-of-existing-doc.js @@ -0,0 +1,101 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +console.log('Running mongoose version %s', mongoose.version); + +/** + * Console schema + */ + +var consoleSchema = Schema({ + name: String + , manufacturer: String + , released: Date +}) +var Console = mongoose.model('Console', consoleSchema); + +/** + * Game schema + */ + +var gameSchema = Schema({ + name: String + , developer: String + , released: Date + , consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }] +}) +var Game = mongoose.model('Game', gameSchema); + +/** + * Connect to the console database on localhost with + * the default port (27017) + */ + +mongoose.connect('mongodb://localhost/console', function (err) { + // if we failed to connect, abort + if (err) throw err; + + // we connected ok + createData(); +}) + +/** + * Data generation + */ + +function createData () { + Console.create({ + name: 'Nintendo 64' + , manufacturer: 'Nintendo' + , released: 'September 29, 1996' + }, function (err, nintendo64) { + if (err) return done(err); + + Game.create({ + name: 'Legend of Zelda: Ocarina of Time' + , developer: 'Nintendo' + , released: new Date('November 21, 1998') + , consoles: [nintendo64] + }, function (err) { + if (err) return done(err); + example(); + }) + }) +} + +/** + * Population + */ + +function example () { + Game + .findOne({ name: /^Legend of Zelda/ }) + .exec(function (err, ocinara) { + if (err) return done(err); + + console.log('"%s" console _id: %s', ocinara.name, ocinara.consoles[0]); + + // population of existing document + ocinara.populate('consoles', function (err) { + if (err) return done(err); + + console.log( + '"%s" was released for the %s on %s' + , ocinara.name + , ocinara.consoles[0].name + , ocinara.released.toLocaleDateString()); + + done(); + }) + }) +} + +function done (err) { + if (err) console.error(err); + Console.remove(function () { + Game.remove(function () { + mongoose.disconnect(); + }) + }) +} diff --git a/node_modules/mongoose/examples/population-of-multiple-existing-docs.js b/node_modules/mongoose/examples/population-of-multiple-existing-docs.js new file mode 100644 index 0000000..6d918ff --- /dev/null +++ b/node_modules/mongoose/examples/population-of-multiple-existing-docs.js @@ -0,0 +1,112 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +console.log('Running mongoose version %s', mongoose.version); + +/** + * Console schema + */ + +var consoleSchema = Schema({ + name: String + , manufacturer: String + , released: Date +}) +var Console = mongoose.model('Console', consoleSchema); + +/** + * Game schema + */ + +var gameSchema = Schema({ + name: String + , developer: String + , released: Date + , consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }] +}) +var Game = mongoose.model('Game', gameSchema); + +/** + * Connect to the console database on localhost with + * the default port (27017) + */ + +mongoose.connect('mongodb://localhost/console', function (err) { + // if we failed to connect, abort + if (err) throw err; + + // we connected ok + createData(); +}) + +/** + * Data generation + */ + +function createData () { + Console.create({ + name: 'Nintendo 64' + , manufacturer: 'Nintendo' + , released: 'September 29, 1996' + }, { + name: 'Super Nintendo' + , manufacturer: 'Nintendo' + , released: 'August 23, 1991' + }, function (err, nintendo64, superNintendo) { + if (err) return done(err); + + Game.create({ + name: 'Legend of Zelda: Ocarina of Time' + , developer: 'Nintendo' + , released: new Date('November 21, 1998') + , consoles: [nintendo64] + }, { + name: 'Mario Kart' + , developer: 'Nintendo' + , released: 'September 1, 1992' + , consoles: [superNintendo] + }, function (err) { + if (err) return done(err); + example(); + }) + }) +} + +/** + * Population + */ + +function example () { + Game + .find({}) + .exec(function (err, games) { + if (err) return done(err); + + console.log('found %d games', games.length); + + var options = { path: 'consoles', select: 'name released -_id' }; + Game.populate(games, options, function (err, games) { + if (err) return done(err); + + games.forEach(function (game) { + console.log( + '"%s" was released for the %s on %s' + , game.name + , game.consoles[0].name + , game.released.toLocaleDateString()); + }) + + done() + }) + }) +} + +function done (err) { + if (err) console.error(err); + Console.remove(function () { + Game.remove(function () { + mongoose.disconnect(); + }) + }) +} diff --git a/node_modules/mongoose/examples/population-options.js b/node_modules/mongoose/examples/population-options.js new file mode 100644 index 0000000..7387b3b --- /dev/null +++ b/node_modules/mongoose/examples/population-options.js @@ -0,0 +1,124 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +console.log('Running mongoose version %s', mongoose.version); + +/** + * Console schema + */ + +var consoleSchema = Schema({ + name: String + , manufacturer: String + , released: Date +}) +var Console = mongoose.model('Console', consoleSchema); + +/** + * Game schema + */ + +var gameSchema = Schema({ + name: String + , developer: String + , released: Date + , consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }] +}) +var Game = mongoose.model('Game', gameSchema); + +/** + * Connect to the console database on localhost with + * the default port (27017) + */ + +mongoose.connect('mongodb://localhost/console', function (err) { + // if we failed to connect, abort + if (err) throw err; + + // we connected ok + createData(); +}) + +/** + * Data generation + */ + +function createData () { + Console.create({ + name: 'Nintendo 64' + , manufacturer: 'Nintendo' + , released: 'September 29, 1996' + }, { + name: 'Super Nintendo' + , manufacturer: 'Nintendo' + , released: 'August 23, 1991' + }, { + name: 'XBOX 360' + , manufacturer: 'Microsoft' + , released: 'November 22, 2005' + }, function (err, nintendo64, superNintendo, xbox360) { + if (err) return done(err); + + Game.create({ + name: 'Legend of Zelda: Ocarina of Time' + , developer: 'Nintendo' + , released: new Date('November 21, 1998') + , consoles: [nintendo64] + }, { + name: 'Mario Kart' + , developer: 'Nintendo' + , released: 'September 1, 1992' + , consoles: [superNintendo] + }, { + name: 'Perfect Dark Zero' + , developer: 'Rare' + , released: 'November 17, 2005' + , consoles: [xbox360] + }, function (err) { + if (err) return done(err); + example(); + }) + }) +} + +/** + * Population + */ + +function example () { + Game + .find({}) + .populate({ + path: 'consoles' + , match: { manufacturer: 'Nintendo' } + , select: 'name' + , options: { comment: 'population' } + }) + .exec(function (err, games) { + if (err) return done(err); + + games.forEach(function (game) { + console.log( + '"%s" was released for the %s on %s' + , game.name + , game.consoles.length ? game.consoles[0].name : '??' + , game.released.toLocaleDateString()); + }) + + return done(); + }) +} + +/** + * Clean up + */ + +function done (err) { + if (err) console.error(err); + Console.remove(function () { + Game.remove(function () { + mongoose.disconnect(); + }) + }) +} diff --git a/node_modules/mongoose/examples/population-plain-objects.js b/node_modules/mongoose/examples/population-plain-objects.js new file mode 100644 index 0000000..50fc9fa --- /dev/null +++ b/node_modules/mongoose/examples/population-plain-objects.js @@ -0,0 +1,96 @@ + +var mongoose = require('mongoose') +var Schema = mongoose.Schema; + +console.log('Running mongoose version %s', mongoose.version); + +/** + * Console schema + */ + +var consoleSchema = Schema({ + name: String + , manufacturer: String + , released: Date +}) +var Console = mongoose.model('Console', consoleSchema); + +/** + * Game schema + */ + +var gameSchema = Schema({ + name: String + , developer: String + , released: Date + , consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }] +}) +var Game = mongoose.model('Game', gameSchema); + +/** + * Connect to the console database on localhost with + * the default port (27017) + */ + +mongoose.connect('mongodb://localhost/console', function (err) { + // if we failed to connect, abort + if (err) throw err; + + // we connected ok + createData(); +}) + +/** + * Data generation + */ + +function createData () { + Console.create({ + name: 'Nintendo 64' + , manufacturer: 'Nintendo' + , released: 'September 29, 1996' + }, function (err, nintendo64) { + if (err) return done(err); + + Game.create({ + name: 'Legend of Zelda: Ocarina of Time' + , developer: 'Nintendo' + , released: new Date('November 21, 1998') + , consoles: [nintendo64] + }, function (err) { + if (err) return done(err); + example(); + }) + }) +} + +/** + * Population + */ + +function example () { + Game + .findOne({ name: /^Legend of Zelda/ }) + .populate('consoles') + .lean() // just return plain objects, not documents wrapped by mongoose + .exec(function (err, ocinara) { + if (err) return done(err); + + console.log( + '"%s" was released for the %s on %s' + , ocinara.name + , ocinara.consoles[0].name + , ocinara.released.toLocaleDateString()); + + done(); + }) +} + +function done (err) { + if (err) console.error(err); + Console.remove(function () { + Game.remove(function () { + mongoose.disconnect(); + }) + }) +} diff --git a/node_modules/mongoose/examples/schema.js b/node_modules/mongoose/examples/schema.js new file mode 100644 index 0000000..d108d05 --- /dev/null +++ b/node_modules/mongoose/examples/schema.js @@ -0,0 +1,102 @@ + +/** + * Module dependencies. + */ + +var mongoose = require('mongoose') + , Schema = mongoose.Schema; + +/** + * Schema definition + */ + +// recursive embedded-document schema + +var Comment = new Schema(); + +Comment.add({ + title : { type: String, index: true } + , date : Date + , body : String + , comments : [Comment] +}); + +var BlogPost = new Schema({ + title : { type: String, index: true } + , slug : { type: String, lowercase: true, trim: true } + , date : Date + , buf : Buffer + , comments : [Comment] + , creator : Schema.ObjectId +}); + +var Person = new Schema({ + name: { + first: String + , last : String + } + , email: { type: String, required: true, index: { unique: true, sparse: true } } + , alive: Boolean +}); + +/** + * Accessing a specific schema type by key + */ + +BlogPost.path('date') +.default(function(){ + return new Date() + }) +.set(function(v){ + return v == 'now' ? new Date() : v; + }); + +/** + * Pre hook. + */ + +BlogPost.pre('save', function(next, done){ + emailAuthor(done); // some async function + next(); +}); + +/** + * Methods + */ + +BlogPost.methods.findCreator = function (callback) { + return this.db.model('Person').findById(this.creator, callback); +} + +BlogPost.statics.findByTitle = function (title, callback) { + return this.find({ title: title }, callback); +} + +BlogPost.methods.expressiveQuery = function (creator, date, callback) { + return this.find('creator', creator).where('date').gte(date).run(callback); +} + +/** + * Plugins + */ + +function slugGenerator (options){ + options = options || {}; + var key = options.key || 'title'; + + return function slugGenerator(schema){ + schema.path(key).set(function(v){ + this.slug = v.toLowerCase().replace(/[^a-z0-9]/g, '').replace(/-+/g, ''); + return v; + }); + }; +}; + +BlogPost.plugin(slugGenerator()); + +/** + * Define model. + */ + +mongoose.model('BlogPost', BlogPost); +mongoose.model('Person', Person); diff --git a/node_modules/mongoose/index.js b/node_modules/mongoose/index.js new file mode 100644 index 0000000..e7e6278 --- /dev/null +++ b/node_modules/mongoose/index.js @@ -0,0 +1,7 @@ + +/** + * Export lib/mongoose + * + */ + +module.exports = require('./lib/'); diff --git a/node_modules/mongoose/lib/collection.js b/node_modules/mongoose/lib/collection.js new file mode 100644 index 0000000..1c38286 --- /dev/null +++ b/node_modules/mongoose/lib/collection.js @@ -0,0 +1,188 @@ + +/*! + * Module dependencies. + */ + +var STATES = require('./connectionstate') + +/** + * Abstract Collection constructor + * + * This is the base class that drivers inherit from and implement. + * + * @param {String} name name of the collection + * @param {Connection} conn A MongooseConnection instance + * @param {Object} opts optional collection options + * @api public + */ + +function Collection (name, conn, opts) { + if (undefined === opts) opts = {}; + if (undefined === opts.capped) opts.capped = {}; + + opts.bufferCommands = undefined === opts.bufferCommands + ? true + : opts.bufferCommands; + + if ('number' == typeof opts.capped) { + opts.capped = { size: opts.capped }; + } + + this.opts = opts; + this.name = name; + this.conn = conn; + this.queue = []; + this.buffer = this.opts.bufferCommands; + + if (STATES.connected == this.conn.readyState) { + this.onOpen(); + } +}; + +/** + * The collection name + * + * @api public + * @property name + */ + +Collection.prototype.name; + +/** + * The Connection instance + * + * @api public + * @property conn + */ + +Collection.prototype.conn; + +/** + * Called when the database connects + * + * @api private + */ + +Collection.prototype.onOpen = function () { + var self = this; + this.buffer = false; + self.doQueue(); +}; + +/** + * Called when the database disconnects + * + * @api private + */ + +Collection.prototype.onClose = function () { + if (this.opts.bufferCommands) { + this.buffer = true; + } +}; + +/** + * Queues a method for later execution when its + * database connection opens. + * + * @param {String} name name of the method to queue + * @param {Array} args arguments to pass to the method when executed + * @api private + */ + +Collection.prototype.addQueue = function (name, args) { + this.queue.push([name, args]); + return this; +}; + +/** + * Executes all queued methods and clears the queue. + * + * @api private + */ + +Collection.prototype.doQueue = function () { + for (var i = 0, l = this.queue.length; i < l; i++){ + this[this.queue[i][0]].apply(this, this.queue[i][1]); + } + this.queue = []; + return this; +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.ensureIndex = function(){ + throw new Error('Collection#ensureIndex unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.findAndModify = function(){ + throw new Error('Collection#findAndModify unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.findOne = function(){ + throw new Error('Collection#findOne unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.find = function(){ + throw new Error('Collection#find unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.insert = function(){ + throw new Error('Collection#insert unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.save = function(){ + throw new Error('Collection#save unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.update = function(){ + throw new Error('Collection#update unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.getIndexes = function(){ + throw new Error('Collection#getIndexes unimplemented by driver'); +}; + +/** + * Abstract method that drivers must implement. + */ + +Collection.prototype.mapReduce = function(){ + throw new Error('Collection#mapReduce unimplemented by driver'); +}; + +/*! + * Module exports. + */ + +module.exports = Collection; diff --git a/node_modules/mongoose/lib/connection.js b/node_modules/mongoose/lib/connection.js new file mode 100644 index 0000000..ef4595f --- /dev/null +++ b/node_modules/mongoose/lib/connection.js @@ -0,0 +1,706 @@ +/*! + * Module dependencies. + */ + +var url = require('url') + , utils = require('./utils') + , EventEmitter = require('events').EventEmitter + , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native' + , Model = require('./model') + , Schema = require('./schema') + , Collection = require(driver + '/collection') + , STATES = require('./connectionstate') + , MongooseError = require('./error') + , assert =require('assert') + , muri = require('muri') + +/*! + * Protocol prefix regexp. + * + * @api private + */ + +var rgxProtocol = /^(?:.)+:\/\//; + +/** + * Connection constructor + * + * For practical reasons, a Connection equals a Db. + * + * @param {Mongoose} base a mongoose instance + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection. + * @event `connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios. + * @event `open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models. + * @event `disconnecting`: Emitted when `connection.close()` was executed. + * @event `disconnected`: Emitted after getting disconnected from the db. + * @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models. + * @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection. + * @event `error`: Emitted when an error occurs on this connection. + * @event `fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected. + * @api public + */ + +function Connection (base) { + this.base = base; + this.collections = {}; + this.models = {}; + this.replica = false; + this.hosts = null; + this.host = null; + this.port = null; + this.user = null; + this.pass = null; + this.name = null; + this.options = null; + this._readyState = STATES.disconnected; + this._closeCalled = false; + this._hasOpened = false; +}; + +/*! + * Inherit from EventEmitter + */ + +Connection.prototype.__proto__ = EventEmitter.prototype; + +/** + * Connection ready state + * + * - 0 = disconnected + * - 1 = connected + * - 2 = connecting + * - 3 = disconnecting + * + * Each state change emits its associated event name. + * + * ####Example + * + * conn.on('connected', callback); + * conn.on('disconnected', callback); + * + * @property readyState + * @api public + */ + +Object.defineProperty(Connection.prototype, 'readyState', { + get: function(){ return this._readyState; } + , set: function (val) { + if (!(val in STATES)) { + throw new Error('Invalid connection state: ' + val); + } + + if (this._readyState !== val) { + this._readyState = val; + + if (STATES.connected === val) + this._hasOpened = true; + + this.emit(STATES[val]); + } + } +}); + +/** + * A hash of the collections associated with this connection + * + * @property collections + */ + +Connection.prototype.collections; + +/** + * The mongodb.Db instance, set when the connection is opened + * + * @property db + */ + +Connection.prototype.db; + +/** + * Opens the connection to MongoDB. + * + * `options` is a hash with the following possible properties: + * + * db - passed to the connection db instance + * server - passed to the connection server instance(s) + * replset - passed to the connection ReplSet instance + * user - username for authentication + * pass - password for authentication + * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate) + * + * ####Notes: + * + * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden. + * Mongoose defaults the server `auto_reconnect` options to true which can be overridden. + * See the node-mongodb-native driver instance for options that it understands. + * + * _Options passed take precedence over options included in connection strings._ + * + * @param {String} connection_string mongodb://uri or the host to which you are connecting + * @param {String} [database] database name + * @param {Number} [port] database port + * @param {Object} [options] options + * @param {Function} [callback] + * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native + * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate + * @api public + */ + +Connection.prototype.open = function (host, database, port, options, callback) { + var self = this + , parsed + , uri; + + if ('string' === typeof database) { + switch (arguments.length) { + case 2: + port = 27017; + case 3: + switch (typeof port) { + case 'function': + callback = port, port = 27017; + break; + case 'object': + options = port, port = 27017; + break; + } + break; + case 4: + if ('function' === typeof options) + callback = options, options = {}; + } + } else { + switch (typeof database) { + case 'function': + callback = database, database = undefined; + break; + case 'object': + options = database; + database = undefined; + callback = port; + break; + } + + if (!rgxProtocol.test(host)) { + host = 'mongodb://' + host; + } + + try { + parsed = muri(host); + } catch (err) { + this.error(err, callback); + return this; + } + + database = parsed.db; + host = parsed.hosts[0].host || parsed.hosts[0].ipc; + port = parsed.hosts[0].port || 27017; + } + + this.options = this.parseOptions(options, parsed && parsed.options); + + // make sure we can open + if (STATES.disconnected !== this.readyState) { + var err = new Error('Trying to open unclosed connection.'); + err.state = this.readyState; + this.error(err, callback); + return this; + } + + if (!host) { + this.error(new Error('Missing hostname.'), callback); + return this; + } + + if (!database) { + this.error(new Error('Missing database name.'), callback); + return this; + } + + // authentication + if (options && options.user && options.pass) { + this.user = options.user; + this.pass = options.pass; + + } else if (parsed && parsed.auth) { + this.user = parsed.auth.user; + this.pass = parsed.auth.pass; + + // Check hostname for user/pass + } else if (/@/.test(host) && /:/.test(host.split('@')[0])) { + host = host.split('@'); + var auth = host.shift().split(':'); + host = host.pop(); + this.user = auth[0]; + this.pass = auth[1]; + + } else { + this.user = this.pass = undefined; + } + + this.name = database; + this.host = host; + this.port = port; + + this._open(callback); + return this; +}; + +/** + * Opens the connection to a replica set. + * + * ####Example: + * + * var db = mongoose.createConnection(); + * db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019"); + * + * The database name and/or auth need only be included in one URI. + * The `options` is a hash which is passed to the internal driver connection object. + * + * Valid `options` + * + * db - passed to the connection db instance + * server - passed to the connection server instance(s) + * replset - passed to the connection ReplSetServer instance + * user - username for authentication + * pass - password for authentication + * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate) + * + * _Options passed take precedence over options included in connection strings._ + * + * ####Notes: + * + * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden. + * Mongoose defaults the server `auto_reconnect` options to true which can be overridden. + * See the node-mongodb-native driver instance for options that it understands. + * + * @param {String} uris comma-separated mongodb:// `URI`s + * @param {String} [database] database name if not included in `uris` + * @param {Object} [options] passed to the internal driver + * @param {Function} [callback] + * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native + * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate + * @api public + */ + +Connection.prototype.openSet = function (uris, database, options, callback) { + if (!rgxProtocol.test(uris)) { + uris = 'mongodb://' + uris; + } + + var self = this; + + switch (arguments.length) { + case 3: + switch (typeof database) { + case 'string': + this.name = database; + break; + case 'object': + callback = options; + options = database; + database = null; + break; + } + + if ('function' === typeof options) { + callback = options; + options = {}; + } + break; + case 2: + switch (typeof database) { + case 'string': + this.name = database; + break; + case 'function': + callback = database, database = null; + break; + case 'object': + options = database, database = null; + break; + } + } + + var parsed; + try { + parsed = muri(uris); + } catch (err) { + this.error(err, callback); + return this; + } + + if (!this.name) { + this.name = parsed.db; + } + + this.hosts = parsed.hosts; + this.options = this.parseOptions(options, parsed && parsed.options); + this.replica = true; + + if (!this.name) { + this.error(new Error('No database name provided for replica set'), callback); + return this; + } + + // authentication + if (options && options.user && options.pass) { + this.user = options.user; + this.pass = options.pass; + + } else if (parsed && parsed.auth) { + this.user = parsed.auth.user; + this.pass = parsed.auth.pass; + + } else { + this.user = this.pass = undefined; + } + + this._open(callback); + return this; +}; + +/** + * error + * + * Graceful error handling, passes error to callback + * if available, else emits error on the connection. + * + * @param {Error} err + * @param {Function} callback optional + * @api private + */ + +Connection.prototype.error = function (err, callback) { + if (callback) return callback(err); + this.emit('error', err); +} + +/** + * Handles opening the connection with the appropriate method based on connection type. + * + * @param {Function} callback + * @api private + */ + +Connection.prototype._open = function (callback) { + this.readyState = STATES.connecting; + this._closeCalled = false; + + var self = this; + + var method = this.replica + ? 'doOpenSet' + : 'doOpen'; + + // open connection + this[method](function (err) { + if (err) { + self.readyState = STATES.disconnected; + if (self._hasOpened) { + if (callback) callback(err); + } else { + self.error(err, callback); + } + return; + } + + self.onOpen(callback); + }); +} + +/** + * Called when the connection is opened + * + * @api private + */ + +Connection.prototype.onOpen = function (callback) { + var self = this; + + function open (err) { + if (err) { + self.readyState = STATES.disconnected; + if (self._hasOpened) { + if (callback) callback(err); + } else { + self.error(err, callback); + } + return; + } + + self.readyState = STATES.connected; + + // avoid having the collection subscribe to our event emitter + // to prevent 0.3 warning + for (var i in self.collections) + self.collections[i].onOpen(); + + callback && callback(); + self.emit('open'); + }; + + // re-authenticate + if (self.user && self.pass) { + self.db.authenticate(self.user, self.pass, self.options.auth, open); + } + else + open(); +}; + +/** + * Closes the connection + * + * @param {Function} [callback] optional + * @return {Connection} self + * @api public + */ + +Connection.prototype.close = function (callback) { + var self = this; + this._closeCalled = true; + + switch (this.readyState){ + case 0: // disconnected + callback && callback(); + break; + + case 1: // connected + this.readyState = STATES.disconnecting; + this.doClose(function(err){ + if (err){ + self.error(err, callback); + } else { + self.onClose(); + callback && callback(); + } + }); + break; + + case 2: // connecting + this.once('open', function(){ + self.close(callback); + }); + break; + + case 3: // disconnecting + if (!callback) break; + this.once('close', function () { + callback(); + }); + break; + } + + return this; +}; + +/** + * Called when the connection closes + * + * @api private + */ + +Connection.prototype.onClose = function () { + this.readyState = STATES.disconnected; + + // avoid having the collection subscribe to our event emitter + // to prevent 0.3 warning + for (var i in this.collections) + this.collections[i].onClose(); + + this.emit('close'); +}; + +/** + * Retrieves a collection, creating it if not cached. + * + * Not typically needed by applications. Just talk to your collection through your model. + * + * @param {String} name of the collection + * @param {Object} [options] optional collection options + * @return {Collection} collection instance + * @api public + */ + +Connection.prototype.collection = function (name, options) { + if (!(name in this.collections)) + this.collections[name] = new Collection(name, this, options); + return this.collections[name]; +}; + +/** + * Defines or retrieves a model. + * + * var mongoose = require('mongoose'); + * var db = mongoose.createConnection(..); + * db.model('Venue', new Schema(..)); + * var Ticket = db.model('Ticket', new Schema(..)); + * var Venue = db.model('Venue'); + * + * _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils_exports.toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._ + * + * ####Example: + * + * var schema = new Schema({ name: String }, { collection: 'actor' }); + * + * // or + * + * schema.set('collection', 'actor'); + * + * // or + * + * var collectionName = 'actor' + * var M = conn.model('Actor', schema, collectionName) + * + * @param {String} name the model name + * @param {Schema} [schema] a schema. necessary when defining a model + * @param {String} [collection] name of mongodb collection (optional) if not given it will be induced from model name + * @see Mongoose#model #index_Mongoose-model + * @return {Model} The compiled model + * @api public + */ + +Connection.prototype.model = function (name, schema, collection) { + // collection name discovery + if ('string' == typeof schema) { + collection = schema; + schema = false; + } + + if (utils.isObject(schema) && !(schema instanceof Schema)) { + schema = new Schema(schema); + } + + if (this.models[name] && !collection) { + // model exists but we are not subclassing with custom collection + if (schema instanceof Schema && schema != this.models[name].schema) { + throw new MongooseError.OverwriteModelError(name); + } + return this.models[name]; + } + + var opts = { cache: false, connection: this } + var model; + + if (schema instanceof Schema) { + // compile a model + model = this.base.model(name, schema, collection, opts) + + // only the first model with this name is cached to allow + // for one-offs with custom collection names etc. + if (!this.models[name]) { + this.models[name] = model; + } + + model.init(); + return model; + } + + if (this.models[name] && collection) { + // subclassing current model with alternate collection + model = this.models[name]; + schema = model.prototype.schema; + var sub = model.__subclass(this, schema, collection); + // do not cache the sub model + return sub; + } + + // lookup model in mongoose module + model = this.base.models[name]; + + if (!model) { + throw new MongooseError.MissingSchemaError(name); + } + + if (this == model.prototype.db + && (!collection || collection == model.collection.name)) { + // model already uses this connection. + + // only the first model with this name is cached to allow + // for one-offs with custom collection names etc. + if (!this.models[name]) { + this.models[name] = model; + } + + return model; + } + + return this.models[name] = model.__subclass(this, schema, collection); +} + +/** + * Returns an array of model names created on this connection. + * @api public + * @return {Array} + */ + +Connection.prototype.modelNames = function () { + return Object.keys(this.models); +} + +/** + * Set profiling level. + * + * @param {Number|String} level either off (0), slow (1), or all (2) + * @param {Number} [ms] the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100. + * @param {Function} callback + * @api public + */ + +Connection.prototype.setProfiling = function (level, ms, callback) { + if (STATES.connected !== this.readyState) { + return this.on('open', this.setProfiling.bind(this, level, ms, callback)); + } + + if (!callback) callback = ms, ms = 100; + + var cmd = {}; + + switch (level) { + case 0: + case 'off': + cmd.profile = 0; + break; + case 1: + case 'slow': + cmd.profile = 1; + if ('number' !== typeof ms) { + ms = parseInt(ms, 10); + if (isNaN(ms)) ms = 100; + } + cmd.slowms = ms; + break; + case 2: + case 'all': + cmd.profile = 2; + break; + default: + return callback(new Error('Invalid profiling level: '+ level)); + } + + this.db.executeDbCommand(cmd, function (err, resp) { + if (err) return callback(err); + + var doc = resp.documents[0]; + + err = 1 === doc.ok + ? null + : new Error('Could not set profiling level to: '+ level) + + callback(err, doc); + }); +}; + +/*! + * Noop. + */ + +function noop () {} + +/*! + * Module exports. + */ + +Connection.STATES = STATES; +module.exports = Connection; diff --git a/node_modules/mongoose/lib/connectionstate.js b/node_modules/mongoose/lib/connectionstate.js new file mode 100644 index 0000000..2d05ab0 --- /dev/null +++ b/node_modules/mongoose/lib/connectionstate.js @@ -0,0 +1,24 @@ + +/*! + * Connection states + */ + +var STATES = module.exports = exports = Object.create(null); + +var disconnected = 'disconnected'; +var connected = 'connected'; +var connecting = 'connecting'; +var disconnecting = 'disconnecting'; +var uninitialized = 'uninitialized'; + +STATES[0] = disconnected; +STATES[1] = connected; +STATES[2] = connecting; +STATES[3] = disconnecting; +STATES[99] = uninitialized; + +STATES[disconnected] = 0; +STATES[connected] = 1; +STATES[connecting] = 2; +STATES[disconnecting] = 3; +STATES[uninitialized] = 99; diff --git a/node_modules/mongoose/lib/document.js b/node_modules/mongoose/lib/document.js new file mode 100644 index 0000000..9a460ae --- /dev/null +++ b/node_modules/mongoose/lib/document.js @@ -0,0 +1,1712 @@ +/*! + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , setMaxListeners = EventEmitter.prototype.setMaxListeners + , MongooseError = require('./error') + , MixedSchema = require('./schema/mixed') + , Schema = require('./schema') + , ValidatorError = require('./schematype').ValidatorError + , utils = require('./utils') + , clone = utils.clone + , isMongooseObject = utils.isMongooseObject + , inspect = require('util').inspect + , ElemMatchError = MongooseError.ElemMatchError + , ValidationError = MongooseError.ValidationError + , DocumentError = MongooseError.DocumentError + , InternalCache = require('./internal') + , deepEqual = utils.deepEqual + , hooks = require('hooks') + , DocumentArray + , MongooseArray + , Embedded + +/** + * Document constructor. + * + * @param {Object} obj the values to set + * @param {Object} [opts] optional object containing the fields which were selected in the query returning this document and any populated paths data + * @param {Boolean} [skipId] bool, should we auto create an ObjectId _id + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose. + * @event `save`: Emitted when the document is successfully saved + * @api private + */ + +function Document (obj, fields, skipId) { + this.$__ = new InternalCache; + this.isNew = true; + this.errors = undefined; + + var schema = this.schema; + + if ('boolean' === typeof fields) { + this.$__.strictMode = fields; + fields = undefined; + } else { + this.$__.strictMode = schema.options && schema.options.strict; + this.$__.selected = fields; + } + + var required = schema.requiredPaths(); + for (var i = 0; i < required.length; ++i) { + this.$__.activePaths.require(required[i]); + } + + setMaxListeners.call(this, 0); + this._doc = this.$__buildDoc(obj, fields, skipId); + + if (obj) { + this.set(obj, undefined, true); + } + + this.$__registerHooks(); +} + +/*! + * Inherit from EventEmitter. + */ + +Document.prototype.__proto__ = EventEmitter.prototype; + +/** + * The documents schema. + * + * @api public + * @property schema + */ + +Document.prototype.schema; + +/** + * Boolean flag specifying if the document is new. + * + * @api public + * @property isNew + */ + +Document.prototype.isNew; + +/** + * The string version of this documents _id. + * + * ####Note: + * + * This getter exists on all documents by default. The getter can be disabled by setting the `id` [option](/docs/guide.html#id) of its `Schema` to false at construction time. + * + * new Schema({ name: String }, { id: false }); + * + * @api public + * @see Schema options /docs/guide.html#options + * @property id + */ + +Document.prototype.id; + +/** + * Hash containing current validation errors. + * + * @api public + * @property errors + */ + +Document.prototype.errors; + +/** + * Builds the default doc structure + * + * @param {Object} obj + * @param {Object} [fields] + * @param {Boolean} [skipId] + * @return {Object} + * @api private + * @method $__buildDoc + * @memberOf Document + */ + +Document.prototype.$__buildDoc = function (obj, fields, skipId) { + var doc = {} + , self = this + , exclude + , keys + , key + , ki + + // determine if this doc is a result of a query with + // excluded fields + if (fields && 'Object' === fields.constructor.name) { + keys = Object.keys(fields); + ki = keys.length; + + while (ki--) { + if ('_id' !== keys[ki]) { + exclude = 0 === fields[keys[ki]]; + break; + } + } + } + + var paths = Object.keys(this.schema.paths) + , plen = paths.length + , ii = 0 + + for (; ii < plen; ++ii) { + var p = paths[ii]; + + if ('_id' == p) { + if (skipId) continue; + if (obj && '_id' in obj) continue; + } + + var type = this.schema.paths[p] + , path = p.split('.') + , len = path.length + , last = len-1 + , doc_ = doc + , i = 0 + + for (; i < len; ++i) { + var piece = path[i] + , def + + if (i === last) { + if (fields) { + if (exclude) { + // apply defaults to all non-excluded fields + if (p in fields) continue; + + def = type.getDefault(self, true); + if ('undefined' !== typeof def) { + doc_[piece] = def; + self.$__.activePaths.default(p); + } + + } else if (p in fields) { + // selected field + def = type.getDefault(self, true); + if ('undefined' !== typeof def) { + doc_[piece] = def; + self.$__.activePaths.default(p); + } + } + } else { + def = type.getDefault(self, true); + if ('undefined' !== typeof def) { + doc_[piece] = def; + self.$__.activePaths.default(p); + } + } + } else { + doc_ = doc_[piece] || (doc_[piece] = {}); + } + } + }; + + return doc; +}; + +/** + * Initializes the document without setters or marking anything modified. + * + * Called internally after a document is returned from mongodb. + * + * @param {Object} doc document returned by mongo + * @param {Function} fn callback + * @api private + */ + +Document.prototype.init = function (doc, opts, fn) { + // do not prefix this method with $__ since its + // used by public hooks + + if ('function' == typeof opts) { + fn = opts; + opts = null; + } + + this.isNew = false; + + // handle docs with populated paths + if (doc._id && opts && opts.populated && opts.populated.length) { + var id = String(doc._id); + for (var i = 0; i < opts.populated.length; ++i) { + var item = opts.populated[i]; + this.populated(item.path, item._docs[id], item); + } + } + + init(this, doc, this._doc); + this.$__storeShard(); + + this.emit('init', this); + if (fn) fn(null); + return this; +}; + +/*! + * Init helper. + * + * @param {Object} self document instance + * @param {Object} obj raw mongodb doc + * @param {Object} doc object we are initializing + * @api private + */ + +function init (self, obj, doc, prefix) { + prefix = prefix || ''; + + var keys = Object.keys(obj) + , len = keys.length + , schema + , path + , i; + + while (len--) { + i = keys[len]; + path = prefix + i; + schema = self.schema.path(path); + + if (!schema && utils.isObject(obj[i]) && + (!obj[i].constructor || 'Object' == obj[i].constructor.name)) { + // assume nested object + if (!doc[i]) doc[i] = {}; + init(self, obj[i], doc[i], path + '.'); + } else { + if (obj[i] === null) { + doc[i] = null; + } else if (obj[i] !== undefined) { + if (schema) { + self.$__try(function(){ + doc[i] = schema.cast(obj[i], self, true); + }); + } else { + doc[i] = obj[i]; + } + } + // mark as hydrated + self.$__.activePaths.init(path); + } + } +}; + +/** + * Stores the current values of the shard keys. + * + * ####Note: + * + * _Shard key values do not / are not allowed to change._ + * + * @api private + * @method $__storeShard + * @memberOf Document + */ + +Document.prototype.$__storeShard = function () { + // backwards compat + var key = this.schema.options.shardKey || this.schema.options.shardkey; + if (!(key && 'Object' == key.constructor.name)) return; + + var orig = this.$__.shardval = {} + , paths = Object.keys(key) + , len = paths.length + , val + + for (var i = 0; i < len; ++i) { + val = this.getValue(paths[i]); + if (isMongooseObject(val)) { + orig[paths[i]] = val.toObject({ depopulate: true }) + } else if (null != val && val.valueOf) { + orig[paths[i]] = val.valueOf(); + } else { + orig[paths[i]] = val; + } + } +} + +/*! + * Set up middleware support + */ + +for (var k in hooks) { + Document.prototype[k] = Document[k] = hooks[k]; +} + +/** + * Sends an update command with this document `_id` as the query selector. + * + * ####Example: + * + * weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback); + * + * ####Valid options: + * + * - same as in [Model.update](#model_Model.update) + * + * @see Model.update #model_Model.update + * @param {Object} doc + * @param {Object} options + * @param {Function} callback + * @return {Query} + * @api public + */ + +Document.prototype.update = function update () { + var args = utils.args(arguments); + args.unshift({_id: this._id}); + return this.constructor.update.apply(this.constructor, args); +} + +/** + * Sets the value of a path, or many paths. + * + * ####Example: + * + * // path, value + * doc.set(path, value) + * + * // object + * doc.set({ + * path : value + * , path2 : { + * path : value + * } + * }) + * + * // only-the-fly cast to number + * doc.set(path, value, Number) + * + * // only-the-fly cast to string + * doc.set(path, value, String) + * + * // changing strict mode behavior + * doc.set(path, value, { strict: false }); + * + * @param {String|Object} path path or object of key/vals to set + * @param {Any} val the value to set + * @param {Schema|String|Number|Buffer|etc..} [type] optionally specify a type for "on-the-fly" attributes + * @param {Object} [options] optionally specify options that modify the behavior of the set + * @api public + */ + +Document.prototype.set = function (path, val, type, options) { + if (type && 'Object' == type.constructor.name) { + options = type; + type = undefined; + } + + var merge = options && options.merge + , adhoc = type && true !== type + , constructing = true === type + , adhocs + + var strict = options && 'strict' in options + ? options.strict + : this.$__.strictMode; + + if (adhoc) { + adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {}); + adhocs[path] = Schema.interpretAsType(path, type); + } + + if ('string' !== typeof path) { + // new Document({ key: val }) + + if (null === path || undefined === path) { + var _ = path; + path = val; + val = _; + + } else { + var prefix = val + ? val + '.' + : ''; + + if (path instanceof Document) path = path._doc; + + var keys = Object.keys(path) + , i = keys.length + , pathtype + , key + + while (i--) { + key = keys[i]; + pathtype = this.schema.pathType(prefix + key); + if (null != path[key] + // need to know if plain object - no Buffer, ObjectId, etc + && utils.isObject(path[key]) + && (!path[key].constructor || 'Object' == path[key].constructor.name) + && 'virtual' != pathtype + && !(this.$__path(prefix + key) instanceof MixedSchema)) { + this.set(path[key], prefix + key, constructing); + } else if (strict) { + if ('real' === pathtype || 'virtual' === pathtype) { + this.set(prefix + key, path[key], constructing); + } else if ('throw' == strict) { + throw new Error("Field `" + key + "` is not in schema."); + } + } else if (undefined !== path[key]) { + this.set(prefix + key, path[key], constructing); + } + } + + return this; + } + } + + // ensure _strict is honored for obj props + // docschema = new Schema({ path: { nest: 'string' }}) + // doc.set('path', obj); + var pathType = this.schema.pathType(path); + if ('nested' == pathType && val && utils.isObject(val) && + (!val.constructor || 'Object' == val.constructor.name)) { + if (!merge) this.setValue(path, null); + this.set(val, path, constructing); + return this; + } + + var schema; + var parts = path.split('.'); + + if ('adhocOrUndefined' == pathType && strict) { + + // check for roots that are Mixed types + var mixed; + + for (var i = 0; i < parts.length; ++i) { + var subpath = parts.slice(0, i+1).join('.'); + schema = this.schema.path(subpath); + if (schema instanceof MixedSchema) { + // allow changes to sub paths of mixed types + mixed = true; + break; + } + } + + if (!mixed) { + if ('throw' == strict) { + throw new Error("Field `" + path + "` is not in schema."); + } + return this; + } + + } else if ('virtual' == pathType) { + schema = this.schema.virtualpath(path); + schema.applySetters(val, this); + return this; + } else { + schema = this.$__path(path); + } + + var pathToMark; + + // When using the $set operator the path to the field must already exist. + // Else mongodb throws: "LEFT_SUBFIELD only supports Object" + + if (parts.length <= 1) { + pathToMark = path; + } else { + for (var i = 0; i < parts.length; ++i) { + var subpath = parts.slice(0, i+1).join('.'); + if (this.isDirectModified(subpath) // earlier prefixes that are already + // marked as dirty have precedence + || this.get(subpath) === null) { + pathToMark = subpath; + break; + } + } + + if (!pathToMark) pathToMark = path; + } + + // if this doc is being constructed we should not trigger getters + var priorVal = constructing + ? undefined + : this.get(path); + + if (!schema || null === val || undefined === val) { + this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal); + return this; + } + + var self = this; + var shouldSet = this.$__try(function(){ + val = schema.applySetters(val, self, false, priorVal); + }); + + if (shouldSet) { + this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal); + } + + return this; +} + +/** + * Determine if we should mark this change as modified. + * + * @return {Boolean} + * @api private + * @method $__shouldModify + * @memberOf Document + */ + +Document.prototype.$__shouldModify = function ( + pathToMark, path, constructing, parts, schema, val, priorVal) { + + if (this.isNew) return true; + if (this.isDirectModified(pathToMark)) return false; + + if (undefined === val && !this.isSelected(path)) { + // when a path is not selected in a query, its initial + // value will be undefined. + return true; + } + + if (undefined === val && path in this.$__.activePaths.states.default) { + // we're just unsetting the default value which was never saved + return false; + } + + if (!deepEqual(val, priorVal || this.get(path))) { + return true; + } + + if (!constructing && + null != val && + path in this.$__.activePaths.states.default && + deepEqual(val, schema.getDefault(this, constructing))) { + // a path with a default was $unset on the server + // and the user is setting it to the same value again + return true; + } + + return false; +} + +/** + * Handles the actual setting of the value and marking the path modified if appropriate. + * + * @api private + * @method $__set + * @memberOf Document + */ + +Document.prototype.$__set = function ( + pathToMark, path, constructing, parts, schema, val, priorVal) { + + var shouldModify = this.$__shouldModify.apply(this, arguments); + + if (shouldModify) { + this.markModified(pathToMark, val); + + // handle directly setting arrays (gh-1126) + MongooseArray || (MongooseArray = require('./types/array')); + if (val instanceof MongooseArray) { + val._registerAtomic('$set', val); + } + } + + var obj = this._doc + , i = 0 + , l = parts.length + + for (; i < l; i++) { + var next = i + 1 + , last = next === l; + + if (last) { + obj[parts[i]] = val; + } else { + if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) { + obj = obj[parts[i]]; + } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) { + obj = obj[parts[i]]; + } else { + obj = obj[parts[i]] = {}; + } + } + } +} + +/** + * Gets a raw value from a path (no getters) + * + * @param {String} path + * @api private + */ + +Document.prototype.getValue = function (path) { + return utils.getValue(path, this._doc); +} + +/** + * Sets a raw value for a path (no casting, setters, transformations) + * + * @param {String} path + * @param {Object} value + * @api private + */ + +Document.prototype.setValue = function (path, val) { + utils.setValue(path, val, this._doc); + return this; +} + +/** + * Returns the value of a path. + * + * ####Example + * + * // path + * doc.get('age') // 47 + * + * // dynamic casting to a string + * doc.get('age', String) // "47" + * + * @param {String} path + * @param {Schema|String|Number|Buffer|etc..} [type] optionally specify a type for on-the-fly attributes + * @api public + */ + +Document.prototype.get = function (path, type) { + var adhocs; + if (type) { + adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {}); + adhocs[path] = Schema.interpretAsType(path, type); + } + + var schema = this.$__path(path) || this.schema.virtualpath(path) + , pieces = path.split('.') + , obj = this._doc; + + for (var i = 0, l = pieces.length; i < l; i++) { + obj = undefined === obj || null === obj + ? undefined + : obj[pieces[i]]; + } + + if (schema) { + obj = schema.applyGetters(obj, this); + } + + return obj; +}; + +/** + * Returns the schematype for the given `path`. + * + * @param {String} path + * @api private + * @method $__path + * @memberOf Document + */ + +Document.prototype.$__path = function (path) { + var adhocs = this.$__.adhocPaths + , adhocType = adhocs && adhocs[path]; + + if (adhocType) { + return adhocType; + } else { + return this.schema.path(path); + } +}; + +/** + * Marks the path as having pending changes to write to the db. + * + * _Very helpful when using [Mixed](./schematypes.html#mixed) types._ + * + * ####Example: + * + * doc.mixed.type = 'changed'; + * doc.markModified('mixed.type'); + * doc.save() // changes to mixed.type are now persisted + * + * @param {String} path the path to mark modified + * @api public + */ + +Document.prototype.markModified = function (path) { + this.$__.activePaths.modify(path); +} + +/** + * Catches errors that occur during execution of `fn` and stores them to later be passed when `save()` is executed. + * + * @param {Function} fn function to execute + * @param {Object} scope the scope with which to call fn + * @api private + * @method $__try + * @memberOf Document + */ + +Document.prototype.$__try = function (fn, scope) { + var res; + try { + fn.call(scope); + res = true; + } catch (e) { + this.$__error(e); + res = false; + } + return res; +}; + +/** + * Returns the list of paths that have been modified. + * + * @return {Array} + * @api public + */ + +Document.prototype.modifiedPaths = function () { + var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify); + + return directModifiedPaths.reduce(function (list, path) { + var parts = path.split('.'); + return list.concat(parts.reduce(function (chains, part, i) { + return chains.concat(parts.slice(0, i).concat(part).join('.')); + }, [])); + }, []); +}; + +/** + * Returns true if this document was modified, else false. + * + * If `path` is given, checks if a path or any full path containing `path` as part of its path chain has been modified. + * + * ####Example + * + * doc.set('documents.0.title', 'changed'); + * doc.isModified() // true + * doc.isModified('documents') // true + * doc.isModified('documents.0.title') // true + * doc.isDirectModified('documents') // false + * + * @param {String} [path] optional + * @return {Boolean} + * @api public + */ + +Document.prototype.isModified = function (path) { + return path + ? !!~this.modifiedPaths().indexOf(path) + : this.$__.activePaths.some('modify'); +}; + +/** + * Returns true if `path` was directly set and modified, else false. + * + * ####Example + * + * doc.set('documents.0.title', 'changed'); + * doc.isDirectModified('documents.0.title') // true + * doc.isDirectModified('documents') // false + * + * @param {String} path + * @return {Boolean} + * @api public + */ + +Document.prototype.isDirectModified = function (path) { + return (path in this.$__.activePaths.states.modify); +}; + +/** + * Checks if `path` was initialized. + * + * @param {String} path + * @return {Boolean} + * @api public + */ + +Document.prototype.isInit = function (path) { + return (path in this.$__.activePaths.states.init); +}; + +/** + * Checks if `path` was selected in the source query which initialized this document. + * + * ####Example + * + * Thing.findOne().select('name').exec(function (err, doc) { + * doc.isSelected('name') // true + * doc.isSelected('age') // false + * }) + * + * @param {String} path + * @return {Boolean} + * @api public + */ + +Document.prototype.isSelected = function isSelected (path) { + if (this.$__.selected) { + + if ('_id' === path) { + return 0 !== this.$__.selected._id; + } + + var paths = Object.keys(this.$__.selected) + , i = paths.length + , inclusive = false + , cur + + if (1 === i && '_id' === paths[0]) { + // only _id was selected. + return 0 === this.$__.selected._id; + } + + while (i--) { + cur = paths[i]; + if ('_id' == cur) continue; + inclusive = !! this.$__.selected[cur]; + break; + } + + if (path in this.$__.selected) { + return inclusive; + } + + i = paths.length; + var pathDot = path + '.'; + + while (i--) { + cur = paths[i]; + if ('_id' == cur) continue; + + if (0 === cur.indexOf(pathDot)) { + return inclusive; + } + + if (0 === pathDot.indexOf(cur + '.')) { + return inclusive; + } + } + + return ! inclusive; + } + + return true; +} + +/** + * Executes registered validation rules for this document. + * + * ####Note: + * + * This method is called `pre` save and if a validation rule is violated, [save](#model_Model-save) is aborted and the error is returned to your `callback`. + * + * ####Example: + * + * doc.validate(function (err) { + * if (err) handleError(err); + * else // validation passed + * }); + * + * @param {Function} cb called after validation completes, passing an error if one occurred + * @api public + */ + +Document.prototype.validate = function (cb) { + var self = this + + // only validate required fields when necessary + var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) { + if (!self.isSelected(path) && !self.isModified(path)) return false; + return true; + }); + + paths = paths.concat(Object.keys(this.$__.activePaths.states.init)); + paths = paths.concat(Object.keys(this.$__.activePaths.states.modify)); + paths = paths.concat(Object.keys(this.$__.activePaths.states.default)); + + if (0 === paths.length) { + complete(); + return this; + } + + var validating = {} + , total = 0; + + paths.forEach(validatePath); + return this; + + function validatePath (path) { + if (validating[path]) return; + + validating[path] = true; + total++; + + process.nextTick(function(){ + var p = self.schema.path(path); + if (!p) return --total || complete(); + + var val = self.getValue(path); + p.doValidate(val, function (err) { + if (err) { + self.invalidate( + path + , err + , undefined + , true // embedded docs + ); + } + --total || complete(); + }, self); + }); + } + + function complete () { + var err = self.$__.validationError; + self.$__.validationError = undefined; + self.emit('validate', self); + cb(err); + } +}; + +/** + * Marks a path as invalid, causing validation to fail. + * + * @param {String} path the field to invalidate + * @param {String|Error} err the error which states the reason `path` was invalid + * @param {Object|String|Number|any} value optional invalid value + * @api public + */ + +Document.prototype.invalidate = function (path, err, val) { + if (!this.$__.validationError) { + this.$__.validationError = new ValidationError(this); + } + + if (!err || 'string' === typeof err) { + // sniffing arguments: + // need to handle case where user does not pass value + // so our error message is cleaner + err = 2 < arguments.length + ? new ValidatorError(path, err, val) + : new ValidatorError(path, err) + } + + this.$__.validationError.errors[path] = err; +} + +/** + * Resets the internal modified state of this document. + * + * @api private + * @return {Document} + * @method $__reset + * @memberOf Document + */ + +Document.prototype.$__reset = function reset () { + var self = this; + DocumentArray || (DocumentArray = require('./types/documentarray')); + + this.$__.activePaths + .map('init', 'modify', function (i) { + return self.getValue(i); + }) + .filter(function (val) { + return val && val instanceof DocumentArray && val.length; + }) + .forEach(function (array) { + var i = array.length; + while (i--) { + var doc = array[i]; + if (!doc) continue; + doc.$__reset(); + } + }); + + // clear atomics + this.$__dirty().forEach(function (dirt) { + var type = dirt.value; + if (type && type._atomics) { + type._atomics = {}; + } + }); + + // Clear 'modify'('dirty') cache + this.$__.activePaths.clear('modify'); + this.$__.validationError = undefined; + this.errors = undefined; + var self = this; + this.schema.requiredPaths().forEach(function (path) { + self.$__.activePaths.require(path); + }); + + return this; +} + +/** + * Returns this documents dirty paths / vals. + * + * @api private + * @method $__dirty + * @memberOf Document + */ + +Document.prototype.$__dirty = function () { + var self = this; + + var all = this.$__.activePaths.map('modify', function (path) { + return { path: path + , value: self.getValue(path) + , schema: self.$__path(path) }; + }); + + // Sort dirty paths in a flat hierarchy. + all.sort(function (a, b) { + return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0)); + }); + + // Ignore "foo.a" if "foo" is dirty already. + var minimal = [] + , lastPath + , top; + + all.forEach(function (item, i) { + if (item.path.indexOf(lastPath) !== 0) { + lastPath = item.path + '.'; + minimal.push(item); + top = item; + } else { + // special case for top level MongooseArrays + if (top.value && top.value._atomics && top.value.hasAtomics()) { + // the `top` array itself and a sub path of `top` are being modified. + // the only way to honor all of both modifications is through a $set + // of entire array. + top.value._atomics = {}; + top.value._atomics.$set = top.value; + } + } + }); + + top = lastPath = null; + return minimal; +} + +/*! + * Compiles schemas. + */ + +function compile (tree, proto, prefix) { + var keys = Object.keys(tree) + , i = keys.length + , limb + , key; + + while (i--) { + key = keys[i]; + limb = tree[key]; + + define(key + , (('Object' === limb.constructor.name + && Object.keys(limb).length) + && (!limb.type || limb.type.type) + ? limb + : null) + , proto + , prefix + , keys); + } +}; + +/*! + * Defines the accessor named prop on the incoming prototype. + */ + +function define (prop, subprops, prototype, prefix, keys) { + var prefix = prefix || '' + , path = (prefix ? prefix + '.' : '') + prop; + + if (subprops) { + + Object.defineProperty(prototype, prop, { + enumerable: true + , get: function () { + if (!this.$__.getters) + this.$__.getters = {}; + + if (!this.$__.getters[path]) { + var nested = Object.create(this); + + // save scope for nested getters/setters + if (!prefix) nested.$__.scope = this; + + // shadow inherited getters from sub-objects so + // thing.nested.nested.nested... doesn't occur (gh-366) + var i = 0 + , len = keys.length; + + for (; i < len; ++i) { + // over-write the parents getter without triggering it + Object.defineProperty(nested, keys[i], { + enumerable: false // It doesn't show up. + , writable: true // We can set it later. + , configurable: true // We can Object.defineProperty again. + , value: undefined // It shadows its parent. + }); + } + + nested.toObject = function () { + return this.get(path); + }; + + compile(subprops, nested, path); + this.$__.getters[path] = nested; + } + + return this.$__.getters[path]; + } + , set: function (v) { + if (v instanceof Document) v = v.toObject(); + return (this.$__.scope || this).set(path, v); + } + }); + + } else { + + Object.defineProperty(prototype, prop, { + enumerable: true + , get: function ( ) { return this.get.call(this.$__.scope || this, path); } + , set: function (v) { return this.set.call(this.$__.scope || this, path, v); } + }); + } +}; + +/** + * Assigns/compiles `schema` into this documents prototype. + * + * @param {Schema} schema + * @api private + * @method $__setSchema + * @memberOf Document + */ + +Document.prototype.$__setSchema = function (schema) { + compile(schema.tree, this); + this.schema = schema; +} + +/** + * Register default hooks + * + * @api private + * @method $__registerHooks + * @memberOf Document + */ + +Document.prototype.$__registerHooks = function () { + if (!this.save) return; + + DocumentArray || (DocumentArray = require('./types/documentarray')); + + this.pre('save', function (next) { + // validate all document arrays. + // we keep the error semaphore to make sure we don't + // call `save` unnecessarily (we only need 1 error) + var subdocs = 0 + , error = false + , self = this; + + // check for DocumentArrays + var arrays = this.$__.activePaths + .map('init', 'modify', function (i) { + return self.getValue(i); + }) + .filter(function (val) { + return val && val instanceof DocumentArray && val.length; + }); + + if (!arrays.length) + return next(); + + arrays.forEach(function (array) { + if (error) return; + + // handle sparse arrays by using for loop vs array.forEach + // which skips the sparse elements + + var len = array.length + subdocs += len; + + for (var i = 0; i < len; ++i) { + if (error) break; + + var doc = array[i]; + if (!doc) { + --subdocs || next(); + continue; + } + + doc.save(handleSave); + } + }); + + function handleSave (err) { + if (error) return; + + if (err) { + self.$__.validationError = undefined; + return next(error = err); + } + + --subdocs || next(); + } + + }, function (err) { + // emit on the Model if listening + if (this.constructor.listeners('error').length) { + this.constructor.emit('error', err); + } else { + // emit on the connection + if (!this.db.listeners('error').length) { + err.stack = 'No listeners detected, throwing. ' + + 'Consider adding an error listener to your connection.\n' + + err.stack + } + this.db.emit('error', err); + } + }).pre('save', function checkForExistingErrors (next) { + // if any doc.set() calls failed + var err = this.$__.saveError; + if (err) { + this.$__.saveError = null; + next(err); + } else { + next(); + } + }).pre('save', function validation (next) { + return this.validate(next); + }); + + // add user defined queues + this.$__doQueue(); +}; + +/** + * Registers an error + * + * @param {Error} err + * @api private + * @method $__error + * @memberOf Document + */ + +Document.prototype.$__error = function (err) { + this.$__.saveError = err; + return this; +}; + +/** + * Executes methods queued from the Schema definition + * + * @api private + * @method $__doQueue + * @memberOf Document + */ + +Document.prototype.$__doQueue = function () { + var q = this.schema && this.schema.callQueue; + if (q) { + for (var i = 0, l = q.length; i < l; i++) { + this[q[i][0]].apply(this, q[i][1]); + } + } + return this; +}; + +/** + * Converts this document into a plain javascript object, ready for storage in MongoDB. + * + * Buffers are converted to instances of [mongodb.Binary](http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html) for proper storage. + * + * ####Options: + * + * - `getters` apply all getters (path and virtual getters) + * - `virtuals` apply virtual getters (can override `getters` option) + * - `minimize` remove empty objects (defaults to true) + * - `transform` a transform function to apply to the resulting document before returning + * + * ####Getters/Virtuals + * + * Example of only applying path getters + * + * doc.toObject({ getters: true, virtuals: false }) + * + * Example of only applying virtual getters + * + * doc.toObject({ virtuals: true }) + * + * Example of applying both path and virtual getters + * + * doc.toObject({ getters: true }) + * + * To apply these options to every document of your schema by default, set your [schemas](#schema_Schema) `toObject` option to the same argument. + * + * schema.set('toObject', { virtuals: true }) + * + * ####Transform + * + * We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional `transform` function. + * + * Transform functions receive three arguments + * + * function (doc, ret, options) {} + * + * - `doc` The mongoose document which is being converted + * - `ret` The plain object representation which has been converted + * - `options` The options in use (either schema options or the options passed inline) + * + * ####Example + * + * // specify the transform schema option + * schema.options.toObject.transform = function (doc, ret, options) { + * // remove the _id of every document before returning the result + * delete ret._id; + * } + * + * // without the transformation in the schema + * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' } + * + * // with the transformation + * doc.toObject(); // { name: 'Wreck-it Ralph' } + * + * With transformations we can do a lot more than remove properties. We can even return completely new customized objects: + * + * schema.options.toObject.transform = function (doc, ret, options) { + * return { movie: ret.name } + * } + * + * // without the transformation in the schema + * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' } + * + * // with the transformation + * doc.toObject(); // { movie: 'Wreck-it Ralph' } + * + * _Note: if a transform function returns `undefined`, the return value will be ignored._ + * + * Transformations may also be applied inline, overridding any transform set in the options: + * + * function xform (doc, ret, options) { + * return { inline: ret.name, custom: true } + * } + * + * // pass the transform as an inline option + * doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true } + * + * _Note: if you call `toObject` and pass any options, the transform declared in your schema options will __not__ be applied. To force its application pass `transform: true`_ + * + * schema.options.toObject.hide = '_id'; + * schema.options.toObject.transform = function (doc, ret, options) { + * if (options.hide) { + * options.hide.split(' ').forEach(function (prop) { + * delete ret[prop]; + * }); + * } + * } + * + * var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }); + * doc.toObject(); // { secret: 47, name: 'Wreck-it Ralph' } + * doc.toObject({ hide: 'secret _id' }); // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' } + * doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' } + * + * Transforms are applied to the document _and each of its sub-documents_. To determine whether or not you are currently operating on a sub-document you might use the following guard: + * + * if ('function' == typeof doc.ownerDocument) { + * // working with a sub doc + * } + * + * Transforms, like all of these options, are also available for `toJSON`. + * + * See [schema options](/docs/guide.html#toObject) for some more details. + * + * _During save, no custom options are applied to the document before being sent to the database._ + * + * @param {Object} [options] + * @return {Object} js object + * @see mongodb.Binary http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html + * @api public + */ + +Document.prototype.toObject = function (options) { + if (options && options.depopulate && this.$__.wasPopulated) { + // populated paths that we set to a document + return clone(this._id, options); + } + + // When internally saving this document we always pass options, + // bypassing the custom schema options. + if (!(options && 'Object' == options.constructor.name)) { + options = this.schema.options.toObject + ? clone(this.schema.options.toObject) + : {}; + } + + ;('minimize' in options) || (options.minimize = this.schema.options.minimize); + + var ret = clone(this._doc, options); + + if (options.virtuals || options.getters && false !== options.virtuals) { + applyGetters(this, ret, 'virtuals', options); + } + + if (options.getters) { + applyGetters(this, ret, 'paths', options); + } + + if (true === options.transform) { + var opts = options.json + ? this.schema.options.toJSON + : this.schema.options.toObject; + if (opts) { + options.transform = opts.transform; + } + } + + if ('function' == typeof options.transform) { + var xformed = options.transform(this, ret, options); + if ('undefined' != typeof xformed) ret = xformed; + } + + return ret; +}; + +/*! + * Applies virtuals properties to `json`. + * + * @param {Document} self + * @param {Object} json + * @param {String} type either `virtuals` or `paths` + * @return {Object} `json` + */ + +function applyGetters (self, json, type, options) { + var schema = self.schema + , paths = Object.keys(schema[type]) + , i = paths.length + , path + + while (i--) { + path = paths[i]; + + var parts = path.split('.') + , plen = parts.length + , last = plen - 1 + , branch = json + , part + + for (var ii = 0; ii < plen; ++ii) { + part = parts[ii]; + if (ii === last) { + branch[part] = clone(self.get(path), options); + } else { + branch = branch[part] || (branch[part] = {}); + } + } + } + + return json; +} + +/** + * The return value of this method is used in calls to JSON.stringify(doc). + * + * This method accepts the same options as [Document#toObject](#document_Document-toObject). To apply the options to every document of your schema by default, set your [schemas](#schema_Schema) `toJSON` option to the same argument. + * + * schema.set('toJSON', { virtuals: true }) + * + * See [schema options](/docs/guide.html#toJSON) for details. + * + * @param {Object} options same options as [Document#toObject](#document_Document-toObject) + * @return {Object} + * @see Document#toObject #document_Document-toObject + + * @api public + */ + +Document.prototype.toJSON = function (options) { + // check for object type since an array of documents + // being stringified passes array indexes instead + // of options objects. JSON.stringify([doc, doc]) + if (!(options && 'Object' == options.constructor.name)) { + options = this.schema.options.toJSON + ? clone(this.schema.options.toJSON) + : {}; + } + options.json = true; + return this.toObject(options); +}; + +/** + * Helper for console.log + * + * @api public + */ + +Document.prototype.inspect = function (options) { + var opts = options && 'Object' == options.constructor.name ? options : + this.schema.options.toObject ? clone(this.schema.options.toObject) : + {}; + opts.minimize = false; + return inspect(this.toObject(opts)); +}; + +/** + * Helper for console.log + * + * @api public + * @method toString + */ + +Document.prototype.toString = Document.prototype.inspect; + +/** + * Returns true if the Document stores the same data as doc. + * + * Documents are considered equal when they have matching `_id`s. + * + * @param {Document} doc a document to compare + * @return {Boolean} + * @api public + */ + +Document.prototype.equals = function (doc) { + var tid = this.get('_id'); + var docid = doc.get('_id'); + return tid.equals + ? tid.equals(docid) + : tid === docid; +} + +/** + * Populates document references, executing the `callback` when complete. + * + * ####Example: + * + * doc + * .populate('company') + * .populate({ + * path: 'notes', + * match: /airline/, + * select: 'text', + * model: 'modelName' + * options: opts + * }, function (err, user) { + * assert(doc._id == user._id) // the document itself is passed + * }) + * + * // summary + * doc.populate(path) // not executed + * doc.populate(options); // not executed + * doc.populate(path, callback) // executed + * doc.populate(options, callback); // executed + * doc.populate(callback); // executed + * + * + * ####NOTE: + * + * Population does not occur unless a `callback` is passed. + * Passing the same path a second time will overwrite the previous path options. + * See [Model.populate()](#model_Model.populate) for explaination of options. + * + * @see Model.populate #model_Model.populate + * @param {String|Object} [path] The path to populate or an options object + * @param {Function} [callback] When passed, population is invoked + * @api public + * @return {Document} this + */ + +Document.prototype.populate = function populate () { + if (0 === arguments.length) return this; + + var pop = this.$__.populate || (this.$__.populate = {}); + var args = utils.args(arguments); + var fn; + + if ('function' == typeof args[args.length-1]) { + fn = args.pop(); + } + + // allow `doc.populate(callback)` + if (args.length) { + // use hash to remove duplicate paths + var res = utils.populate.apply(null, args); + for (var i = 0; i < res.length; ++i) { + pop[res[i].path] = res[i]; + } + } + + if (fn) { + var paths = utils.object.vals(pop); + this.$__.populate = undefined; + this.constructor.populate(this, paths, fn); + } + + return this; +} + +/** + * Gets _id(s) used during population of the given `path`. + * + * ####Example: + * + * Model.findOne().populate('author').exec(function (err, doc) { + * console.log(doc.author.name) // Dr.Seuss + * console.log(doc.populated('author')) // '5144cf8050f071d979c118a7' + * }) + * + * If the path was not populated, undefined is returned. + * + * @param {String} path + * @return {Array|ObjectId|Number|Buffer|String|undefined} + * @api public + */ + +Document.prototype.populated = function (path, val, options) { + // val and options are internal + + if (null == val) { + if (!this.$__.populated) return undefined; + var v = this.$__.populated[path]; + if (v) return v.value; + return undefined; + } + + // internal + + if (true === val) { + if (!this.$__.populated) return undefined; + return this.$__.populated[path]; + } + + this.$__.populated || (this.$__.populated = {}); + this.$__.populated[path] = { value: val, options: options }; + return val; +} + +/** + * Returns the full path to this document. + * + * @param {String} [path] + * @return {String} + * @api private + * @method $__fullPath + * @memberOf Document + */ + +Document.prototype.$__fullPath = function (path) { + // overridden in SubDocuments + return path || ''; +} + +/*! + * Module exports. + */ + +Document.ValidationError = ValidationError; +module.exports = exports = Document; +exports.Error = DocumentError; diff --git a/node_modules/mongoose/lib/drivers/SPEC.md b/node_modules/mongoose/lib/drivers/SPEC.md new file mode 100644 index 0000000..6464693 --- /dev/null +++ b/node_modules/mongoose/lib/drivers/SPEC.md @@ -0,0 +1,4 @@ + +# Driver Spec + +TODO diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js new file mode 100644 index 0000000..0480d31 --- /dev/null +++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js @@ -0,0 +1,8 @@ + +/*! + * Module dependencies. + */ + +var Binary = require('mongodb').BSONPure.Binary; + +module.exports = exports = Binary; diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js new file mode 100644 index 0000000..ff5dd5c --- /dev/null +++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js @@ -0,0 +1,211 @@ + +/*! + * Module dependencies. + */ + +var MongooseCollection = require('../../collection') + , Collection = require('mongodb').Collection + , STATES = require('../../connectionstate') + , utils = require('../../utils') + +/** + * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation. + * + * All methods methods from the [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver are copied and wrapped in queue management. + * + * @inherits Collection + * @api private + */ + +function NativeCollection () { + this.collection = null; + MongooseCollection.apply(this, arguments); +} + +/*! + * Inherit from abstract Collection. + */ + +NativeCollection.prototype.__proto__ = MongooseCollection.prototype; + +/** + * Called when the connection opens. + * + * @api private + */ + +NativeCollection.prototype.onOpen = function () { + var self = this; + + // always get a new collection in case the user changed host:port + // of parent db instance when re-opening the connection. + + if (!self.opts.capped.size) { + // non-capped + return self.conn.db.collection(self.name, callback); + } + + // capped + return self.conn.db.collection(self.name, function (err, c) { + if (err) return callback(err); + + // discover if this collection exists and if it is capped + c.options(function (err, exists) { + if (err) return callback(err); + + if (exists) { + if (exists.capped) { + callback(null, c); + } else { + var msg = 'A non-capped collection exists with the name: '+ self.name +'\n\n' + + ' To use this collection as a capped collection, please ' + + 'first convert it.\n' + + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped' + err = new Error(msg); + callback(err); + } + } else { + // create + var opts = utils.clone(self.opts.capped); + opts.capped = true; + self.conn.db.createCollection(self.name, opts, callback); + } + }); + }); + + function callback (err, collection) { + if (err) { + // likely a strict mode error + self.conn.emit('error', err); + } else { + self.collection = collection; + MongooseCollection.prototype.onOpen.call(self); + } + }; +}; + +/** + * Called when the connection closes + * + * @api private + */ + +NativeCollection.prototype.onClose = function () { + MongooseCollection.prototype.onClose.call(this); +}; + +/*! + * Copy the collection methods and make them subject to queues + */ + +for (var i in Collection.prototype) { + (function(i){ + NativeCollection.prototype[i] = function () { + if (this.buffer) { + this.addQueue(i, arguments); + return; + } + + var collection = this.collection + , args = arguments + , self = this + , debug = self.conn.base.options.debug; + + if (debug) { + if ('function' === typeof debug) { + debug.apply(debug + , [self.name, i].concat(utils.args(args, 0, args.length-1))); + } else { + console.error('\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s' + , self.name + , i + , print(args[0]) + , print(args[1]) + , print(args[2]) + , print(args[3])) + } + } + + collection[i].apply(collection, args); + }; + })(i); +} + +/*! + * Debug print helper + */ + +function print (arg) { + var type = typeof arg; + if ('function' === type || 'undefined' === type) return ''; + return format(arg); +} + +/*! + * Debug print helper + */ + +function format (obj, sub) { + var x = utils.clone(obj); + if (x) { + if ('Binary' === x.constructor.name) { + x = '[object Buffer]'; + } else if ('ObjectID' === x.constructor.name) { + var representation = 'ObjectId("' + x.toHexString() + '")'; + x = { inspect: function() { return representation; } }; + } else if ('Date' === x.constructor.name) { + var representation = 'new Date("' + x.toUTCString() + '")'; + x = { inspect: function() { return representation; } }; + } else if ('Object' === x.constructor.name) { + var keys = Object.keys(x) + , i = keys.length + , key + while (i--) { + key = keys[i]; + if (x[key]) { + if ('Binary' === x[key].constructor.name) { + x[key] = '[object Buffer]'; + } else if ('Object' === x[key].constructor.name) { + x[key] = format(x[key], true); + } else if ('ObjectID' === x[key].constructor.name) { + ;(function(x){ + var representation = 'ObjectId("' + x[key].toHexString() + '")'; + x[key] = { inspect: function() { return representation; } }; + })(x) + } else if ('Date' === x[key].constructor.name) { + ;(function(x){ + var representation = 'new Date("' + x[key].toUTCString() + '")'; + x[key] = { inspect: function() { return representation; } }; + })(x) + } else if (Array.isArray(x[key])) { + x[key] = x[key].map(function (o) { + return format(o, true) + }); + } + } + } + } + if (sub) return x; + } + + return require('util') + .inspect(x, false, 10, true) + .replace(/\n/g, '') + .replace(/\s{2,}/g, ' ') +} + +/** + * Retreives information about this collections indexes. + * + * @param {Function} callback + * @method getIndexes + * @api public + */ + +NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation; + +/*! + * Module exports. + */ + +module.exports = NativeCollection; diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js new file mode 100644 index 0000000..5325419 --- /dev/null +++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js @@ -0,0 +1,303 @@ +/*! + * Module dependencies. + */ + +var MongooseConnection = require('../../connection') + , mongo = require('mongodb') + , Db = mongo.Db + , Server = mongo.Server + , Mongos = mongo.Mongos + , STATES = require('../../connectionstate') + , ReplSetServers = mongo.ReplSetServers; + +/** + * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation. + * + * @inherits Connection + * @api private + */ + +function NativeConnection() { + MongooseConnection.apply(this, arguments); + this._listening = false; +}; + +/*! + * Inherits from Connection. + */ + +NativeConnection.prototype.__proto__ = MongooseConnection.prototype; + +/** + * Opens the connection to MongoDB. + * + * @param {Function} fn + * @return {Connection} this + * @api private + */ + +NativeConnection.prototype.doOpen = function (fn) { + if (this.db) { + mute(this); + } + + var server = new Server(this.host, this.port, this.options.server); + this.db = new Db(this.name, server, this.options.db); + + var self = this; + this.db.open(function (err) { + if (err) return fn(err); + listen(self); + fn(); + }); + + return this; +}; + +/*! + * Register listeners for important events and bubble appropriately. + */ + +function listen (conn) { + if (conn._listening) return; + conn._listening = true; + + conn.db.on('close', function(){ + if (conn._closeCalled) return; + + // the driver never emits an `open` event. auto_reconnect still + // emits a `close` event but since we never get another + // `open` we can't emit close + if (conn.db.serverConfig.autoReconnect) { + conn.readyState = STATES.disconnected; + conn.emit('close'); + return; + } + conn.onClose(); + }); + conn.db.on('error', function(err){ + conn.emit('error', err); + }); + conn.db.on('timeout', function(err){ + var error = new Error(err && err.err || 'connection timeout'); + conn.emit('error', error); + }); + conn.db.on('open', function (err, db) { + if (STATES.disconnected === conn.readyState && db && db.databaseName) { + conn.readyState = STATES.connected; + conn.emit('reconnected') + } + }) +} + +/*! + * Remove listeners registered in `listen` + */ + +function mute (conn) { + if (!conn.db) throw new Error('missing db'); + conn.db.removeAllListeners("close"); + conn.db.removeAllListeners("error"); + conn.db.removeAllListeners("timeout"); + conn.db.removeAllListeners("open"); + conn.db.removeAllListeners("fullsetup"); + conn._listening = false; +} + +/** + * Opens a connection to a MongoDB ReplicaSet. + * + * See description of [doOpen](#NativeConnection-doOpen) for server options. In this case `options.replset` is also passed to ReplSetServers. + * + * @param {Function} fn + * @api private + * @return {Connection} this + */ + +NativeConnection.prototype.doOpenSet = function (fn) { + if (this.db) { + mute(this); + } + + var servers = [] + , self = this; + + this.hosts.forEach(function (server) { + var host = server.host || server.ipc; + var port = server.port || 27017; + servers.push(new Server(host, port, self.options.server)); + }) + + var server = this.options.mongos + ? new Mongos(servers, this.options.mongos) + : new ReplSetServers(servers, this.options.replset); + this.db = new Db(this.name, server, this.options.db); + + this.db.on('fullsetup', function () { + self.emit('fullsetup') + }); + + this.db.open(function (err) { + if (err) return fn(err); + fn(); + listen(self); + }); + + return this; +}; + +/** + * Closes the connection + * + * @param {Function} fn + * @return {Connection} this + * @api private + */ + +NativeConnection.prototype.doClose = function (fn) { + this.db.close(); + if (fn) fn(); + return this; +} + +/** + * Prepares default connection options for the node-mongodb-native driver. + * + * _NOTE: `passed` options take precedence over connection string options._ + * + * @param {Object} passed options that were passed directly during connection + * @param {Object} [connStrOptions] options that were passed in the connection string + * @api private + */ + +NativeConnection.prototype.parseOptions = function (passed, connStrOpts) { + var o = passed || {}; + o.db || (o.db = {}); + o.auth || (o.auth = {}); + o.server || (o.server = {}); + o.replset || (o.replset = {}); + o.server.socketOptions || (o.server.socketOptions = {}); + o.replset.socketOptions || (o.replset.socketOptions = {}); + + var opts = connStrOpts || {}; + Object.keys(opts).forEach(function (name) { + switch (name) { + case 'poolSize': + if ('undefined' == typeof o.server.poolSize) { + o.server.poolSize = o.replset.poolSize = opts[name]; + } + break; + case 'slaveOk': + if ('undefined' == typeof o.server.slave_ok) { + o.server.slave_ok = opts[name]; + } + break; + case 'autoReconnect': + if ('undefined' == typeof o.server.auto_reconnect) { + o.server.auto_reconnect = opts[name]; + } + break; + case 'ssl': + case 'socketTimeoutMS': + case 'connectTimeoutMS': + if ('undefined' == typeof o.server.socketOptions[name]) { + o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name]; + } + break; + case 'authdb': + if ('undefined' == typeof o.auth.authdb) { + o.auth.authdb = opts[name]; + } + break; + case 'authSource': + if ('undefined' == typeof o.auth.authSource) { + o.auth.authSource = opts[name]; + } + break; + case 'retries': + case 'reconnectWait': + case 'rs_name': + if ('undefined' == typeof o.replset[name]) { + o.replset[name] = opts[name]; + } + break; + case 'replicaSet': + if ('undefined' == typeof o.replset.rs_name) { + o.replset.rs_name = opts[name]; + } + break; + case 'readSecondary': + if ('undefined' == typeof o.replset.read_secondary) { + o.replset.read_secondary = opts[name]; + } + break; + case 'nativeParser': + if ('undefined' == typeof o.db.native_parser) { + o.db.native_parser = opts[name]; + } + break; + case 'w': + case 'safe': + case 'fsync': + case 'journal': + case 'wtimeoutMS': + if ('undefined' == typeof o.db[name]) { + o.db[name] = opts[name]; + } + break; + case 'readPreference': + if ('undefined' == typeof o.db.read_preference) { + o.db.read_preference = opts[name]; + } + break; + case 'readPreferenceTags': + if ('undefined' == typeof o.db.read_preference_tags) { + o.db.read_preference_tags = opts[name]; + } + break; + } + }) + + if (!('auto_reconnect' in o.server)) { + o.server.auto_reconnect = true; + } + + if (!o.db.read_preference) { + // read from primaries by default + o.db.read_preference = 'primary'; + } + + // mongoose creates its own ObjectIds + o.db.forceServerObjectId = false; + + // default safe using new nomenclature + if (!('journal' in o.db || 'j' in o.db || + 'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) { + o.db.w = 1; + } + + validate(o); + return o; +} + +/*! + * Validates the driver db options. + * + * @param {Object} o + */ + +function validate (o) { + if (-1 === o.db.w || 0 === o.db.w) { + if (o.db.journal || o.db.fsync || o.db.safe) { + throw new Error( + 'Invalid writeConcern: ' + + 'w set to -1 or 0 cannot be combined with safe|fsync|journal'); + } + } +} + +/*! + * Module exports. + */ + +module.exports = NativeConnection; diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js new file mode 100644 index 0000000..3c46c93 --- /dev/null +++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js @@ -0,0 +1,29 @@ + +/*! + * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId + * @constructor NodeMongoDbObjectId + * @see ObjectId + */ + +var ObjectId = require('mongodb').BSONPure.ObjectID; + +/*! + * ignore + */ + +var ObjectIdToString = ObjectId.toString.bind(ObjectId); +module.exports = exports = ObjectId; + +ObjectId.fromString = function(str){ + // patch native driver bug in V0.9.6.4 + if (!('string' === typeof str && 24 === str.length)) { + throw new Error("Invalid ObjectId"); + } + + return ObjectId.createFromHexString(str); +}; + +ObjectId.toString = function(oid){ + if (!arguments.length) return ObjectIdToString(); + return oid.toHexString(); +}; diff --git a/node_modules/mongoose/lib/error.js b/node_modules/mongoose/lib/error.js new file mode 100644 index 0000000..6d00f80 --- /dev/null +++ b/node_modules/mongoose/lib/error.js @@ -0,0 +1,39 @@ + +/** + * MongooseError constructor + * + * @param {String} msg Error message + * @inherits Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error + */ + +function MongooseError (msg) { + Error.call(this); + Error.captureStackTrace(this, arguments.callee); + this.message = msg; + this.name = 'MongooseError'; +}; + +/*! + * Inherits from Error. + */ + +MongooseError.prototype.__proto__ = Error.prototype; + +/*! + * Module exports. + */ + +module.exports = exports = MongooseError; + +/*! + * Expose subclasses + */ + +MongooseError.CastError = require('./errors/cast'); +MongooseError.DocumentError = require('./errors/document'); +MongooseError.ValidationError = require('./errors/validation') +MongooseError.ValidatorError = require('./errors/validator') +MongooseError.VersionError =require('./errors/version') +MongooseError.OverwriteModelError = require('./errors/overwriteModel') +MongooseError.MissingSchemaError = require('./errors/missingSchema') +MongooseError.DivergentArrayError = require('./errors/divergentArray') diff --git a/node_modules/mongoose/lib/errors/cast.js b/node_modules/mongoose/lib/errors/cast.js new file mode 100644 index 0000000..055063a --- /dev/null +++ b/node_modules/mongoose/lib/errors/cast.js @@ -0,0 +1,35 @@ +/*! + * Module dependencies. + */ + +var MongooseError = require('../error'); + +/** + * Casting Error constructor. + * + * @param {String} type + * @param {String} value + * @inherits MongooseError + * @api private + */ + +function CastError (type, value, path) { + MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"'); + Error.captureStackTrace(this, arguments.callee); + this.name = 'CastError'; + this.type = type; + this.value = value; + this.path = path; +}; + +/*! + * Inherits from MongooseError. + */ + +CastError.prototype.__proto__ = MongooseError.prototype; + +/*! + * exports + */ + +module.exports = CastError; diff --git a/node_modules/mongoose/lib/errors/divergentArray.js b/node_modules/mongoose/lib/errors/divergentArray.js new file mode 100644 index 0000000..45809bc --- /dev/null +++ b/node_modules/mongoose/lib/errors/divergentArray.js @@ -0,0 +1,40 @@ + +/*! + * Module dependencies. + */ + +var MongooseError = require('../error'); + +/*! + * DivergentArrayError constructor. + * + * @inherits MongooseError + */ + +function DivergentArrayError (paths) { + var msg = 'For your own good, using `document.save()` to update an array ' + + 'which was selected using an $elemMatch projection OR ' + + 'populated using skip, limit, query conditions, or exclusion of ' + + 'the _id field when the operation results in a $pop or $set of ' + + 'the entire array is not supported. The following ' + + 'path(s) would have been modified unsafely:\n' + + ' ' + paths.join('\n ') + '\n' + + 'Use Model.update() to update these arrays instead.' + // TODO write up a docs page (FAQ) and link to it + + MongooseError.call(this, msg); + Error.captureStackTrace(this, arguments.callee); + this.name = 'DivergentArrayError'; +}; + +/*! + * Inherits from MongooseError. + */ + +DivergentArrayError.prototype.__proto__ = MongooseError.prototype; + +/*! + * exports + */ + +module.exports = DivergentArrayError; diff --git a/node_modules/mongoose/lib/errors/document.js b/node_modules/mongoose/lib/errors/document.js new file mode 100644 index 0000000..6955256 --- /dev/null +++ b/node_modules/mongoose/lib/errors/document.js @@ -0,0 +1,32 @@ + +/*! + * Module requirements + */ + +var MongooseError = require('../error') + +/** + * Document Error + * + * @param {String} msg + * @inherits MongooseError + * @api private + */ + +function DocumentError (msg) { + MongooseError.call(this, msg); + Error.captureStackTrace(this, arguments.callee); + this.name = 'DocumentError'; +}; + +/*! + * Inherits from MongooseError. + */ + +DocumentError.prototype.__proto__ = MongooseError.prototype; + +/*! + * Module exports. + */ + +module.exports = exports = DocumentError; diff --git a/node_modules/mongoose/lib/errors/missingSchema.js b/node_modules/mongoose/lib/errors/missingSchema.js new file mode 100644 index 0000000..02a02ee --- /dev/null +++ b/node_modules/mongoose/lib/errors/missingSchema.js @@ -0,0 +1,32 @@ + +/*! + * Module dependencies. + */ + +var MongooseError = require('../error'); + +/*! + * MissingSchema Error constructor. + * + * @inherits MongooseError + */ + +function MissingSchemaError (name) { + var msg = 'Schema hasn\'t been registered for model "' + name + '".\n' + + 'Use mongoose.model(name, schema)'; + MongooseError.call(this, msg); + Error.captureStackTrace(this, arguments.callee); + this.name = 'MissingSchemaError'; +}; + +/*! + * Inherits from MongooseError. + */ + +MissingSchemaError.prototype.__proto__ = MongooseError.prototype; + +/*! + * exports + */ + +module.exports = MissingSchemaError; diff --git a/node_modules/mongoose/lib/errors/overwriteModel.js b/node_modules/mongoose/lib/errors/overwriteModel.js new file mode 100644 index 0000000..2591581 --- /dev/null +++ b/node_modules/mongoose/lib/errors/overwriteModel.js @@ -0,0 +1,30 @@ + +/*! + * Module dependencies. + */ + +var MongooseError = require('../error'); + +/*! + * OverwriteModel Error constructor. + * + * @inherits MongooseError + */ + +function OverwriteModelError (name) { + MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.'); + Error.captureStackTrace(this, arguments.callee); + this.name = 'OverwriteModelError'; +}; + +/*! + * Inherits from MongooseError. + */ + +OverwriteModelError.prototype.__proto__ = MongooseError.prototype; + +/*! + * exports + */ + +module.exports = OverwriteModelError; diff --git a/node_modules/mongoose/lib/errors/validation.js b/node_modules/mongoose/lib/errors/validation.js new file mode 100644 index 0000000..1679849 --- /dev/null +++ b/node_modules/mongoose/lib/errors/validation.js @@ -0,0 +1,49 @@ + +/*! + * Module requirements + */ + +var MongooseError = require('../error') + +/** + * Document Validation Error + * + * @api private + * @param {Document} instance + * @inherits MongooseError + */ + +function ValidationError (instance) { + MongooseError.call(this, "Validation failed"); + Error.captureStackTrace(this, arguments.callee); + this.name = 'ValidationError'; + this.errors = instance.errors = {}; +}; + +/** + * Console.log helper + */ + +ValidationError.prototype.toString = function () { + var ret = this.name + ': '; + var msgs = []; + + Object.keys(this.errors).forEach(function (key) { + if (this == this.errors[key]) return; + msgs.push(String(this.errors[key])); + }, this) + + return ret + msgs.join(', '); +}; + +/*! + * Inherits from MongooseError. + */ + +ValidationError.prototype.__proto__ = MongooseError.prototype; + +/*! + * Module exports + */ + +module.exports = exports = ValidationError; diff --git a/node_modules/mongoose/lib/errors/validator.js b/node_modules/mongoose/lib/errors/validator.js new file mode 100644 index 0000000..2498b05 --- /dev/null +++ b/node_modules/mongoose/lib/errors/validator.js @@ -0,0 +1,51 @@ +/*! + * Module dependencies. + */ + +var MongooseError = require('../error'); + +/** + * Schema validator error + * + * @param {String} path + * @param {String} msg + * @param {String|Number|any} val + * @inherits MongooseError + * @api private + */ + +function ValidatorError (path, type, val) { + var msg = type + ? '"' + type + '" ' + : ''; + + var message = 'Validator ' + msg + 'failed for path ' + path + if (2 < arguments.length) message += ' with value `' + String(val) + '`'; + + MongooseError.call(this, message); + Error.captureStackTrace(this, arguments.callee); + this.name = 'ValidatorError'; + this.path = path; + this.type = type; + this.value = val; +}; + +/*! + * toString helper + */ + +ValidatorError.prototype.toString = function () { + return this.message; +} + +/*! + * Inherits from MongooseError + */ + +ValidatorError.prototype.__proto__ = MongooseError.prototype; + +/*! + * exports + */ + +module.exports = ValidatorError; diff --git a/node_modules/mongoose/lib/errors/version.js b/node_modules/mongoose/lib/errors/version.js new file mode 100644 index 0000000..b2388aa --- /dev/null +++ b/node_modules/mongoose/lib/errors/version.js @@ -0,0 +1,31 @@ + +/*! + * Module dependencies. + */ + +var MongooseError = require('../error'); + +/** + * Version Error constructor. + * + * @inherits MongooseError + * @api private + */ + +function VersionError () { + MongooseError.call(this, 'No matching document found.'); + Error.captureStackTrace(this, arguments.callee); + this.name = 'VersionError'; +}; + +/*! + * Inherits from MongooseError. + */ + +VersionError.prototype.__proto__ = MongooseError.prototype; + +/*! + * exports + */ + +module.exports = VersionError; diff --git a/node_modules/mongoose/lib/index.js b/node_modules/mongoose/lib/index.js new file mode 100644 index 0000000..ca4cfa0 --- /dev/null +++ b/node_modules/mongoose/lib/index.js @@ -0,0 +1,580 @@ + +/*! + * Module dependencies. + */ + +var Schema = require('./schema') + , SchemaType = require('./schematype') + , VirtualType = require('./virtualtype') + , SchemaTypes = Schema.Types + , SchemaDefaults = require('./schemadefault') + , Types = require('./types') + , Query = require('./query') + , Promise = require('./promise') + , Model = require('./model') + , Document = require('./document') + , utils = require('./utils') + , format = utils.toCollectionName + , mongodb = require('mongodb') + +/** + * Mongoose constructor. + * + * The exports object of the `mongoose` module is an instance of this class. + * Most apps will only use this one instance. + * + * @api public + */ + +function Mongoose () { + this.connections = []; + this.plugins = []; + this.models = {}; + this.modelSchemas = {}; + this.options = {}; + this.createConnection(); // default connection +}; + +/** + * Sets mongoose options + * + * ####Example: + * + * mongoose.set('test', value) // sets the 'test' option to `value` + * + * mongoose.set('debug', true) // enable logging collection methods + arguments to the console + * + * @param {String} key + * @param {String} value + * @api public + */ + +Mongoose.prototype.set = function (key, value) { + if (arguments.length == 1) + return this.options[key]; + this.options[key] = value; + return this; +}; + +/** + * Gets mongoose options + * + * ####Example: + * + * mongoose.get('test') // returns the 'test' value + * + * @param {String} key + * @method get + * @api public + */ + +Mongoose.prototype.get = Mongoose.prototype.set; + +/*! + * ReplSet connection string check. + */ + +var rgxReplSet = /^.+,.+$/; + +/** + * Creates a Connection instance. + * + * Each `connection` instance maps to a single database. This method is helpful when mangaging multiple db connections. + * + * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately. This means we can pass `db`, `server`, and `replset` options to the driver. + * + * _Options passed take precedence over options included in connection strings._ + * + * ####Example: + * + * // with mongodb:// URI + * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database'); + * + * // and options + * var opts = { db: { native_parser: true }} + * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts); + * + * // replica sets + * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port'); + * + * // and options + * var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }} + * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts); + * + * // with [host, database_name[, port] signature + * db = mongoose.createConnection('localhost', 'database', port) + * + * // and options + * var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' } + * db = mongoose.createConnection('localhost', 'database', port, opts) + * + * // initialize now, connect later + * db = mongoose.createConnection(); + * db.open('localhost', 'database', port, [opts]); + * + * @param {String} [uri] a mongodb:// URI + * @param {Object} [options] options to pass to the driver + * @see Connection#open #connection_Connection-open + * @see Connection#openSet #connection_Connection-openSet + * @return {Connection} the created Connection object + * @api public + */ + +Mongoose.prototype.createConnection = function () { + var conn = new Connection(this); + this.connections.push(conn); + + if (arguments.length) { + if (rgxReplSet.test(arguments[0])) { + conn.openSet.apply(conn, arguments); + } else { + conn.open.apply(conn, arguments); + } + } + + return conn; +}; + +/** + * Opens the default mongoose connection. + * + * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately. + * + * _Options passed take precedence over options included in connection strings._ + * + * @see Mongoose#createConnection #index_Mongoose-createConnection + * @api public + * @return {Mongoose} this + */ + +Mongoose.prototype.connect = function () { + var conn = this.connection; + + if (rgxReplSet.test(arguments[0])) { + conn.openSet.apply(conn, arguments); + } else { + conn.open.apply(conn, arguments); + } + + return this; +}; + +/** + * Disconnects all connections. + * + * @param {Function} [fn] called after all connection close. + * @return {Mongoose} this + * @api public + */ + +Mongoose.prototype.disconnect = function (fn) { + var count = this.connections.length + , error + + this.connections.forEach(function(conn){ + conn.close(function(err){ + if (error) return; + + if (err) { + error = err; + if (fn) return fn(err); + throw err; + } + + if (fn) + --count || fn(); + }); + }); + return this; +}; + +/** + * Defines a model or retrieves it. + * + * Models defined on the `mongoose` instance are available to all connection created by the same `mongoose` instance. + * + * ####Example: + * + * var mongoose = require('mongoose'); + * + * // define an Actor model with this mongoose instance + * mongoose.model('Actor', new Schema({ name: String })); + * + * // create a new connection + * var conn = mongoose.createConnection(..); + * + * // retrieve the Actor model + * var Actor = conn.model('Actor'); + * + * _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils_exports.toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._ + * + * ####Example: + * + * var schema = new Schema({ name: String }, { collection: 'actor' }); + * + * // or + * + * schema.set('collection', 'actor'); + * + * // or + * + * var collectionName = 'actor' + * var M = mongoose.model('Actor', schema, collectionName) + * + * @param {String} name model name + * @param {Schema} [schema] + * @param {String} [collection] name (optional, induced from model name) + * @param {Boolean} [skipInit] whether to skip initialization (defaults to false) + * @api public + */ + +Mongoose.prototype.model = function (name, schema, collection, skipInit) { + if ('string' == typeof schema) { + collection = schema; + schema = false; + } + + if (utils.isObject(schema) && !(schema instanceof Schema)) { + schema = new Schema(schema); + } + + if ('boolean' === typeof collection) { + skipInit = collection; + collection = null; + } + + // handle internal options from connection.model() + var options; + if (skipInit && utils.isObject(skipInit)) { + options = skipInit; + skipInit = true; + } else { + options = {}; + } + + // look up schema for the collection. this might be a + // default schema like system.indexes stored in SchemaDefaults. + if (!this.modelSchemas[name]) { + if (!schema && name in SchemaDefaults) { + schema = SchemaDefaults[name]; + } + + if (schema) { + // cache it so we only apply plugins once + this.modelSchemas[name] = schema; + this._applyPlugins(schema); + } else { + throw new mongoose.Error.MissingSchemaError(name); + } + } + + var model; + var sub; + + // connection.model() may be passing a different schema for + // an existing model name. in this case don't read from cache. + if (this.models[name] && false !== options.cache) { + if (schema instanceof Schema && schema != this.models[name].schema) { + throw new mongoose.Error.OverwriteModelError(name); + } + + if (collection) { + // subclass current model with alternate collection + model = this.models[name]; + schema = model.prototype.schema; + sub = model.__subclass(this.connection, schema, collection); + // do not cache the sub model + return sub; + } + + return this.models[name]; + } + + // ensure a schema exists + if (!schema) { + schema = this.modelSchemas[name]; + if (!schema) { + throw new mongoose.Error.MissingSchemaError(name); + } + } + + if (!collection) { + collection = schema.get('collection') || format(name); + } + + var connection = options.connection || this.connection; + model = Model.compile(name, schema, collection, connection, this); + + if (!skipInit) { + model.init(); + } + + if (false === options.cache) { + return model; + } + + return this.models[name] = model; +} + +/** + * Returns an array of model names created on this instance of Mongoose. + * + * ####Note: + * + * _Does not include names of models created using `connection.model()`._ + * + * @api public + * @return {Array} + */ + +Mongoose.prototype.modelNames = function () { + var names = Object.keys(this.models); + return names; +} + +/** + * Applies global plugins to `schema`. + * + * @param {Schema} schema + * @api private + */ + +Mongoose.prototype._applyPlugins = function (schema) { + for (var i = 0, l = this.plugins.length; i < l; i++) { + schema.plugin(this.plugins[i][0], this.plugins[i][1]); + } +} + +/** + * Declares a global plugin executed on all Schemas. + * + * Equivalent to calling `.plugin(fn)` on each Schema you create. + * + * @param {Function} fn plugin callback + * @param {Object} [opts] optional options + * @return {Mongoose} this + * @see plugins ./plugins.html + * @api public + */ + +Mongoose.prototype.plugin = function (fn, opts) { + this.plugins.push([fn, opts]); + return this; +}; + +/** + * The default connection of the mongoose module. + * + * ####Example: + * + * var mongoose = require('mongoose'); + * mongoose.connect(...); + * mongoose.connection.on('error', cb); + * + * This is the connection used by default for every model created using [mongoose.model](#index_Mongoose-model). + * + * @property connection + * @return {Connection} + * @api public + */ + +Mongoose.prototype.__defineGetter__('connection', function(){ + return this.connections[0]; +}); + +/*! + * Driver depentend APIs + */ + +var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'; + +/*! + * Connection + */ + +var Connection = require(driver + '/connection'); + +/*! + * Collection + */ + +var Collection = require(driver + '/collection'); + +/** + * The Mongoose Collection constructor + * + * @method Collection + * @api public + */ + +Mongoose.prototype.Collection = Collection; + +/** + * The Mongoose [Connection](#connection_Connection) constructor + * + * @method Connection + * @api public + */ + +Mongoose.prototype.Connection = Connection; + +/** + * The Mongoose version + * + * @property version + * @api public + */ + +Mongoose.prototype.version = require(__dirname + '/../package.json').version; + +/** + * The Mongoose constructor + * + * The exports of the mongoose module is an instance of this class. + * + * ####Example: + * + * var mongoose = require('mongoose'); + * var mongoose2 = new mongoose.Mongoose(); + * + * @method Mongoose + * @api public + */ + +Mongoose.prototype.Mongoose = Mongoose; + +/** + * The Mongoose [Schema](#schema_Schema) constructor + * + * ####Example: + * + * var mongoose = require('mongoose'); + * var Schema = mongoose.Schema; + * var CatSchema = new Schema(..); + * + * @method Schema + * @api public + */ + +Mongoose.prototype.Schema = Schema; + +/** + * The Mongoose [SchemaType](#schematype_SchemaType) constructor + * + * @method SchemaType + * @api public + */ + +Mongoose.prototype.SchemaType = SchemaType; + +/** + * The various Mongoose SchemaTypes. + * + * ####Note: + * + * _Alias of mongoose.Schema.Types for backwards compatibility._ + * + * @property SchemaTypes + * @see Schema.SchemaTypes #schema_Schema.Types + * @api public + */ + +Mongoose.prototype.SchemaTypes = Schema.Types; + +/** + * The Mongoose [VirtualType](#virtualtype_VirtualType) constructor + * + * @method VirtualType + * @api public + */ + +Mongoose.prototype.VirtualType = VirtualType; + +/** + * The various Mongoose Types. + * + * ####Example: + * + * var mongoose = require('mongoose'); + * var array = mongoose.Types.Array; + * + * ####Types: + * + * - [ObjectId](#types-objectid-js) + * - [Buffer](#types-buffer-js) + * - [SubDocument](#types-embedded-js) + * - [Array](#types-array-js) + * - [DocumentArray](#types-documentarray-js) + * + * Using this exposed access to the `ObjectId` type, we can construct ids on demand. + * + * var ObjectId = mongoose.Types.ObjectId; + * var id1 = new ObjectId; + * + * @property Types + * @api public + */ + +Mongoose.prototype.Types = Types; + +/** + * The Mongoose [Query](#query_Query) constructor. + * + * @method Query + * @api public + */ + +Mongoose.prototype.Query = Query; + +/** + * The Mongoose [Promise](#promise_Promise) constructor. + * + * @method Promise + * @api public + */ + +Mongoose.prototype.Promise = Promise; + +/** + * The Mongoose [Model](#model_Model) constructor. + * + * @method Model + * @api public + */ + +Mongoose.prototype.Model = Model; + +/** + * The Mongoose [Document](#document-js) constructor. + * + * @method Document + * @api public + */ + +Mongoose.prototype.Document = Document; + +/** + * The [MongooseError](#error_MongooseError) constructor. + * + * @method Error + * @api public + */ + +Mongoose.prototype.Error = require('./error'); + +/** + * The [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver Mongoose uses. + * + * @property mongo + * @api public + */ + +Mongoose.prototype.mongo = require('mongodb'); + +/*! + * The exports object is an instance of Mongoose. + * + * @api public + */ + +var mongoose = module.exports = exports = new Mongoose; diff --git a/node_modules/mongoose/lib/internal.js b/node_modules/mongoose/lib/internal.js new file mode 100644 index 0000000..d5a3f12 --- /dev/null +++ b/node_modules/mongoose/lib/internal.js @@ -0,0 +1,31 @@ +/*! + * Dependencies + */ + +var StateMachine = require('./statemachine') +var ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default') + +module.exports = exports = InternalCache; + +function InternalCache () { + this.strictMode = undefined; + this.selected = undefined; + this.shardval = undefined; + this.saveError = undefined; + this.validationError = undefined; + this.adhocPaths = undefined; + this.removing = undefined; + this.inserting = undefined; + this.version = undefined; + this.getters = {}; + this._id = undefined; + this.populate = undefined; // what we want to populate in this doc + this.populated = undefined;// the _ids that have been populated + this.wasPopulated = false; // if this doc was the result of a population + this.scope = undefined; + this.activePaths = new ActiveRoster; + + // embedded docs + this.ownerDocument = undefined; + this.fullPath = undefined; +} diff --git a/node_modules/mongoose/lib/model.js b/node_modules/mongoose/lib/model.js new file mode 100644 index 0000000..7b5419e --- /dev/null +++ b/node_modules/mongoose/lib/model.js @@ -0,0 +1,2254 @@ +/*! + * Module dependencies. + */ + +var Document = require('./document') + , MongooseArray = require('./types/array') + , MongooseBuffer = require('./types/buffer') + , MongooseError = require('./error') + , VersionError = MongooseError.VersionError + , DivergentArrayError = MongooseError.DivergentArrayError + , Query = require('./query') + , Schema = require('./schema') + , Types = require('./schema/index') + , utils = require('./utils') + , hasOwnProperty = utils.object.hasOwnProperty + , isMongooseObject = utils.isMongooseObject + , EventEmitter = require('events').EventEmitter + , merge = utils.merge + , Promise = require('./promise') + , assert = require('assert') + , tick = utils.tick + +var VERSION_WHERE = 1 + , VERSION_INC = 2 + , VERSION_ALL = VERSION_WHERE | VERSION_INC; + +/** + * Model constructor + * + * @param {Object} doc values to with which to create the document + * @inherits Document + * @event `error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model. + * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event. + * @api public + */ + +function Model (doc, fields, skipId) { + Document.call(this, doc, fields, skipId); +}; + +/*! + * Inherits from Document. + * + * All Model.prototype features are available on + * top level (non-sub) documents. + */ + +Model.prototype.__proto__ = Document.prototype; + +/** + * Connection the model uses. + * + * @api public + * @property db + */ + +Model.prototype.db; + +/** + * Collection the model uses. + * + * @api public + * @property collection + */ + +Model.prototype.collection; + +/** + * The name of the model + * + * @api public + * @property modelName + */ + +Model.prototype.modelName; + +/*! + * Handles doc.save() callbacks + */ + +function handleSave (promise, self) { + return tick(function handleSave (err, result) { + if (err) { + // If the initial insert fails provide a second chance. + // (If we did this all the time we would break updates) + if (self.$__.inserting) { + self.isNew = true; + self.emit('isNew', true); + } + promise.error(err); + promise = self = null; + return; + } + + self.$__storeShard(); + + var numAffected; + if (result) { + // when inserting, the array of created docs is returned + numAffected = result.length + ? result.length + : result; + } else { + numAffected = 0; + } + + // was this an update that required a version bump? + if (self.$__.version && !self.$__.inserting) { + var doIncrement = VERSION_INC === (VERSION_INC & self.$__.version); + self.$__.version = undefined; + + // increment version if was successful + if (numAffected > 0) { + if (doIncrement) { + var key = self.schema.options.versionKey; + var version = self.getValue(key) | 0; + self.setValue(key, version + 1); + } + } else { + // the update failed. pass an error back + promise.error(new VersionError); + promise = self = null; + return; + } + } + + self.emit('save', self, numAffected); + promise.complete(self, numAffected); + promise = self = null; + }); +} + +/** + * Saves this document. + * + * ####Example: + * + * product.sold = Date.now(); + * product.save(function (err, product, numberAffected) { + * if (err) .. + * }) + * + * The callback will receive three parameters, `err` if an error occurred, `product` which is the saved `product`, and `numberAffected` which will be 1 when the document was found and updated in the database, otherwise 0. + * + * The `fn` callback is optional. If no `fn` is passed and validation fails, the validation error will be emitted on the connection used to create this model. + * + * var db = mongoose.createConnection(..); + * var schema = new Schema(..); + * var Product = db.model('Product', schema); + * + * db.on('error', handleError); + * + * However, if you desire more local error handling you can add an `error` listener to the model and handle errors there instead. + * + * Product.on('error', handleError); + * + * @param {Function} [fn] optional callback + * @api public + * @see middleware http://mongoosejs.com/docs/middleware.html + */ + +Model.prototype.save = function save (fn) { + var promise = new Promise(fn) + , complete = handleSave(promise, this) + , options = {} + + if (this.schema.options.safe) { + options.safe = this.schema.options.safe; + } + + if (this.isNew) { + // send entire doc + var obj = this.toObject({ depopulate: 1 }); + this.$__version(true, obj); + this.collection.insert(obj, options, complete); + this.$__reset(); + this.isNew = false; + this.emit('isNew', false); + // Make it possible to retry the insert + this.$__.inserting = true; + + } else { + // Make sure we don't treat it as a new object on error, + // since it already exists + this.$__.inserting = false; + + var delta = this.$__delta(); + if (delta) { + if (delta instanceof Error) return complete(delta); + var where = this.$__where(delta[0]); + this.$__reset(); + this.collection.update(where, delta[1], options, complete); + } else { + this.$__reset(); + complete(null); + } + + this.emit('isNew', false); + } +}; + +/*! + * Apply the operation to the delta (update) clause as + * well as track versioning for our where clause. + * + * @param {Document} self + * @param {Object} where + * @param {Object} delta + * @param {Object} data + * @param {Mixed} val + * @param {String} [operation] + */ + +function operand (self, where, delta, data, val, op) { + // delta + op || (op = '$set'); + if (!delta[op]) delta[op] = {}; + delta[op][data.path] = val; + + // disabled versioning? + if (false === self.schema.options.versionKey) return; + + // already marked for versioning? + if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return; + + switch (op) { + case '$set': + case '$unset': + case '$pop': + case '$pull': + case '$pullAll': + case '$push': + case '$pushAll': + case '$addToSet': + break; + default: + // nothing to do + return; + } + + // ensure updates sent with positional notation are + // editing the correct array element. + // only increment the version if an array position changes. + // modifying elements of an array is ok if position does not change. + + if ('$push' == op || '$pushAll' == op || '$addToSet' == op) { + self.$__.version = VERSION_INC; + } + else if (/^\$p/.test(op)) { + // potentially changing array positions + self.increment(); + } + else if (Array.isArray(val)) { + // $set an array + self.increment(); + } + // now handling $set, $unset + else if (/\.\d+\.|\.\d+$/.test(data.path)) { + // subpath of array + self.$__.version = VERSION_WHERE; + } +} + +/*! + * Compiles an update and where clause for a `val` with _atomics. + * + * @param {Document} self + * @param {Object} where + * @param {Object} delta + * @param {Object} data + * @param {Array} value + */ + +function handleAtomics (self, where, delta, data, value) { + if (delta.$set && delta.$set[data.path]) { + // $set has precedence over other atomics + return; + } + + if ('function' == typeof value.$__getAtomics) { + value.$__getAtomics().forEach(function (atomic) { + var op = atomic[0]; + var val = atomic[1]; + operand(self, where, delta, data, val, op); + }) + return; + } + + // legacy support for plugins + + var atomics = value._atomics + , ops = Object.keys(atomics) + , i = ops.length + , val + , op; + + if (0 === i) { + // $set + + if (isMongooseObject(value)) { + value = value.toObject({ depopulate: 1 }); + } else if (value.valueOf) { + value = value.valueOf(); + } + + return operand(self, where, delta, data, value); + } + + while (i--) { + op = ops[i]; + val = atomics[op]; + + if (isMongooseObject(val)) { + val = val.toObject({ depopulate: 1 }) + } else if (Array.isArray(val)) { + val = val.map(function (mem) { + return isMongooseObject(mem) + ? mem.toObject({ depopulate: 1 }) + : mem; + }) + } else if (val.valueOf) { + val = val.valueOf() + } + + if ('$addToSet' === op) + val = { $each: val }; + + operand(self, where, delta, data, val, op); + } +} + +/** + * Produces a special query document of the modified properties used in updates. + * + * @api private + * @method $__delta + * @memberOf Model + */ + +Model.prototype.$__delta = function () { + var dirty = this.$__dirty(); + if (!dirty.length && VERSION_ALL != this.$__.version) return; + + var where = {} + , delta = {} + , len = dirty.length + , divergent = [] + , d = 0 + , val + , obj + + for (; d < len; ++d) { + var data = dirty[d] + var value = data.value + var schema = data.schema + + var match = checkDivergentArray(this, data.path, value); + if (match) { + divergent.push(match); + continue; + } + + if (divergent.length) continue; + + if (undefined === value) { + operand(this, where, delta, data, 1, '$unset'); + + } else if (null === value) { + operand(this, where, delta, data, null); + + } else if (value._path && value._atomics) { + // arrays and other custom types (support plugins etc) + handleAtomics(this, where, delta, data, value); + + } else if (value._path && Buffer.isBuffer(value)) { + // MongooseBuffer + value = value.toObject(); + operand(this, where, delta, data, value); + + } else { + value = utils.clone(value, { depopulate: 1 }); + operand(this, where, delta, data, value); + } + } + + if (divergent.length) { + return new DivergentArrayError(divergent); + } + + if (this.$__.version) { + this.$__version(where, delta); + } + + return [where, delta]; +} + +/*! + * Determine if array was populated with some form of filter and is now + * being updated in a manner which could overwrite data unintentionally. + * + * @see https://github.com/LearnBoost/mongoose/issues/1334 + * @param {Document} doc + * @param {String} path + * @return {String|undefined} + */ + +function checkDivergentArray (doc, path, array) { + // see if we populated this path + var pop = doc.populated(path, true); + + if (!pop && doc.$__.selected) { + // If any array was selected using an $elemMatch projection, we deny the update. + // NOTE: MongoDB only supports projected $elemMatch on top level array. + var top = path.split('.')[0]; + if (doc.$__.selected[top] && doc.$__.selected[top].$elemMatch) { + return top; + } + } + + if (!(pop && array instanceof MongooseArray)) return; + + // If the array was populated using options that prevented all + // documents from being returned (match, skip, limit) or they + // deselected the _id field, $pop and $set of the array are + // not safe operations. If _id was deselected, we do not know + // how to remove elements. $pop will pop off the _id from the end + // of the array in the db which is not guaranteed to be the + // same as the last element we have here. $set of the entire array + // would be similarily destructive as we never received all + // elements of the array and potentially would overwrite data. + var check = pop.options.match || + pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted + pop.options.options && pop.options.options.skip || // 0 is permitted + pop.options.select && // deselected _id? + (0 === pop.options.select._id || + /\s?-_id\s?/.test(pop.options.select)) + + if (check) { + var atomics = array._atomics; + if (0 === Object.keys(atomics).length || atomics.$set || atomics.$pop) { + return path; + } + } +} + +/** + * Appends versioning to the where and update clauses. + * + * @api private + * @method $__version + * @memberOf Model + */ + +Model.prototype.$__version = function (where, delta) { + var key = this.schema.options.versionKey; + + if (true === where) { + // this is an insert + if (key) this.setValue(key, delta[key] = 0); + return; + } + + // updates + + // only apply versioning if our versionKey was selected. else + // there is no way to select the correct version. we could fail + // fast here and force them to include the versionKey but + // thats a bit intrusive. can we do this automatically? + if (!this.isSelected(key)) { + return; + } + + // $push $addToSet don't need the where clause set + if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) { + where[key] = this.getValue(key); + } + + if (VERSION_INC === (VERSION_INC & this.$__.version)) { + delta.$inc || (delta.$inc = {}); + delta.$inc[key] = 1; + } +} + +/** + * Signal that we desire an increment of this documents version. + * + * ####Example: + * + * Model.findById(id, function (err, doc) { + * doc.increment(); + * doc.save(function (err) { .. }) + * }) + * + * @see versionKeys http://mongoosejs.com/docs/guide.html#versionKey + * @api public + */ + +Model.prototype.increment = function increment () { + this.$__.version = VERSION_ALL; + return this; +} + +/** + * Returns a query object which applies shardkeys if they exist. + * + * @api private + * @method $__where + * @memberOf Model + */ + +Model.prototype.$__where = function _where (where) { + where || (where = {}); + + var paths + , len + + if (this.$__.shardval) { + paths = Object.keys(this.$__.shardval) + len = paths.length + + for (var i = 0; i < len; ++i) { + where[paths[i]] = this.$__.shardval[paths[i]]; + } + } + + where._id = this._doc._id; + return where; +} + +/** + * Removes this document from the db. + * + * ####Example: + * + * product.remove(function (err, product) { + * if (err) return handleError(err); + * Product.findById(product._id, function (err, product) { + * console.log(product) // null + * }) + * }) + * + * @param {Function} [fn] optional callback + * @api public + */ + +Model.prototype.remove = function remove (fn) { + if (this.$__.removing) { + this.$__.removing.addBack(fn); + return this; + } + + var promise = this.$__.removing = new Promise(fn) + , where = this.$__where() + , self = this + , options = {} + + if (this.schema.options.safe) { + options.safe = this.schema.options.safe; + } + + this.collection.remove(where, options, tick(function (err) { + if (err) { + promise.error(err); + promise = self = self.$__.removing = where = options = null; + return; + } + self.emit('remove', self); + promise.complete(); + promise = self = where = options = null; + })); + + return this; +}; + +/** + * Returns another Model instance. + * + * ####Example: + * + * var doc = new Tank; + * doc.model('User').findById(id, callback); + * + * @param {String} name model name + * @api public + */ + +Model.prototype.model = function model (name) { + return this.db.model(name); +}; + +// Model (class) features + +/*! + * Give the constructor the ability to emit events. + */ + +for (var i in EventEmitter.prototype) + Model[i] = EventEmitter.prototype[i]; + +/** + * Called when the model compiles. + * + * @api private + */ + +Model.init = function init () { + if (this.schema.options.autoIndex) { + this.ensureIndexes(); + } + + this.schema.emit('init', this); +}; + +/** + * Sends `ensureIndex` commands to mongo for each index declared in the schema. + * + * ####Example: + * + * Event.ensureIndexes(function (err) { + * if (err) return handleError(err); + * }); + * + * After completion, an `index` event is emitted on this `Model` passing an error if one occurred. + * + * ####Example: + * + * var eventSchema = new Schema({ thing: { type: 'string', unique: true }}) + * var Event = mongoose.model('Event', eventSchema); + * + * Event.on('index', function (err) { + * if (err) console.error(err); // error occurred during index creation + * }) + * + * _NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution._ + * + * The `ensureIndex` commands are not sent in parallel. This is to avoid the `MongoError: cannot add index with a background operation in progress` error. See [this ticket](https://github.com/LearnBoost/mongoose/issues/1365) for more information. + * + * @param {Function} [cb] optional callback + * @api public + */ + +Model.ensureIndexes = function ensureIndexes (cb) { + var indexes = this.schema.indexes(); + if (!indexes.length) { + return cb && process.nextTick(cb); + } + + // Indexes are created one-by-one to support how MongoDB < 2.4 deals + // with background indexes. + + var self = this + , safe = self.schema.options.safe + + function done (err) { + self.emit('index', err); + cb && cb(err); + } + + function create () { + var index = indexes.shift(); + if (!index) return done(); + + var options = index[1]; + options.safe = safe; + self.collection.ensureIndex(index[0], options, tick(function (err) { + if (err) return done(err); + create(); + })); + } + + create(); +} + +/** + * Schema the model uses. + * + * @property schema + * @receiver Model + * @api public + */ + +Model.schema; + +/*! + * Connection instance the model uses. + * + * @property db + * @receiver Model + * @api public + */ + +Model.db; + +/*! + * Collection the model uses. + * + * @property collection + * @receiver Model + * @api public + */ + +Model.collection; + +/** + * Base Mongoose instance the model uses. + * + * @property base + * @receiver Model + * @api public + */ + +Model.base; + +/** + * Removes documents from the collection. + * + * ####Example: + * + * Comment.remove({ title: 'baby born from alien father' }, function (err) { + * + * }); + * + * ####Note: + * + * To remove documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js): + * + * var query = Comment.remove({ _id: id }); + * query.exec(); + * + * ####Note: + * + * This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, _no middleware (hooks) are executed_. + * + * @param {Object} conditions + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.remove = function remove (conditions, callback) { + if ('function' === typeof conditions) { + callback = conditions; + conditions = {}; + } + + var query = new Query(conditions).bind(this, 'remove'); + + if ('undefined' === typeof callback) + return query; + + this._applyNamedScope(query); + return query.remove(callback); +}; + +/** + * Finds documents + * + * The `conditions` are cast to their respective SchemaTypes before the command is sent. + * + * ####Examples: + * + * // named john and at least 18 + * MyModel.find({ name: 'john', age: { $gte: 18 }}); + * + * // executes immediately, passing results to callback + * MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {}); + * + * // name LIKE john and only selecting the "name" and "friends" fields, executing immediately + * MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { }) + * + * // passing options + * MyModel.find({ name: /john/i }, null, { skip: 10 }) + * + * // passing options and executing immediately + * MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {}); + * + * // executing a query explicitly + * var query = MyModel.find({ name: /john/i }, null, { skip: 10 }) + * query.exec(function (err, docs) {}); + * + * // using the promise returned from executing a query + * var query = MyModel.find({ name: /john/i }, null, { skip: 10 }); + * var promise = query.exec(); + * promise.addBack(function (err, docs) {}); + * + * @param {Object} conditions + * @param {Object} [fields] optional fields to select + * @param {Object} [options] optional + * @param {Function} [callback] + * @return {Query} + * @see field selection #query_Query-select + * @see promise #promise-js + * @api public + */ + +Model.find = function find (conditions, fields, options, callback) { + if ('function' == typeof conditions) { + callback = conditions; + conditions = {}; + fields = null; + options = null; + } else if ('function' == typeof fields) { + callback = fields; + fields = null; + options = null; + } else if ('function' == typeof options) { + callback = options; + options = null; + } + + var query = new Query(conditions, options); + query.bind(this, 'find'); + query.select(fields); + + if ('undefined' === typeof callback) + return query; + + this._applyNamedScope(query); + return query.find(callback); +}; + +/** + * Merges the current named scope query into `query`. + * + * @param {Query} query + * @return {Query} + * @api private + */ + +Model._applyNamedScope = function _applyNamedScope (query) { + var cQuery = this._cumulativeQuery; + + if (cQuery) { + merge(query._conditions, cQuery._conditions); + if (query._fields && cQuery._fields) + merge(query._fields, cQuery._fields); + if (query.options && cQuery.options) + merge(query.options, cQuery.options); + delete this._cumulativeQuery; + } + + return query; +} + +/** + * Finds a single document by id. + * + * The `id` is cast based on the Schema before sending the command. + * + * ####Example: + * + * // find adventure by id and execute immediately + * Adventure.findById(id, function (err, adventure) {}); + * + * // same as above + * Adventure.findById(id).exec(callback); + * + * // select only the adventures name and length + * Adventure.findById(id, 'name length', function (err, adventure) {}); + * + * // same as above + * Adventure.findById(id, 'name length').exec(callback); + * + * // include all properties except for `length` + * Adventure.findById(id, '-length').exec(function (err, adventure) {}); + * + * // passing options (in this case return the raw js objects, not mongoose documents by passing `lean` + * Adventure.findById(id, 'name', { lean: true }, function (err, doc) {}); + * + * // same as above + * Adventure.findById(id, 'name').lean().exec(function (err, doc) {}); + * + * @param {ObjectId|HexId} id objectid, or a value that can be casted to one + * @param {Object} [fields] optional fields to select + * @param {Object} [options] optional + * @param {Function} [callback] + * @return {Query} + * @see field selection #query_Query-select + * @see lean queries #query_Query-lean + * @api public + */ + +Model.findById = function findById (id, fields, options, callback) { + return this.findOne({ _id: id }, fields, options, callback); +}; + +/** + * Finds one document. + * + * The `conditions` are cast to their respective SchemaTypes before the command is sent. + * + * ####Example: + * + * // find one iphone adventures - iphone adventures?? + * Adventure.findOne({ type: 'iphone' }, function (err, adventure) {}); + * + * // same as above + * Adventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {}); + * + * // select only the adventures name + * Adventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {}); + * + * // same as above + * Adventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {}); + * + * // specify options, in this case lean + * Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback); + * + * // same as above + * Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback); + * + * // chaining findOne queries (same as above) + * Adventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback); + * + * @param {Object} conditions + * @param {Object} [fields] optional fields to select + * @param {Object} [options] optional + * @param {Function} [callback] + * @return {Query} + * @see field selection #query_Query-select + * @see lean queries #query_Query-lean + * @api public + */ + +Model.findOne = function findOne (conditions, fields, options, callback) { + if ('function' == typeof options) { + callback = options; + options = null; + } else if ('function' == typeof fields) { + callback = fields; + fields = null; + options = null; + } else if ('function' == typeof conditions) { + callback = conditions; + conditions = {}; + fields = null; + options = null; + } + + var query = new Query(conditions, options).select(fields).bind(this, 'findOne'); + + if ('undefined' == typeof callback) + return query; + + this._applyNamedScope(query); + return query.findOne(callback); +}; + +/** + * Counts number of matching documents in a database collection. + * + * ####Example: + * + * Adventure.count({ type: 'jungle' }, function (err, count) { + * if (err) .. + * console.log('there are %d jungle adventures', count); + * }); + * + * @param {Object} conditions + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.count = function count (conditions, callback) { + if ('function' === typeof conditions) + callback = conditions, conditions = {}; + + var query = new Query(conditions).bind(this, 'count'); + if ('undefined' == typeof callback) + return query; + + this._applyNamedScope(query); + return query.count(callback); +}; + +/** + * Executes a DISTINCT command + * + * ####Example + * + * Link.distinct('url', { clicks: {$gt: 100}}, function (err, result) { + * if (err) return handleError(err); + * + * assert(Array.isArray(result)); + * console.log('unique urls with more than 100 clicks', result); + * }) + * + * @param {String} field + * @param {Object} [conditions] optional + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.distinct = function distinct (field, conditions, callback) { + if ('function' == typeof conditions) { + callback = conditions; + conditions = {}; + } + + var query = new Query(conditions).bind(this, 'distinct'); + if ('undefined' == typeof callback) { + query._distinctArg = field; + return query; + } + + this._applyNamedScope(query); + return query.distinct(field, callback); +}; + +/** + * Creates a Query, applies the passed conditions, and returns the Query. + * + * For example, instead of writing: + * + * User.find({age: {$gte: 21, $lte: 65}}, callback); + * + * we can instead write: + * + * User.where('age').gte(21).lte(65).exec(callback); + * + * Since the Query class also supports `where` you can continue chaining + * + * User + * .where('age').gte(21).lte(65) + * .where('name', /^b/i) + * ... etc + * + * @param {String} path + * @param {Object} [val] optional value + * @return {Query} + * @api public + */ + +Model.where = function where (path, val) { + var q = new Query().bind(this, 'find'); + return q.where.apply(q, arguments); +}; + +/** + * Creates a `Query` and specifies a `$where` condition. + * + * Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model. + * + * Blog.$where('this.comments.length > 5').exec(function (err, docs) {}); + * + * @param {String|Function} argument is a javascript string or anonymous function + * @method $where + * @memberOf Model + * @return {Query} + * @see Query.$where #query_Query-%24where + * @api public + */ + +Model.$where = function $where () { + var q = new Query().bind(this, 'find'); + return q.$where.apply(q, arguments); +}; + +/** + * Issues a mongodb findAndModify update command. + * + * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned. + * + * ####Options: + * + * - `new`: bool - true to return the modified document rather than the original. defaults to true + * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `select`: sets the document fields to return + * + * ####Examples: + * + * A.findOneAndUpdate(conditions, update, options, callback) // executes + * A.findOneAndUpdate(conditions, update, options) // returns Query + * A.findOneAndUpdate(conditions, update, callback) // executes + * A.findOneAndUpdate(conditions, update) // returns Query + * A.findOneAndUpdate() // returns Query + * + * ####Note: + * + * All top level update keys which are not `atomic` operation names are treated as set operations: + * + * ####Example: + * + * var query = { name: 'borne' }; + * Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback) + * + * // is sent as + * Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback) + * + * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`. + * + * ####Note: + * + * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied: + * + * - defaults + * - setters + * - validators + * - middleware + * + * If you need those features, use the traditional approach of first retrieving the document. + * + * Model.findOne({ name: 'borne' }, function (err, doc) { + * if (err) .. + * doc.name = 'jason borne'; + * doc.save(callback); + * }) + * + * @param {Object} [conditions] + * @param {Object} [update] + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @api public + */ + +Model.findOneAndUpdate = function (conditions, update, options, callback) { + if ('function' == typeof options) { + callback = options; + options = null; + } + else if (1 === arguments.length) { + if ('function' == typeof conditions) { + var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n' + + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n' + + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n' + + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\n' + + ' ' + this.modelName + '.findOneAndUpdate(update)\n' + + ' ' + this.modelName + '.findOneAndUpdate()\n'; + throw new TypeError(msg) + } + update = conditions; + conditions = undefined; + } + + var fields; + if (options && options.fields) { + fields = options.fields; + options.fields = undefined; + } + + var query = new Query(conditions); + query.setOptions(options); + query.select(fields); + query.bind(this, 'findOneAndUpdate', update); + + if ('undefined' == typeof callback) + return query; + + this._applyNamedScope(query); + return query.findOneAndUpdate(callback); +} + +/** + * Issues a mongodb findAndModify update command by a documents id. + * + * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned. + * + * ####Options: + * + * - `new`: bool - true to return the modified document rather than the original. defaults to true + * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `select`: sets the document fields to return + * + * ####Examples: + * + * A.findByIdAndUpdate(id, update, options, callback) // executes + * A.findByIdAndUpdate(id, update, options) // returns Query + * A.findByIdAndUpdate(id, update, callback) // executes + * A.findByIdAndUpdate(id, update) // returns Query + * A.findByIdAndUpdate() // returns Query + * + * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned. + * + * ####Options: + * + * - `new`: bool - true to return the modified document rather than the original. defaults to true + * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * + * ####Note: + * + * All top level update keys which are not `atomic` operation names are treated as set operations: + * + * ####Example: + * + * Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback) + * + * // is sent as + * Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback) + * + * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`. + * + * ####Note: + * + * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied: + * + * - defaults + * - setters + * - validators + * - middleware + * + * If you need those features, use the traditional approach of first retrieving the document. + * + * Model.findById(id, function (err, doc) { + * if (err) .. + * doc.name = 'jason borne'; + * doc.save(callback); + * }) + * + * @param {ObjectId|HexId} id an ObjectId or string that can be cast to one. + * @param {Object} [update] + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @see Model.findOneAndUpdate #model_Model.findOneAndUpdate + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @api public + */ + +Model.findByIdAndUpdate = function (id, update, options, callback) { + var args; + + if (1 === arguments.length) { + if ('function' == typeof id) { + var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n' + + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n' + + ' ' + this.modelName + '.findByIdAndUpdate(id)\n' + + ' ' + this.modelName + '.findByIdAndUpdate()\n'; + throw new TypeError(msg) + } + return this.findOneAndUpdate({_id: id }, undefined); + } + + args = utils.args(arguments, 1); + args.unshift({ _id: id }); + return this.findOneAndUpdate.apply(this, args); +} + +/** + * Issue a mongodb findAndModify remove command. + * + * Finds a matching document, removes it, passing the found document (if any) to the callback. + * + * Executes immediately if `callback` is passed else a Query object is returned. + * + * ####Options: + * + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `select`: sets the document fields to return + * + * ####Examples: + * + * A.findOneAndRemove(conditions, options, callback) // executes + * A.findOneAndRemove(conditions, options) // return Query + * A.findOneAndRemove(conditions, callback) // executes + * A.findOneAndRemove(conditions) // returns Query + * A.findOneAndRemove() // returns Query + * + * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied: + * + * - defaults + * - setters + * - validators + * - middleware + * + * If you need those features, use the traditional approach of first retrieving the document. + * + * Model.findById(id, function (err, doc) { + * if (err) .. + * doc.remove(callback); + * }) + * + * @param {Object} conditions + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @api public + */ + +Model.findOneAndRemove = function (conditions, options, callback) { + if (1 === arguments.length && 'function' == typeof conditions) { + var msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n' + + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\n' + + ' ' + this.modelName + '.findOneAndRemove(conditions)\n' + + ' ' + this.modelName + '.findOneAndRemove()\n'; + throw new TypeError(msg) + } + + if ('function' == typeof options) { + callback = options; + options = undefined; + } + + var fields; + if (options) { + fields = options.select; + options.select = undefined; + } + + var query = new Query(conditions); + query.setOptions(options); + query.select(fields); + query.bind(this, 'findOneAndRemove'); + + if ('undefined' == typeof callback) + return query; + + this._applyNamedScope(query); + return query.findOneAndRemove(callback); +} + +/** + * Issue a mongodb findAndModify remove command by a documents id. + * + * Finds a matching document, removes it, passing the found document (if any) to the callback. + * + * Executes immediately if `callback` is passed, else a `Query` object is returned. + * + * ####Options: + * + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * - `select`: sets the document fields to return + * + * ####Examples: + * + * A.findByIdAndRemove(id, options, callback) // executes + * A.findByIdAndRemove(id, options) // return Query + * A.findByIdAndRemove(id, callback) // executes + * A.findByIdAndRemove(id) // returns Query + * A.findByIdAndRemove() // returns Query + * + * @param {ObjectId|HexString} id ObjectId or string that can be cast to one + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @see Model.findOneAndRemove #model_Model.findOneAndRemove + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + */ + +Model.findByIdAndRemove = function (id, options, callback) { + if (1 === arguments.length && 'function' == typeof id) { + var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n' + + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\n' + + ' ' + this.modelName + '.findByIdAndRemove(id)\n' + + ' ' + this.modelName + '.findByIdAndRemove()\n'; + throw new TypeError(msg) + } + + return this.findOneAndRemove({ _id: id }, options, callback); +} + +/** + * Shortcut for creating a new Document that is automatically saved to the db if valid. + * + * ####Example: + * + * Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) { + * if (err) // ... + * }); + * + * var array = [{ type: 'jelly bean' }, { type: 'snickers' }]; + * Candy.create(array, function (err, jellybean, snickers) { + * if (err) // ... + * }); + * + * @param {Array|Object...} doc + * @param {Function} fn callback + * @api public + */ + +Model.create = function create (doc, fn) { + if (1 === arguments.length) { + return 'function' === typeof doc && doc(null); + } + + var self = this + , docs = [null] + , promise + , count + , args + + if (Array.isArray(doc)) { + args = doc; + } else { + args = utils.args(arguments, 0, arguments.length - 1); + fn = arguments[arguments.length - 1]; + } + + if (0 === args.length) return fn(null); + + promise = new Promise(fn); + count = args.length; + + args.forEach(function (arg, i) { + var doc = new self(arg); + docs[i+1] = doc; + doc.save(function (err) { + if (err) return promise.error(err); + --count || fn.apply(null, docs); + }); + }); +}; + +/** + * Updates documents in the database without returning them. + * + * ####Examples: + * + * MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn); + * MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) { + * if (err) return handleError(err); + * console.log('The number of updated documents was %d', numberAffected); + * console.log('The raw response from Mongo was ', raw); + * }); + * + * ####Valid options: + * + * - `safe` (boolean) safe mode (defaults to value set in schema (true)) + * - `upsert` (boolean) whether to create the doc if it doesn't match (false) + * - `multi` (boolean) whether multiple documents should be updated (false) + * - `strict` (boolean) overrides the `strict` option for this update + * + * All `update` values are cast to their appropriate SchemaTypes before being sent. + * + * The `callback` function receives `(err, numberAffected, rawResponse)`. + * + * - `err` is the error if any occurred + * - `numberAffected` is the count of updated documents Mongo reported + * - `rawResponse` is the full response from Mongo + * + * ####Note: + * + * All top level keys which are not `atomic` operation names are treated as set operations: + * + * ####Example: + * + * var query = { name: 'borne' }; + * Model.update(query, { name: 'jason borne' }, options, callback) + * + * // is sent as + * Model.update(query, { $set: { name: 'jason borne' }}, options, callback) + * + * This helps prevent accidentally overwriting all documents in your collection with `{ name: 'jason borne' }`. + * + * ####Note: + * + * Be careful to not use an existing model instance for the update clause (this won't work and can cause weird behavior like infinite loops). Also, ensure that the update clause does not have an _id property, which causes Mongo to return a "Mod on _id not allowed" error. + * + * ####Note: + * + * To update documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js): + * + * Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec(); + * + * ####Note: + * + * Although values are casted to their appropriate types when using update, the following are *not* applied: + * + * - defaults + * - setters + * - validators + * - middleware + * + * If you need those features, use the traditional approach of first retrieving the document. + * + * Model.findOne({ name: 'borne' }, function (err, doc) { + * if (err) .. + * doc.name = 'jason borne'; + * doc.save(callback); + * }) + * + * @see strict schemas http://mongoosejs.com/docs/guide.html#strict + * @param {Object} conditions + * @param {Object} update + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} + * @api public + */ + +Model.update = function update (conditions, doc, options, callback) { + if (arguments.length < 4) { + if ('function' === typeof options) { + // Scenario: update(conditions, doc, callback) + callback = options; + options = null; + } else if ('function' === typeof doc) { + // Scenario: update(doc, callback); + callback = doc; + doc = conditions; + conditions = {}; + options = null; + } + } + + var query = new Query(conditions, options).bind(this, 'update', doc); + + if ('undefined' == typeof callback) + return query; + + this._applyNamedScope(query); + return query.update(doc, callback); +}; + +/** + * Executes a mapReduce command. + * + * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. + * + * ####Example: + * + * var o = {}; + * o.map = function () { emit(this.name, 1) } + * o.reduce = function (k, vals) { return vals.length } + * User.mapReduce(o, function (err, results) { + * console.log(results) + * }) + * + * ####Other options: + * + * - `query` {Object} query filter object. + * - `limit` {Number} max number of documents + * - `keeptemp` {Boolean, default:false} keep temporary data + * - `finalize` {Function} finalize function + * - `scope` {Object} scope variables exposed to map/reduce/finalize during execution + * - `jsMode` {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X + * - `verbose` {Boolean, default:false} provide statistics on job execution time. + * - `out*` {Object, default: {inline:1}} sets the output target for the map reduce job. + * + * ####* out options: + * + * - `{inline:1}` the results are returned in an array + * - `{replace: 'collectionName'}` add the results to collectionName: the results replace the collection + * - `{reduce: 'collectionName'}` add the results to collectionName: if dups are detected, uses the reducer / finalize functions + * - `{merge: 'collectionName'}` add the results to collectionName: if dups exist the new docs overwrite the old + * + * If `options.out` is set to `replace`, `merge`, or `reduce`, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the `lean` option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc). + * + * ####Example: + * + * var o = {}; + * o.map = function () { emit(this.name, 1) } + * o.reduce = function (k, vals) { return vals.length } + * o.out = { replace: 'createdCollectionNameForResults' } + * o.verbose = true; + * User.mapReduce(o, function (err, model, stats) { + * console.log('map reduce took %d ms', stats.processtime) + * model.find().where('value').gt(10).exec(function (err, docs) { + * console.log(docs); + * }); + * }) + * + * @param {Object} o an object specifying map-reduce options + * @param {Function} callback + * @see http://www.mongodb.org/display/DOCS/MapReduce + * @api public + */ + +Model.mapReduce = function mapReduce (o, callback) { + if ('function' != typeof callback) throw new Error('missing callback'); + + var self = this; + + if (!Model.mapReduce.schema) { + var opts = { noId: true, noVirtualId: true, strict: false } + Model.mapReduce.schema = new Schema({}, opts); + } + + if (!o.out) o.out = { inline: 1 }; + + o.map = String(o.map); + o.reduce = String(o.reduce); + + if (o.query) { + var q = new Query(o.query); + q.cast(this); + o.query = q._conditions; + q = undefined; + } + + this.collection.mapReduce(null, null, o, function (err, ret, stats) { + if (err) return callback(err); + + if (ret.findOne && ret.mapReduce) { + // returned a collection, convert to Model + var model = Model.compile( + '_mapreduce_' + ret.collectionName + , Model.mapReduce.schema + , ret.collectionName + , self.db + , self.base); + + model._mapreduce = true; + + return callback(err, model, stats); + } + + callback(err, ret, stats); + }); +} + +/** + * Executes an aggregate command on this models collection. + * + * ####Example: + * + * // find the max age of all users + * Users.aggregate( + * { $group: { _id: null, maxAge: { $max: '$age' }}} + * , { $project: { _id: 0, maxAge: 1 }} + * , function (err, res) { + * if (err) return handleError(err); + * console.log(res); // [ { maxAge: 98 } ] + * }); + * + * ####NOTE: + * + * - At this time, arguments are not cast to the schema because $project operators allow redefining the "shape" of the documents at any stage of the pipeline. + * - The documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned). + * - Requires MongoDB >= 2.1 + * + * @param {Array} array an array of pipeline commands + * @param {Object} [options] + * @param {Function} callback + * @see aggregation http://docs.mongodb.org/manual/applications/aggregation/ + * @see driver http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate + * @api public + */ + +Model.aggregate = function aggregate () { + return this.collection.aggregate.apply(this.collection, arguments); +} + +/** + * Populates document references. + * + * ####Available options: + * + * - path: space delimited path(s) to populate + * - select: optional fields to select + * - match: optional query conditions to match + * - model: optional name of the model to use for population + * - options: optional query options like sort, limit, etc + * + * ####Examples: + * + * // populates a single object + * User.findById(id, function (err, user) { + * var opts = [ + * { path: 'company', match: { x: 1 }, select: 'name' } + * , { path: 'notes', options: { limit: 10 }, model: 'override' } + * ] + * + * User.populate(user, opts, function (err, user) { + * console.log(user); + * }) + * }) + * + * // populates an array of objects + * User.find(match, function (err, users) { + * var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }] + * + * User.populate(users, opts, function (err, user) { + * console.log(user); + * }) + * }) + * + * // imagine a Weapon model exists with two saved documents: + * // { _id: 389, name: 'whip' } + * // { _id: 8921, name: 'boomerang' } + * + * var user = { name: 'Indiana Jones', weapon: 389 } + * Weapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) { + * console.log(user.weapon.name) // whip + * }) + * + * // populate many plain objects + * var users = [{ name: 'Indiana Jones', weapon: 389 }] + * users.push({ name: 'Batman', weapon: 8921 }) + * Weapon.populate(users, { path: 'weapon' }, function (err, users) { + * users.forEach(function (user) { + * console.log('%s uses a %s', users.name, user.weapon.name) + * // Indiana Jones uses a whip + * // Batman uses a boomerang + * }) + * }) + * // Note that we didn't need to specify the Weapon model because + * // we were already using it's populate() method. + * + * @param {Document|Array} docs Either a single document or array of documents to populate. + * @param {Object} options A hash of key/val (path, options) used for population. + * @param {Function} cb(err,doc) A callback, executed upon completion. Receives `err` and the `doc(s)`. + * @api public + */ + +Model.populate = function (docs, paths, cb) { + assert.equal('function', typeof cb); + + // always callback on nextTick for consistent async behavior + function callback () { + var args = utils.args(arguments); + process.nextTick(function () { + cb.apply(null, args); + }); + } + + // normalized paths + var paths = utils.populate(paths); + var pending = paths.length; + + if (0 === pending) { + return callback(null, docs); + } + + // each path has its own query options and must be executed separately + var i = pending; + var path; + while (i--) { + path = paths[i]; + populate(this, docs, path, next); + } + + function next (err) { + if (next.err) return; + if (err) return callback(next.err = err); + if (--pending) return; + callback(null, docs); + } +} + +/*! + * Prepare population options + */ + +function populate (model, docs, options, cb) { + var path = options.path + var schema = model._getSchema(path); + + // handle document arrays + if (schema && schema.caster) { + schema = schema.caster; + } + + // model name for the populate query + var modelName = options.model && options.model.modelName + || options.model // query options + || schema && schema.options.ref // declared in schema + || model.modelName // an ad-hoc structure + + var Model = model.db.model(modelName); + + // expose the model used + options.model = Model; + + // normalize single / multiple docs passed + if (!Array.isArray(docs)) { + docs = [docs]; + } + + if (0 === docs.length || docs.every(utils.isNullOrUndefined)) { + return cb(); + } + + populateDocs(docs, options, cb); +} + +/*! + * Populates `docs` + */ + +function populateDocs (docs, options, cb) { + var select = options.select; + var match = options.match; + var path = options.path; + var Model = options.model; + + var rawIds = []; + var i, doc, id; + var len = docs.length; + var found = 0; + var isDocument; + var subpath; + var ret; + + for (i = 0; i < len; i++) { + ret = undefined; + doc = docs[i]; + id = String(utils.getValue("_id", doc)); + isDocument = !! doc.$__; + + if (isDocument && !doc.isModified(path)) { + // it is possible a previously populated path is being + // populated again. because users can specify matcher + // clauses in their populate arguments we use the cached + // _ids from the original populate call to ensure all _ids + // are looked up, but only if the path wasn't modified which + // signifies the users intent of the state of the path. + ret = doc.populated(path); + } + + if (!ret || Array.isArray(ret) && 0 === ret.length) { + ret = utils.getValue(path, doc); + } + + if (ret) { + // previously we always assigned this even if the document had no _id + options._docs[id] = Array.isArray(ret) + ? ret.slice() + : ret; + } + + // always retain original values, even empty values. these are + // used to map the query results back to the correct position. + rawIds.push(ret); + + if (isDocument) { + // cache original populated _ids and model used + doc.populated(path, options._docs[id], options); + } + } + + var ids = utils.array.flatten(rawIds, function (item) { + // no need to include undefined values in our query + return undefined !== item; + }); + + if (0 === ids.length || ids.every(utils.isNullOrUndefined)) { + return cb(); + } + + // preserve original match conditions by copying + if (match) { + match = utils.object.shallowCopy(match); + } else { + match = {}; + } + + match._id || (match._id = { $in: ids }); + + var assignmentOpts = {}; + assignmentOpts.sort = options.options && options.options.sort || undefined; + assignmentOpts.excludeId = /\s?-_id\s?/.test(select) || (select && 0 === select._id); + + if (assignmentOpts.excludeId) { + // override the exclusion from the query so we can use the _id + // for document matching during assignment. we'll delete the + // _id back off before returning the result. + if ('string' == typeof select) { + select = null; + } else { + // preserve original select conditions by copying + select = utils.object.shallowCopy(select); + delete select._id; + } + } + + Model.find(match, select, options.options, function (err, vals) { + if (err) return cb(err); + + var lean = options.options && options.options.lean; + var len = vals.length; + var rawOrder = {}; + var rawDocs = {} + var key; + var val; + + // optimization: + // record the document positions as returned by + // the query result. + for (var i = 0; i < len; i++) { + val = vals[i]; + key = String(utils.getValue('_id', val)); + rawDocs[key] = val; + rawOrder[key] = i; + + // flag each as result of population + if (!lean) val.$__.wasPopulated = true; + } + + assignVals({ + rawIds: rawIds, + rawDocs: rawDocs, + rawOrder: rawOrder, + docs: docs, + path: path, + options: assignmentOpts + }); + + cb(); + }); +} + +/*! + * Assigns documents returned from a population query back + * to the original document path. + */ + +function assignVals (o) { + // replace the original ids in our intermediate _ids structure + // with the documents found by query + + assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, o.options); + + // now update the original documents being populated using the + // result structure that contains real documents. + + var docs = o.docs; + var path = o.path; + var rawIds = o.rawIds; + var options = o.options; + + for (var i = 0; i < docs.length; ++i) { + utils.setValue(path, rawIds[i], docs[i], function (val) { + return valueFilter(val, options); + }); + } +} + +/*! + * 1) Apply backwards compatible find/findOne behavior to sub documents + * + * find logic: + * a) filter out non-documents + * b) remove _id from sub docs when user specified + * + * findOne + * a) if no doc found, set to null + * b) remove _id from sub docs when user specified + * + * 2) Remove _ids when specified by users query. + * + * background: + * _ids are left in the query even when user excludes them so + * that population mapping can occur. + */ + +function valueFilter (val, assignmentOpts) { + if (Array.isArray(val)) { + // find logic + var ret = []; + for (var i = 0; i < val.length; ++i) { + var subdoc = val[i]; + if (!isDoc(subdoc)) continue; + maybeRemoveId(subdoc, assignmentOpts); + ret.push(subdoc); + } + return ret; + } + + // findOne + if (isDoc(val)) { + maybeRemoveId(val, assignmentOpts); + return val; + } + + return null; +} + +/*! + * Remove _id from `subdoc` if user specified "lean" query option + */ + +function maybeRemoveId (subdoc, assignmentOpts) { + if (assignmentOpts.excludeId) { + if ('function' == typeof subdoc.setValue) { + subdoc.setValue('_id', undefined); + } else { + delete subdoc._id; + } + } +} + +/*! + * Determine if `doc` is a document returned + * by a populate query. + */ + +function isDoc (doc) { + if (null == doc) + return false; + + var type = typeof doc; + if ('string' == type) + return false; + + if ('number' == type) + return false; + + if (Buffer.isBuffer(doc)) + return false; + + if ('ObjectID' == doc.constructor.name) + return false; + + // only docs + return true; +} + +/*! + * Assign `vals` returned by mongo query to the `rawIds` + * structure returned from utils.getVals() honoring + * query sort order if specified by user. + * + * This can be optimized. + * + * Rules: + * + * if the value of the path is not an array, use findOne rules, else find. + * for findOne the results are assigned directly to doc path (including null results). + * for find, if user specified sort order, results are assigned directly + * else documents are put back in original order of array if found in results + * + * @param {Array} rawIds + * @param {Array} vals + * @param {Boolean} sort + * @api private + */ + +function assignRawDocsToIdStructure (rawIds, resultDocs, resultOrder, options, recursed) { + // honor user specified sort order + var newOrder = []; + var sorting = options.sort && rawIds.length > 1; + var found; + var doc; + var sid; + var id; + + for (var i = 0; i < rawIds.length; ++i) { + id = rawIds[i]; + + if (Array.isArray(id)) { + // handle [ [id0, id2], [id3] ] + assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true); + newOrder.push(id); + continue; + } + + if (null === id && !sorting) { + // keep nulls for findOne unless sorting, which always + // removes them (backward compat) + newOrder.push(id); + continue; + } + + sid = String(id); + found = false; + + if (recursed) { + // apply find behavior + + // assign matching documents in original order unless sorting + doc = resultDocs[sid]; + if (doc) { + if (sorting) { + newOrder[resultOrder[sid]] = doc; + } else { + newOrder.push(doc); + } + } else { + newOrder.push(id); + } + } else { + // apply findOne behavior - if document in results, assign, else assign null + newOrder[i] = doc = resultDocs[sid] || null; + } + } + + rawIds.length = 0; + if (newOrder.length) { + // reassign the documents based on corrected order + + // forEach skips over sparse entries in arrays so we + // can safely use this to our advantage dealing with sorted + // result sets too. + newOrder.forEach(function (doc, i) { + rawIds[i] = doc; + }); + } +} + +/** + * Finds the schema for `path`. This is different than + * calling `schema.path` as it also resolves paths with + * positional selectors (something.$.another.$.path). + * + * @param {String} path + * @return {Schema} + * @api private + */ + +Model._getSchema = function _getSchema (path) { + var schema = this.schema + , pathschema = schema.path(path); + + if (pathschema) + return pathschema; + + // look for arrays + return (function search (parts, schema) { + var p = parts.length + 1 + , foundschema + , trypath + + while (p--) { + trypath = parts.slice(0, p).join('.'); + foundschema = schema.path(trypath); + if (foundschema) { + if (foundschema.caster) { + + // array of Mixed? + if (foundschema.caster instanceof Types.Mixed) { + return foundschema.caster; + } + + // Now that we found the array, we need to check if there + // are remaining document paths to look up for casting. + // Also we need to handle array.$.path since schema.path + // doesn't work for that. + if (p !== parts.length) { + if ('$' === parts[p]) { + // comments.$.comments.$.title + return search(parts.slice(p+1), foundschema.schema); + } else { + // this is the last path of the selector + return search(parts.slice(p), foundschema.schema); + } + } + } + return foundschema; + } + } + })(path.split('.'), schema) +} + +/*! + * Compiler utility. + * + * @param {String} name model name + * @param {Schema} schema + * @param {String} collectionName + * @param {Connection} connection + * @param {Mongoose} base mongoose instance + */ + +Model.compile = function compile (name, schema, collectionName, connection, base) { + var versioningEnabled = false !== schema.options.versionKey; + + if (versioningEnabled && !schema.paths[schema.options.versionKey]) { + // add versioning to top level documents only + var o = {}; + o[schema.options.versionKey] = Number; + schema.add(o); + } + + // generate new class + function model (doc, fields, skipId) { + if (!(this instanceof model)) + return new model(doc, fields, skipId); + Model.call(this, doc, fields, skipId); + }; + + model.base = base; + model.modelName = name; + model.__proto__ = Model; + model.prototype.__proto__ = Model.prototype; + model.model = Model.prototype.model; + model.db = model.prototype.db = connection; + + model.prototype.$__setSchema(schema); + + var collectionOptions = { + bufferCommands: schema.options.bufferCommands + , capped: schema.options.capped + }; + + model.prototype.collection = connection.collection( + collectionName + , collectionOptions + ); + + // apply methods + for (var i in schema.methods) + model.prototype[i] = schema.methods[i]; + + // apply statics + for (var i in schema.statics) + model[i] = schema.statics[i]; + + // apply named scopes + if (schema.namedScopes) schema.namedScopes.compile(model); + + model.schema = model.prototype.schema; + model.options = model.prototype.options; + model.collection = model.prototype.collection; + + return model; +}; + +/*! + * Subclass this model with `conn`, `schema`, and `collection` settings. + * + * @param {Connection} conn + * @param {Schema} [schema] + * @param {String} [collection] + * @return {Model} + */ + +Model.__subclass = function subclass (conn, schema, collection) { + // subclass model using this connection and collection name + var model = this; + + var Model = function Model (doc, fields, skipId) { + if (!(this instanceof Model)) { + return new Model(doc, fields, skipId); + } + model.call(this, doc, fields, skipId); + } + + Model.__proto__ = model; + Model.prototype.__proto__ = model.prototype; + Model.db = Model.prototype.db = conn; + + var s = schema && 'string' != typeof schema + ? schema + : model.prototype.schema; + + if (!collection) { + collection = model.prototype.schema.get('collection') + || utils.toCollectionName(model.modelName); + } + + var collectionOptions = { + bufferCommands: s ? s.options.bufferCommands : true + , capped: s && s.options.capped + }; + + Model.prototype.collection = conn.collection(collection, collectionOptions); + Model.collection = Model.prototype.collection; + Model.init(); + return Model; +} + +/*! + * Module exports. + */ + +module.exports = exports = Model; diff --git a/node_modules/mongoose/lib/namedscope.js b/node_modules/mongoose/lib/namedscope.js new file mode 100644 index 0000000..1b3f5d4 --- /dev/null +++ b/node_modules/mongoose/lib/namedscope.js @@ -0,0 +1,70 @@ +var Query = require('./query'); +function NamedScope () {} + +NamedScope.prototype.query; + +NamedScope.prototype.where = function () { + var q = this.query || (this.query = new Query()); + q.where.apply(q, arguments); + return q; +}; + +/** + * Decorate + * + * @param {NamedScope} target + * @param {Object} getters + * @api private + */ + +NamedScope.prototype.decorate = function (target, getters) { + var name = this.name + , block = this.block + , query = this.query; + if (block) { + if (block.length === 0) { + Object.defineProperty(target, name, { + get: getters.block0(block) + }); + } else { + target[name] = getters.blockN(block); + } + } else { + Object.defineProperty(target, name, { + get: getters.basic(query) + }); + } +}; + +NamedScope.prototype.compile = function (model) { + var allScopes = this.scopesByName + , scope; + for (var k in allScopes) { + scope = allScopes[k]; + scope.decorate(model, { + block0: function (block) { + return function () { + var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this)); + block.call(cquery); + return this; + }; + }, + blockN: function (block) { + return function () { + var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this)); + block.apply(cquery, arguments); + return this; + }; + }, + basic: function (query) { + return function () { + var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this)); + cquery.find(query); + return this; + }; + } + }); + } +}; + +module.exports = NamedScope; diff --git a/node_modules/mongoose/lib/promise.js b/node_modules/mongoose/lib/promise.js new file mode 100644 index 0000000..20ab42a --- /dev/null +++ b/node_modules/mongoose/lib/promise.js @@ -0,0 +1,231 @@ + +/*! + * Module dependencies + */ + +var MPromise = require('mpromise'); + +/** + * Promise constructor. + * + * Promises are returned from executed queries. Example: + * + * var query = Candy.find({ bar: true }); + * var promise = query.exec(); + * + * @param {Function} fn a function which will be called when the promise is resolved that accepts `fn(err, ...){}` as signature + * @inherits mpromise https://github.com/aheckmann/mpromise + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `err`: Emits when the promise is rejected + * @event `complete`: Emits when the promise is fulfilled + * @api public + */ + +function Promise (fn) { + MPromise.call(this, fn); +} + +/*! + * Inherit from mpromise + */ + +Promise.prototype = Object.create(MPromise.prototype, { + constructor: { + value: Promise + , enumerable: false + , writable: true + , configurable: true + } +}); + +/*! + * Override event names for backward compatibility. + */ + +Promise.SUCCESS = 'complete'; +Promise.FAILURE = 'err'; + +/** + * Adds `listener` to the `event`. + * + * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event. + * + * @see mpromise#on https://github.com/aheckmann/mpromise#on + * @method on + * @memberOf Promise + * @param {String} event + * @param {Function} listener + * @return {Promise} this + * @api public + */ + +/** + * Rejects this promise with `reason`. + * + * If the promise has already been fulfilled or rejected, not action is taken. + * + * @see mpromise#reject https://github.com/aheckmann/mpromise#reject + * @method reject + * @memberOf Promise + * @param {Object|String|Error} reason + * @return {Promise} this + * @api public + */ + +/** + * Rejects this promise with `err`. + * + * If the promise has already been fulfilled or rejected, not action is taken. + * + * Differs from [#reject](#promise_Promise-reject) by first casting `err` to an `Error` if it is not `instanceof Error`. + * + * @api public + * @param {Error|String} err + * @return {Promise} this + */ + +Promise.prototype.error = function (err) { + if (!(err instanceof Error)) err = new Error(err); + return this.reject(err); +} + +/** + * Resolves this promise to a rejected state if `err` is passed or a fulfilled state if no `err` is passed. + * + * If the promise has already been fulfilled or rejected, not action is taken. + * + * `err` will be cast to an Error if not already instanceof Error. + * + * _NOTE: overrides [mpromise#resolve](https://github.com/aheckmann/mpromise#resolve) to provide error casting._ + * + * @param {Error} [err] error or null + * @param {Object} [val] value to fulfill the promise with + * @api public + */ + +Promise.prototype.resolve = function (err, val) { + if (err) return this.error(err); + return this.fulfill(val); +} + +/** + * Adds a single function as a listener to both err and complete. + * + * It will be executed with traditional node.js argument position when the promise is resolved. + * + * promise.addBack(function (err, args...) { + * if (err) return handleError(err); + * console.log('success'); + * }) + * + * Alias of [mpromise#onResolve](https://github.com/aheckmann/mpromise#onresolve). + * + * @method addBack + * @param {Function} listener + * @return {Promise} this + */ + +Promise.prototype.addBack = Promise.prototype.onResolve; + +/** + * Fulfills this promise with passed arguments. + * + * Alias of [mpromise#fulfill](https://github.com/aheckmann/mpromise#fulfill). + * + * @method complete + * @param {any} args + * @api public + */ + +Promise.prototype.complete = MPromise.prototype.fulfill; + +/** + * Adds a listener to the `complete` (success) event. + * + * Alias of [mpromise#onFulfill](https://github.com/aheckmann/mpromise#onfulfill). + * + * @method addCallback + * @param {Function} listener + * @return {Promise} this + * @api public + */ + +Promise.prototype.addCallback = Promise.prototype.onFulfill; + +/** + * Adds a listener to the `err` (rejected) event. + * + * Alias of [mpromise#onReject](https://github.com/aheckmann/mpromise#onreject). + * + * @method addErrback + * @param {Function} listener + * @return {Promise} this + * @api public + */ + +Promise.prototype.addErrback = Promise.prototype.onReject; + +/** + * Creates a new promise and returns it. If `onFulfill` or `onReject` are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick. + * + * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification. + * + * ####Example: + * + * var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec(); + * promise.then(function (meetups) { + * var ids = meetups.map(function (m) { + * return m._id; + * }); + * return People.find({ meetups: { $in: ids }).exec(); + * }).then(function (people) { + * if (people.length < 10000) { + * throw new Error('Too few people!!!'); + * } else { + * throw new Error('Still need more people!!!'); + * } + * }).then(null, function (err) { + * assert.ok(err instanceof Error); + * }); + * + * @see promises-A+ https://github.com/promises-aplus/promises-spec + * @see mpromise#then https://github.com/aheckmann/mpromise#then + * @method then + * @memberOf Promise + * @param {Function} onFulFill + * @param {Function} onReject + * @return {Promise} newPromise + */ + +/** + * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught. + * + * ####Example: + * + * var p = new Promise; + * p.then(function(){ throw new Error('shucks') }); + * setTimeout(function () { + * p.fulfill(); + * // error was caught and swallowed by the promise returned from + * // p.then(). we either have to always register handlers on + * // the returned promises or we can do the following... + * }, 10); + * + * // this time we use .end() which prevents catching thrown errors + * var p = new Promise; + * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- + * setTimeout(function () { + * p.fulfill(); // throws "shucks" + * }, 10); + * + * @api public + * @see mpromise#end https://github.com/aheckmann/mpromise#end + * @method end + * @memberOf Promise + */ + +/*! + * expose + */ + +module.exports = Promise; diff --git a/node_modules/mongoose/lib/query.js b/node_modules/mongoose/lib/query.js new file mode 100644 index 0000000..384876d --- /dev/null +++ b/node_modules/mongoose/lib/query.js @@ -0,0 +1,2612 @@ +/*! + * Module dependencies. + */ + +var utils = require('./utils') + , merge = utils.merge + , Promise = require('./promise') + , Document = require('./document') + , Types = require('./schema/index') + , inGroupsOf = utils.inGroupsOf + , tick = utils.tick + , QueryStream = require('./querystream') + , helpers = require('./queryhelpers') + , ReadPref = require('mongodb').ReadPreference + +/** + * Query constructor used for building queries. + * + * ####Example: + * + * var query = Model.find(); + * query.where('age').gte(21).exec(callback); + * + * @param {Object} criteria + * @param {Object} options + * @api public + */ + +function Query (criteria, options) { + this.setOptions(options, true); + this._conditions = {}; + this._updateArg = {}; + this._fields = undefined; + this._geoComparison = undefined; + if (criteria) this.find(criteria); +} + +/** + * Sets query options. + * + * ####Options: + * + * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) * + * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) * + * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) * + * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) * + * - [maxscan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) * + * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) * + * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) * + * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) * + * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) * + * - [slaveOk](http://docs.mongodb.org/manual/applications/replication/#read-preference) * + * - [lean](./api.html#query_Query-lean) * + * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command) + * + * _* denotes a query helper method is also available_ + * + * @param {Object} options + * @api public + */ + +Query.prototype.setOptions = function (options, overwrite) { + // overwrite is internal use only + if (overwrite) { + options = this.options = options || {}; + this.safe = options.safe; + if ('populate' in options) { + this.populate(this.options.populate); + } + return this; + } + + if (!(options && 'Object' == options.constructor.name)) + return this; + + if ('safe' in options) + this.safe = options.safe; + + // set arbitrary options + var methods = Object.keys(options) + , i = methods.length + , method + + while (i--) { + method = methods[i]; + + // use methods if exist (safer option manipulation) + if ('function' == typeof this[method]) { + var args = Array.isArray(options[method]) + ? options[method] + : [options[method]]; + this[method].apply(this, args) + } else { + this.options[method] = options[method]; + } + } + + return this; +} + +/** + * Binds this query to a model. + * + * @param {Model} model the model to which the query is bound + * @param {String} op the operation to execute + * @param {Object} updateArg used in update methods + * @return {Query} + * @api private + */ + +Query.prototype.bind = function bind (model, op, updateArg) { + this.model = model; + this.op = op; + + if (model._mapreduce) this.options.lean = true; + + if (op == 'update' || op == 'findOneAndUpdate') { + merge(this._updateArg, updateArg || {}); + } + + return this; +}; + +/** + * Executes the query + * + * ####Examples + * + * query.exec(); + * query.exec(callback); + * query.exec('update'); + * query.exec('find', callback); + * + * @param {String|Function} [operation] + * @param {Function} [callback] + * @return {Promise} + * @api public + */ + +Query.prototype.exec = function exec (op, callback) { + var promise = new Promise(); + + switch (typeof op) { + case 'function': + callback = op; + op = null; + break; + case 'string': + this.op = op; + break; + } + + if (callback) promise.addBack(callback); + + if (!this.op) { + promise.complete(); + return promise; + } + + if ('update' == this.op) { + this[this.op](this._updateArg, promise.resolve.bind(promise)); + return promise; + } + + if ('distinct' == this.op) { + this.distinct(this._distinctArg, promise.resolve.bind(promise)); + return promise; + } + + this[this.op](promise.resolve.bind(promise)); + return promise; +}; + +/** + * Finds documents. + * + * When no `callback` is passed, the query is not executed. + * + * ####Example + * + * query.find({ name: 'Los Pollos Hermanos' }).find(callback) + * + * @param {Object} [criteria] mongodb selector + * @param {Function} [callback] + * @return {Query} this + * @api public + */ + +Query.prototype.find = function (criteria, callback) { + this.op = 'find'; + if ('function' === typeof criteria) { + callback = criteria; + criteria = {}; + } else if (criteria instanceof Query) { + // TODO Merge options, too + merge(this._conditions, criteria._conditions); + } else if (criteria instanceof Document) { + merge(this._conditions, criteria.toObject()); + } else if (criteria && 'Object' === criteria.constructor.name) { + merge(this._conditions, criteria); + } + if (!callback) return this; + return this.execFind(callback); +}; + +/** + * Casts this query to the schema of `model` + * + * ####Note + * + * If `obj` is present, it is cast instead of this query. + * + * @param {Model} model + * @param {Object} [obj] + * @return {Object} + * @api public + */ + +Query.prototype.cast = function (model, obj) { + obj || (obj= this._conditions); + + var schema = model.schema + , paths = Object.keys(obj) + , i = paths.length + , any$conditionals + , schematype + , nested + , path + , type + , val; + + while (i--) { + path = paths[i]; + val = obj[path]; + + if ('$or' === path || '$nor' === path || '$and' === path) { + var k = val.length + , orComponentQuery; + + while (k--) { + orComponentQuery = new Query(val[k]); + orComponentQuery.cast(model); + val[k] = orComponentQuery._conditions; + } + + } else if (path === '$where') { + type = typeof val; + + if ('string' !== type && 'function' !== type) { + throw new Error("Must have a string or function for $where"); + } + + if ('function' === type) { + obj[path] = val.toString(); + } + + continue; + + } else { + + if (!schema) { + // no casting for Mixed types + continue; + } + + schematype = schema.path(path); + + if (!schematype) { + // Handle potential embedded array queries + var split = path.split('.') + , j = split.length + , pathFirstHalf + , pathLastHalf + , remainingConds + , castingQuery; + + // Find the part of the var path that is a path of the Schema + while (j--) { + pathFirstHalf = split.slice(0, j).join('.'); + schematype = schema.path(pathFirstHalf); + if (schematype) break; + } + + // If a substring of the input path resolves to an actual real path... + if (schematype) { + // Apply the casting; similar code for $elemMatch in schema/array.js + if (schematype.caster && schematype.caster.schema) { + remainingConds = {}; + pathLastHalf = split.slice(j).join('.'); + remainingConds[pathLastHalf] = val; + castingQuery = new Query(remainingConds); + castingQuery.cast(schematype.caster); + obj[path] = castingQuery._conditions[pathLastHalf]; + } else { + obj[path] = val; + } + continue; + } + + if (utils.isObject(val)) { + // handle geo schemas that use object notation + // { loc: { long: Number, lat: Number } + + var geo = val.$near ? '$near' : + val.$nearSphere ? '$nearSphere' : + val.$within ? '$within' : + val.$geoIntersects ? '$geoIntersects' : ''; + + if (!geo) { + continue; + } + + var numbertype = new Types.Number('__QueryCasting__') + var value = val[geo]; + + if (val.$maxDistance) { + val.$maxDistance = numbertype.castForQuery(val.$maxDistance); + } + + if ('$within' == geo) { + var withinType = value.$center + || value.$centerSphere + || value.$box + || value.$polygon; + + if (!withinType) { + throw new Error('Bad $within paramater: ' + JSON.stringify(val)); + } + + value = withinType; + + } else if ('$near' == geo && + 'string' == typeof value.type && Array.isArray(value.coordinates)) { + // geojson; cast the coordinates + value = value.coordinates; + + } else if (('$near' == geo || '$geoIntersects' == geo) && + value.$geometry && 'string' == typeof value.$geometry.type && + Array.isArray(value.$geometry.coordinates)) { + // geojson; cast the coordinates + value = value.$geometry.coordinates; + } + + ;(function _cast (val) { + if (Array.isArray(val)) { + val.forEach(function (item, i) { + if (Array.isArray(item) || utils.isObject(item)) { + return _cast(item); + } + val[i] = numbertype.castForQuery(item); + }); + } else { + var nearKeys= Object.keys(val); + var nearLen = nearKeys.length; + while (nearLen--) { + var nkey = nearKeys[nearLen]; + var item = val[nkey]; + if (Array.isArray(item) || utils.isObject(item)) { + _cast(item); + val[nkey] = item; + } else { + val[nkey] = numbertype.castForQuery(item); + } + } + } + })(value); + } + + } else if (val === null || val === undefined) { + continue; + } else if ('Object' === val.constructor.name) { + + any$conditionals = Object.keys(val).some(function (k) { + return k.charAt(0) === '$' && k !== '$id' && k !== '$ref'; + }); + + if (!any$conditionals) { + obj[path] = schematype.castForQuery(val); + } else { + + var ks = Object.keys(val) + , k = ks.length + , $cond; + + while (k--) { + $cond = ks[k]; + nested = val[$cond]; + + if ('$exists' === $cond) { + if ('boolean' !== typeof nested) { + throw new Error("$exists parameter must be Boolean"); + } + continue; + } + + if ('$type' === $cond) { + if ('number' !== typeof nested) { + throw new Error("$type parameter must be Number"); + } + continue; + } + + if ('$not' === $cond) { + this.cast(model, nested); + } else { + val[$cond] = schematype.castForQuery($cond, nested); + } + } + } + } else { + obj[path] = schematype.castForQuery(val); + } + } + } + + return obj; +}; + +/** + * Returns default options. + * @param {Model} model + * @api private + */ + +Query.prototype._optionsForExec = function (model) { + var options = utils.clone(this.options, { retainKeyOrder: true }); + delete options.populate; + + if (!('safe' in options)) + options.safe = model.schema.options.safe; + + if (!('readPreference' in options) && model.schema.options.read) + options.readPreference = model.schema.options.read; + + return options; +}; + +/** + * Applies schematype selected options to this query. + * @api private + */ + +Query.prototype._applyPaths = function applyPaths () { + // determine if query is selecting or excluding fields + + var fields = this._fields + , exclude + , keys + , ki + + if (fields) { + keys = Object.keys(fields); + ki = keys.length; + + while (ki--) { + if ('+' == keys[ki][0]) continue; + exclude = 0 === fields[keys[ki]]; + break; + } + } + + // if selecting, apply default schematype select:true fields + // if excluding, apply schematype select:false fields + + var selected = [] + , excluded = [] + , seen = []; + + analyzeSchema(this.model.schema); + + switch (exclude) { + case true: + excluded.length && this.select('-' + excluded.join(' -')); + break; + case false: + selected.length && this.select(selected.join(' ')); + break; + case undefined: + // user didn't specify fields, implies returning all fields. + // only need to apply excluded fields + excluded.length && this.select('-' + excluded.join(' -')); + break; + } + + return seen = excluded = selected = keys = fields = null; + + function analyzeSchema (schema, prefix) { + prefix || (prefix = ''); + + // avoid recursion + if (~seen.indexOf(schema)) return; + seen.push(schema); + + schema.eachPath(function (path, type) { + if (prefix) path = prefix + '.' + path; + + analyzePath(path, type); + + // array of subdocs? + if (type.schema) { + analyzeSchema(type.schema, path); + } + + }); + } + + function analyzePath (path, type) { + if ('boolean' != typeof type.selected) return; + + var plusPath = '+' + path; + if (fields && plusPath in fields) { + // forced inclusion + delete fields[plusPath]; + + // if there are other fields being included, add this one + // if no other included fields, leave this out (implied inclusion) + if (false === exclude && keys.length > 1 && !~keys.indexOf(path)) { + fields[path] = 1; + } + + return + }; + + // check for parent exclusions + var root = path.split('.')[0]; + if (~excluded.indexOf(root)) return; + + ;(type.selected ? selected : excluded).push(path); + } +} + +/** + * Specifies a javascript function or expression to pass to MongoDBs query system. + * + * ####Example + * + * query.$where('this.comments.length > 10 || this.name.length > 5') + * + * // or + * + * query.$where(function () { + * return this.comments.length > 10 || this.name.length > 5; + * }) + * + * ####NOTE: + * + * Only use `$where` when you have a condition that cannot be met using other MongoDB operators like `$lt`. + * **Be sure to read about all of [its caveats](http://docs.mongodb.org/manual/reference/operator/where/) before using.** + * + * @see $where http://docs.mongodb.org/manual/reference/operator/where/ + * @param {String|Function} js javascript string or function + * @return {Query} this + * @memberOf Query + * @method $where + * @api public + */ + +Query.prototype.$where = function (js) { + this._conditions['$where'] = js; + return this; +}; + +/** + * Specifies a `path` for use with chaining. + * + * ####Example + * + * // instead of writing: + * User.find({age: {$gte: 21, $lte: 65}}, callback); + * + * // we can instead write: + * User.where('age').gte(21).lte(65); + * + * // Moreover, you can also chain a bunch of these together: + * + * User + * .where('age').gte(21).lte(65) + * .where('name', /^b/i) + * .where('friends').slice(10) + * .exec(callback) + * + * @param {String} [path] + * @param {Object} [val] + * @return {Query} this + * @api public + */ + +Query.prototype.where = function (path, val) { + if (!arguments.length) return this; + + if ('string' != typeof path) { + throw new TypeError('path must be a string'); + } + + this._currPath = path; + + if (2 === arguments.length) { + this._conditions[path] = val; + } + + return this; +}; + +/** + * Specifies the complementary comparison value for paths specified with `where()` + * + * ####Example + * + * User.where('age').equals(49); + * + * // is the same as + * + * User.where('age', 49); + * + * @param {Object} val + * @return {Query} this + * @api public + */ + +Query.prototype.equals = function equals (val) { + var path = this._currPath; + if (!path) throw new Error('equals() must be used after where()'); + this._conditions[path] = val; + return this; +} + +/** + * Specifies arguments for an `$or` condition. + * + * ####Example + * + * query.or([{ color: 'red' }, { status: 'emergency' }]) + * + * @see $or http://docs.mongodb.org/manual/reference/operator/or/ + * @param {Array} array array of conditions + * @return {Query} this + * @api public + */ + +Query.prototype.or = function or (array) { + var or = this._conditions.$or || (this._conditions.$or = []); + if (!Array.isArray(array)) array = [array]; + or.push.apply(or, array); + return this; +} + +/** + * Specifies arguments for a `$nor` condition. + * + * ####Example + * + * query.nor([{ color: 'green' }, { status: 'ok' }]) + * + * @see $nor http://docs.mongodb.org/manual/reference/operator/nor/ + * @param {Array} array array of conditions + * @return {Query} this + * @api public + */ + +Query.prototype.nor = function nor (array) { + var nor = this._conditions.$nor || (this._conditions.$nor = []); + if (!Array.isArray(array)) array = [array]; + nor.push.apply(nor, array); + return this; +} + +/** + * Specifies arguments for a `$and` condition. + * + * ####Example + * + * query.and([{ color: 'green' }, { status: 'ok' }]) + * + * @see $and http://docs.mongodb.org/manual/reference/operator/and/ + * @param {Array} array array of conditions + * @return {Query} this + * @api public + */ + +Query.prototype.and = function and (array) { + var and = this._conditions.$and || (this._conditions.$and = []); + if (!Array.isArray(array)) array = [array]; + and.push.apply(and, array); + return this; +} + +/** + * Specifies a $gt query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * ####Example + * + * Thing.find().where('age').gt(21) + * + * // or + * Thing.find().gt('age', 21) + * + * @see $gt http://docs.mongodb.org/manual/reference/operator/gt/ + * @method gt + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies a $gte query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $gte http://docs.mongodb.org/manual/reference/operator/gte/ + * @method gte + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies a $lt query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $lt http://docs.mongodb.org/manual/reference/operator/lt/ + * @method lt + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies a $lte query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $lte http://docs.mongodb.org/manual/reference/operator/lte/ + * @method lte + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies a $ne query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $ne http://docs.mongodb.org/manual/reference/operator/ne/ + * @method ne + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies an $in query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $in http://docs.mongodb.org/manual/reference/operator/in/ + * @method in + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies an $nin query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $nin http://docs.mongodb.org/manual/reference/operator/nin/ + * @method nin + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies an $all query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $all http://docs.mongodb.org/manual/reference/operator/all/ + * @method all + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies an $size query condition. + * + * ####Example + * + * MyModel.where('tags').size(0).exec(function (err, docs) { + * if (err) return handleError(err); + * + * assert(Array.isArray(docs)); + * console.log('documents with 0 tags', docs); + * }) + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $size http://docs.mongodb.org/manual/reference/operator/size/ + * @method size + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies a $regex query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $regex http://docs.mongodb.org/manual/reference/operator/regex/ + * @method regex + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/** + * Specifies a $maxDistance query condition. + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/ + * @method maxDistance + * @memberOf Query + * @param {String} path + * @param {Number} val + * @api public + */ + +/*! + * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance + * + * Thing.where('type').nin(array) + */ + +'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) { + Query.prototype[$conditional] = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$' + $conditional] = val; + return this; + }; +}); + +/** + * Specifies a `$near` condition + * + * @param {String} path + * @param {Number} val + * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $near http://docs.mongodb.org/manual/reference/operator/near/ + * @api public + */ + +Query.prototype.near = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath + } else if (arguments.length === 2 && !Array.isArray(val)) { + val = utils.args(arguments); + path = this._currPath; + } else if (arguments.length === 3) { + val = utils.args(arguments, 1); + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$near = val; + return this; +} + +/** + * Specifies a `$nearSphere` condition. + * + * @param {String} path + * @param {Object} val + * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $nearSphere http://docs.mongodb.org/manual/reference/operator/nearSphere/ + * @api public + */ + +Query.prototype.nearSphere = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath + } else if (arguments.length === 2 && !Array.isArray(val)) { + val = utils.args(arguments); + path = this._currPath; + } else if (arguments.length === 3) { + val = utils.args(arguments, 1); + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$nearSphere = val; + return this; +} + +/** + * Specifies a `$mod` condition + * + * @param {String} path + * @param {Number} val + * @return {Query} this + * @see $mod http://docs.mongodb.org/manual/reference/operator/mod/ + * @api public + */ + +Query.prototype.mod = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath + } else if (arguments.length === 2 && !Array.isArray(val)) { + val = utils.args(arguments); + path = this._currPath; + } else if (arguments.length === 3) { + val = utils.args(arguments, 1); + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds.$mod = val; + return this; +} + +/** + * Specifies an `$exists` condition + * + * @param {String} path + * @param {Number} val + * @return {Query} this + * @see $exists http://docs.mongodb.org/manual/reference/operator/exists/ + * @api public + */ + +Query.prototype.exists = function (path, val) { + if (arguments.length === 0) { + path = this._currPath + val = true; + } else if (arguments.length === 1) { + if ('boolean' === typeof path) { + val = path; + path = this._currPath; + } else { + val = true; + } + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$exists'] = val; + return this; +}; + +/** + * Specifies an `$elemMatch` condition + * + * ####Example + * + * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}}) + * + * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}}) + * + * query.elemMatch('comment', function (elem) { + * elem.where('author').equals('autobot'); + * elem.where('votes').gte(5); + * }) + * + * query.where('comment').elemMatch(function (elem) { + * elem.where('author').equals('autobot'); + * elem.where('votes').gte(5); + * }) + * + * @param {String|Object|Function} path + * @param {Object|Function} criteria + * @return {Query} this + * @see $elemMatch http://docs.mongodb.org/manual/reference/operator/elemMatch/ + * @api public + */ + +Query.prototype.elemMatch = function (path, criteria) { + var block; + if ('Object' === path.constructor.name) { + criteria = path; + path = this._currPath; + } else if ('function' === typeof path) { + block = path; + path = this._currPath; + } else if ('Object' === criteria.constructor.name) { + } else if ('function' === typeof criteria) { + block = criteria; + } else { + throw new Error("Argument error"); + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + if (block) { + criteria = new Query(); + block(criteria); + conds['$elemMatch'] = criteria._conditions; + } else { + conds['$elemMatch'] = criteria; + } + return this; +}; + +// Spatial queries + +/** + * Defines a $within query for `box()`, `center()`, etc + * + * ####Example + * + * query.within.box() + * query.within.center() + * query.within.geometry() + * + * @property within + * @memberOf Query + * @see Query#box #query_Query-box + * @see Query#center #query_Query-center + * @see Query#centerSphere #query_Query-centerSphere + * @see Query#polygon #query_Query-polygon + * @see Query#geometry #query_Query-geometry + * @see $geoWithin http://docs.mongodb.org/manual/reference/operator/within/ + * @return {Query} this + * @api public + */ + +Object.defineProperty(Query.prototype, 'within', { + get: function () { + this._geoComparison = '$within'; + return this + } +}); + +/** + * Declares an intersects query for `geometry()`. + * + * ####Example + * + * query.intersects.geometry({ + * type: 'LineString' + * , coordinates: [[180.0, 11.0], [180, 9.0]] + * }) + * + * @property intersects + * @see Query#geometry #query_Query-geometry + * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/ + * @see geoIntersects http://docs.mongodb.org/manual/reference/operator/geoIntersects/ + * @memberOf Query + * @return {Query} this + * @api public + */ + +Object.defineProperty(Query.prototype, 'intersects', { + get: function () { + this._geoComparison = '$geoIntersects'; + return this + } +}); + +/** + * Specifies a $box condition + * + * ####Example + * + * var lowerLeft = [40.73083, -73.99756] + * var upperRight= [40.741404, -73.988135] + * query.where('loc').within.box({ ll: lowerLeft , ur: upperRight }) + * + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see Query#within #query_Query-within + * @see $box http://docs.mongodb.org/manual/reference/operator/box/ + * @param {String} path + * @param {Object} val + * @return {Query} this + * @api public + */ + +Query.prototype.box = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath; + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$within'] = { '$box': [val.ll, val.ur] }; + return this; +}; + +/** + * Specifies a $center condition + * + * ####Example + * + * var area = { center: [50, 50], radius: 10 } + * query.where('loc').within.center(area) + * + * @param {String} path + * @param {Object} val + * @param {Object} [opts] options e.g. { $uniqueDocs: true } + * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $center http://docs.mongodb.org/manual/reference/operator/center/ + * @api public + */ + +Query.prototype.center = function (path, val, opts) { + if (arguments.length === 1) { + val = path; + path = this._currPath; + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$within'] = { '$center': [val.center, val.radius] }; + + // copy any options + if (opts && 'Object' == opts.constructor.name) { + utils.options(opts, conds.$within); + } + + return this; +}; + +/** + * Specifies a $centerSphere condition + * + * ####Example + * + * var area = { center: [50, 50], radius: 10 } + * query.where('loc').within.centerSphere(area) + * + * @param {String} [path] + * @param {Object} val + * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/ + * @api public + */ + +Query.prototype.centerSphere = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath; + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$within'] = { '$centerSphere': [val.center, val.radius] }; + return this; +}; + +/** + * Specifies a $polygon condition + * + * ####Example + * + * var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ] + * query.where('loc').within.polygon(polyA) + * + * // or + * var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } } + * query.where('loc').within.polygon(polyB) + * + * @param {String} [path] + * @param {Array|Object} val + * @return {Query} this + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $polygon http://docs.mongodb.org/manual/reference/operator/polygon/ + * @api public + */ + +Query.prototype.polygon = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath; + } + var conds = this._conditions[path] || (this._conditions[path] = {}); + conds['$within'] = { '$polygon': val }; + return this; +}; + +/** + * Specifies a $geometry condition + * + * ####Example + * + * var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]] + * query.where('loc').within.geometry({ type: 'Polygon', coordinates: polyA }) + * + * // or + * var polyB = [[ 0, 0 ], [ 1, 1 ]] + * query.where('loc').within.geometry({ type: 'LineString', coordinates: polyB }) + * + * // or + * var polyC = [ 0, 0 ] + * query.where('loc').within.geometry({ type: 'Point', coordinates: polyC }) + * + * // or + * var polyC = [ 0, 0 ] + * query.where('loc').intersects.geometry({ type: 'Point', coordinates: polyC }) + * + * ####NOTE: + * + * `geometry()` **must** come after either `intersects` or `within`. + * + * The `object` argument must contain `type` and `coordinates` properties. + * - type {String} + * - coordinates {Array} + * + * When called with one argument, the most recent path passed to `where()` is used. + * + * @param {String} [path] Optional name of a path to match against + * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the example. + * @return {Query} this + * @see http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry + * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing + * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/ + * @api public + */ + +Query.prototype.geometry = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath; + } + + var conds = this._conditions[path] || (this._conditions[path] = {}); + + if (!this._geoComparison) { + throw new Error('query.geometry() must come after either `within` or `intersects`'); + } + + conds[this._geoComparison] = { $geometry: val }; + return this; +}; + +/** + * Specifies which document fields to include or exclude + * + * When using string syntax, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. Lastly, if a path is prefixed with `+`, it forces inclusion of the path, which is useful for paths excluded at the [schema level](/docs/api.html#schematype_SchemaType-select). + * + * ####Example + * + * // include a and b, exclude c + * query.select('a b -c'); + * + * // or you may use object notation, useful when + * // you have keys already prefixed with a "-" + * query.select({a: 1, b: 1, c: 0}); + * + * // force inclusion of field excluded at schema level + * query.select('+path') + * + * ####NOTE: + * + * _v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3._ + * + * @param {Object|String} arg + * @return {Query} this + * @see SchemaType + * @api public + */ + +Query.prototype.select = function select (arg) { + if (!arg) return this; + + var fields = this._fields || (this._fields = {}); + + if ('Object' === arg.constructor.name) { + Object.keys(arg).forEach(function (field) { + fields[field] = arg[field]; + }); + } else if (1 === arguments.length && 'string' == typeof arg) { + arg.split(/\s+/).forEach(function (field) { + if (!field) return; + var include = '-' == field[0] ? 0 : 1; + if (include === 0) field = field.substring(1); + fields[field] = include; + }); + } else { + throw new TypeError('Invalid select() argument. Must be a string or object.'); + } + + return this; +}; + +/** + * Specifies a $slice projection for an array. + * + * ####Example + * + * query.slice('comments', 5) + * query.slice('comments', -5) + * query.slice('comments', [10, 5]) + * query.where('comments').slice(5) + * query.where('comments').slice([-10, 5]) + * + * @param {String} path + * @param {Number} val number of elements to slice + * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements + * @see $slice http://docs.mongodb.org/manual/reference/projection/slice/#prj._S_slice + * @api public + */ + +Query.prototype.slice = function (path, val) { + if (arguments.length === 1) { + val = path; + path = this._currPath + } else if (arguments.length === 2) { + if ('number' === typeof path) { + val = [path, val]; + path = this._currPath; + } + } else if (arguments.length === 3) { + val = utils.args(arguments, 1); + } + var myFields = this._fields || (this._fields = {}); + myFields[path] = { '$slice': val }; + return this; +}; + +/** + * Sets the sort order + * + * If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`. + * + * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending. + * + * ####Example + * + * // sort by "field" ascending and "test" descending + * query.sort({ field: 'asc', test: -1 }); + * + * // equivalent + * query.sort('field -test'); + * + * @param {Object|String} arg + * @return {Query} this + * @see cursor.sort http://docs.mongodb.org/manual/reference/method/cursor.sort/ + * @api public + */ + +Query.prototype.sort = function (arg) { + if (!arg) return this; + + var sort = this.options.sort || (this.options.sort = []); + + if ('Object' === arg.constructor.name) { + Object.keys(arg).forEach(function (field) { + push(sort, field, arg[field]); + }); + } else if (1 === arguments.length && 'string' == typeof arg) { + arg.split(/\s+/).forEach(function (field) { + if (!field) return; + var ascend = '-' == field[0] ? -1 : 1; + if (ascend === -1) field = field.substring(1); + push(sort, field, ascend); + }); + } else { + throw new TypeError('Invalid sort() argument. Must be a string or object.'); + } + + return this; +}; + +/*! + * @ignore + */ + +function push (arr, field, value) { + var val = String(value || 1).toLowerCase(); + if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) { + if (Array.isArray(value)) value = '['+value+']'; + throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }'); + } + arr.push([field, value]); +} + +/** + * Specifies the maximum number of documents the query will return. + * + * ####Example + * + * Kitten.find().limit(20).exec(callback) + * + * @method limit + * @memberOf Query + * @param {Number} val + * @api public + */ +/** + * Specifies the number of documents to skip. + * + * ####Example + * + * Kitten.find().skip(100).limit(20) + * + * @method skip + * @memberOf Query + * @param {Number} val + * @see cursor.skip http://docs.mongodb.org/manual/reference/method/cursor.skip/ + * @api public + */ +/** + * Specifies the maxscan option. + * + * ####Example + * + * Kitten.find().maxscan(100) + * + * @method maxscan + * @memberOf Query + * @param {Number} val + * @see maxScan http://docs.mongodb.org/manual/reference/operator/maxScan/ + * @api public + */ +/** + * Specifies the batchSize option. + * + * ####Example + * + * Kitten.find().batchSize(100) + * + * @method batchSize + * @memberOf Query + * @param {Number} val + * @see batchSize http://docs.mongodb.org/manual/reference/method/cursor.batchSize/ + * @api public + */ +/** + * Specifies the `comment` option. + * + * ####Example + * + * Kitten.findOne(condition).comment('login query') + * + * @method comment + * @memberOf Query + * @param {Number} val + * @see comment http://docs.mongodb.org/manual/reference/operator/comment/ + * @api public + */ + +/*! + * limit, skip, maxscan, batchSize, comment + * + * Sets these associated options. + * + * query.comment('feed query'); + */ + +;['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) { + Query.prototype[method] = function (v) { + this.options[method] = v; + return this; + }; +}); + +/** + * Specifies this query as a `snapshot` query. + * + * ####Example + * + * Kitten.find().snapshot() + * + * @see snapshot http://docs.mongodb.org/manual/reference/operator/snapshot/ + * @return {Query} this + * @api public + */ + +Query.prototype.snapshot = function () { + this.options.snapshot = true; + return this; +}; + +/** + * Sets query hints. + * + * ####Example + * + * Model.find().hint({ indexA: 1, indexB: -1}) + * + * @param {Object} val a hint object + * @return {Query} this + * @see $hint http://docs.mongodb.org/manual/reference/operator/hint/ + * @api public + */ + +Query.prototype.hint = function (val) { + if (!val) return this; + + var hint = this.options.hint || (this.options.hint = {}); + + if ('Object' === val.constructor.name) { + // must keep object keys in order so don't use Object.keys() + for (var k in val) { + hint[k] = val[k]; + } + } else { + throw new TypeError('Invalid hint. ' + val); + } + + return this; +}; + +/** + * Sets the slaveOk option. _Deprecated_ in MongoDB 2.2 in favor of [read preferences](#query_Query-read). + * + * ####Example: + * + * new Query().slaveOk() // true + * new Query().slaveOk(true) + * new Query().slaveOk(false) + * + * @param {Boolean} v defaults to true + * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference + * @see slaveOk http://docs.mongodb.org/manual/reference/method/rs.slaveOk/ + * @return {Query} this + * @api public + */ + +Query.prototype.slaveOk = function (v) { + this.options.slaveOk = arguments.length ? !!v : true; + return this; +} + +/** + * Determines the MongoDB nodes from which to read. + * + * ####Preferences: + * + * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags. + * secondary Read from secondary if available, otherwise error. + * primaryPreferred Read from primary if available, otherwise a secondary. + * secondaryPreferred Read from a secondary if available, otherwise read from the primary. + * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the selection. + * + * Aliases + * + * p primary + * pp primaryPreferred + * s secondary + * sp secondaryPreferred + * n nearest + * + * ####Example: + * + * new Query().read('primary') + * new Query().read('p') // same as primary + * + * new Query().read('primaryPreferred') + * new Query().read('pp') // same as primaryPreferred + * + * new Query().read('secondary') + * new Query().read('s') // same as secondary + * + * new Query().read('secondaryPreferred') + * new Query().read('sp') // same as secondaryPreferred + * + * new Query().read('nearest') + * new Query().read('n') // same as nearest + * + * // read from secondaries with matching tags + * new Query().read('secondary', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }]) + * + * Read more about how to use read preferrences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences). + * + * @param {String} pref one of the listed preference options or aliases + * @param {Array} [tags] optional tags for this query + * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference + * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences + * @return {Query} this + * @api public + */ + +Query.prototype.read = function (pref, tags) { + this.options.readPreference = utils.readPref(pref, tags); + return this; +} + +/** + * Sets the lean option. + * + * Documents returned from queries with the `lean` option enabled are plain javascript objects, not [MongooseDocuments](#document-js). They have no `save` method, getters/setters or other Mongoose magic applied. + * + * ####Example: + * + * new Query().lean() // true + * new Query().lean(true) + * new Query().lean(false) + * + * Model.find().lean().exec(function (err, docs) { + * docs[0] instanceof mongoose.Document // false + * }); + * + * This is a [great](https://groups.google.com/forum/#!topic/mongoose-orm/u2_DzDydcnA/discussion) option in high-performance read-only scenarios, especially when combined with [stream](#query_Query-stream). + * + * @param {Boolean} bool defaults to true + * @return {Query} this + * @api public + */ + +Query.prototype.lean = function (v) { + this.options.lean = arguments.length ? !!v : true; + return this; +} + +/** + * Sets the tailable option (for use with capped collections). + * + * ####Example + * + * Kitten.find().tailable() // true + * Kitten.find().tailable(true) + * Kitten.find().tailable(false) + * + * @param {Boolean} bool defaults to true + * @see tailable http://docs.mongodb.org/manual/tutorial/create-tailable-cursor/ + * @api public + */ + +Query.prototype.tailable = function (v) { + this.options.tailable = arguments.length ? !!v : true; + return this; +}; + +/** + * Executes the query as a find() operation. + * + * @param {Function} callback + * @return {Query} this + * @api private + */ + +Query.prototype.execFind = function (callback) { + var model = this.model + , promise = new Promise(callback); + + try { + this.cast(model); + } catch (err) { + promise.error(err); + return this; + } + + // apply default schematype path selections + this._applyPaths(); + + var self = this + , castQuery = this._conditions + , options = this._optionsForExec(model) + , fields = utils.clone(this._fields) + + options.fields = this._castFields(fields); + if (options.fields instanceof Error) { + promise.error(options.fields); + return this; + } + + model.collection.find(castQuery, options, function (err, cursor) { + if (err) return promise.error(err); + cursor.toArray(tick(cb)); + }); + + function cb (err, docs) { + if (err) return promise.error(err); + + if (0 === docs.length) { + return promise.complete(docs); + } + + if (!self.options.populate) { + return true === options.lean + ? promise.complete(docs) + : completeMany(model, docs, fields, self, null, promise); + } + + var pop = helpers.preparePopulationOptions(self, options); + model.populate(docs, pop, function (err, docs) { + if (err) return promise.error(err); + return true === options.lean + ? promise.complete(docs) + : completeMany(model, docs, fields, self, pop, promise); + }); + } + + return this; +} + +/*! + * hydrates many documents + * + * @param {Model} model + * @param {Array} docs + * @param {Object} fields + * @param {Query} self + * @param {Array} [pop] array of paths used in population + * @param {Promise} promise + */ + +function completeMany (model, docs, fields, self, pop, promise) { + var arr = []; + var count = docs.length; + var len = count; + var i = 0; + var opts = pop ? + { populated: pop } + : undefined; + + for (; i < len; ++i) { + arr[i] = new model(undefined, fields, true); + arr[i].init(docs[i], opts, function (err) { + if (err) return promise.error(err); + --count || promise.complete(arr); + }); + } +} + +/** + * Executes the query as a findOne() operation, passing the first found document to the callback. + * + * ####Example + * + * var query = Kitten.find({ color: 'white'}); + * + * query.findOne(function (err, kitten) { + * if (err) return handleError(err); + * + * // kitten may be null if no document matched + * if (kitten) { + * ... + * } + * }) + * + * @param {Function} callback + * @return {Query} this + * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/ + * @api public + */ + +Query.prototype.findOne = function (callback) { + this.op = 'findOne'; + + if (!callback) return this; + + var model = this.model; + var promise = new Promise(callback); + + try { + this.cast(model); + } catch (err) { + promise.error(err); + return this; + } + + // apply default schematype path selections + this._applyPaths(); + + var self = this + , castQuery = this._conditions + , options = this._optionsForExec(model) + , fields = utils.clone(this._fields) + + options.fields = this._castFields(fields); + if (options.fields instanceof Error) { + promise.error(options.fields); + return this; + } + + model.collection.findOne(castQuery, options, tick(function (err, doc) { + if (err) return promise.error(err); + if (!doc) return promise.complete(null); + + if (!self.options.populate) { + return true === options.lean + ? promise.complete(doc) + : completeOne(model, doc, fields, self, null, promise); + } + + var pop = helpers.preparePopulationOptions(self, options); + model.populate(doc, pop, function (err, doc) { + if (err) return promise.error(err); + return true === options.lean + ? promise.complete(doc) + : completeOne(model, doc, fields, self, pop, promise); + }) + })); + + return this; +} + +/*! + * hydrates a document + * + * @param {Model} model + * @param {Document} doc + * @param {Object} fields + * @param {Query} self + * @param {Array} [pop] array of paths used in population + * @param {Promise} promise + */ + +function completeOne (model, doc, fields, self, pop, promise) { + var opts = pop ? + { populated: pop } + : undefined; + + var casted = new model(undefined, fields, true); + casted.init(doc, opts, function (err) { + if (err) return promise.error(err); + promise.complete(casted); + }); +} + +/** + * Exectues the query as a count() operation. + * + * ####Example + * + * Kitten.where('color', 'black').count(function (err, count) { + * if (err) return handleError(err); + * console.log('there are %d black kittens', count); + * }) + * + * @param {Function} callback + * @return {Query} this + * @see count http://docs.mongodb.org/manual/reference/method/db.collection.count/ + * @api public + */ + +Query.prototype.count = function (callback) { + this.op = 'count'; + if (!callback) return this; + + var model = this.model; + + try { + this.cast(model); + } catch (err) { + return callback(err); + } + + var castQuery = this._conditions; + model.collection.count(castQuery, tick(callback)); + + return this; +}; + +/** + * Executes this query as a distict() operation. + * + * ####Example + * + * Link.find({ clicks: { $gt: 100 }}).distinct('url', function (err, result) { + * if (err) return handleError(err); + * + * assert(Array.isArray(result)); + * console.log('unique urls with more than 100 clicks', result); + * }) + * + * @param {String} field + * @param {Function} callback + * @return {Query} this + * @see distinct http://docs.mongodb.org/manual/reference/method/db.collection.distinct/ + * @api public + */ + +Query.prototype.distinct = function (field, callback) { + this.op = 'distinct'; + var model = this.model; + + try { + this.cast(model); + } catch (err) { + return callback(err); + } + + var castQuery = this._conditions; + model.collection.distinct(field, castQuery, tick(callback)); + + return this; +}; + +/*! + * These operators require casting docs + * to real Documents for Update operations. + */ + +var castOps = { + $push: 1 + , $pushAll: 1 + , $addToSet: 1 + , $set: 1 +}; + +/*! + * These operators should be cast to numbers instead + * of their path schema type. + */ + +var numberOps = { + $pop: 1 + , $unset: 1 + , $inc: 1 +} + +/** + * Executes this query as an update() operation. + * + * _All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility._ + * + * ####Example + * + * Model.update({..}, { title: 'remove words' }, ...) + * + * // becomes + * + * Model.update({..}, { $set: { title: 'remove words' }}, ...) + * + * ####Note + * + * Passing an empty object `{}` as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection. + * + * @param {Object} doc the update conditions + * @param {Function} callback + * @return {Query} this + * @api public + * @see Model.update #model_Model.update + * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/ + */ + +Query.prototype.update = function update (doc, callback) { + this.op = 'update'; + this._updateArg = doc; + + var model = this.model + , options = this._optionsForExec(model) + , fn = 'function' == typeof callback + , castedQuery + , castedDoc + + castedQuery = castQuery(this); + if (castedQuery instanceof Error) { + if (fn) { + process.nextTick(callback.bind(null, castedQuery)); + return this; + } + throw castedQuery; + } + + castedDoc = castDoc(this); + if (!castedDoc) { + fn && process.nextTick(callback.bind(null, null, 0)); + return this; + } + + if (castedDoc instanceof Error) { + if (fn) { + process.nextTick(callback.bind(null, castedDoc)); + return this; + } + throw castedDoc; + } + + if (!fn) { + options.safe = { w: 0 }; + } + + model.collection.update(castedQuery, castedDoc, options, tick(callback)); + return this; +}; + +/** + * Casts obj for an update command. + * + * @param {Object} obj + * @return {Object} obj after casting its values + * @api private + */ + +Query.prototype._castUpdate = function _castUpdate (obj) { + var ops = Object.keys(obj) + , i = ops.length + , ret = {} + , hasKeys + , val + + while (i--) { + var op = ops[i]; + if ('$' !== op[0]) { + // fix up $set sugar + if (!ret.$set) { + if (obj.$set) { + ret.$set = obj.$set; + } else { + ret.$set = {}; + } + } + ret.$set[op] = obj[op]; + ops.splice(i, 1); + if (!~ops.indexOf('$set')) ops.push('$set'); + } else if ('$set' === op) { + if (!ret.$set) { + ret[op] = obj[op]; + } + } else { + ret[op] = obj[op]; + } + } + + // cast each value + i = ops.length; + + while (i--) { + op = ops[i]; + val = ret[op]; + if ('Object' === val.constructor.name) { + hasKeys |= this._walkUpdatePath(val, op); + } else { + var msg = 'Invalid atomic update value for ' + op + '. ' + + 'Expected an object, received ' + typeof val; + throw new Error(msg); + } + } + + return hasKeys && ret; +} + +/** + * Walk each path of obj and cast its values + * according to its schema. + * + * @param {Object} obj - part of a query + * @param {String} op - the atomic operator ($pull, $set, etc) + * @param {String} pref - path prefix (internal only) + * @return {Bool} true if this path has keys to update + * @api private + */ + +Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) { + var prefix = pref ? pref + '.' : '' + , keys = Object.keys(obj) + , i = keys.length + , hasKeys = false + , schema + , key + , val + + var strict = 'strict' in this.options + ? this.options.strict + : this.model.schema.options.strict; + + while (i--) { + key = keys[i]; + val = obj[key]; + + if (val && 'Object' === val.constructor.name) { + // watch for embedded doc schemas + schema = this._getSchema(prefix + key); + if (schema && schema.caster && op in castOps) { + // embedded doc schema + + if (strict && !schema) { + // path is not in our strict schema + if ('throw' == strict) { + throw new Error('Field `' + key + '` is not in schema.'); + } else { + // ignore paths not specified in schema + delete obj[key]; + } + } else { + hasKeys = true; + + if ('$each' in val) { + obj[key] = { + $each: this._castUpdateVal(schema, val.$each, op) + } + + if (val.$slice) { + obj[key].$slice = val.$slice | 0; + } + + if (val.$sort) { + obj[key].$sort = val.$sort; + } + + } else { + obj[key] = this._castUpdateVal(schema, val, op); + } + } + } else { + hasKeys |= this._walkUpdatePath(val, op, prefix + key); + } + } else { + schema = '$each' === key + ? this._getSchema(pref) + : this._getSchema(prefix + key); + + var skip = strict && + !schema && + !/real|nested/.test(this.model.schema.pathType(prefix + key)); + + if (skip) { + if ('throw' == strict) { + throw new Error('Field `' + prefix + key + '` is not in schema.'); + } else { + delete obj[key]; + } + } else { + hasKeys = true; + obj[key] = this._castUpdateVal(schema, val, op, key); + } + } + } + return hasKeys; +} + +/** + * Casts `val` according to `schema` and atomic `op`. + * + * @param {Schema} schema + * @param {Object} val + * @param {String} op - the atomic operator ($pull, $set, etc) + * @param {String} [$conditional] + * @api private + */ + +Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) { + if (!schema) { + // non-existing schema path + return op in numberOps + ? Number(val) + : val + } + + if (schema.caster && op in castOps && + ('Object' === val.constructor.name || Array.isArray(val))) { + // Cast values for ops that add data to MongoDB. + // Ensures embedded documents get ObjectIds etc. + var tmp = schema.cast(val); + + if (Array.isArray(val)) { + val = tmp; + } else { + val = tmp[0]; + } + } + + if (op in numberOps) return Number(val); + if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val); + return schema.castForQuery(val) +} + +/** + * Finds the schema for `path`. This is different than + * calling `schema.path` as it also resolves paths with + * positional selectors (something.$.another.$.path). + * + * @param {String} path + * @api private + */ + +Query.prototype._getSchema = function _getSchema (path) { + return this.model._getSchema(path); +} + +/** + * Casts selected field arguments for field selection with mongo 2.2 + * + * query.select({ ids: { $elemMatch: { $in: [hexString] }}) + * + * @param {Object} fields + * @see https://github.com/LearnBoost/mongoose/issues/1091 + * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/ + * @api private + */ + +Query.prototype._castFields = function _castFields (fields) { + var selected + , elemMatchKeys + , keys + , key + , out + , i + + if (fields) { + keys = Object.keys(fields); + elemMatchKeys = []; + i = keys.length; + + // collect $elemMatch args + while (i--) { + key = keys[i]; + if (fields[key].$elemMatch) { + selected || (selected = {}); + selected[key] = fields[key]; + elemMatchKeys.push(key); + } + } + } + + if (selected) { + // they passed $elemMatch, cast em + try { + out = this.cast(this.model, selected); + } catch (err) { + return err; + } + + // apply the casted field args + i = elemMatchKeys.length; + while (i--) { + key = elemMatchKeys[i]; + fields[key] = out[key]; + } + } + + return fields; +} + +/** + * Executes this query as a remove() operation. + * + * ####Example + * + * Cassette.where('artist').equals('Anne Murray').remove(callback) + * + * @param {Function} callback + * @api public + * @see remove http://docs.mongodb.org/manual/reference/method/db.collection.remove/ + */ + +Query.prototype.remove = function (callback) { + this.op = 'remove'; + + var model = this.model + , options = this._optionsForExec(model) + , cb = 'function' == typeof callback + + try { + this.cast(model); + } catch (err) { + if (cb) return callback(err); + throw err; + } + + if (!cb) { + options.safe = { w: 0 }; + } + + var castQuery = this._conditions; + model.collection.remove(castQuery, options, tick(callback)); + return this; +}; + +/** + * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command. + * + * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned. + * + * ####Available options + * + * - `new`: bool - true to return the modified document rather than the original. defaults to true + * - `upsert`: bool - creates the object if it doesn't exist. defaults to false. + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * + * ####Examples + * + * query.findOneAndUpdate(conditions, update, options, callback) // executes + * query.findOneAndUpdate(conditions, update, options) // returns Query + * query.findOneAndUpdate(conditions, update, callback) // executes + * query.findOneAndUpdate(conditions, update) // returns Query + * query.findOneAndUpdate(callback) // executes + * query.findOneAndUpdate() // returns Query + * + * @param {Object} [query] + * @param {Object} [doc] + * @param {Object} [options] + * @param {Function} [callback] + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @return {Query} this + * @api public + */ + +Query.prototype.findOneAndUpdate = function (query, doc, options, callback) { + this.op = 'findOneAndUpdate'; + + switch (arguments.length) { + case 3: + if ('function' == typeof options) + callback = options, options = {}; + break; + case 2: + if ('function' == typeof doc) { + callback = doc; + doc = query; + query = undefined; + } + options = undefined; + break; + case 1: + if ('function' == typeof query) { + callback = query; + query = options = doc = undefined; + } else { + doc = query; + query = options = undefined; + } + } + + // apply query + if (query) { + if ('Object' === query.constructor.name) { + merge(this._conditions, query); + } else if (query instanceof Query) { + merge(this._conditions, query._conditions); + } else if (query instanceof Document) { + merge(this._conditions, query.toObject()); + } + } + + // apply doc + if (doc) { + merge(this._updateArg, doc); + } + + // apply options + options && this.setOptions(options); + + if (!callback) return this; + + return this._findAndModify('update', callback); +} + +/** + * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command. + * + * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed else a Query object is returned. + * + * ####Available options + * + * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update + * + * ####Examples + * + * A.where().findOneAndRemove(conditions, options, callback) // executes + * A.where().findOneAndRemove(conditions, options) // return Query + * A.where().findOneAndRemove(conditions, callback) // executes + * A.where().findOneAndRemove(conditions) // returns Query + * A.where().findOneAndRemove(callback) // executes + * A.where().findOneAndRemove() // returns Query + * + * @param {Object} [conditions] + * @param {Object} [options] + * @param {Function} [callback] + * @return {Query} this + * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command + * @api public + */ + +Query.prototype.findOneAndRemove = function (conditions, options, callback) { + this.op = 'findOneAndRemove'; + + if ('function' == typeof options) { + callback = options; + options = undefined; + } else if ('function' == typeof conditions) { + callback = conditions; + conditions = undefined; + } + + // apply conditions + if (conditions) { + if ('Object' === conditions.constructor.name) { + merge(this._conditions, conditions); + } else if (conditions instanceof Query) { + merge(this._conditions, conditions._conditions); + } else if (conditions instanceof Document) { + merge(this._conditions, conditions.toObject()); + } + } + + // apply options + options && this.setOptions(options); + + if (!callback) return this; + + return this._findAndModify('remove', callback); +} + +/** + * _findAndModify + * + * @param {String} type - either "remove" or "update" + * @param {Function} callback + * @api private + */ + +Query.prototype._findAndModify = function (type, callback) { + var model = this.model + , promise = new Promise(callback) + , self = this + , castedQuery + , castedDoc + , fields + , sort + , opts + + castedQuery = castQuery(this); + if (castedQuery instanceof Error) { + process.nextTick(promise.error.bind(promise, castedQuery)); + return promise; + } + + opts = this._optionsForExec(model); + + if ('remove' == type) { + opts.remove = true; + } else { + if (!('new' in opts)) opts.new = true; + if (!('upsert' in opts)) opts.upsert = false; + + castedDoc = castDoc(this); + if (!castedDoc) { + if (opts.upsert) { + // still need to do the upsert to empty doc + castedDoc = { $set: {} }; + } else { + return this.findOne(callback); + } + } else if (castedDoc instanceof Error) { + process.nextTick(promise.error.bind(promise, castedDoc)); + return promise; + } + } + + this._applyPaths(); + + if (this._fields) { + fields = utils.clone(this._fields) + opts.fields = this._castFields(fields); + if (opts.fields instanceof Error) { + process.nextTick(promise.error.bind(promise, opts.fields)); + return promise; + } + } + + // the driver needs a default + sort = opts.sort || []; + + model + .collection + .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) { + if (err) return promise.error(err); + if (!doc || (utils.isObject(doc) && Object.keys(doc).length === 0)) { + return promise.complete(null); + } + + if (!self.options.populate) { + return true === opts.lean + ? promise.complete(doc) + : completeOne(model, doc, fields, self, null, promise); + } + + var pop = helpers.preparePopulationOptions(self, opts); + model.populate(doc, pop, function (err, doc) { + if (err) return promise.error(err); + return true === opts.lean + ? promise.complete(doc) + : completeOne(model, doc, fields, self, pop, promise); + }) + })); + + return promise; +} + +/** + * Specifies paths which should be populated with other documents. + * + * ####Example: + * + * Kitten.findOne().populate('owner').exec(function (err, kitten) { + * console.log(kitten.owner.name) // Max + * }) + * + * Kitten.find().populate({ + * path: 'owner' + * , select: 'name' + * , match: { color: 'black' } + * , options: { sort: { name: -1 }} + * }).exec(function (err, kittens) { + * console.log(kittens[0].owner.name) // Zoopa + * }) + * + * // alternatively + * Kitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) { + * console.log(kittens[0].owner.name) // Zoopa + * }) + * + * Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback. + * + * @param {Object|String} path either the path to populate or an object specifying all parameters + * @param {Object|String} [select] Field selection for the population query + * @param {Model} [model] The name of the model you wish to use for population. If not specified, the name is looked up from the Schema ref. + * @param {Object} [match] Conditions for the population query + * @param {Object} [options] Options for the population query (sort, etc) + * @see population ./populate.html + * @see Query#select #query_Query-select + * @see Model.populate #model_Model.populate + * @return {Query} this + * @api public + */ + +Query.prototype.populate = function populate () { + var res = utils.populate.apply(null, arguments); + var opts = this.options; + + if (!utils.isObject(opts.populate)) { + opts.populate = {}; + } + + for (var i = 0; i < res.length; ++i) { + opts.populate[res[i].path] = res[i]; + } + + return this; +} + +/** + * Returns a Node.js 0.8 style [read stream](http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream) interface. + * + * ####Example + * + * // follows the nodejs 0.8 stream api + * Thing.find({ name: /^hello/ }).stream().pipe(res) + * + * // manual streaming + * var stream = Thing.find({ name: /^hello/ }).stream(); + * + * stream.on('data', function (doc) { + * // do something with the mongoose document + * }).on('error', function (err) { + * // handle the error + * }).on('close', function () { + * // the stream is closed + * }); + * + * ####Valid options + * + * - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data`. + * + * ####Example + * + * // JSON.stringify all documents before emitting + * var stream = Thing.find().stream({ transform: JSON.stringify }); + * stream.pipe(writeStream); + * + * @return {QueryStream} + * @param {Object} [options] + * @see QueryStream + * @api public + */ + +Query.prototype.stream = function stream (opts) { + return new QueryStream(this, opts); +} + +// helpers + +/*! + * castDoc + * @api private + */ + +function castDoc (query) { + try { + return query._castUpdate(query._updateArg); + } catch (err) { + return err; + } +} + +/*! + * castQuery + * @api private + */ + +function castQuery (query) { + try { + return query.cast(query.model); + } catch (err) { + return err; + } +} + +/*! + * Exports. + */ + +module.exports = Query; +module.exports.QueryStream = QueryStream; diff --git a/node_modules/mongoose/lib/queryhelpers.js b/node_modules/mongoose/lib/queryhelpers.js new file mode 100644 index 0000000..4637fad --- /dev/null +++ b/node_modules/mongoose/lib/queryhelpers.js @@ -0,0 +1,35 @@ + +/*! + * Module dependencies + */ + +var utils = require('./utils') + +/*! + * Prepare a set of path options for query population. + * + * @param {Query} query + * @param {Object} options + * @return {Array} + */ + +exports.preparePopulationOptions = function preparePopulationOptions (query, options) { + var pop = utils.object.vals(query.options.populate); + + // lean options should trickle through all queries + if (options.lean) pop.forEach(makeLean); + + return pop; +} + +/*! + * Set each path query option to lean + * + * @param {Object} option + */ + +function makeLean (option) { + option.options || (option.options = {}); + option.options.lean = true; +} + diff --git a/node_modules/mongoose/lib/querystream.js b/node_modules/mongoose/lib/querystream.js new file mode 100644 index 0000000..6db7570 --- /dev/null +++ b/node_modules/mongoose/lib/querystream.js @@ -0,0 +1,336 @@ + +/*! + * Module dependencies. + */ + +var Stream = require('stream').Stream +var utils = require('./utils') +var helpers = require('./queryhelpers') +var K = function(k){ return k } + +/** + * Provides a Node.js 0.8 style [ReadStream](http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream) interface for Queries. + * + * var stream = Model.find().stream(); + * + * stream.on('data', function (doc) { + * // do something with the mongoose document + * }).on('error', function (err) { + * // handle the error + * }).on('close', function () { + * // the stream is closed + * }); + * + * + * The stream interface allows us to simply "plug-in" to other _Node.js 0.8_ style write streams. + * + * Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream); + * + * ####Valid options + * + * - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data`. + * + * ####Example + * + * // JSON.stringify all documents before emitting + * var stream = Thing.find().stream({ transform: JSON.stringify }); + * stream.pipe(writeStream); + * + * _NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary._ + * + * _NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work._ + * + * @param {Query} query + * @param {Object} [options] + * @inherits NodeJS Stream http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream + * @event `data`: emits a single Mongoose document + * @event `error`: emits when an error occurs during streaming. This will emit _before_ the `close` event. + * @event `close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted. + * @api public + */ + +function QueryStream (query, options) { + Stream.call(this); + + this.query = query; + this.readable = true; + this.paused = false; + this._cursor = null; + this._destroyed = null; + this._fields = null; + this._buffer = null; + this._inline = T_INIT; + this._running = false; + this._transform = options && 'function' == typeof options.transform + ? options.transform + : K; + + // give time to hook up events + var self = this; + process.nextTick(function () { + self._init(); + }); +} + +/*! + * Inherit from Stream + */ + +QueryStream.prototype.__proto__ = Stream.prototype; + +/** + * Flag stating whether or not this stream is readable. + * + * @property readable + * @api public + */ + +QueryStream.prototype.readable; + +/** + * Flag stating whether or not this stream is paused. + * + * @property paused + * @api public + */ + +QueryStream.prototype.paused; + +// trampoline flags +var T_INIT = 0; +var T_IDLE = 1; +var T_CONT = 2; + +/** + * Initializes the query. + * + * @api private + */ + +QueryStream.prototype._init = function () { + if (this._destroyed) return; + + var query = this.query + , model = query.model + , options = query._optionsForExec(model) + , self = this + + try { + query.cast(model); + } catch (err) { + return self.destroy(err); + } + + self._fields = utils.clone(query._fields); + options.fields = query._castFields(self._fields); + + model.collection.find(query._conditions, options, function (err, cursor) { + if (err) return self.destroy(err); + self._cursor = cursor; + self._next(); + }); +} + +/** + * Trampoline for pulling the next doc from cursor. + * + * @see QueryStream#__next #querystream_QueryStream-__next + * @api private + */ + +QueryStream.prototype._next = function _next () { + if (this.paused || this._destroyed) { + return this._running = false; + } + + this._running = true; + + if (this._buffer && this._buffer.length) { + var arg; + while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) { + this._onNextObject.apply(this, arg); + } + } + + // avoid stack overflows with large result sets. + // trampoline instead of recursion. + while (this.__next()) {} +} + +/** + * Pulls the next doc from the cursor. + * + * @see QueryStream#_next #querystream_QueryStream-_next + * @api private + */ + +QueryStream.prototype.__next = function () { + if (this.paused || this._destroyed) + return this._running = false; + + var self = this; + self._inline = T_INIT; + + self._cursor.nextObject(function cursorcb (err, doc) { + self._onNextObject(err, doc); + }); + + // if onNextObject() was already called in this tick + // return ourselves to the trampoline. + if (T_CONT === this._inline) { + return true; + } else { + // onNextObject() hasn't fired yet. tell onNextObject + // that its ok to call _next b/c we are not within + // the trampoline anymore. + this._inline = T_IDLE; + } +} + +/** + * Transforms raw `doc`s returned from the cursor into a model instance. + * + * @param {Error|null} err + * @param {Object} doc + * @api private + */ + +QueryStream.prototype._onNextObject = function _onNextObject (err, doc) { + if (this._destroyed) return; + + if (this.paused) { + this._buffer || (this._buffer = []); + this._buffer.push([err, doc]); + return this._running = false; + } + + if (err) return this.destroy(err); + + // when doc is null we hit the end of the cursor + if (!doc) { + this.emit('end'); + return this.destroy(); + } + + var opts = this.query.options; + + if (!opts.populate) { + return true === opts.lean + ? emit(this, doc) + : createAndEmit(this, doc); + } + + var self = this; + var pop = helpers.preparePopulationOptions(self.query, self.query.options); + + self.query.model.populate(doc, pop, function (err, doc) { + if (err) return self.destroy(err); + return true === opts.lean + ? emit(self, doc) + : createAndEmit(self, doc); + }) +} + +function createAndEmit (self, doc) { + var instance = new self.query.model(undefined, self._fields, true); + instance.init(doc, function (err) { + if (err) return self.destroy(err); + emit(self, instance); + }); +} + +/*! + * Emit a data event and manage the trampoline state + */ + +function emit (self, doc) { + self.emit('data', self._transform(doc)); + + // trampoline management + if (T_IDLE === self._inline) { + // no longer in trampoline. restart it. + self._next(); + } else { + // in a trampoline. tell __next that its + // ok to continue jumping. + self._inline = T_CONT; + } +} + +/** + * Pauses this stream. + * + * @api public + */ + +QueryStream.prototype.pause = function () { + this.paused = true; +} + +/** + * Resumes this stream. + * + * @api public + */ + +QueryStream.prototype.resume = function () { + this.paused = false; + + if (!this._cursor) { + // cannot start if not initialized + return; + } + + // are we within the trampoline? + if (T_INIT === this._inline) { + return; + } + + if (!this._running) { + // outside QueryStream control, need manual restart + return this._next(); + } +} + +/** + * Destroys the stream, closing the underlying cursor. No more events will be emitted. + * + * @param {Error} [err] + * @api public + */ + +QueryStream.prototype.destroy = function (err) { + if (this._destroyed) return; + this._destroyed = true; + this._running = false; + this.readable = false; + + if (this._cursor) { + this._cursor.close(); + } + + if (err) { + this.emit('error', err); + } + + this.emit('close'); +} + +/** + * Pipes this query stream into another stream. This method is inherited from NodeJS Streams. + * + * ####Example: + * + * query.stream().pipe(writeStream [, options]) + * + * @method pipe + * @memberOf QueryStream + * @see NodeJS http://nodejs.org/api/stream.html + * @api public + */ + +/*! + * Module exports + */ + +module.exports = exports = QueryStream; diff --git a/node_modules/mongoose/lib/schema.js b/node_modules/mongoose/lib/schema.js new file mode 100644 index 0000000..53effd4 --- /dev/null +++ b/node_modules/mongoose/lib/schema.js @@ -0,0 +1,910 @@ +/*! + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , VirtualType = require('./virtualtype') + , utils = require('./utils') + , NamedScope + , Query + , Types + +/** + * Schema constructor. + * + * ####Example: + * + * var child = new Schema({ name: String }); + * var schema = new Schema({ name: String, age: Number, children: [child] }); + * var Tree = mongoose.model('Tree', schema); + * + * // setting schema options + * new Schema({ name: String }, { _id: false, autoIndex: false }) + * + * ####Options: + * + * - [autoIndex](/docs/guide.html#autoIndex): bool - defaults to true + * - [bufferCommands](/docs/guide.html#bufferCommands): bool - defaults to true + * - [capped](/docs/guide.html#capped): bool - defaults to false + * - [collection](/docs/guide.html#collection): string - no default + * - [id](/docs/guide.html#id): bool - defaults to true + * - [_id](/docs/guide.html#_id): bool - defaults to true + * - `minimize`: bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - defaults to true + * - [read](/docs/guide.html#read): string + * - [safe](/docs/guide.html#safe): bool - defaults to true. + * - [shardKey](/docs/guide.html#shardKey): bool - defaults to `null` + * - [strict](/docs/guide.html#strict): bool - defaults to true + * - [toJSON](/docs/guide.html#toJSON) - object - no default + * - [toObject](/docs/guide.html#toObject) - object - no default + * - [versionKey](/docs/guide.html#versionKey): bool - defaults to "__v" + * + * ####Note: + * + * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into is parent._ + * + * @param {Object} definition + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `init`: Emitted after the schema is compiled into a `Model`. + * @api public + */ + +function Schema (obj, options) { + if (!(this instanceof Schema)) + return new Schema(obj, options); + + this.paths = {}; + this.subpaths = {}; + this.virtuals = {}; + this.nested = {}; + this.inherits = {}; + this.callQueue = []; + this._indexes = []; + this.methods = {}; + this.statics = {}; + this.tree = {}; + this._requiredpaths = undefined; + + this.options = this.defaultOptions(options); + + // build paths + if (obj) { + this.add(obj); + } + + // ensure the documents get an auto _id unless disabled + var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id); + if (auto_id) { + this.add({ _id: {type: Schema.ObjectId, auto: true} }); + } + + // ensure the documents receive an id getter unless disabled + var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id); + if (autoid) { + this.virtual('id').get(idGetter); + } +} + +/*! + * Returns this documents _id cast to a string. + */ + +function idGetter () { + if (this.$__._id) { + return this.$__._id; + } + + return this.$__._id = null == this._id + ? null + : String(this._id); +} + +/*! + * Inherit from EventEmitter. + */ + +Schema.prototype.__proto__ = EventEmitter.prototype; + +/** + * Schema as flat paths + * + * ####Example: + * { + * '_id' : SchemaType, + * , 'nested.key' : SchemaType, + * } + * + * @api private + * @property paths + */ + +Schema.prototype.paths; + +/** + * Schema as a tree + * + * ####Example: + * { + * '_id' : ObjectId + * , 'nested' : { + * 'key' : String + * } + * } + * + * @api private + * @property tree + */ + +Schema.prototype.tree; + +/** + * Returns default options for this schema, merged with `options`. + * + * @param {Object} options + * @return {Object} + * @api private + */ + +Schema.prototype.defaultOptions = function (options) { + if (options && false === options.safe) { + options.safe = { w: 0 }; + } + + options = utils.options({ + strict: true + , bufferCommands: true + , capped: false // { size, max, autoIndexId } + , versionKey: '__v' + , minimize: true + , autoIndex: true + , shardKey: null + , read: null + // the following are only applied at construction time + , noId: false // deprecated, use { _id: false } + , _id: true + , noVirtualId: false // deprecated, use { id: false } + , id: true + }, options); + + if (options.read) + options.read = utils.readPref(options.read); + + return options; +} + +/** + * Adds key path / schema type pairs to this schema. + * + * ####Example: + * + * var ToySchema = new Schema; + * ToySchema.add({ name: 'string', color: 'string', price: 'number' }); + * + * @param {Object} obj + * @param {String} prefix + * @api public + */ + +Schema.prototype.add = function add (obj, prefix) { + prefix = prefix || ''; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + + if (null == obj[key]) { + throw new TypeError('Invalid value for schema path `'+ prefix + key +'`'); + } + + if (utils.isObject(obj[key]) && (!obj[key].constructor || 'Object' == obj[key].constructor.name) && (!obj[key].type || obj[key].type.type)) { + if (Object.keys(obj[key]).length) { + // nested object { last: { name: String }} + this.nested[prefix + key] = true; + this.add(obj[key], prefix + key + '.'); + } else { + this.path(prefix + key, obj[key]); // mixed type + } + } else { + this.path(prefix + key, obj[key]); + } + } +}; + +/** + * Reserved document keys. + * + * Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error. + * + * on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject + * + * _NOTE:_ Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on. + * + * var schema = new Schema(..); + * schema.methods.init = function () {} // potentially breaking + */ + +Schema.reserved = Object.create(null); +var reserved = Schema.reserved; +reserved.on = +reserved.db = +reserved.init = +reserved.isNew = +reserved.errors = +reserved.schema = +reserved.options = +reserved.modelName = +reserved.collection = +reserved.toObject = +reserved.emit = // EventEmitter +reserved._events = // EventEmitter +reserved._pres = reserved._posts = 1 // hooks.js + +/** + * Gets/sets schema paths. + * + * Sets a path (if arity 2) + * Gets a path (if arity 1) + * + * ####Example + * + * schema.path('name') // returns a SchemaType + * schema.path('name', Number) // changes the schemaType of `name` to Number + * + * @param {String} path + * @param {Object} constructor + * @api public + */ + +Schema.prototype.path = function (path, obj) { + if (obj == undefined) { + if (this.paths[path]) return this.paths[path]; + if (this.subpaths[path]) return this.subpaths[path]; + + // subpaths? + return /\.\d+\.?.*$/.test(path) + ? getPositionalPath(this, path) + : undefined; + } + + // some path names conflict with document methods + if (reserved[path]) { + throw new Error("`" + path + "` may not be used as a schema pathname"); + } + + // update the tree + var subpaths = path.split(/\./) + , last = subpaths.pop() + , branch = this.tree; + + subpaths.forEach(function(sub, i) { + if (!branch[sub]) branch[sub] = {}; + if ('object' != typeof branch[sub]) { + var msg = 'Cannot set nested path `' + path + '`. ' + + 'Parent path `' + + subpaths.slice(0, i).concat([sub]).join('.') + + '` already set to type ' + branch[sub].name + + '.'; + throw new Error(msg); + } + branch = branch[sub]; + }); + + branch[last] = utils.clone(obj); + + this.paths[path] = Schema.interpretAsType(path, obj); + return this; +}; + +/** + * Converts type arguments into Mongoose Types. + * + * @param {String} path + * @param {Object} obj constructor + * @api private + */ + +Schema.interpretAsType = function (path, obj) { + if (obj.constructor && obj.constructor.name != 'Object') + obj = { type: obj }; + + // Get the type making sure to allow keys named "type" + // and default to mixed if not specified. + // { type: { type: String, default: 'freshcut' } } + var type = obj.type && !obj.type.type + ? obj.type + : {}; + + if ('Object' == type.constructor.name || 'mixed' == type) { + return new Types.Mixed(path, obj); + } + + if (Array.isArray(type) || Array == type || 'array' == type) { + // if it was specified through { type } look for `cast` + var cast = (Array == type || 'array' == type) + ? obj.cast + : type[0]; + + if (cast instanceof Schema) { + return new Types.DocumentArray(path, cast, obj); + } + + if ('string' == typeof cast) { + cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)]; + } else if (cast && (!cast.type || cast.type.type) + && 'Object' == cast.constructor.name + && Object.keys(cast).length) { + return new Types.DocumentArray(path, new Schema(cast), obj); + } + + return new Types.Array(path, cast || Types.Mixed, obj); + } + + var name = 'string' == typeof type + ? type + : type.name; + + if (name) { + name = name.charAt(0).toUpperCase() + name.substring(1); + } + + if (undefined == Types[name]) { + throw new TypeError('Undefined type at `' + path + + '`\n Did you try nesting Schemas? ' + + 'You can only nest using refs or arrays.'); + } + + return new Types[name](path, obj); +}; + +/** + * Iterates the schemas paths similar to Array#forEach. + * + * The callback is passed the pathname and schemaType as arguments on each iteration. + * + * @param {Function} fn callback function + * @return {Schema} this + * @api public + */ + +Schema.prototype.eachPath = function (fn) { + var keys = Object.keys(this.paths) + , len = keys.length; + + for (var i = 0; i < len; ++i) { + fn(keys[i], this.paths[keys[i]]); + } + + return this; +}; + +/** + * Returns an Array of path strings that are required by this schema. + * + * @api public + * @return {Array} + */ + +Schema.prototype.requiredPaths = function requiredPaths () { + if (this._requiredpaths) return this._requiredpaths; + + var paths = Object.keys(this.paths) + , i = paths.length + , ret = []; + + while (i--) { + var path = paths[i]; + if (this.paths[path].isRequired) ret.push(path); + } + + return this._requiredpaths = ret; +} + +/** + * Returns the pathType of `path` for this schema. + * + * Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path. + * + * @param {String} path + * @return {String} + * @api public + */ + +Schema.prototype.pathType = function (path) { + if (path in this.paths) return 'real'; + if (path in this.virtuals) return 'virtual'; + if (path in this.nested) return 'nested'; + if (path in this.subpaths) return 'real'; + + if (/\.\d+\.|\.\d+$/.test(path) && getPositionalPath(this, path)) { + return 'real'; + } else { + return 'adhocOrUndefined' + } +}; + +/*! + * ignore + */ + +function getPositionalPath (self, path) { + var subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean); + if (subpaths.length < 2) { + return self.paths[subpaths[0]]; + } + + var val = self.path(subpaths[0]); + if (!val) return val; + + var last = subpaths.length - 1 + , subpath + , i = 1; + + for (; i < subpaths.length; ++i) { + subpath = subpaths[i]; + + if (i === last && val && !val.schema && !/\D/.test(subpath)) { + if (val instanceof Types.Array) { + // StringSchema, NumberSchema, etc + val = val.caster; + } else { + val = undefined; + } + break; + } + + // ignore if its just a position segment: path.0.subpath + if (!/\D/.test(subpath)) continue; + + if (!(val && val.schema)) { + val = undefined; + break; + } + + val = val.schema.path(subpath); + } + + return self.subpaths[path] = val; +} + +/** + * Adds a method call to the queue. + * + * @param {String} name name of the document method to call later + * @param {Array} args arguments to pass to the method + * @api private + */ + +Schema.prototype.queue = function(name, args){ + this.callQueue.push([name, args]); + return this; +}; + +/** + * Defines a pre hook for the document. + * + * ####Example + * + * var toySchema = new Schema(..); + * + * toySchema.pre('save', function (next) { + * if (!this.created) this.created = new Date; + * next(); + * }) + * + * toySchema.pre('validate', function (next) { + * if (this.name != 'Woody') this.name = 'Woody'; + * next(); + * }) + * + * @param {String} method + * @param {Function} callback + * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3 + * @api public + */ + +Schema.prototype.pre = function(){ + return this.queue('pre', arguments); +}; + +/** + * Defines a post for the document + * + * Post hooks fire `on` the event emitted from document instances of Models compiled from this schema. + * + * var schema = new Schema(..); + * schema.post('save', function (doc) { + * console.log('this fired after a document was saved'); + * }); + * + * var Model = mongoose.model('Model', schema); + * + * var m = new Model(..); + * m.save(function (err) { + * console.log('this fires after the `post` hook'); + * }); + * + * @param {String} method name of the method to hook + * @param {Function} fn callback + * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3 + * @api public + */ + +Schema.prototype.post = function(method, fn){ + return this.queue('on', arguments); +}; + +/** + * Registers a plugin for this schema. + * + * @param {Function} plugin callback + * @param {Object} opts + * @see plugins + * @api public + */ + +Schema.prototype.plugin = function (fn, opts) { + fn(this, opts); + return this; +}; + +/** + * Adds an instance method to documents constructed from Models compiled from this schema. + * + * ####Example + * + * var schema = kittySchema = new Schema(..); + * + * schema.method('meow', function () { + * console.log('meeeeeoooooooooooow'); + * }) + * + * var Kitty = mongoose.model('Kitty', schema); + * + * var fizz = new Kitty; + * fizz.meow(); // meeeeeooooooooooooow + * + * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods. + * + * schema.method({ + * purr: function () {} + * , scratch: function () {} + * }); + * + * // later + * fizz.purr(); + * fizz.scratch(); + * + * @param {String|Object} method name + * @param {Function} [fn] + * @api public + */ + +Schema.prototype.method = function (name, fn) { + if ('string' != typeof name) + for (var i in name) + this.methods[i] = name[i]; + else + this.methods[name] = fn; + return this; +}; + +/** + * Adds static "class" methods to Models compiled from this schema. + * + * ####Example + * + * var schema = new Schema(..); + * schema.static('findByName', function (name, callback) { + * return this.find({ name: name }, callback); + * }); + * + * var Drink = mongoose.model('Drink', schema); + * Drink.findByName('sanpellegrino', function (err, drinks) { + * // + * }); + * + * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics. + * + * @param {String} name + * @param {Function} fn + * @api public + */ + +Schema.prototype.static = function(name, fn) { + if ('string' != typeof name) + for (var i in name) + this.statics[i] = name[i]; + else + this.statics[name] = fn; + return this; +}; + +/** + * Defines an index (most likely compound) for this schema. + * + * ####Example + * + * schema.index({ first: 1, last: -1 }) + * + * @param {Object} fields + * @param {Object} [options] + * @api public + */ + +Schema.prototype.index = function (fields, options) { + options || (options = {}); + + if (options.expires) + utils.expires(options); + + this._indexes.push([fields, options]); + return this; +}; + +/** + * Sets/gets a schema option. + * + * @param {String} key option name + * @param {Object} [value] if not passed, the current option value is returned + * @api public + */ + +Schema.prototype.set = function (key, value, _tags) { + if (1 === arguments.length) { + return this.options[key]; + } + + switch (key) { + case 'read': + this.options[key] = utils.readPref(value, _tags) + break; + case 'safe': + this.options[key] = false === value + ? { w: 0 } + : value + break; + default: + this.options[key] = value; + } + + return this; +} + +/** + * Gets a schema option. + * + * @param {String} key option name + * @api public + */ + +Schema.prototype.get = function (key) { + return this.options[key]; +} + +/** + * The allowed index types + * + * @static indexTypes + * @receiver Schema + * @api public + */ + +var indexTypes = '2d 2dsphere hashed text'.split(' '); + +Object.defineProperty(Schema, 'indexTypes', { + get: function () { return indexTypes } + , set: function () { throw new Error('Cannot overwrite Schema.indexTypes') } +}) + +/** + * Compiles indexes from fields and schema-level indexes + * + * @api public + */ + +Schema.prototype.indexes = function () { + 'use strict'; + + var indexes = [] + , seenSchemas = [] + collectIndexes(this); + return indexes; + + function collectIndexes (schema, prefix) { + if (~seenSchemas.indexOf(schema)) return; + seenSchemas.push(schema); + + prefix = prefix || ''; + + var key, path, index, field, isObject, options, type; + var keys = Object.keys(schema.paths); + + for (var i = 0; i < keys.length; ++i) { + key = keys[i]; + path = schema.paths[key]; + + if (path instanceof Types.DocumentArray) { + collectIndexes(path.schema, key + '.'); + } else { + index = path._index; + + if (false !== index && null != index) { + field = {}; + isObject = utils.isObject(index); + options = isObject ? index : {}; + type = 'string' == typeof index ? index : + isObject ? index.type : + false; + + if (type && ~Schema.indexTypes.indexOf(type)) { + field[prefix + key] = type; + } else { + field[prefix + key] = 1; + } + + delete options.type; + if (!('background' in options)) { + options.background = true; + } + + indexes.push([field, options]); + } + } + } + + if (prefix) { + fixSubIndexPaths(schema, prefix); + } else { + schema._indexes.forEach(function (index) { + if (!('background' in index[1])) index[1].background = true; + }); + indexes = indexes.concat(schema._indexes); + } + } + + /*! + * Checks for indexes added to subdocs using Schema.index(). + * These indexes need their paths prefixed properly. + * + * schema._indexes = [ [indexObj, options], [indexObj, options] ..] + */ + + function fixSubIndexPaths (schema, prefix) { + var subindexes = schema._indexes + , len = subindexes.length + , indexObj + , newindex + , klen + , keys + , key + , i = 0 + , j + + for (i = 0; i < len; ++i) { + indexObj = subindexes[i][0]; + keys = Object.keys(indexObj); + klen = keys.length; + newindex = {}; + + // use forward iteration, order matters + for (j = 0; j < klen; ++j) { + key = keys[j]; + newindex[prefix + key] = indexObj[key]; + } + + indexes.push([newindex, subindexes[i][1]]); + } + } +} + +/** + * Creates a virtual type with the given name. + * + * @param {String} name + * @param {Object} [options] + * @return {VirtualType} + */ + +Schema.prototype.virtual = function (name, options) { + var virtuals = this.virtuals; + var parts = name.split('.'); + return virtuals[name] = parts.reduce(function (mem, part, i) { + mem[part] || (mem[part] = (i === parts.length-1) + ? new VirtualType(options, name) + : {}); + return mem[part]; + }, this.tree); +}; + +/** + * Returns the virtual type with the given `name`. + * + * @param {String} name + * @return {VirtualType} + */ + +Schema.prototype.virtualpath = function (name) { + return this.virtuals[name]; +}; + +/** + * These still haven't been fixed. Once they're working we'll make them public again. + * @api private + */ + +Schema.prototype.namedScope = function (name, fn) { + var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope) + , newScope = Object.create(namedScopes) + , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {}); + allScopes[name] = newScope; + newScope.name = name; + newScope.block = fn; + newScope.query = new Query(); + newScope.decorate(namedScopes, { + block0: function (block) { + return function () { + block.call(this.query); + return this; + }; + }, + blockN: function (block) { + return function () { + block.apply(this.query, arguments); + return this; + }; + }, + basic: function (query) { + return function () { + this.query.find(query); + return this; + }; + } + }); + return newScope; +}; + +/*! + * Module exports. + */ + +module.exports = exports = Schema; + +// require down here because of reference issues + +/** + * The various built-in Mongoose Schema Types. + * + * ####Example: + * + * var mongoose = require('mongoose'); + * var ObjectId = mongoose.Schema.Types.ObjectId; + * + * ####Types: + * + * - [String](#schema-string-js) + * - [Number](#schema-number-js) + * - [Boolean](#schema-boolean-js) | Bool + * - [Array](#schema-array-js) + * - [Buffer](#schema-buffer-js) + * - [Date](#schema-date-js) + * - [ObjectId](#schema-objectid-js) | Oid + * - [Mixed](#schema-mixed-js) + * + * Using this exposed access to the `Mixed` SchemaType, we can use them in our schema. + * + * var Mixed = mongoose.Schema.Types.Mixed; + * new mongoose.Schema({ _user: Mixed }) + * + * @api public + */ + +Schema.Types = require('./schema/index'); + +/*! + * ignore + */ + +Types = Schema.Types; +NamedScope = require('./namedscope') +Query = require('./query'); +var ObjectId = exports.ObjectId = Types.ObjectId; + diff --git a/node_modules/mongoose/lib/schema/array.js b/node_modules/mongoose/lib/schema/array.js new file mode 100644 index 0000000..3bdbbce --- /dev/null +++ b/node_modules/mongoose/lib/schema/array.js @@ -0,0 +1,316 @@ +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype') + , CastError = SchemaType.CastError + , NumberSchema = require('./number') + , Types = { + Boolean: require('./boolean') + , Date: require('./date') + , Number: require('./number') + , String: require('./string') + , ObjectId: require('./objectid') + , Buffer: require('./buffer') + } + , MongooseArray = require('../types').Array + , EmbeddedDoc = require('../types').Embedded + , Mixed = require('./mixed') + , Query = require('../query') + , utils = require('../utils') + , isMongooseObject = utils.isMongooseObject + +/** + * Array SchemaType constructor + * + * @param {String} key + * @param {SchemaType} cast + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function SchemaArray (key, cast, options) { + if (cast) { + var castOptions = {}; + + if ('Object' === cast.constructor.name) { + if (cast.type) { + // support { type: Woot } + castOptions = utils.clone(cast); // do not alter user arguments + delete castOptions.type; + cast = cast.type; + } else { + cast = Mixed; + } + } + + // support { type: 'String' } + var name = 'string' == typeof cast + ? cast + : cast.name; + + var caster = name in Types + ? Types[name] + : cast; + + this.casterConstructor = caster; + this.caster = new caster(null, castOptions); + if (!(this.caster instanceof EmbeddedDoc)) { + this.caster.path = key; + } + } + + SchemaType.call(this, key, options); + + var self = this + , defaultArr + , fn; + + if (this.defaultValue) { + defaultArr = this.defaultValue; + fn = 'function' == typeof defaultArr; + } + + this.default(function(){ + var arr = fn ? defaultArr() : defaultArr || []; + return new MongooseArray(arr, self.path, this); + }); +}; + +/*! + * Inherits from SchemaType. + */ + +SchemaArray.prototype.__proto__ = SchemaType.prototype; + +/** + * Check required + * + * @param {Array} value + * @api private + */ + +SchemaArray.prototype.checkRequired = function (value) { + return !!(value && value.length); +}; + +/** + * Overrides the getters application for the population special-case + * + * @param {Object} value + * @param {Object} scope + * @api private + */ + +SchemaArray.prototype.applyGetters = function (value, scope) { + if (this.caster.options && this.caster.options.ref) { + // means the object id was populated + return value; + } + + return SchemaType.prototype.applyGetters.call(this, value, scope); +}; + +/** + * Casts contents + * + * @param {Object} value + * @param {Document} doc document that triggers the casting + * @param {Boolean} init whether this is an initialization cast + * @api private + */ + +SchemaArray.prototype.cast = function (value, doc, init) { + if (Array.isArray(value)) { + if (!(value instanceof MongooseArray)) { + value = new MongooseArray(value, this.path, doc); + } + + if (this.caster) { + try { + for (var i = 0, l = value.length; i < l; i++) { + value[i] = this.caster.cast(value[i], doc, init); + } + } catch (e) { + // rethrow + throw new CastError(e.type, value, this.path); + } + } + + return value; + } else { + return this.cast([value], doc, init); + } +}; + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [value] + * @api private + */ + +SchemaArray.prototype.castForQuery = function ($conditional, value) { + var handler + , val; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) + throw new Error("Can't use " + $conditional + " with Array."); + val = handler.call(this, value); + } else { + val = $conditional; + var proto = this.casterConstructor.prototype; + var method = proto.castForQuery || proto.cast; + + var caster = this.caster; + if (Array.isArray(val)) { + val = val.map(function (v) { + if (method) v = method.call(caster, v); + + return isMongooseObject(v) + ? v.toObject() + : v; + }); + } else if (method) { + val = method.call(caster, val); + } + } + return val && isMongooseObject(val) + ? val.toObject() + : val; +}; + +/*! + * @ignore + */ + +function castToNumber (val) { + return Types.Number.prototype.cast.call(this, val); +} + +function castArray (arr, self) { + self || (self = this); + + arr.forEach(function (v, i) { + if (Array.isArray(v)) { + castArray(v, self); + } else { + arr[i] = castToNumber.call(self, v); + } + }); +} + +SchemaArray.prototype.$conditionalHandlers = { + '$all': function handle$all (val) { + if (!Array.isArray(val)) { + val = [val]; + } + + val = val.map(function (v) { + if (v && 'Object' === v.constructor.name) { + var o = {}; + o[this.path] = v; + var query = new Query(o); + query.cast(this.casterConstructor); + return query._conditions[this.path]; + } + return v; + }, this); + + return this.castForQuery(val); + } + , '$elemMatch': function (val) { + if (val.$in) { + val.$in = this.castForQuery('$in', val.$in); + return val; + } + + var query = new Query(val); + query.cast(this.casterConstructor); + return query._conditions; + } + , '$size': castToNumber + , '$ne': SchemaArray.prototype.castForQuery + , '$in': SchemaArray.prototype.castForQuery + , '$nin': SchemaArray.prototype.castForQuery + , '$regex': SchemaArray.prototype.castForQuery + , '$options': String + , '$near': SchemaArray.prototype.castForQuery + , '$nearSphere': SchemaArray.prototype.castForQuery + , '$gt': SchemaArray.prototype.castForQuery + , '$gte': SchemaArray.prototype.castForQuery + , '$lt': SchemaArray.prototype.castForQuery + , '$lte': SchemaArray.prototype.castForQuery + , '$within': function (val) { + var self = this; + + if (val.$maxDistance) { + val.$maxDistance = castToNumber.call(this, val.$maxDistance); + } + + if (val.$box || val.$polygon) { + var type = val.$box ? '$box' : '$polygon'; + val[type].forEach(function (arr) { + if (!Array.isArray(arr)) { + var msg = 'Invalid $within $box argument. ' + + 'Expected an array, received ' + arr; + throw new TypeError(msg); + } + arr.forEach(function (v, i) { + arr[i] = castToNumber.call(this, v); + }); + }) + } else if (val.$center || val.$centerSphere) { + var type = val.$center ? '$center' : '$centerSphere'; + val[type].forEach(function (item, i) { + if (Array.isArray(item)) { + item.forEach(function (v, j) { + item[j] = castToNumber.call(this, v); + }); + } else { + val[type][i] = castToNumber.call(this, item); + } + }) + } else if (val.$geometry) { + switch (val.$geometry.type) { + case 'Polygon': + case 'LineString': + case 'Point': + val.$geometry.coordinates.forEach(castArray); + break; + default: + // ignore unknowns + break; + } + } + + return val; + } + , '$geoIntersects': function (val) { + var geo = val.$geometry; + if (!geo) return; + + switch (val.$geometry.type) { + case 'Polygon': + case 'LineString': + case 'Point': + val.$geometry.coordinates.forEach(castArray); + break; + default: + // ignore unknowns + break; + } + + return val; + } + , '$maxDistance': castToNumber +}; + +/*! + * Module exports. + */ + +module.exports = SchemaArray; diff --git a/node_modules/mongoose/lib/schema/boolean.js b/node_modules/mongoose/lib/schema/boolean.js new file mode 100644 index 0000000..cc16b7a --- /dev/null +++ b/node_modules/mongoose/lib/schema/boolean.js @@ -0,0 +1,92 @@ +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype'); + +/** + * Boolean SchemaType constructor. + * + * @param {String} path + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function SchemaBoolean (path, options) { + SchemaType.call(this, path, options); +}; + +/*! + * Inherits from SchemaType. + */ +SchemaBoolean.prototype.__proto__ = SchemaType.prototype; + +/** + * Required validator + * + * @api private + */ + +SchemaBoolean.prototype.checkRequired = function (value) { + return value === true || value === false; +}; + +/** + * Casts to boolean + * + * @param {Object} value + * @api private + */ + +SchemaBoolean.prototype.cast = function (value) { + if (null === value) return value; + if ('0' === value) return false; + if ('true' === value) return true; + if ('false' === value) return false; + return !! value; +} + +/*! + * ignore + */ + +function handleArray (val) { + var self = this; + return val.map(function (m) { + return self.cast(m); + }); +} + +SchemaBoolean.$conditionalHandlers = { + '$in': handleArray +} + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} val + * @api private + */ + +SchemaBoolean.prototype.castForQuery = function ($conditional, val) { + var handler; + if (2 === arguments.length) { + handler = SchemaBoolean.$conditionalHandlers[$conditional]; + + if (handler) { + return handler.call(this, val); + } + + return this.cast(val); + } + + return this.cast($conditional); +}; + +/*! + * Module exports. + */ + +module.exports = SchemaBoolean; diff --git a/node_modules/mongoose/lib/schema/buffer.js b/node_modules/mongoose/lib/schema/buffer.js new file mode 100644 index 0000000..e699c10 --- /dev/null +++ b/node_modules/mongoose/lib/schema/buffer.js @@ -0,0 +1,168 @@ +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype') + , CastError = SchemaType.CastError + , MongooseBuffer = require('../types').Buffer + , Binary = MongooseBuffer.Binary + , Query = require('../query') + , utils = require('../utils') + , Document + +/** + * Buffer SchemaType constructor + * + * @param {String} key + * @param {SchemaType} cast + * @inherits SchemaType + * @api private + */ + +function SchemaBuffer (key, options) { + SchemaType.call(this, key, options, 'Buffer'); +}; + +/*! + * Inherits from SchemaType. + */ + +SchemaBuffer.prototype.__proto__ = SchemaType.prototype; + +/** + * Check required + * + * @api private + */ + +SchemaBuffer.prototype.checkRequired = function (value, doc) { + if (SchemaType._isRef(this, value, doc, true)) { + return null != value; + } else { + return !!(value && value.length); + } +}; + +/** + * Casts contents + * + * @param {Object} value + * @param {Document} doc document that triggers the casting + * @param {Boolean} init + * @api private + */ + +SchemaBuffer.prototype.cast = function (value, doc, init) { + if (SchemaType._isRef(this, value, doc, init)) { + // wait! we may need to cast this to a document + + if (null == value) { + return value; + } + + // lazy load + Document || (Document = require('./../document')); + + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } + + // setting a populated path + if (Buffer.isBuffer(value)) { + return value; + } else if (!utils.isObject(value)) { + throw new CastError('buffer', value, this.path); + } + + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + return ret; + } + + // documents + if (value && value._id) { + value = value._id; + } + + if (Buffer.isBuffer(value)) { + if (!(value instanceof MongooseBuffer)) { + value = new MongooseBuffer(value, [this.path, doc]); + } + + return value; + } else if (value instanceof Binary) { + var ret = new MongooseBuffer(value.value(true), [this.path, doc]); + ret._subtype = value.sub_type; + // do not override Binary subtypes. users set this + // to whatever they want. + return ret; + } + + if (null === value) return value; + + var type = typeof value; + if ('string' == type || 'number' == type || Array.isArray(value)) { + var ret = new MongooseBuffer(value, [this.path, doc]); + return ret; + } + + throw new CastError('buffer', value, this.path); +}; + +/*! + * ignore + */ +function handleSingle (val) { + return this.castForQuery(val); +} + +function handleArray (val) { + var self = this; + return val.map( function (m) { + return self.castForQuery(m); + }); +} + +SchemaBuffer.prototype.$conditionalHandlers = { + '$ne' : handleSingle + , '$in' : handleArray + , '$nin': handleArray + , '$gt' : handleSingle + , '$lt' : handleSingle + , '$gte': handleSingle + , '$lte': handleSingle +}; + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [value] + * @api private + */ + +SchemaBuffer.prototype.castForQuery = function ($conditional, val) { + var handler; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) + throw new Error("Can't use " + $conditional + " with Buffer."); + return handler.call(this, val); + } else { + val = $conditional; + return this.cast(val).toObject(); + } +}; + +/*! + * Module exports. + */ + +module.exports = SchemaBuffer; diff --git a/node_modules/mongoose/lib/schema/date.js b/node_modules/mongoose/lib/schema/date.js new file mode 100644 index 0000000..86e4062 --- /dev/null +++ b/node_modules/mongoose/lib/schema/date.js @@ -0,0 +1,167 @@ +/*! + * Module requirements. + */ + +var SchemaType = require('../schematype'); +var CastError = SchemaType.CastError; +var utils = require('../utils'); + +/** + * Date SchemaType constructor. + * + * @param {String} key + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function SchemaDate (key, options) { + SchemaType.call(this, key, options); +}; + +/*! + * Inherits from SchemaType. + */ + +SchemaDate.prototype.__proto__ = SchemaType.prototype; + +/** + * Declares a TTL index (rounded to the nearest second) for _Date_ types only. + * + * This sets the `expiresAfterSeconds` index option available in MongoDB >= 2.1.2. + * This index type is only compatible with Date types. + * + * ####Example: + * + * // expire in 24 hours + * new Schema({ createdAt: { type: Date, expires: 60*60*24 }}); + * + * `expires` utilizes the `ms` module from [guille](https://github.com/guille/) allowing us to use a friendlier syntax: + * + * ####Example: + * + * // expire in 24 hours + * new Schema({ createdAt: { type: Date, expires: '24h' }}); + * + * // expire in 1.5 hours + * new Schema({ createdAt: { type: Date, expires: '1.5h' }}); + * + * // expire in 7 days + * var schema = new Schema({ createdAt: Date }); + * schema.path('createdAt').expires('7d'); + * + * @param {Number|String} when + * @added 3.0.0 + * @return {SchemaType} this + * @api public + */ + +SchemaDate.prototype.expires = function (when) { + if (!this._index || 'Object' !== this._index.constructor.name) { + this._index = {}; + } + + this._index.expires = when; + utils.expires(this._index); + return this; +}; + +/** + * Required validator for date + * + * @api private + */ + +SchemaDate.prototype.checkRequired = function (value) { + return value instanceof Date; +}; + +/** + * Casts to date + * + * @param {Object} value to cast + * @api private + */ + +SchemaDate.prototype.cast = function (value) { + if (value === null || value === '') + return null; + + if (value instanceof Date) + return value; + + var date; + + // support for timestamps + if (value instanceof Number || 'number' == typeof value + || String(value) == Number(value)) + date = new Date(Number(value)); + + // support for date strings + else if (value.toString) + date = new Date(value.toString()); + + if (date.toString() != 'Invalid Date') + return date; + + throw new CastError('date', value, this.path); +}; + +/*! + * Date Query casting. + * + * @api private + */ + +function handleSingle (val) { + return this.cast(val); +} + +function handleArray (val) { + var self = this; + return val.map( function (m) { + return self.cast(m); + }); +} + +SchemaDate.prototype.$conditionalHandlers = { + '$lt': handleSingle + , '$lte': handleSingle + , '$gt': handleSingle + , '$gte': handleSingle + , '$ne': handleSingle + , '$in': handleArray + , '$nin': handleArray + , '$all': handleArray +}; + + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [value] + * @api private + */ + +SchemaDate.prototype.castForQuery = function ($conditional, val) { + var handler; + + if (2 !== arguments.length) { + return this.cast($conditional); + } + + handler = this.$conditionalHandlers[$conditional]; + + if (!handler) { + throw new Error("Can't use " + $conditional + " with Date."); + } + + return handler.call(this, val); +}; + +/*! + * Module exports. + */ + +module.exports = SchemaDate; diff --git a/node_modules/mongoose/lib/schema/documentarray.js b/node_modules/mongoose/lib/schema/documentarray.js new file mode 100644 index 0000000..3b02887 --- /dev/null +++ b/node_modules/mongoose/lib/schema/documentarray.js @@ -0,0 +1,189 @@ + +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype') + , ArrayType = require('./array') + , MongooseDocumentArray = require('../types/documentarray') + , Subdocument = require('../types/embedded') + , Document = require('../document'); + +/** + * SubdocsArray SchemaType constructor + * + * @param {String} key + * @param {Schema} schema + * @param {Object} options + * @inherits SchemaArray + * @api private + */ + +function DocumentArray (key, schema, options) { + + // compile an embedded document for this schema + function EmbeddedDocument () { + Subdocument.apply(this, arguments); + } + + EmbeddedDocument.prototype.__proto__ = Subdocument.prototype; + EmbeddedDocument.prototype.$__setSchema(schema); + EmbeddedDocument.schema = schema; + + // apply methods + for (var i in schema.methods) { + EmbeddedDocument.prototype[i] = schema.methods[i]; + } + + // apply statics + for (var i in schema.statics) + EmbeddedDocument[i] = schema.statics[i]; + + EmbeddedDocument.options = options; + this.schema = schema; + + ArrayType.call(this, key, EmbeddedDocument, options); + + this.schema = schema; + var path = this.path; + var fn = this.defaultValue; + + this.default(function(){ + var arr = fn.call(this); + if (!Array.isArray(arr)) arr = [arr]; + return new MongooseDocumentArray(arr, path, this); + }); +}; + +/*! + * Inherits from ArrayType. + */ + +DocumentArray.prototype.__proto__ = ArrayType.prototype; + +/** + * Performs local validations first, then validations on each embedded doc + * + * @api private + */ + +DocumentArray.prototype.doValidate = function (array, fn, scope) { + var self = this; + + SchemaType.prototype.doValidate.call(this, array, function (err) { + if (err) return fn(err); + + var count = array && array.length + , error; + + if (!count) return fn(); + + // handle sparse arrays, do not use array.forEach which does not + // iterate over sparse elements yet reports array.length including + // them :( + + for (var i = 0, len = count; i < len; ++i) { + // sidestep sparse entries + var doc = array[i]; + if (!doc) { + --count || fn(); + continue; + } + + ;(function (i) { + doc.validate(function (err) { + if (err && !error) { + // rewrite the key + err.key = self.key + '.' + i + '.' + err.key; + return fn(error = err); + } + --count || fn(); + }); + })(i); + } + }, scope); +}; + +/** + * Casts contents + * + * @param {Object} value + * @param {Document} document that triggers the casting + * @api private + */ + +DocumentArray.prototype.cast = function (value, doc, init, prev) { + var selected + , subdoc + , i + + if (!Array.isArray(value)) { + return this.cast([value], doc, init, prev); + } + + if (!(value instanceof MongooseDocumentArray)) { + value = new MongooseDocumentArray(value, this.path, doc); + } + + i = value.length; + + while (i--) { + if (!(value[i] instanceof Subdocument) && value[i]) { + if (init) { + selected || (selected = scopePaths(this, doc.$__.selected, init)); + subdoc = new this.casterConstructor(null, value, true, selected); + value[i] = subdoc.init(value[i]); + } else { + if (prev && (subdoc = prev.id(value[i]._id))) { + // handle resetting doc with existing id but differing data + // doc.array = [{ doc: 'val' }] + subdoc.set(value[i]); + } else { + subdoc = new this.casterConstructor(value[i], value); + } + + // if set() is hooked it will have no return value + // see gh-746 + value[i] = subdoc; + } + } + } + + return value; +} + +/*! + * Scopes paths selected in a query to this array. + * Necessary for proper default application of subdocument values. + * + * @param {DocumentArray} array - the array to scope `fields` paths + * @param {Object|undefined} fields - the root fields selected in the query + * @param {Boolean|undefined} init - if we are being created part of a query result + */ + +function scopePaths (array, fields, init) { + if (!(init && fields)) return undefined; + + var path = array.path + '.' + , keys = Object.keys(fields) + , i = keys.length + , selected = {} + , hasKeys + , key + + while (i--) { + key = keys[i]; + if (0 === key.indexOf(path)) { + hasKeys || (hasKeys = true); + selected[key.substring(path.length)] = fields[key]; + } + } + + return hasKeys && selected || undefined; +} + +/*! + * Module exports. + */ + +module.exports = DocumentArray; diff --git a/node_modules/mongoose/lib/schema/index.js b/node_modules/mongoose/lib/schema/index.js new file mode 100644 index 0000000..d1347ed --- /dev/null +++ b/node_modules/mongoose/lib/schema/index.js @@ -0,0 +1,28 @@ + +/*! + * Module exports. + */ + +exports.String = require('./string'); + +exports.Number = require('./number'); + +exports.Boolean = require('./boolean'); + +exports.DocumentArray = require('./documentarray'); + +exports.Array = require('./array'); + +exports.Buffer = require('./buffer'); + +exports.Date = require('./date'); + +exports.ObjectId = require('./objectid'); + +exports.Mixed = require('./mixed'); + +// alias + +exports.Oid = exports.ObjectId; +exports.Object = exports.Mixed; +exports.Bool = exports.Boolean; diff --git a/node_modules/mongoose/lib/schema/mixed.js b/node_modules/mongoose/lib/schema/mixed.js new file mode 100644 index 0000000..6e2e4d3 --- /dev/null +++ b/node_modules/mongoose/lib/schema/mixed.js @@ -0,0 +1,83 @@ + +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype'); +var utils = require('../utils'); + +/** + * Mixed SchemaType constructor. + * + * @param {String} path + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function Mixed (path, options) { + if (options && options.default) { + var def = options.default; + if (Array.isArray(def) && 0 === def.length) { + // make sure empty array defaults are handled + options.default = Array; + } else if (!options.shared && + utils.isObject(def) && + 0 === Object.keys(def).length) { + // prevent odd "shared" objects between documents + options.default = function () { + return {} + } + } + } + + SchemaType.call(this, path, options); +}; + +/*! + * Inherits from SchemaType. + */ + +Mixed.prototype.__proto__ = SchemaType.prototype; + +/** + * Required validator + * + * @api private + */ + +Mixed.prototype.checkRequired = function (val) { + return true; +}; + +/** + * Casts `val` for Mixed. + * + * _this is a no-op_ + * + * @param {Object} value to cast + * @api private + */ + +Mixed.prototype.cast = function (val) { + return val; +}; + +/** + * Casts contents for queries. + * + * @param {String} $cond + * @param {any} [val] + * @api private + */ + +Mixed.prototype.castForQuery = function ($cond, val) { + if (arguments.length === 2) return val; + return $cond; +}; + +/*! + * Module exports. + */ + +module.exports = Mixed; diff --git a/node_modules/mongoose/lib/schema/number.js b/node_modules/mongoose/lib/schema/number.js new file mode 100644 index 0000000..5e127dd --- /dev/null +++ b/node_modules/mongoose/lib/schema/number.js @@ -0,0 +1,227 @@ +/*! + * Module requirements. + */ + +var SchemaType = require('../schematype') + , CastError = SchemaType.CastError + , utils = require('../utils') + , Document + +/** + * Number SchemaType constructor. + * + * @param {String} key + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function SchemaNumber (key, options) { + SchemaType.call(this, key, options, 'Number'); +}; + +/*! + * Inherits from SchemaType. + */ + +SchemaNumber.prototype.__proto__ = SchemaType.prototype; + +/** + * Required validator for number + * + * @api private + */ + +SchemaNumber.prototype.checkRequired = function checkRequired (value, doc) { + if (SchemaType._isRef(this, value, doc, true)) { + return null != value; + } else { + return typeof value == 'number' || value instanceof Number; + } +}; + +/** + * Sets a minimum number validator. + * + * ####Example: + * + * var s = new Schema({ n: { type: Number, min: 10 }) + * var M = db.model('M', s) + * var m = new M({ n: 9 }) + * m.save(function (err) { + * console.error(err) // validator error + * m.n = 10; + * m.save() // success + * }) + * + * @param {Number} value minimum number + * @return {SchemaType} this + * @api public + */ + +SchemaNumber.prototype.min = function (value) { + if (this.minValidator) { + this.validators = this.validators.filter(function (v) { + return 'min' != v[1]; + }); + } + + if (value != null) { + this.validators.push([this.minValidator = function (v) { + return v === null || v >= value; + }, 'min']); + } + + return this; +}; + +/** + * Sets a maximum number validator. + * + * ####Example: + * + * var s = new Schema({ n: { type: Number, max: 10 }) + * var M = db.model('M', s) + * var m = new M({ n: 11 }) + * m.save(function (err) { + * console.error(err) // validator error + * m.n = 10; + * m.save() // success + * }) + * + * @param {Number} maximum number + * @return {SchemaType} this + * @api public + */ + +SchemaNumber.prototype.max = function (value) { + if (this.maxValidator) { + this.validators = this.validators.filter(function(v){ + return 'max' != v[1]; + }); + } + + if (value != null) { + this.validators.push([this.maxValidator = function(v){ + return v === null || v <= value; + }, 'max']); + } + + return this; +}; + +/** + * Casts to number + * + * @param {Object} value value to cast + * @param {Document} doc document that triggers the casting + * @param {Boolean} init + * @api private + */ + +SchemaNumber.prototype.cast = function (value, doc, init) { + if (SchemaType._isRef(this, value, doc, init)) { + // wait! we may need to cast this to a document + + if (null == value) { + return value; + } + + // lazy load + Document || (Document = require('./../document')); + + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } + + // setting a populated path + if ('number' == typeof value) { + return value; + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('number', value, this.path); + } + + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + return ret; + } + + var val = value && value._id + ? value._id // documents + : value; + + if (!isNaN(val)){ + if (null === val) return val; + if ('' === val) return null; + if ('string' == typeof val) val = Number(val); + if (val instanceof Number) return val + if ('number' == typeof val) return val; + if (val.toString && !Array.isArray(val) && + val.toString() == Number(val)) { + return new Number(val) + } + } + + throw new CastError('number', value, this.path); +}; + +/*! + * ignore + */ + +function handleSingle (val) { + return this.cast(val) +} + +function handleArray (val) { + var self = this; + return val.map(function (m) { + return self.cast(m) + }); +} + +SchemaNumber.prototype.$conditionalHandlers = { + '$lt' : handleSingle + , '$lte': handleSingle + , '$gt' : handleSingle + , '$gte': handleSingle + , '$ne' : handleSingle + , '$in' : handleArray + , '$nin': handleArray + , '$mod': handleArray + , '$all': handleArray +}; + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [value] + * @api private + */ + +SchemaNumber.prototype.castForQuery = function ($conditional, val) { + var handler; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) + throw new Error("Can't use " + $conditional + " with Number."); + return handler.call(this, val); + } else { + val = this.cast($conditional); + return val == null ? val : val + } +}; + +/*! + * Module exports. + */ + +module.exports = SchemaNumber; diff --git a/node_modules/mongoose/lib/schema/objectid.js b/node_modules/mongoose/lib/schema/objectid.js new file mode 100644 index 0000000..99f9623 --- /dev/null +++ b/node_modules/mongoose/lib/schema/objectid.js @@ -0,0 +1,186 @@ +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype') + , CastError = SchemaType.CastError + , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native' + , oid = require('../types/objectid') + , utils = require('../utils') + , Document + +/** + * ObjectId SchemaType constructor. + * + * @param {String} key + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function ObjectId (key, options) { + SchemaType.call(this, key, options, 'ObjectID'); +}; + +/*! + * Inherits from SchemaType. + */ + +ObjectId.prototype.__proto__ = SchemaType.prototype; + +/** + * Adds an auto-generated ObjectId default if turnOn is true. + * @param {Boolean} turnOn auto generated ObjectId defaults + * @api public + * @return {SchemaType} this + */ + +ObjectId.prototype.auto = function (turnOn) { + if (turnOn) { + this.default(defaultId); + this.set(resetId) + } + + return this; +}; + +/** + * Check required + * + * @api private + */ + +ObjectId.prototype.checkRequired = function checkRequired (value, doc) { + if (SchemaType._isRef(this, value, doc, true)) { + return null != value; + } else { + return value instanceof oid; + } +}; + +/** + * Casts to ObjectId + * + * @param {Object} value + * @param {Object} doc + * @param {Boolean} init whether this is an initialization cast + * @api private + */ + +ObjectId.prototype.cast = function (value, doc, init) { + if (SchemaType._isRef(this, value, doc, init)) { + // wait! we may need to cast this to a document + + if (null == value) { + return value; + } + + // lazy load + Document || (Document = require('./../document')); + + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } + + // setting a populated path + if (value instanceof oid) { + return value; + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('ObjectId', value, this.path); + } + + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + return ret; + } + + if (value === null) return value; + + if (value instanceof oid) + return value; + + if (value._id && value._id instanceof oid) + return value._id; + + if (value.toString) { + try { + return oid.fromString(value.toString()); + } catch (err) { + throw new CastError('ObjectId', value, this.path); + } + } + + throw new CastError('ObjectId', value, this.path); +}; + +/*! + * ignore + */ + +function handleSingle (val) { + return this.cast(val); +} + +function handleArray (val) { + var self = this; + return val.map(function (m) { + return self.cast(m); + }); +} + +ObjectId.prototype.$conditionalHandlers = { + '$ne': handleSingle + , '$in': handleArray + , '$nin': handleArray + , '$gt': handleSingle + , '$lt': handleSingle + , '$gte': handleSingle + , '$lte': handleSingle + , '$all': handleArray +}; + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [val] + * @api private + */ + +ObjectId.prototype.castForQuery = function ($conditional, val) { + var handler; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) + throw new Error("Can't use " + $conditional + " with ObjectId."); + return handler.call(this, val); + } else { + return this.cast($conditional); + } +}; + +/*! + * ignore + */ + +function defaultId () { + return new oid(); +}; + +function resetId (v) { + this.$__._id = null; + return v; +} + +/*! + * Module exports. + */ + +module.exports = ObjectId; diff --git a/node_modules/mongoose/lib/schema/string.js b/node_modules/mongoose/lib/schema/string.js new file mode 100644 index 0000000..235a12f --- /dev/null +++ b/node_modules/mongoose/lib/schema/string.js @@ -0,0 +1,312 @@ + +/*! + * Module dependencies. + */ + +var SchemaType = require('../schematype') + , CastError = SchemaType.CastError + , utils = require('../utils') + , Document + +/** + * String SchemaType constructor. + * + * @param {String} key + * @param {Object} options + * @inherits SchemaType + * @api private + */ + +function SchemaString (key, options) { + this.enumValues = []; + this.regExp = null; + SchemaType.call(this, key, options, 'String'); +}; + +/*! + * Inherits from SchemaType. + */ + +SchemaString.prototype.__proto__ = SchemaType.prototype; + +/** + * Adds enumeration values and a coinciding validator. + * + * ####Example: + * + * var states = 'opening open closing closed'.split(' ') + * var s = new Schema({ state: { type: String, enum: states }) + * var M = db.model('M', s) + * var m = new M({ state: 'invalid' }) + * m.save(function (err) { + * console.error(err) // validator error + * m.state = 'open' + * m.save() // success + * }) + * + * @param {String} [args...] enumeration values + * @return {SchemaType} this + * @api public + */ + +SchemaString.prototype.enum = function () { + var len = arguments.length; + + if (!len || undefined === arguments[0] || false === arguments[0]) { + if (this.enumValidator){ + this.enumValidator = false; + this.validators = this.validators.filter(function(v){ + return v[1] != 'enum'; + }); + } + return this; + } + + for (var i = 0; i < len; i++) { + if (undefined !== arguments[i]) { + this.enumValues.push(this.cast(arguments[i])); + } + } + + if (!this.enumValidator) { + var values = this.enumValues; + this.enumValidator = function(v){ + return undefined === v || ~values.indexOf(v); + }; + this.validators.push([this.enumValidator, 'enum']); + } + + return this; +}; + +/** + * Adds a lowercase setter. + * + * ####Example: + * + * var s = new Schema({ email: { type: String, lowercase: true }}) + * var M = db.model('M', s); + * var m = new M({ email: 'SomeEmail@example.COM' }); + * console.log(m.email) // someemail@example.com + * + * @api public + * @return {SchemaType} this + */ + +SchemaString.prototype.lowercase = function () { + return this.set(function (v, self) { + if ('string' != typeof v) v = self.cast(v) + if (v) return v.toLowerCase(); + return v; + }); +}; + +/** + * Adds an uppercase setter. + * + * ####Example: + * + * var s = new Schema({ caps: { type: String, uppercase: true }}) + * var M = db.model('M', s); + * var m = new M({ caps: 'an example' }); + * console.log(m.caps) // AN EXAMPLE + * + * @api public + * @return {SchemaType} this + */ + +SchemaString.prototype.uppercase = function () { + return this.set(function (v, self) { + if ('string' != typeof v) v = self.cast(v) + if (v) return v.toUpperCase(); + return v; + }); +}; + +/** + * Adds a trim setter. + * + * The string value will be trimmed when set. + * + * ####Example: + * + * var s = new Schema({ name: { type: String, trim: true }}) + * var M = db.model('M', s) + * var string = ' some name ' + * console.log(string.length) // 11 + * var m = new M({ name: string }) + * console.log(m.name.length) // 9 + * + * @api public + * @return {SchemaType} this + */ + +SchemaString.prototype.trim = function () { + return this.set(function (v, self) { + if ('string' != typeof v) v = self.cast(v) + if (v) return v.trim(); + return v; + }); +}; + +/** + * Sets a regexp validator. + * + * Any value that does not pass `regExp`.test(val) will fail validation. + * + * ####Example: + * + * var s = new Schema({ name: { type: String, match: /^a/ }}) + * var M = db.model('M', s) + * var m = new M({ name: 'invalid' }) + * m.validate(function (err) { + * console.error(err) // validation error + * m.name = 'apples' + * m.validate(function (err) { + * assert.ok(err) // success + * }) + * }) + * + * @param {RegExp} regExp regular expression to test against + * @return {SchemaType} this + * @api public + */ + +SchemaString.prototype.match = function match (regExp) { + this.validators.push([function(v){ + return null != v && '' !== v + ? regExp.test(v) + : true + }, 'regexp']); + + return this; +}; + +/** + * Check required + * + * @param {String|null|undefined} value + * @api private + */ + +SchemaString.prototype.checkRequired = function checkRequired (value, doc) { + if (SchemaType._isRef(this, value, doc, true)) { + return null != value; + } else { + return (value instanceof String || typeof value == 'string') && value.length; + } +}; + +/** + * Casts to String + * + * @api private + */ + +SchemaString.prototype.cast = function (value, doc, init) { + if (SchemaType._isRef(this, value, doc, init)) { + // wait! we may need to cast this to a document + + if (null == value) { + return value; + } + + // lazy load + Document || (Document = require('./../document')); + + if (value instanceof Document) { + value.$__.wasPopulated = true; + return value; + } + + // setting a populated path + if ('string' == typeof value) { + return value; + } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { + throw new CastError('string', value, this.path); + } + + // Handle the case where user directly sets a populated + // path to a plain object; cast to the Model used in + // the population query. + var path = doc.$__fullPath(this.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + var pop = owner.populated(path, true); + var ret = new pop.options.model(value); + ret.$__.wasPopulated = true; + return ret; + } + + if (value === null) { + return value; + } + + if ('undefined' !== typeof value) { + // handle documents being passed + if (value._id && 'string' == typeof value._id) { + return value._id; + } + if (value.toString) { + return value.toString(); + } + } + + + throw new CastError('string', value, this.path); +}; + +/*! + * ignore + */ + +function handleSingle (val) { + return this.castForQuery(val); +} + +function handleArray (val) { + var self = this; + return val.map(function (m) { + return self.castForQuery(m); + }); +} + +SchemaString.prototype.$conditionalHandlers = { + '$ne' : handleSingle + , '$in' : handleArray + , '$nin': handleArray + , '$gt' : handleSingle + , '$lt' : handleSingle + , '$gte': handleSingle + , '$lte': handleSingle + , '$all': handleArray + , '$regex': handleSingle + , '$options': handleSingle +}; + +/** + * Casts contents for queries. + * + * @param {String} $conditional + * @param {any} [val] + * @api private + */ + +SchemaString.prototype.castForQuery = function ($conditional, val) { + var handler; + if (arguments.length === 2) { + handler = this.$conditionalHandlers[$conditional]; + if (!handler) + throw new Error("Can't use " + $conditional + " with String."); + return handler.call(this, val); + } else { + val = $conditional; + if (val instanceof RegExp) return val; + return this.cast(val); + } +}; + +/*! + * Module exports. + */ + +module.exports = SchemaString; diff --git a/node_modules/mongoose/lib/schemadefault.js b/node_modules/mongoose/lib/schemadefault.js new file mode 100644 index 0000000..aebcff5 --- /dev/null +++ b/node_modules/mongoose/lib/schemadefault.js @@ -0,0 +1,34 @@ + +/*! + * Module dependencies. + */ + +var Schema = require('./schema') + +/** + * Default model for querying the system.profiles collection. + * + * @property system.profile + * @receiver exports + * @api private + */ + +exports['system.profile'] = new Schema({ + ts: Date + , info: String // deprecated + , millis: Number + , op: String + , ns: String + , query: Schema.Types.Mixed + , updateobj: Schema.Types.Mixed + , ntoreturn: Number + , nreturned: Number + , nscanned: Number + , responseLength: Number + , client: String + , user: String + , idhack: Boolean + , scanAndOrder: Boolean + , keyUpdates: Number + , cursorid: Number +}, { noVirtualId: true, noId: true }); diff --git a/node_modules/mongoose/lib/schematype.js b/node_modules/mongoose/lib/schematype.js new file mode 100644 index 0000000..b396efa --- /dev/null +++ b/node_modules/mongoose/lib/schematype.js @@ -0,0 +1,628 @@ +/*! + * Module dependencies. + */ + +var utils = require('./utils'); +var CastError = require('./error').CastError; +var ValidatorError = require('./error').ValidatorError; + +/** + * SchemaType constructor + * + * @param {String} path + * @param {Object} [options] + * @param {String} [instance] + * @api public + */ + +function SchemaType (path, options, instance) { + this.path = path; + this.instance = instance; + this.validators = []; + this.setters = []; + this.getters = []; + this.options = options; + this._index = null; + this.selected; + + for (var i in options) if (this[i] && 'function' == typeof this[i]) { + // { unique: true, index: true } + if ('index' == i && this._index) continue; + + var opts = Array.isArray(options[i]) + ? options[i] + : [options[i]]; + + this[i].apply(this, opts); + } +}; + +/** + * Sets a default value for this SchemaType. + * + * ####Example: + * + * var schema = new Schema({ n: { type: Number, default: 10 }) + * var M = db.model('M', schema) + * var m = new M; + * console.log(m.n) // 10 + * + * Defaults can be either `functions` which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation. + * + * ####Example: + * + * // values are cast: + * var schema = new Schema({ aNumber: Number, default: "4.815162342" }) + * var M = db.model('M', schema) + * var m = new M; + * console.log(m.aNumber, typeof m.aNumber) // 4.815162342 "number" + * + * @param {Function|any} val the default value + * @return {defaultValue} + * @api public + */ + +SchemaType.prototype.default = function (val) { + if (1 === arguments.length) { + this.defaultValue = typeof val === 'function' + ? val + : this.cast(val); + return this; + } else if (arguments.length > 1) { + this.defaultValue = utils.args(arguments); + } + return this.defaultValue; +}; + +/** + * Declares the index options for this schematype. + * + * ####Example: + * + * var s = new Schema({ name: { type: String, index: true }) + * var s = new Schema({ loc: { type: [Number], index: 'hashed' }) + * var s = new Schema({ loc: { type: [Number], index: '2d', sparse: true }) + * var s = new Schema({ loc: { type: [Number], index: { type: '2dsphere', sparse: true }}) + * var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }}) + * Schema.path('my.path').index(true); + * Schema.path('my.date').index({ expires: 60 }); + * Schema.path('my.path').index({ unique: true, sparse: true }); + * + * ####NOTE: + * + * _Indexes are created in the background by default. Specify `background: false` to override._ + * + * [Direction doesn't matter for single key indexes](http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeysIndexes) + * + * @param {Object|Boolean|String} options + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.index = function (options) { + this._index = options; + utils.expires(this._index); + return this; +}; + +/** + * Declares an unique index. + * + * ####Example: + * + * var s = new Schema({ name: { type: String, unique: true }) + * Schema.path('name').index({ unique: true }); + * + * _NOTE: violating the constraint returns an `E11000` error from MongoDB when saving, not a Mongoose validation error._ + * + * @param {Boolean} bool + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.unique = function (bool) { + if (null == this._index || 'boolean' == typeof this._index) { + this._index = {}; + } else if ('string' == typeof this._index) { + this._index = { type: this._index }; + } + + this._index.unique = bool; + return this; +}; + +/** + * Declares a sparse index. + * + * ####Example: + * + * var s = new Schema({ name: { type: String, sparse: true }) + * Schema.path('name').index({ sparse: true }); + * + * @param {Boolean} bool + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.sparse = function (bool) { + if (null == this._index || 'boolean' == typeof this._index) { + this._index = {}; + } else if ('string' == typeof this._index) { + this._index = { type: this._index }; + } + + this._index.sparse = bool; + return this; +}; + +/** + * Adds a setter to this schematype. + * + * ####Example: + * + * function capitalize (val) { + * if ('string' != typeof val) val = ''; + * return val.charAt(0).toUpperCase() + val.substring(1); + * } + * + * // defining within the schema + * var s = new Schema({ name: { type: String, set: capitalize }}) + * + * // or by retreiving its SchemaType + * var s = new Schema({ name: String }) + * s.path('name').set(capitalize) + * + * Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key. + * + * Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM. + * + * You can set up email lower case normalization easily via a Mongoose setter. + * + * function toLower (v) { + * return v.toLowerCase(); + * } + * + * var UserSchema = new Schema({ + * email: { type: String, set: toLower } + * }) + * + * var User = db.model('User', UserSchema) + * + * var user = new User({email: 'AVENUE@Q.COM'}) + * console.log(user.email); // 'avenue@q.com' + * + * // or + * var user = new User + * user.email = 'Avenue@Q.com' + * console.log(user.email) // 'avenue@q.com' + * + * As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key. + * + * _NOTE: we could have also just used the built-in `lowercase: true` SchemaType option instead of defining our own function._ + * + * new Schema({ email: { type: String, lowercase: true }}) + * + * Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema. + * + * function inspector (val, schematype) { + * if (schematype.options.required) { + * return schematype.path + ' is required'; + * } else { + * return val; + * } + * } + * + * var VirusSchema = new Schema({ + * name: { type: String, required: true, set: inspector }, + * taxonomy: { type: String, set: inspector } + * }) + * + * var Virus = db.model('Virus', VirusSchema); + * var v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' }); + * + * console.log(v.name); // name is required + * console.log(v.taxonomy); // Parvovirinae + * + * @param {Function} fn + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.set = function (fn) { + if ('function' != typeof fn) + throw new TypeError('A setter must be a function.'); + this.setters.push(fn); + return this; +}; + +/** + * Adds a getter to this schematype. + * + * ####Example: + * + * function dob (val) { + * if (!val) return val; + * return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear(); + * } + * + * // defining within the schema + * var s = new Schema({ born: { type: Date, get: dob }) + * + * // or by retreiving its SchemaType + * var s = new Schema({ born: Date }) + * s.path('born').get(dob) + * + * Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see. + * + * Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way: + * + * function obfuscate (cc) { + * return '****-****-****-' + cc.slice(cc.length-4, cc.length); + * } + * + * var AccountSchema = new Schema({ + * creditCardNumber: { type: String, get: obfuscate } + * }); + * + * var Account = db.model('Account', AccountSchema); + * + * Account.findById(id, function (err, found) { + * console.log(found.creditCardNumber); // '****-****-****-1234' + * }); + * + * Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema. + * + * function inspector (val, schematype) { + * if (schematype.options.required) { + * return schematype.path + ' is required'; + * } else { + * return schematype.path + ' is not'; + * } + * } + * + * var VirusSchema = new Schema({ + * name: { type: String, required: true, get: inspector }, + * taxonomy: { type: String, get: inspector } + * }) + * + * var Virus = db.model('Virus', VirusSchema); + * + * Virus.findById(id, function (err, virus) { + * console.log(virus.name); // name is required + * console.log(virus.taxonomy); // taxonomy is not + * }) + * + * @param {Function} fn + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.get = function (fn) { + if ('function' != typeof fn) + throw new TypeError('A getter must be a function.'); + this.getters.push(fn); + return this; +}; + +/** + * Adds validator(s) for this document path. + * + * Validators always receive the value to validate as their first argument and must return `Boolean`. Returning false is interpreted as validation failure. + * + * ####Examples: + * + * function validator (val) { + * return val == 'something'; + * } + * + * new Schema({ name: { type: String, validate: validator }}); + * + * // with a custom error message + * + * var custom = [validator, 'validation failed'] + * new Schema({ name: { type: String, validate: custom }}); + * + * var many = [ + * { validator: validator, msg: 'uh oh' } + * , { validator: fn, msg: 'failed' } + * ] + * new Schema({ name: { type: String, validate: many }}); + * + * // or utilizing SchemaType methods directly: + * + * var schema = new Schema({ name: 'string' }); + * schema.path('name').validate(validator, 'validation failed'); + * + * ####Asynchronous validation: + * + * Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either `true` or `false` when validation is complete. + * + * schema.path('name').validate(function (value, respond) { + * doStuff(value, function () { + * ... + * respond(false); // validation failed + * }) +* }, 'my error type'); +* + * You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs. + * + * Validation occurs `pre('save')` or whenever you manually execute [document#validate](#document_Document-validate). + * + * If validation fails during `pre('save')` and no callback was passed to receive the error, an `error` event will be emitted on your Models associated db [connection](#connection_Connection), passing the validation error object along. + * + * var conn = mongoose.createConnection(..); + * conn.on('error', handleError); + * + * var Product = conn.model('Product', yourSchema); + * var dvd = new Product(..); + * dvd.save(); // emits error on the `conn` above + * + * If you desire handling these errors at the Model level, attach an `error` listener to your Model and the event will instead be emitted there. + * + * // registering an error listener on the Model lets us handle errors more locally + * Product.on('error', handleError); + * + * @param {RegExp|Function|Object} obj validator + * @param {String} [error] optional error message + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.validate = function (obj, error) { + if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) { + this.validators.push([obj, error]); + return this; + } + + var i = arguments.length + , arg + + while (i--) { + arg = arguments[i]; + if (!(arg && 'Object' == arg.constructor.name)) { + var msg = 'Invalid validator. Received (' + typeof arg + ') ' + + arg + + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate'; + + throw new Error(msg); + } + this.validate(arg.validator, arg.msg); + } + + return this; +}; + +/** + * Adds a required validator to this schematype. + * + * ####Example: + * + * var s = new Schema({ born: { type: Date, required: true }) + * // or + * Schema.path('name').required(true); + * + * + * @param {Boolean} required enable/disable the validator + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.required = function (required) { + var self = this; + + function __checkRequired (v) { + // in here, `this` refers to the validating document. + // no validation when this path wasn't selected in the query. + if ('isSelected' in this && + !this.isSelected(self.path) && + !this.isModified(self.path)) return true; + return self.checkRequired(v, this); + } + + if (false === required) { + this.isRequired = false; + this.validators = this.validators.filter(function (v) { + return v[0].name !== '__checkRequired'; + }); + } else { + this.isRequired = true; + this.validators.push([__checkRequired, 'required']); + } + + return this; +}; + +/** + * Gets the default value + * + * @param {Object} scope the scope which callback are executed + * @param {Boolean} init + * @api private + */ + +SchemaType.prototype.getDefault = function (scope, init) { + var ret = 'function' === typeof this.defaultValue + ? this.defaultValue.call(scope) + : this.defaultValue; + + if (null !== ret && undefined !== ret) { + return this.cast(ret, scope, init); + } else { + return ret; + } +}; + +/** + * Applies setters + * + * @param {Object} value + * @param {Object} scope + * @param {Boolean} init + * @api private + */ + +SchemaType.prototype.applySetters = function (value, scope, init, priorVal) { + if (SchemaType._isRef(this, value, scope, init)) { + return init + ? value + : this.cast(value, scope, init, priorVal); + } + + var v = value + , setters = this.setters + , len = setters.length + + if (!len) { + if (null === v || undefined === v) return v; + return this.cast(v, scope, init, priorVal) + } + + while (len--) { + v = setters[len].call(scope, v, this); + } + + if (null === v || undefined === v) return v; + + // do not cast until all setters are applied #665 + v = this.cast(v, scope, init, priorVal); + + return v; +}; + +/** + * Applies getters to a value + * + * @param {Object} value + * @param {Object} scope + * @api private + */ + +SchemaType.prototype.applyGetters = function (value, scope) { + if (SchemaType._isRef(this, value, scope, true)) return value; + + var v = value + , getters = this.getters + , len = getters.length; + + if (!len) { + return v; + } + + while (len--) { + v = getters[len].call(scope, v, this); + } + + return v; +}; + +/** + * Sets default `select()` behavior for this path. + * + * Set to `true` if this path should always be included in the results, `false` if it should be excluded by default. This setting can be overridden at the query level. + * + * ####Example: + * + * T = db.model('T', new Schema({ x: { type: String, select: true }})); + * T.find(..); // field x will always be selected .. + * // .. unless overridden; + * T.find().select('-x').exec(callback); + * + * @param {Boolean} val + * @return {SchemaType} this + * @api public + */ + +SchemaType.prototype.select = function select (val) { + this.selected = !! val; + return this; +} + +/** + * Performs a validation of `value` using the validators declared for this SchemaType. + * + * @param {any} value + * @param {Function} callback + * @param {Object} scope + * @api private + */ + +SchemaType.prototype.doValidate = function (value, fn, scope) { + var err = false + , path = this.path + , count = this.validators.length; + + if (!count) return fn(null); + + function validate (ok, msg, val) { + if (err) return; + if (ok === undefined || ok) { + --count || fn(null); + } else { + fn(err = new ValidatorError(path, msg, val)); + } + } + + this.validators.forEach(function (v) { + var validator = v[0] + , message = v[1]; + + if (validator instanceof RegExp) { + validate(validator.test(value), message, value); + } else if ('function' === typeof validator) { + if (2 === validator.length) { + validator.call(scope, value, function (ok) { + validate(ok, message, value); + }); + } else { + validate(validator.call(scope, value), message, value); + } + } + }); +}; + +/** + * Determines if value is a valid Reference. + * + * @param {SchemaType} self + * @param {Object} value + * @param {Document} doc + * @param {Boolean} init + * @return {Boolean} + * @api private + */ + +SchemaType._isRef = function (self, value, doc, init) { + // fast path + var ref = init && self.options && self.options.ref; + + if (!ref && doc && doc.$__fullPath) { + // checks for + // - this populated with adhoc model and no ref was set in schema OR + // - setting / pushing values after population + var path = doc.$__fullPath(self.path); + var owner = doc.ownerDocument ? doc.ownerDocument() : doc; + ref = owner.populated(path); + } + + if (ref) { + if (null == value) return true; + if (!Buffer.isBuffer(value) && // buffers are objects too + 'Binary' != value._bsontype // raw binary value from the db + && utils.isObject(value) // might have deselected _id in population query + ) { + return true; + } + } + + return false; +} + +/*! + * Module exports. + */ + +module.exports = exports = SchemaType; + +exports.CastError = CastError; + +exports.ValidatorError = ValidatorError; diff --git a/node_modules/mongoose/lib/statemachine.js b/node_modules/mongoose/lib/statemachine.js new file mode 100644 index 0000000..76005d8 --- /dev/null +++ b/node_modules/mongoose/lib/statemachine.js @@ -0,0 +1,179 @@ + +/*! + * Module dependencies. + */ + +var utils = require('./utils'); + +/*! + * StateMachine represents a minimal `interface` for the + * constructors it builds via StateMachine.ctor(...). + * + * @api private + */ + +var StateMachine = module.exports = exports = function StateMachine () { + this.paths = {}; + this.states = {}; +} + +/*! + * StateMachine.ctor('state1', 'state2', ...) + * A factory method for subclassing StateMachine. + * The arguments are a list of states. For each state, + * the constructor's prototype gets state transition + * methods named after each state. These transition methods + * place their path argument into the given state. + * + * @param {String} state + * @param {String} [state] + * @return {Function} subclass constructor + * @private + */ + +StateMachine.ctor = function () { + var states = utils.args(arguments); + + var ctor = function () { + StateMachine.apply(this, arguments); + this.stateNames = states; + + var i = states.length + , state; + + while (i--) { + state = states[i]; + this.states[state] = {}; + } + }; + + ctor.prototype.__proto__ = StateMachine.prototype; + + states.forEach(function (state) { + // Changes the `path`'s state to `state`. + ctor.prototype[state] = function (path) { + this._changeState(path, state); + } + }); + + return ctor; +}; + +/*! + * This function is wrapped by the state change functions: + * + * - `require(path)` + * - `modify(path)` + * - `init(path)` + * + * @api private + */ + +StateMachine.prototype._changeState = function _changeState (path, nextState) { + var prevBucket = this.states[this.paths[path]]; + if (prevBucket) delete prevBucket[path]; + + this.paths[path] = nextState; + this.states[nextState][path] = true; +} + +/*! + * ignore + */ + +StateMachine.prototype.clear = function clear (state) { + var keys = Object.keys(this.states[state]) + , i = keys.length + , path + + while (i--) { + path = keys[i]; + delete this.states[state][path]; + delete this.paths[path]; + } +} + +/*! + * Checks to see if at least one path is in the states passed in via `arguments` + * e.g., this.some('required', 'inited') + * + * @param {String} state that we want to check for. + * @private + */ + +StateMachine.prototype.some = function some () { + var self = this; + var what = arguments.length ? arguments : this.stateNames; + return Array.prototype.some.call(what, function (state) { + return Object.keys(self.states[state]).length; + }); +} + +/*! + * This function builds the functions that get assigned to `forEach` and `map`, + * since both of those methods share a lot of the same logic. + * + * @param {String} iterMethod is either 'forEach' or 'map' + * @return {Function} + * @api private + */ + +StateMachine.prototype._iter = function _iter (iterMethod) { + return function () { + var numArgs = arguments.length + , states = utils.args(arguments, 0, numArgs-1) + , callback = arguments[numArgs-1]; + + if (!states.length) states = this.stateNames; + + var self = this; + + var paths = states.reduce(function (paths, state) { + return paths.concat(Object.keys(self.states[state])); + }, []); + + return paths[iterMethod](function (path, i, paths) { + return callback(path, i, paths); + }); + }; +} + +/*! + * Iterates over the paths that belong to one of the parameter states. + * + * The function profile can look like: + * this.forEach(state1, fn); // iterates over all paths in state1 + * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2 + * this.forEach(fn); // iterates over all paths in all states + * + * @param {String} [state] + * @param {String} [state] + * @param {Function} callback + * @private + */ + +StateMachine.prototype.forEach = function forEach () { + this.forEach = this._iter('forEach'); + return this.forEach.apply(this, arguments); +} + +/*! + * Maps over the paths that belong to one of the parameter states. + * + * The function profile can look like: + * this.forEach(state1, fn); // iterates over all paths in state1 + * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2 + * this.forEach(fn); // iterates over all paths in all states + * + * @param {String} [state] + * @param {String} [state] + * @param {Function} callback + * @return {Array} + * @private + */ + +StateMachine.prototype.map = function map () { + this.map = this._iter('map'); + return this.map.apply(this, arguments); +} + diff --git a/node_modules/mongoose/lib/types/array.js b/node_modules/mongoose/lib/types/array.js new file mode 100644 index 0000000..e0d7700 --- /dev/null +++ b/node_modules/mongoose/lib/types/array.js @@ -0,0 +1,679 @@ + +/*! + * Module dependencies. + */ + +var EmbeddedDocument = require('./embedded'); +var Document = require('../document'); +var ObjectId = require('./objectid'); +var utils = require('../utils'); +var isMongooseObject = utils.isMongooseObject; + +/** + * Mongoose Array constructor. + * + * ####NOTE: + * + * _Values always have to be passed to the constructor to initialize, otherwise `MongooseArray#push` will mark the array as modified._ + * + * @param {Array} values + * @param {String} path + * @param {Document} doc parent document + * @api private + * @inherits Array + * @see http://bit.ly/f6CnZU + */ + +function MongooseArray (values, path, doc) { + var arr = []; + arr.push.apply(arr, values); + arr.__proto__ = MongooseArray.prototype; + + arr._atomics = {}; + arr.validators = []; + arr._path = path; + + if (doc) { + arr._parent = doc; + arr._schema = doc.schema.path(path); + } + + return arr; +}; + +/*! + * Inherit from Array + */ + +MongooseArray.prototype = new Array; + +/** + * Stores a queue of atomic operations to perform + * + * @property _atomics + * @api private + */ + +MongooseArray.prototype._atomics; + +/** + * Parent owner document + * + * @property _parent + * @api private + */ + +MongooseArray.prototype._parent; + +/** + * Casts a member based on this arrays schema. + * + * @param {any} value + * @return value the casted value + * @api private + */ + +MongooseArray.prototype._cast = function (value) { + var owner = this._owner; + var populated = false; + var Model; + + if (this._parent) { + // if a populated array, we must cast to the same model + // instance as specified in the original query. + if (!owner) { + owner = this._owner = this._parent.ownerDocument + ? this._parent.ownerDocument() + : this._parent; + } + + populated = owner.populated(this._path, true); + } + + if (populated && null != value) { + // cast to the populated Models schema + var Model = populated.options.model; + + // only objects are permitted so we can safely assume that + // non-objects are to be interpreted as _id + if (Buffer.isBuffer(value) || + value instanceof ObjectId || !utils.isObject(value)) { + value = { _id: value }; + } + + value = new Model(value); + return this._schema.caster.cast(value, this._parent, true) + } + + return this._schema.caster.cast(value, this._parent, false) +} + +/** + * Marks this array as modified. + * + * If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments) + * + * @param {EmbeddedDocument} embeddedDoc the embedded doc that invoked this method on the Array + * @param {String} embeddedPath the path which changed in the embeddedDoc + * @api private + */ + +MongooseArray.prototype._markModified = function (elem, embeddedPath) { + var parent = this._parent + , dirtyPath; + + if (parent) { + dirtyPath = this._path; + + if (arguments.length) { + if (null != embeddedPath) { + // an embedded doc bubbled up the change + dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath; + } else { + // directly set an index + dirtyPath = dirtyPath + '.' + elem; + } + } + parent.markModified(dirtyPath); + } + + return this; +}; + +/** + * Register an atomic operation with the parent. + * + * @param {Array} op operation + * @param {any} val + * @api private + */ + +MongooseArray.prototype._registerAtomic = function (op, val) { + if ('$set' == op) { + // $set takes precedence over all other ops. + // mark entire array modified. + this._atomics = { $set: val }; + return this; + } + + var atomics = this._atomics; + + // reset pop/shift after save + if ('$pop' == op && !('$pop' in atomics)) { + var self = this; + this._parent.once('save', function () { + self._popped = self._shifted = null; + }); + } + + // check for impossible $atomic combos (Mongo denies more than one + // $atomic op on a single path + if (this._atomics.$set || + Object.keys(atomics).length && !(op in atomics)) { + // a different op was previously registered. + // save the entire thing. + this._atomics = { $set: this }; + return this; + } + + if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') { + atomics[op] || (atomics[op] = []); + atomics[op] = atomics[op].concat(val); + } else if (op === '$pullDocs') { + var pullOp = atomics['$pull'] || (atomics['$pull'] = {}) + , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] }); + selector['$in'] = selector['$in'].concat(val); + } else { + atomics[op] = val; + } + + return this; +}; + +/** + * Depopulates stored atomic operation values as necessary for direct insertion to MongoDB. + * + * If no atomics exist, we return all array values after conversion. + * + * @return {Array} + * @method $__getAtomics + * @memberOf MongooseArray + * @api private + */ + +MongooseArray.prototype.$__getAtomics = function () { + var ret = []; + var keys = Object.keys(this._atomics); + var i = keys.length; + + if (0 === i) { + ret[0] = ['$set', this.toObject({ depopulate: 1 })]; + return ret; + } + + while (i--) { + var op = keys[i]; + var val = this._atomics[op]; + + // the atomic values which are arrays are not MongooseArrays. we + // need to convert their elements as if they were MongooseArrays + // to handle populated arrays versus DocumentArrays properly. + if (isMongooseObject(val)) { + val = val.toObject({ depopulate: 1 }); + } else if (Array.isArray(val)) { + val = this.toObject.call(val, { depopulate: 1 }); + } else if (val.valueOf) { + val = val.valueOf(); + } + + if ('$addToSet' == op) { + val = { $each: val } + } + + ret.push([op, val]); + } + + return ret; +} + +/** + * Returns the number of pending atomic operations to send to the db for this array. + * + * @api private + * @return {Number} + */ + +MongooseArray.prototype.hasAtomics = function hasAtomics () { + if (!(this._atomics && 'Object' === this._atomics.constructor.name)) { + return 0; + } + + return Object.keys(this._atomics).length; +} + +/** + * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking. + * + * @param {Object} [args...] + * @api public + */ + +MongooseArray.prototype.push = function () { + var values = [].map.call(arguments, this._cast, this) + , ret = [].push.apply(this, values); + + // $pushAll might be fibbed (could be $push). But it makes it easier to + // handle what could have been $push, $pushAll combos + this._registerAtomic('$pushAll', values); + this._markModified(); + return ret; +}; + +/** + * Pushes items to the array non-atomically. + * + * ####NOTE: + * + * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._ + * + * @param {any} [args...] + * @api public + */ + +MongooseArray.prototype.nonAtomicPush = function () { + var values = [].map.call(arguments, this._cast, this) + , ret = [].push.apply(this, values); + this._registerAtomic('$set', this); + this._markModified(); + return ret; +}; + +/** + * Pops the array atomically at most one time per document `save()`. + * + * #### NOTE: + * + * _Calling this mulitple times on an array before saving sends the same command as calling it once._ + * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._ + * + * doc.array = [1,2,3]; + * + * var popped = doc.array.$pop(); + * console.log(popped); // 3 + * console.log(doc.array); // [1,2] + * + * // no affect + * popped = doc.array.$pop(); + * console.log(doc.array); // [1,2] + * + * doc.save(function (err) { + * if (err) return handleError(err); + * + * // we saved, now $pop works again + * popped = doc.array.$pop(); + * console.log(popped); // 2 + * console.log(doc.array); // [1] + * }) + * + * @api public + * @method $pop + * @memberOf MongooseArray + * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop + */ + +MongooseArray.prototype.$pop = function () { + this._registerAtomic('$pop', 1); + this._markModified(); + + // only allow popping once + if (this._popped) return; + this._popped = true; + + return [].pop.call(this); +}; + +/** + * Wraps [`Array#pop`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/pop) with proper change tracking. + * + * ####Note: + * + * _marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it._ + * + * @see MongooseArray#$pop #types_array_MongooseArray-%24pop + * @api public + */ + +MongooseArray.prototype.pop = function () { + var ret = [].pop.call(this); + this._registerAtomic('$set', this); + this._markModified(); + return ret; +}; + +/** + * Atomically shifts the array at most one time per document `save()`. + * + * ####NOTE: + * + * _Calling this mulitple times on an array before saving sends the same command as calling it once._ + * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._ + * + * doc.array = [1,2,3]; + * + * var shifted = doc.array.$shift(); + * console.log(shifted); // 1 + * console.log(doc.array); // [2,3] + * + * // no affect + * shifted = doc.array.$shift(); + * console.log(doc.array); // [2,3] + * + * doc.save(function (err) { + * if (err) return handleError(err); + * + * // we saved, now $shift works again + * shifted = doc.array.$shift(); + * console.log(shifted ); // 2 + * console.log(doc.array); // [3] + * }) + * + * @api public + * @memberOf MongooseArray + * @method $shift + * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop + */ + +MongooseArray.prototype.$shift = function $shift () { + this._registerAtomic('$pop', -1); + this._markModified(); + + // only allow shifting once + if (this._shifted) return; + this._shifted = true; + + return [].shift.call(this); +}; + +/** + * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking. + * + * ####Example: + * + * doc.array = [2,3]; + * var res = doc.array.shift(); + * console.log(res) // 2 + * console.log(doc.array) // [3] + * + * ####Note: + * + * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._ + * + * @api public + */ + +MongooseArray.prototype.shift = function () { + var ret = [].shift.call(this); + this._registerAtomic('$set', this); + this._markModified(); + return ret; +}; + +/** + * Pulls items from the array atomically. + * + * ####Examples: + * + * doc.array.pull(ObjectId) + * doc.array.pull({ _id: 'someId' }) + * doc.array.pull(36) + * doc.array.pull('tag 1', 'tag 2') + * + * To remove a document from a subdocument array we may pass an object with a matching `_id`. + * + * doc.subdocs.push({ _id: 4815162342 }) + * doc.subdocs.pull({ _id: 4815162342 }) // removed + * + * Or we may passing the _id directly and let mongoose take care of it. + * + * doc.subdocs.push({ _id: 4815162342 }) + * doc.subdocs.pull(4815162342); // works + * + * @param {any} [args...] + * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull + * @api public + */ + +MongooseArray.prototype.pull = function () { + var values = [].map.call(arguments, this._cast, this) + , cur = this._parent.get(this._path) + , i = cur.length + , mem; + + while (i--) { + mem = cur[i]; + if (mem instanceof EmbeddedDocument) { + if (values.some(function (v) { return v.equals(mem); } )) { + [].splice.call(cur, i, 1); + } + } else if (~cur.indexOf.call(values, mem)) { + [].splice.call(cur, i, 1); + } + } + + if (values[0] instanceof EmbeddedDocument) { + this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } )); + } else { + this._registerAtomic('$pullAll', values); + } + + this._markModified(); + return this; +}; + +/** + * Alias of [pull](#types_array_MongooseArray-pull) + * + * @see MongooseArray#pull #types_array_MongooseArray-pull + * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull + * @api public + * @memberOf MongooseArray + * @method remove + */ + +MongooseArray.prototype.remove = MongooseArray.prototype.pull; + +/** + * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting. + * + * ####Note: + * + * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._ + * + * @api public + */ + +MongooseArray.prototype.splice = function splice () { + var ret, vals, i; + + if (arguments.length) { + vals = []; + for (i = 0; i < arguments.length; ++i) { + vals[i] = i < 2 + ? arguments[i] + : this._cast(arguments[i]); + } + ret = [].splice.apply(this, vals); + this._registerAtomic('$set', this); + this._markModified(); + } + + return ret; +} + +/** + * Wraps [`Array#unshift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking. + * + * ####Note: + * + * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._ + * + * @api public + */ + +MongooseArray.prototype.unshift = function () { + var values = [].map.call(arguments, this._cast, this); + [].unshift.apply(this, values); + this._registerAtomic('$set', this); + this._markModified(); + return this.length; +}; + +/** + * Wraps [`Array#sort`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort) with proper change tracking. + * + * ####NOTE: + * + * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._ + * + * @api public + */ + +MongooseArray.prototype.sort = function () { + var ret = [].sort.apply(this, arguments); + this._registerAtomic('$set', this); + this._markModified(); + return ret; +} + +/** + * Adds values to the array if not already present. + * + * ####Example: + * + * console.log(doc.array) // [2,3,4] + * var added = doc.array.addToSet(4,5); + * console.log(doc.array) // [2,3,4,5] + * console.log(added) // [5] + * + * @param {any} [args...] + * @return {Array} the values that were added + * @api public + */ + +MongooseArray.prototype.addToSet = function addToSet () { + var values = [].map.call(arguments, this._cast, this) + , added = [] + , type = values[0] instanceof EmbeddedDocument ? 'doc' : + values[0] instanceof Date ? 'date' : + ''; + + values.forEach(function (v) { + var found; + switch (type) { + case 'doc': + found = this.some(function(doc){ return doc.equals(v) }); + break; + case 'date': + var val = +v; + found = this.some(function(d){ return +d === val }); + break; + default: + found = ~this.indexOf(v); + } + + if (!found) { + [].push.call(this, v); + this._registerAtomic('$addToSet', v); + this._markModified(); + [].push.call(added, v); + } + }, this); + + return added; +}; + +/** + * Sets the casted `val` at index `i` and marks the array modified. + * + * ####Example: + * + * // given documents based on the following + * var Doc = mongoose.model('Doc', new Schema({ array: [Number] })); + * + * var doc = new Doc({ array: [2,3,4] }) + * + * console.log(doc.array) // [2,3,4] + * + * doc.array.set(1,"5"); + * console.log(doc.array); // [2,5,4] // properly cast to number + * doc.save() // the change is saved + * + * // VS not using array#set + * doc.array[1] = "5"; + * console.log(doc.array); // [2,"5",4] // no casting + * doc.save() // change is not saved + * + * @return {Array} this + * @api public + */ + +MongooseArray.prototype.set = function set (i, val) { + this[i] = this._cast(val); + this._markModified(i); + return this; +} + +/** + * Returns a native js Array. + * + * @param {Object} options + * @return {Array} + * @api public + */ + +MongooseArray.prototype.toObject = function (options) { + if (options && options.depopulate) { + return this.map(function (doc) { + return doc instanceof Document + ? doc.toObject(options) + : doc + }); + } + + return this.slice(); +} + +/** + * Helper for console.log + * + * @api public + */ + +MongooseArray.prototype.inspect = function () { + return '[' + this.map(function (doc) { + return ' ' + doc; + }) + ' ]'; +}; + +/** + * Return the index of `obj` or `-1` if not found. + * + * @param {Object} obj the item to look for + * @return {Number} + * @api public + */ + +MongooseArray.prototype.indexOf = function indexOf (obj) { + if (obj instanceof ObjectId) obj = obj.toString(); + for (var i = 0, len = this.length; i < len; ++i) { + if (obj == this[i]) + return i; + } + return -1; +}; + +/*! + * Module exports. + */ + +module.exports = exports = MongooseArray; diff --git a/node_modules/mongoose/lib/types/buffer.js b/node_modules/mongoose/lib/types/buffer.js new file mode 100644 index 0000000..b409772 --- /dev/null +++ b/node_modules/mongoose/lib/types/buffer.js @@ -0,0 +1,214 @@ + +/*! + * Access driver. + */ + +var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'; + +/*! + * Module dependencies. + */ + +var Binary = require(driver + '/binary'); + +/** + * Mongoose Buffer constructor. + * + * Values always have to be passed to the constructor to initialize. + * + * @param {Buffer} value + * @param {String} encode + * @param {Number} offset + * @api private + * @inherits Buffer + * @see http://bit.ly/f6CnZU + */ + +function MongooseBuffer (value, encode, offset) { + var length = arguments.length; + var val; + + if (0 === length || null === arguments[0] || undefined === arguments[0]) { + val = 0; + } else { + val = value; + } + + var encoding; + var path; + var doc; + + if (Array.isArray(encode)) { + // internal casting + path = encode[0]; + doc = encode[1]; + } else { + encoding = encode; + } + + var buf = new Buffer(val, encoding, offset); + buf.__proto__ = MongooseBuffer.prototype; + + // make sure these internal props don't show up in Object.keys() + Object.defineProperties(buf, { + validators: { value: [] } + , _path: { value: path } + , _parent: { value: doc } + }); + + if (doc && "string" === typeof path) { + Object.defineProperty(buf, '_schema', { + value: doc.schema.path(path) + }); + } + + buf._subtype = 0; + return buf; +}; + +/*! + * Inherit from Buffer. + */ + +MongooseBuffer.prototype = new Buffer(0); + +/** + * Parent owner document + * + * @api private + * @property _parent + */ + +MongooseBuffer.prototype._parent; + +/** + * Marks this buffer as modified. + * + * @api private + */ + +MongooseBuffer.prototype._markModified = function () { + var parent = this._parent; + + if (parent) { + parent.markModified(this._path); + } + return this; +}; + +/** +* Writes the buffer. +*/ + +MongooseBuffer.prototype.write = function () { + var written = Buffer.prototype.write.apply(this, arguments); + + if (written > 0) { + this._markModified(); + } + + return written; +}; + +/** + * Copies the buffer. + * + * ####Note: + * + * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this. + * + * @return {MongooseBuffer} + * @param {Buffer} target + */ + +MongooseBuffer.prototype.copy = function (target) { + var ret = Buffer.prototype.copy.apply(this, arguments); + + if (target instanceof MongooseBuffer) { + target._markModified(); + } + + return ret; +}; + +/*! + * Compile other Buffer methods marking this buffer as modified. + */ + +;( +// node < 0.5 +'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' + +'writeFloat writeDouble fill ' + +'utf8Write binaryWrite asciiWrite set ' + + +// node >= 0.5 +'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' + +'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' + +'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE' +).split(' ').forEach(function (method) { + if (!Buffer.prototype[method]) return; + MongooseBuffer.prototype[method] = new Function( + 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' + + 'this._markModified();' + + 'return ret;' + ) +}); + +/** + * Converts this buffer to its Binary type representation. + * + * ####SubTypes: + * + * var bson = require('bson') + * bson.BSON_BINARY_SUBTYPE_DEFAULT + * bson.BSON_BINARY_SUBTYPE_FUNCTION + * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY + * bson.BSON_BINARY_SUBTYPE_UUID + * bson.BSON_BINARY_SUBTYPE_MD5 + * bson.BSON_BINARY_SUBTYPE_USER_DEFINED + * + * doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED); + * + * @see http://bsonspec.org/#/specification + * @param {Hex} [subtype] + * @return {Binary} + * @api public + */ + +MongooseBuffer.prototype.toObject = function (options) { + var subtype = 'number' == typeof options + ? options + : (this._subtype || 0x00); + return new Binary(this, subtype); +}; + +/** + * Determines if this buffer is equals to `other` buffer + * + * @param {Buffer} other + * @return {Boolean} + */ + +MongooseBuffer.prototype.equals = function (other) { + if (!Buffer.isBuffer(other)) { + return false; + } + + if (this.length !== other.length) { + return false; + } + + for (var i = 0; i < this.length; ++i) { + if (this[i] !== other[i]) return false; + } + + return true; +} + +/*! + * Module exports. + */ + +MongooseBuffer.Binary = Binary; + +module.exports = MongooseBuffer; diff --git a/node_modules/mongoose/lib/types/documentarray.js b/node_modules/mongoose/lib/types/documentarray.js new file mode 100644 index 0000000..0cbe6ca --- /dev/null +++ b/node_modules/mongoose/lib/types/documentarray.js @@ -0,0 +1,192 @@ + +/*! + * Module dependencies. + */ + +var MongooseArray = require('./array') + , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native' + , ObjectId = require(driver + '/objectid') + , ObjectIdSchema = require('../schema/objectid') + , utils = require('../utils') + , util = require('util') + , Document = require('../document') + +/** + * DocumentArray constructor + * + * @param {Array} values + * @param {String} path the path to this array + * @param {Document} doc parent document + * @api private + * @return {MongooseDocumentArray} + * @inherits MongooseArray + * @see http://bit.ly/f6CnZU + */ + +function MongooseDocumentArray (values, path, doc) { + var arr = []; + + // Values always have to be passed to the constructor to initialize, since + // otherwise MongooseArray#push will mark the array as modified to the parent. + arr.push.apply(arr, values); + arr.__proto__ = MongooseDocumentArray.prototype; + + arr._atomics = {}; + arr.validators = []; + arr._path = path; + + if (doc) { + arr._parent = doc; + arr._schema = doc.schema.path(path); + doc.on('save', arr.notify('save')); + doc.on('isNew', arr.notify('isNew')); + } + + return arr; +}; + +/*! + * Inherits from MongooseArray + */ + +MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype; + +/** + * Overrides MongooseArray#cast + * + * @api private + */ + +MongooseDocumentArray.prototype._cast = function (value) { + if (value instanceof this._schema.casterConstructor) { + if (!(value.__parent && value.__parentArray)) { + // value may have been created using array.create() + value.__parent = this._parent; + value.__parentArray = this; + } + return value; + } + + // handle cast('string') or cast(ObjectId) etc. + // only objects are permitted so we can safely assume that + // non-objects are to be interpreted as _id + if (Buffer.isBuffer(value) || + value instanceof ObjectId || !utils.isObject(value)) { + value = { _id: value }; + } + + return new this._schema.casterConstructor(value, this); +}; + +/** + * Searches array items for the first document with a matching _id. + * + * ####Example: + * + * var embeddedDoc = m.array.id(some_id); + * + * @return {EmbeddedDocument|null} the subdocuent or null if not found. + * @param {ObjectId|String|Number|Buffer} id + * @api public + */ + +MongooseDocumentArray.prototype.id = function (id) { + var casted + , sid + , _id + + try { + casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id)); + } catch (e) { + casted = null; + } + + for (var i = 0, l = this.length; i < l; i++) { + _id = this[i].get('_id'); + + if (_id instanceof Document) { + sid || (sid = String(id)); + if (sid == _id._id) return this[i]; + } else if (!(_id instanceof ObjectId)) { + sid || (sid = String(id)); + if (sid == _id) return this[i]; + } else if (casted == _id) { + return this[i]; + } + } + + return null; +}; + +/** + * Returns a native js Array of plain js objects + * + * ####NOTE: + * + * _Each sub-document is converted to a plain object by calling its `#toObject` method._ + * + * @param {Object} [options] optional options to pass to each documents `toObject` method call during conversion + * @return {Array} + * @api public + */ + +MongooseDocumentArray.prototype.toObject = function (options) { + return this.map(function (doc) { + return doc && doc.toObject(options) || null; + }); +}; + +/** + * Helper for console.log + * + * @api public + */ + +MongooseDocumentArray.prototype.inspect = function () { + return '[' + this.map(function (doc) { + if (doc) { + return doc.inspect + ? doc.inspect() + : util.inspect(doc) + } + return 'null' + }).join('\n') + ']'; +}; + +/** + * Creates a subdocument casted to this schema. + * + * This is the same subdocument constructor used for casting. + * + * @param {Object} obj the value to cast to this arrays SubDocument schema + * @api public + */ + +MongooseDocumentArray.prototype.create = function (obj) { + return new this._schema.casterConstructor(obj); +} + +/** + * Creates a fn that notifies all child docs of `event`. + * + * @param {String} event + * @return {Function} + * @api private + */ + +MongooseDocumentArray.prototype.notify = function notify (event) { + var self = this; + return function notify (val) { + var i = self.length; + while (i--) { + if (!self[i]) continue; + self[i].emit(event, val); + } + } +} + +/*! + * Module exports. + */ + +module.exports = MongooseDocumentArray; diff --git a/node_modules/mongoose/lib/types/embedded.js b/node_modules/mongoose/lib/types/embedded.js new file mode 100644 index 0000000..6de36e6 --- /dev/null +++ b/node_modules/mongoose/lib/types/embedded.js @@ -0,0 +1,244 @@ +/*! + * Module dependencies. + */ + +var Document = require('../document') + , inspect = require('util').inspect; + +/** + * EmbeddedDocument constructor. + * + * @param {Object} obj js object returned from the db + * @param {MongooseDocumentArray} parentArr the parent array of this document + * @param {Boolean} skipId + * @inherits Document + * @api private + */ + +function EmbeddedDocument (obj, parentArr, skipId, fields) { + if (parentArr) { + this.__parentArray = parentArr; + this.__parent = parentArr._parent; + } else { + this.__parentArray = undefined; + this.__parent = undefined; + } + + Document.call(this, obj, fields, skipId); + + var self = this; + this.on('isNew', function (val) { + self.isNew = val; + }); +}; + +/*! + * Inherit from Document + */ + +EmbeddedDocument.prototype.__proto__ = Document.prototype; + +/** + * Marks the embedded doc modified. + * + * ####Example: + * + * var doc = blogpost.comments.id(hexstring); + * doc.mixed.type = 'changed'; + * doc.markModified('mixed.type'); + * + * @param {String} path the path which changed + * @api public + */ + +EmbeddedDocument.prototype.markModified = function (path) { + if (!this.__parentArray) return; + + this.$__.activePaths.modify(path); + + if (this.isNew) { + // Mark the WHOLE parent array as modified + // if this is a new document (i.e., we are initializing + // a document), + this.__parentArray._markModified(); + } else + this.__parentArray._markModified(this, path); +}; + +/** + * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3) + * + * ####NOTE: + * + * _This is a no-op. Does not actually save the doc to the db._ + * + * @param {Function} [fn] + * @return {EmbeddedDocument} this + * @api private + */ + +EmbeddedDocument.prototype.save = function(fn) { + if (fn) + fn(null); + return this; +}; + +/** + * Removes the subdocument from its parent array. + * + * @param {Function} [fn] + * @api public + */ + +EmbeddedDocument.prototype.remove = function (fn) { + if (!this.__parentArray) return this; + + var _id; + if (!this.willRemove) { + _id = this._doc._id; + if (!_id) { + throw new Error('For your own good, Mongoose does not know ' + + 'how to remove an EmbeddedDocument that has no _id'); + } + this.__parentArray.pull({ _id: _id }); + this.willRemove = true; + } + + if (fn) + fn(null); + + return this; +}; + +/** + * Override #update method of parent documents. + * @api private + */ + +EmbeddedDocument.prototype.update = function () { + throw new Error('The #update method is not available on EmbeddedDocuments'); +} + +/** + * Helper for console.log + * + * @api public + */ + +EmbeddedDocument.prototype.inspect = function () { + return inspect(this.toObject()); +}; + +/** + * Marks a path as invalid, causing validation to fail. + * + * @param {String} path the field to invalidate + * @param {String|Error} err error which states the reason `path` was invalid + * @return {Boolean} + * @api public + */ + +EmbeddedDocument.prototype.invalidate = function (path, err, val, first) { + if (!this.__parent) { + var msg = 'Unable to invalidate a subdocument that has not been added to an array.' + throw new Error(msg); + } + + var index = this.__parentArray.indexOf(this); + var parentPath = this.__parentArray._path; + var fullPath = [parentPath, index, path].join('.'); + + // sniffing arguments: + // need to check if user passed a value to keep + // our error message clean. + if (2 < arguments.length) { + this.__parent.invalidate(fullPath, err, val); + } else { + this.__parent.invalidate(fullPath, err); + } + + if (first) + this.$__.validationError = this.ownerDocument().$__.validationError; + return true; +} + +/** + * Returns the top level document of this sub-document. + * + * @return {Document} + */ + +EmbeddedDocument.prototype.ownerDocument = function () { + if (this.$__.ownerDocument) { + return this.$__.ownerDocument; + } + + var parent = this.__parent; + if (!parent) return this; + + while (parent.__parent) { + parent = parent.__parent; + } + + return this.$__.ownerDocument = parent; +} + +/** + * Returns the full path to this document. If optional `path` is passed, it is appended to the full path. + * + * @param {String} [path] + * @return {String} + * @api private + * @method $__fullPath + * @memberOf EmbeddedDocument + */ + +EmbeddedDocument.prototype.$__fullPath = function (path) { + if (!this.$__.fullPath) { + var parent = this; + if (!parent.__parent) return path; + + var paths = []; + while (parent.__parent) { + paths.unshift(parent.__parentArray._path); + parent = parent.__parent; + } + + this.$__.fullPath = paths.join('.'); + + if (!this.$__.ownerDocument) { + // optimization + this.$__.ownerDocument = parent; + } + } + + return path + ? this.$__.fullPath + '.' + path + : this.$__.fullPath; +} + +/** + * Returns this sub-documents parent document. + * + * @api public + */ + +EmbeddedDocument.prototype.parent = function () { + return this.__parent; +} + +/** + * Returns this sub-documents parent array. + * + * @api public + */ + +EmbeddedDocument.prototype.parentArray = function () { + return this.__parentArray; +} + +/*! + * Module exports. + */ + +module.exports = EmbeddedDocument; diff --git a/node_modules/mongoose/lib/types/index.js b/node_modules/mongoose/lib/types/index.js new file mode 100644 index 0000000..e6a9901 --- /dev/null +++ b/node_modules/mongoose/lib/types/index.js @@ -0,0 +1,13 @@ + +/*! + * Module exports. + */ + +exports.Array = require('./array'); +exports.Buffer = require('./buffer'); + +exports.Document = // @deprecate +exports.Embedded = require('./embedded'); + +exports.DocumentArray = require('./documentarray'); +exports.ObjectId = require('./objectid'); diff --git a/node_modules/mongoose/lib/types/objectid.js b/node_modules/mongoose/lib/types/objectid.js new file mode 100644 index 0000000..44ad43f --- /dev/null +++ b/node_modules/mongoose/lib/types/objectid.js @@ -0,0 +1,43 @@ + +/*! + * Access driver. + */ + +var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'; + +/** + * ObjectId type constructor + * + * ####Example + * + * var id = new mongoose.Types.ObjectId; + * + * @constructor ObjectId + */ + +var ObjectId = require(driver + '/objectid'); +module.exports = ObjectId; + +/** + * Creates an ObjectId from `str` + * + * @param {ObjectId|HexString} str + * @static fromString + * @receiver ObjectId + * @return {ObjectId} + * @api private + */ + +ObjectId.fromString; + +/** + * Converts `oid` to a string. + * + * @param {ObjectId} oid ObjectId instance + * @static toString + * @receiver ObjectId + * @return {String} + * @api private + */ + +ObjectId.toString; diff --git a/node_modules/mongoose/lib/utils.js b/node_modules/mongoose/lib/utils.js new file mode 100644 index 0000000..678a7a8 --- /dev/null +++ b/node_modules/mongoose/lib/utils.js @@ -0,0 +1,671 @@ +/*! + * Module dependencies. + */ + +var ReadPref = require('mongodb').ReadPreference + , ObjectId = require('./types/objectid') + , cloneRegExp = require('regexp-clone') + , sliced = require('sliced') + , mpath = require('mpath') + , ms = require('ms') + , MongooseBuffer + , MongooseArray + , Document + +/*! + * Produces a collection name from model `name`. + * + * @param {String} name a model name + * @return {String} a collection name + * @api private + */ + +exports.toCollectionName = function (name) { + if ('system.profile' === name) return name; + if ('system.indexes' === name) return name; + return pluralize(name.toLowerCase()); +}; + +/** + * Pluralization rules. + * + * These rules are applied while processing the argument to `toCollectionName`. + * + * @deprecated remove in 4.x gh-1350 + */ + +exports.pluralization = [ + [/(m)an$/gi, '$1en'], + [/(pe)rson$/gi, '$1ople'], + [/(child)$/gi, '$1ren'], + [/^(ox)$/gi, '$1en'], + [/(ax|test)is$/gi, '$1es'], + [/(octop|vir)us$/gi, '$1i'], + [/(alias|status)$/gi, '$1es'], + [/(bu)s$/gi, '$1ses'], + [/(buffal|tomat|potat)o$/gi, '$1oes'], + [/([ti])um$/gi, '$1a'], + [/sis$/gi, 'ses'], + [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'], + [/(hive)$/gi, '$1s'], + [/([^aeiouy]|qu)y$/gi, '$1ies'], + [/(x|ch|ss|sh)$/gi, '$1es'], + [/(matr|vert|ind)ix|ex$/gi, '$1ices'], + [/([m|l])ouse$/gi, '$1ice'], + [/(quiz)$/gi, '$1zes'], + [/s$/gi, 's'], + [/$/gi, 's'] +]; +var rules = exports.pluralization; + +/** + * Uncountable words. + * + * These words are applied while processing the argument to `toCollectionName`. + * @api public + */ + +exports.uncountables = [ + 'advice', + 'energy', + 'excretion', + 'digestion', + 'cooperation', + 'health', + 'justice', + 'labour', + 'machinery', + 'equipment', + 'information', + 'pollution', + 'sewage', + 'paper', + 'money', + 'species', + 'series', + 'rain', + 'rice', + 'fish', + 'sheep', + 'moose', + 'deer', + 'news', + 'expertise', + 'status', + 'media' +]; +var uncountables = exports.uncountables; + +/*! + * Pluralize function. + * + * @author TJ Holowaychuk (extracted from _ext.js_) + * @param {String} string to pluralize + * @api private + */ + +function pluralize (str) { + var rule, found; + if (!~uncountables.indexOf(str.toLowerCase())){ + found = rules.filter(function(rule){ + return str.match(rule[0]); + }); + if (found[0]) return str.replace(found[0][0], found[0][1]); + } + return str; +}; + +/*! + * Determines if `a` and `b` are deep equal. + * + * Modified from node/lib/assert.js + * + * @param {any} a a value to compare to `b` + * @param {any} b a value to compare to `a` + * @return {Boolean} + * @api private + */ + +exports.deepEqual = function deepEqual (a, b) { + if (a === b) return true; + + if (a instanceof Date && b instanceof Date) + return a.getTime() === b.getTime(); + + if (a instanceof ObjectId && b instanceof ObjectId) { + return a.toString() === b.toString(); + } + + if (a instanceof RegExp && b instanceof RegExp) { + return a.source == b.source && + a.ignoreCase == b.ignoreCase && + a.multiline == b.multiline && + a.global == b.global; + } + + if (typeof a !== 'object' && typeof b !== 'object') + return a == b; + + if (a === null || b === null || a === undefined || b === undefined) + return false + + if (a.prototype !== b.prototype) return false; + + // Handle MongooseNumbers + if (a instanceof Number && b instanceof Number) { + return a.valueOf() === b.valueOf(); + } + + if (Buffer.isBuffer(a)) { + if (!Buffer.isBuffer(b)) return false; + if (a.length !== b.length) return false; + for (var i = 0, len = a.length; i < len; ++i) { + if (a[i] !== b[i]) return false; + } + return true; + } + + if (isMongooseObject(a)) a = a.toObject(); + if (isMongooseObject(b)) b = b.toObject(); + + try { + var ka = Object.keys(a), + kb = Object.keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key])) return false; + } + + return true; +}; + +/*! + * Object clone with Mongoose natives support. + * + * If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible. + * + * Functions are never cloned. + * + * @param {Object} obj the object to clone + * @param {Object} options + * @return {Object} the cloned object + * @api private + */ + +exports.clone = function clone (obj, options) { + if (obj === undefined || obj === null) + return obj; + + if (Array.isArray(obj)) + return cloneArray(obj, options); + + if (isMongooseObject(obj)) { + if (options && options.json && 'function' === typeof obj.toJSON) { + return obj.toJSON(options); + } else { + return obj.toObject(options); + } + } + + if (obj.constructor) { + switch (obj.constructor.name) { + case 'Object': + return cloneObject(obj, options); + case 'Date': + return new obj.constructor(+obj); + case 'RegExp': + return cloneRegExp(obj); + default: + // ignore + break; + } + } + + if (obj instanceof ObjectId) + return new ObjectId(obj.id); + + if (!obj.constructor && exports.isObject(obj)) { + // object created with Object.create(null) + return cloneObject(obj, options); + } + + if (obj.valueOf) + return obj.valueOf(); +}; +var clone = exports.clone; + +/*! + * ignore + */ + +function cloneObject (obj, options) { + var retainKeyOrder = options && options.retainKeyOrder + , minimize = options && options.minimize + , ret = {} + , hasKeys + , keys + , val + , k + , i + + if (retainKeyOrder) { + for (k in obj) { + val = clone(obj[k], options); + + if (!minimize || ('undefined' !== typeof val)) { + hasKeys || (hasKeys = true); + ret[k] = val; + } + } + } else { + // faster + + keys = Object.keys(obj); + i = keys.length; + + while (i--) { + k = keys[i]; + val = clone(obj[k], options); + + if (!minimize || ('undefined' !== typeof val)) { + if (!hasKeys) hasKeys = true; + ret[k] = val; + } + } + } + + return minimize + ? hasKeys && ret + : ret; +}; + +function cloneArray (arr, options) { + var ret = []; + for (var i = 0, l = arr.length; i < l; i++) + ret.push(clone(arr[i], options)); + return ret; +}; + +/*! + * Shallow copies defaults into options. + * + * @param {Object} defaults + * @param {Object} options + * @return {Object} the merged object + * @api private + */ + +exports.options = function (defaults, options) { + var keys = Object.keys(defaults) + , i = keys.length + , k ; + + options = options || {}; + + while (i--) { + k = keys[i]; + if (!(k in options)) { + options[k] = defaults[k]; + } + } + + return options; +}; + +/*! + * Generates a random string + * + * @api private + */ + +exports.random = function () { + return Math.random().toString().substr(3); +}; + +/*! + * Merges `from` into `to` without overwriting existing properties. + * + * @param {Object} to + * @param {Object} from + * @api private + */ + +exports.merge = function merge (to, from) { + var keys = Object.keys(from) + , i = keys.length + , key + + while (i--) { + key = keys[i]; + if ('undefined' === typeof to[key]) { + to[key] = from[key]; + } else { + if (exports.isObject(from[key])) { + merge(to[key], from[key]); + } else { + to[key] = from[key]; + } + } + } +}; + +/*! + * toString helper + */ + +var toString = Object.prototype.toString; + +/*! + * Determines if `arg` is an object. + * + * @param {Object|Array|String|Function|RegExp|any} arg + * @api private + * @return {Boolean} + */ + +exports.isObject = function (arg) { + return '[object Object]' == toString.call(arg); +} + +/*! + * A faster Array.prototype.slice.call(arguments) alternative + * @api private + */ + +exports.args = sliced; + +/*! + * process.nextTick helper. + * + * Wraps `callback` in a try/catch + nextTick. + * + * node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback. + * + * @param {Function} callback + * @api private + */ + +exports.tick = function tick (callback) { + if ('function' !== typeof callback) return; + return function () { + try { + callback.apply(this, arguments); + } catch (err) { + // only nextTick on err to get out of + // the event loop and avoid state corruption. + process.nextTick(function () { + throw err; + }); + } + } +} + +/*! + * Returns if `v` is a mongoose object that has a `toObject()` method we can use. + * + * This is for compatibility with libs like Date.js which do foolish things to Natives. + * + * @param {any} v + * @api private + */ + +exports.isMongooseObject = function (v) { + Document || (Document = require('./document')); + MongooseArray || (MongooseArray = require('./types').Array); + MongooseBuffer || (MongooseBuffer = require('./types').Buffer); + + return v instanceof Document || + v instanceof MongooseArray || + v instanceof MongooseBuffer +} +var isMongooseObject = exports.isMongooseObject; + +/*! + * Converts `expires` options of index objects to `expiresAfterSeconds` options for MongoDB. + * + * @param {Object} object + * @api private + */ + +exports.expires = function expires (object) { + if (!(object && 'Object' == object.constructor.name)) return; + if (!('expires' in object)) return; + + var when; + if ('string' != typeof object.expires) { + when = object.expires; + } else { + when = Math.round(ms(object.expires) / 1000); + } + object.expireAfterSeconds = when; + delete object.expires; +} + +/*! + * Converts arguments to ReadPrefs the driver + * can understand. + * + * @TODO move this into the driver layer + * @param {String|Array} pref + * @param {Array} [tags] + */ + +exports.readPref = function readPref (pref, tags) { + if (Array.isArray(pref)) { + tags = pref[1]; + pref = pref[0]; + } + + switch (pref) { + case 'p': + pref = 'primary'; + break; + case 'pp': + pref = 'primaryPreferred'; + break; + case 's': + pref = 'secondary'; + break; + case 'sp': + pref = 'secondaryPreferred'; + break; + case 'n': + pref = 'nearest'; + break; + } + + return new ReadPref(pref, tags); +} + +/*! + * Populate options constructor + */ + +function PopulateOptions (path, select, match, options, model) { + this.path = path; + this.match = match; + this.select = select; + this.options = options; + this.model = model; + this._docs = {}; +} + +// make it compatible with utils.clone +PopulateOptions.prototype.constructor = Object; + +// expose +exports.PopulateOptions = PopulateOptions; + +/*! + * populate helper + */ + +exports.populate = function populate (path, select, model, match, options) { + // The order of select/conditions args is opposite Model.find but + // necessary to keep backward compatibility (select could be + // an array, string, or object literal). + + // might have passed an object specifying all arguments + if (1 === arguments.length) { + if (path instanceof PopulateOptions) { + return [path]; + } + + if (Array.isArray(path)) { + return path.map(function(o){ + return exports.populate(o)[0]; + }); + } + + if (exports.isObject(path)) { + match = path.match; + options = path.options; + select = path.select; + model = path.model; + path = path.path; + } + } else if ('string' !== typeof model) { + options = match; + match = model; + model = undefined; + } + + if ('string' != typeof path) { + throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`'); + } + + var ret = []; + var paths = path.split(' '); + for (var i = 0; i < paths.length; ++i) { + ret.push(new PopulateOptions(paths[i], select, match, options, model)); + } + + return ret; +} + +/*! + * Return the value of `obj` at the given `path`. + * + * @param {String} path + * @param {Object} obj + */ + +exports.getValue = function (path, obj, map) { + return mpath.get(path, obj, '_doc', map); +} + +/*! + * Sets the value of `obj` at the given `path`. + * + * @param {String} path + * @param {Anything} val + * @param {Object} obj + */ + +exports.setValue = function (path, val, obj, map) { + mpath.set(path, val, obj, '_doc', map); +} + +/*! + * Returns an array of values from object `o`. + * + * @param {Object} o + * @return {Array} + * @private + */ + +exports.object = {}; +exports.object.vals = function vals (o) { + var keys = Object.keys(o) + , i = keys.length + , ret = []; + + while (i--) { + ret.push(o[keys[i]]); + } + + return ret; +} + +/*! + * @see exports.options + */ + +exports.object.shallowCopy = exports.options; + +/*! + * Safer helper for hasOwnProperty checks + * + * @param {Object} obj + * @param {String} prop + */ + +exports.object.hasOwnProperty = function (obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +/*! + * Determine if `val` is null or undefined + * + * @return {Boolean} + */ + +exports.isNullOrUndefined = function (val) { + return null == val +} + +/*! + * ignore + */ + +exports.array = {}; + +/*! + * Flattens an array. + * + * [ 1, [ 2, 3, [4] ]] -> [1,2,3,4] + * + * @param {Array} arr + * @param {Function} [filter] If passed, will be invoked with each item in the array. If `filter` returns a falsey value, the item will not be included in the results. + * @return {Array} + * @private + */ + +exports.array.flatten = function flatten (arr, filter, ret) { + ret || (ret = []); + + arr.forEach(function (item) { + if (Array.isArray(item)) { + flatten(item, filter, ret); + } else { + if (!filter || filter(item)) { + ret.push(item); + } + } + }); + + return ret; +} + diff --git a/node_modules/mongoose/lib/virtualtype.js b/node_modules/mongoose/lib/virtualtype.js new file mode 100644 index 0000000..819ac10 --- /dev/null +++ b/node_modules/mongoose/lib/virtualtype.js @@ -0,0 +1,103 @@ + +/** + * VirtualType constructor + * + * This is what mongoose uses to define virtual attributes via `Schema.prototype.virtual`. + * + * ####Example: + * + * var fullname = schema.virtual('fullname'); + * fullname instanceof mongoose.VirtualType // true + * + * @parma {Object} options + * @api public + */ + +function VirtualType (options, name) { + this.path = name; + this.getters = []; + this.setters = []; + this.options = options || {}; +} + +/** + * Defines a getter. + * + * ####Example: + * + * var virtual = schema.virtual('fullname'); + * virtual.get(function () { + * return this.name.first + ' ' + this.name.last; + * }); + * + * @param {Function} fn + * @return {VirtualType} this + * @api public + */ + +VirtualType.prototype.get = function (fn) { + this.getters.push(fn); + return this; +}; + +/** + * Defines a setter. + * + * ####Example: + * + * var virtual = schema.virtual('fullname'); + * virtual.set(function (v) { + * var parts = v.split(' '); + * this.name.first = parts[0]; + * this.name.last = parts[1]; + * }); + * + * @param {Function} fn + * @return {VirtualType} this + * @api public + */ + +VirtualType.prototype.set = function (fn) { + this.setters.push(fn); + return this; +}; + +/** + * Applies getters to `value` using optional `scope`. + * + * @param {Object} value + * @param {Object} scope + * @return {any} the value after applying all getters + * @api public + */ + +VirtualType.prototype.applyGetters = function (value, scope) { + var v = value; + for (var l = this.getters.length - 1; l >= 0; l--) { + v = this.getters[l].call(scope, v, this); + } + return v; +}; + +/** + * Applies setters to `value` using optional `scope`. + * + * @param {Object} value + * @param {Object} scope + * @return {any} the value after applying all setters + * @api public + */ + +VirtualType.prototype.applySetters = function (value, scope) { + var v = value; + for (var l = this.setters.length - 1; l >= 0; l--) { + v = this.setters[l].call(scope, v, this); + } + return v; +}; + +/*! + * exports + */ + +module.exports = VirtualType; diff --git a/node_modules/mongoose/node_modules/hooks/.npmignore b/node_modules/mongoose/node_modules/hooks/.npmignore new file mode 100644 index 0000000..96e29a8 --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/.npmignore @@ -0,0 +1,2 @@ +**.swp +node_modules diff --git a/node_modules/mongoose/node_modules/hooks/Makefile b/node_modules/mongoose/node_modules/hooks/Makefile new file mode 100644 index 0000000..1db5d65 --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/Makefile @@ -0,0 +1,9 @@ +test: + @NODE_ENV=test ./node_modules/expresso/bin/expresso \ + $(TESTFLAGS) \ + ./test.js + +test-cov: + @TESTFLAGS=--cov $(MAKE) test + +.PHONY: test test-cov diff --git a/node_modules/mongoose/node_modules/hooks/README.md b/node_modules/mongoose/node_modules/hooks/README.md new file mode 100644 index 0000000..af90a48 --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/README.md @@ -0,0 +1,306 @@ +hooks +============ + +Add pre and post middleware hooks to your JavaScript methods. + +## Installation + npm install hooks + +## Motivation +Suppose you have a JavaScript object with a `save` method. + +It would be nice to be able to declare code that runs before `save` and after `save`. +For example, you might want to run validation code before every `save`, +and you might want to dispatch a job to a background job queue after `save`. + +One might have an urge to hard code this all into `save`, but that turns out to +couple all these pieces of functionality (validation, save, and job creation) more +tightly than is necessary. For example, what if someone does not want to do background +job creation after the logical save? + +It is nicer to tack on functionality using what we call `pre` and `post` hooks. These +are functions that you define and that you direct to execute before or after particular +methods. + +## Example +We can use `hooks` to add validation and background jobs in the following way: + + var hooks = require('hooks') + , Document = require('./path/to/some/document/constructor'); + + // Add hooks' methods: `hook`, `pre`, and `post` + for (var k in hooks) { + Document[k] = hooks[k]; + } + + // Define a new method that is able to invoke pre and post middleware + Document.hook('save', Document.prototype.save); + + // Define a middleware function to be invoked before 'save' + Document.pre('save', function validate (next) { + // The `this` context inside of `pre` and `post` functions + // is the Document instance + if (this.isValid()) next(); // next() passes control to the next middleware + // or to the target method itself + else next(new Error("Invalid")); // next(error) invokes an error callback + }); + + // Define a middleware function to be invoked after 'save' + Document.post('save', function createJob () { + this.sendToBackgroundQueue(); + }); + +If you already have defined `Document.prototype` methods for which you want pres and posts, +then you do not need to explicitly invoke `Document.hook(...)`. Invoking `Document.pre(methodName, fn)` +or `Document.post(methodName, fn)` will automatically and lazily change `Document.prototype[methodName]` +so that it plays well with `hooks`. An equivalent way to implement the previous example is: + +```javascript +var hooks = require('hooks') + , Document = require('./path/to/some/document/constructor'); + +// Add hooks' methods: `hook`, `pre`, and `post` +for (var k in hooks) { + Document[k] = hooks[k]; +} + +Document.prototype.save = function () { + // ... +}; + +// Define a middleware function to be invoked before 'save' +Document.pre('save', function validate (next) { + // The `this` context inside of `pre` and `post` functions + // is the Document instance + if (this.isValid()) next(); // next() passes control to the next middleware + // or to the target method itself + else next(new Error("Invalid")); // next(error) invokes an error callback +}); + +// Define a middleware function to be invoked after 'save' +Document.post('save', function createJob () { + this.sendToBackgroundQueue(); +}); +``` + +## Pres and Posts as Middleware +We structure pres and posts as middleware to give you maximum flexibility: + +1. You can define **multiple** pres (or posts) for a single method. +2. These pres (or posts) are then executed as a chain of methods. +3. Any functions in this middleware chain can choose to halt the chain's execution by `next`ing an Error from that middleware function. If this occurs, then none of the other middleware in the chain will execute, and the main method (e.g., `save`) will not execute. This is nice, for example, when we don't want a document to save if it is invalid. + +## Defining multiple pres (or posts) +`pre` is chainable, so you can define multiple pres via: + Document.pre('save', function (next, halt) { + console.log("hello"); + }).pre('save', function (next, halt) { + console.log("world"); + }); + +As soon as one pre finishes executing, the next one will be invoked, and so on. + +## Error Handling +You can define a default error handler by passing a 2nd function as the 3rd argument to `hook`: + Document.hook('set', function (path, val) { + this[path] = val; + }, function (err) { + // Handler the error here + console.error(err); + }); + +Then, we can pass errors to this handler from a pre or post middleware function: + Document.pre('set', function (next, path, val) { + next(new Error()); + }); + +If you do not set up a default handler, then `hooks` makes the default handler that just throws the `Error`. + +The default error handler can be over-rided on a per method invocation basis. + +If the main method that you are surrounding with pre and post middleware expects its last argument to be a function +with callback signature `function (error, ...)`, then that callback becomes the error handler, over-riding the default +error handler you may have set up. + +```javascript +Document.hook('save', function (callback) { + // Save logic goes here + ... +}); + +var doc = new Document(); +doc.save( function (err, saved) { + // We can pass err via `next` in any of our pre or post middleware functions + if (err) console.error(err); + + // Rest of callback logic follows ... +}); +``` + +## Mutating Arguments via Middleware +`pre` and `post` middleware can also accept the intended arguments for the method +they augment. This is useful if you want to mutate the arguments before passing +them along to the next middleware and eventually pass a mutated arguments list to +the main method itself. + +As a simple example, let's define a method `set` that just sets a key, value pair. +If we want to namespace the key, we can do so by adding a `pre` middleware hook +that runs before `set`, alters the arguments by namespacing the `key` argument, and passes them onto `set`: + + Document.hook('set', function (key, val) { + this[key] = val; + }); + Document.pre('set', function (next, key, val) { + next('namespace-' + key, val); + }); + var doc = new Document(); + doc.set('hello', 'world'); + console.log(doc.hello); // undefined + console.log(doc['namespace-hello']); // 'world' + +As you can see above, we pass arguments via `next`. + +If you are not mutating the arguments, then you can pass zero arguments +to `next`, and the next middleware function will still have access +to the arguments. + + Document.hook('set', function (key, val) { + this[key] = val; + }); + Document.pre('set', function (next, key, val) { + // I have access to key and val here + next(); // We don't need to pass anything to next + }); + Document.pre('set', function (next, key, val) { + // And I still have access to the original key and val here + next(); + }); + +Finally, you can add arguments that downstream middleware can also see: + + // Note that in the definition of `set`, there is no 3rd argument, options + Document.hook('set', function (key, val) { + // But... + var options = arguments[2]; // ...I have access to an options argument + // because of pre function pre2 (defined below) + console.log(options); // '{debug: true}' + this[key] = val; + }); + Document.pre('set', function pre1 (next, key, val) { + // I only have access to key and val arguments + console.log(arguments.length); // 3 + next(key, val, {debug: true}); + }); + Document.pre('set', function pre2 (next, key, val, options) { + console.log(arguments.length); // 4 + console.log(options); // '{ debug: true}' + next(); + }); + Document.pre('set', function pre3 (next, key, val, options) { + // I still have access to key, val, AND the options argument introduced via the preceding middleware + console.log(arguments.length); // 4 + console.log(options); // '{ debug: true}' + next(); + }); + + var doc = new Document() + doc.set('hey', 'there'); + +## Parallel `pre` middleware + +All middleware up to this point has been "serial" middleware -- i.e., middleware whose logic +is executed as a serial chain. + +Some scenarios call for parallel middleware -- i.e., middleware that can wait for several +asynchronous services at once to respond. + +For instance, you may only want to save a Document only after you have checked +that the Document is valid according to two different remote services. + +We accomplish asynchronous middleware by adding a second kind of flow control callback +(the only flow control callback so far has been `next`), called `done`. + +- `next` passes control to the next middleware in the chain +- `done` keeps track of how many parallel middleware have invoked `done` and passes + control to the target method when ALL parallel middleware have invoked `done`. If + you pass an `Error` to `done`, then the error is handled, and the main method that is + wrapped by pres and posts will not get invoked. + +We declare pre middleware that is parallel by passing a 3rd boolean argument to our `pre` +definition method. + +We illustrate via the parallel validation example mentioned above: + + Document.hook('save', function targetFn (callback) { + // Save logic goes here + // ... + // This only gets run once the two `done`s are both invoked via preOne and preTwo. + }); + + // true marks this as parallel middleware + Document.pre('save', true, function preOne (next, doneOne, callback) { + remoteServiceOne.validate(this.serialize(), function (err, isValid) { + // The code in here will probably be run after the `next` below this block + // and could possibly be run after the console.log("Hola") in `preTwo + if (err) return doneOne(err); + if (isValid) doneOne(); + }); + next(); // Pass control to the next middleware + }); + + // We will suppose that we need 2 different remote services to validate our document + Document.pre('save', true, function preTwo (next, doneTwo, callback) { + remoteServiceTwo.validate(this.serialize(), function (err, isValid) { + if (err) return doneTwo(err); + if (isValid) doneTwo(); + }); + next(); + }); + + // While preOne and preTwo are parallel, preThree is a serial pre middleware + Document.pre('save', function preThree (next, callback) { + next(); + }); + + var doc = new Document(); + doc.save( function (err, doc) { + // Do stuff with the saved doc here... + }); + +In the above example, flow control may happen in the following way: + +(1) doc.save -> (2) preOne --(next)--> (3) preTwo --(next)--> (4) preThree --(next)--> (wait for dones to invoke) -> (5) doneTwo -> (6) doneOne -> (7) targetFn + +So what's happening is that: + +1. You call `doc.save(...)` +2. First, your preOne middleware gets executed. It makes a remote call to the validation service and `next()`s to the preTwo middleware. +3. Now, your preTwo middleware gets executed. It makes a remote call to another validation service and `next()`s to the preThree middleware. +4. Your preThree middleware gets executed. It immediately `next()`s. But nothing else gets executing until both `doneOne` and `doneTwo` are invoked inside the callbacks handling the response from the two valiation services. +5. We will suppose that validation remoteServiceTwo returns a response to us first. In this case, we call `doneTwo` inside the callback to remoteServiceTwo. +6. Some fractions of a second later, remoteServiceOne returns a response to us. In this case, we call `doneOne` inside the callback to remoteServiceOne. +7. `hooks` implementation keeps track of how many parallel middleware has been defined per target function. It detects that both asynchronous pre middlewares (`preOne` and `preTwo`) have finally called their `done` functions (`doneOne` and `doneTwo`), so the implementation finally invokes our `targetFn` (i.e., our core `save` business logic). + +## Removing Pres + +You can remove a particular pre associated with a hook: + + Document.pre('set', someFn); + Document.removePre('set', someFn); + +And you can also remove all pres associated with a hook: + Document.removePre('set'); // Removes all declared `pre`s on the hook 'set' + +## Tests +To run the tests: + make test + +### Contributors +- [Brian Noguchi](https://github.com/bnoguchi) + +### License +MIT License + +--- +### Author +Brian Noguchi diff --git a/node_modules/mongoose/node_modules/hooks/hooks.alt.js b/node_modules/mongoose/node_modules/hooks/hooks.alt.js new file mode 100644 index 0000000..6ced357 --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/hooks.alt.js @@ -0,0 +1,134 @@ +/** + * Hooks are useful if we want to add a method that automatically has `pre` and `post` hooks. + * For example, it would be convenient to have `pre` and `post` hooks for `save`. + * _.extend(Model, mixins.hooks); + * Model.hook('save', function () { + * console.log('saving'); + * }); + * Model.pre('save', function (next, done) { + * console.log('about to save'); + * next(); + * }); + * Model.post('save', function (next, done) { + * console.log('saved'); + * next(); + * }); + * + * var m = new Model(); + * m.save(); + * // about to save + * // saving + * // saved + */ + +// TODO Add in pre and post skipping options +module.exports = { + /** + * Declares a new hook to which you can add pres and posts + * @param {String} name of the function + * @param {Function} the method + * @param {Function} the error handler callback + */ + hook: function (name, fn, err) { + if (arguments.length === 1 && typeof name === 'object') { + for (var k in name) { // `name` is a hash of hookName->hookFn + this.hook(k, name[k]); + } + return; + } + + if (!err) err = fn; + + var proto = this.prototype || this + , pres = proto._pres = proto._pres || {} + , posts = proto._posts = proto._posts || {}; + pres[name] = pres[name] || []; + posts[name] = posts[name] || []; + + function noop () {} + + proto[name] = function () { + var self = this + , pres = this._pres[name] + , posts = this._posts[name] + , numAsyncPres = 0 + , hookArgs = [].slice.call(arguments) + , preChain = pres.map( function (pre, i) { + var wrapper = function () { + if (arguments[0] instanceof Error) + return err(arguments[0]); + if (numAsyncPres) { + // arguments[1] === asyncComplete + if (arguments.length) + hookArgs = [].slice.call(arguments, 2); + pre.apply(self, + [ preChain[i+1] || allPresInvoked, + asyncComplete + ].concat(hookArgs) + ); + } else { + if (arguments.length) + hookArgs = [].slice.call(arguments); + pre.apply(self, + [ preChain[i+1] || allPresDone ].concat(hookArgs)); + } + }; // end wrapper = function () {... + if (wrapper.isAsync = pre.isAsync) + numAsyncPres++; + return wrapper; + }); // end posts.map(...) + function allPresInvoked () { + if (arguments[0] instanceof Error) + err(arguments[0]); + } + + function allPresDone () { + if (arguments[0] instanceof Error) + return err(arguments[0]); + if (arguments.length) + hookArgs = [].slice.call(arguments); + fn.apply(self, hookArgs); + var postChain = posts.map( function (post, i) { + var wrapper = function () { + if (arguments[0] instanceof Error) + return err(arguments[0]); + if (arguments.length) + hookArgs = [].slice.call(arguments); + post.apply(self, + [ postChain[i+1] || noop].concat(hookArgs)); + }; // end wrapper = function () {... + return wrapper; + }); // end posts.map(...) + if (postChain.length) postChain[0](); + } + + if (numAsyncPres) { + complete = numAsyncPres; + function asyncComplete () { + if (arguments[0] instanceof Error) + return err(arguments[0]); + --complete || allPresDone.call(this); + } + } + (preChain[0] || allPresDone)(); + }; + + return this; + }, + + pre: function (name, fn, isAsync) { + var proto = this.prototype + , pres = proto._pres = proto._pres || {}; + if (fn.isAsync = isAsync) { + this.prototype[name].numAsyncPres++; + } + (pres[name] = pres[name] || []).push(fn); + return this; + }, + post: function (name, fn, isAsync) { + var proto = this.prototype + , posts = proto._posts = proto._posts || {}; + (posts[name] = posts[name] || []).push(fn); + return this; + } +}; diff --git a/node_modules/mongoose/node_modules/hooks/hooks.js b/node_modules/mongoose/node_modules/hooks/hooks.js new file mode 100644 index 0000000..9a887c7 --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/hooks.js @@ -0,0 +1,161 @@ +// TODO Add in pre and post skipping options +module.exports = { + /** + * Declares a new hook to which you can add pres and posts + * @param {String} name of the function + * @param {Function} the method + * @param {Function} the error handler callback + */ + hook: function (name, fn, errorCb) { + if (arguments.length === 1 && typeof name === 'object') { + for (var k in name) { // `name` is a hash of hookName->hookFn + this.hook(k, name[k]); + } + return; + } + + var proto = this.prototype || this + , pres = proto._pres = proto._pres || {} + , posts = proto._posts = proto._posts || {}; + pres[name] = pres[name] || []; + posts[name] = posts[name] || []; + + proto[name] = function () { + var self = this + , hookArgs // arguments eventually passed to the hook - are mutable + , lastArg = arguments[arguments.length-1] + , pres = this._pres[name] + , posts = this._posts[name] + , _total = pres.length + , _current = -1 + , _asyncsLeft = proto[name].numAsyncPres + , _next = function () { + if (arguments[0] instanceof Error) { + return handleError(arguments[0]); + } + var _args = Array.prototype.slice.call(arguments) + , currPre + , preArgs; + if (_args.length && !(arguments[0] == null && typeof lastArg === 'function')) + hookArgs = _args; + if (++_current < _total) { + currPre = pres[_current] + if (currPre.isAsync && currPre.length < 2) + throw new Error("Your pre must have next and done arguments -- e.g., function (next, done, ...)"); + if (currPre.length < 1) + throw new Error("Your pre must have a next argument -- e.g., function (next, ...)"); + preArgs = (currPre.isAsync + ? [once(_next), once(_asyncsDone)] + : [once(_next)]).concat(hookArgs); + return currPre.apply(self, preArgs); + } else if (!proto[name].numAsyncPres) { + return _done.apply(self, hookArgs); + } + } + , _done = function () { + var args_ = Array.prototype.slice.call(arguments) + , ret, total_, current_, next_, done_, postArgs; + if (_current === _total) { + ret = fn.apply(self, args_); + total_ = posts.length; + current_ = -1; + next_ = function () { + if (arguments[0] instanceof Error) { + return handleError(arguments[0]); + } + var args_ = Array.prototype.slice.call(arguments, 1) + , currPost + , postArgs; + if (args_.length) hookArgs = args_; + if (++current_ < total_) { + currPost = posts[current_] + if (currPost.length < 1) + throw new Error("Your post must have a next argument -- e.g., function (next, ...)"); + postArgs = [once(next_)].concat(hookArgs); + return currPost.apply(self, postArgs); + } + }; + if (total_) return next_(); + return ret; + } + }; + if (_asyncsLeft) { + function _asyncsDone (err) { + if (err && err instanceof Error) { + return handleError(err); + } + --_asyncsLeft || _done.apply(self, hookArgs); + } + } + function handleError (err) { + if ('function' == typeof lastArg) + return lastArg(err); + if (errorCb) return errorCb.call(self, err); + throw err; + } + return _next.apply(this, arguments); + }; + + proto[name].numAsyncPres = 0; + + return this; + }, + + pre: function (name, isAsync, fn, errorCb) { + if ('boolean' !== typeof arguments[1]) { + errorCb = fn; + fn = isAsync; + isAsync = false; + } + var proto = this.prototype || this + , pres = proto._pres = proto._pres || {}; + + this._lazySetupHooks(proto, name, errorCb); + + if (fn.isAsync = isAsync) { + proto[name].numAsyncPres++; + } + + (pres[name] = pres[name] || []).push(fn); + return this; + }, + post: function (name, isAsync, fn) { + if (arguments.length === 2) { + fn = isAsync; + isAsync = false; + } + var proto = this.prototype || this + , posts = proto._posts = proto._posts || {}; + + this._lazySetupHooks(proto, name); + (posts[name] = posts[name] || []).push(fn); + return this; + }, + removePre: function (name, fnToRemove) { + var proto = this.prototype || this + , pres = proto._pres || (proto._pres || {}); + if (!pres[name]) return this; + if (arguments.length === 1) { + // Remove all pre callbacks for hook `name` + pres[name].length = 0; + } else { + pres[name] = pres[name].filter( function (currFn) { + return currFn !== fnToRemove; + }); + } + return this; + }, + _lazySetupHooks: function (proto, methodName, errorCb) { + if ('undefined' === typeof proto[methodName].numAsyncPres) { + this.hook(methodName, proto[methodName], errorCb); + } + } +}; + +function once (fn, scope) { + return function fnWrapper () { + if (fnWrapper.hookCalled) return; + fnWrapper.hookCalled = true; + fn.apply(scope, arguments); + }; +} diff --git a/node_modules/mongoose/node_modules/hooks/package.json b/node_modules/mongoose/node_modules/hooks/package.json new file mode 100644 index 0000000..48e0a8c --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/package.json @@ -0,0 +1,50 @@ +{ + "name": "hooks", + "description": "Adds pre and post hook functionality to your JavaScript methods.", + "version": "0.2.1", + "keywords": [ + "node", + "hooks", + "middleware", + "pre", + "post" + ], + "homepage": "https://github.com/bnoguchi/hooks-js/", + "repository": { + "type": "git", + "url": "git://github.com/bnoguchi/hooks-js.git" + }, + "author": { + "name": "Brian Noguchi", + "email": "brian.noguchi@gmail.com", + "url": "https://github.com/bnoguchi/" + }, + "main": "./hooks.js", + "directories": { + "lib": "." + }, + "scripts": { + "test": "make test" + }, + "dependencies": {}, + "devDependencies": { + "expresso": ">=0.7.6", + "should": ">=0.2.1", + "underscore": ">=1.1.4" + }, + "engines": { + "node": ">=0.4.0" + }, + "licenses": [ + "MIT" + ], + "optionalDependencies": {}, + "readme": "hooks\n============\n\nAdd pre and post middleware hooks to your JavaScript methods.\n\n## Installation\n npm install hooks\n\n## Motivation\nSuppose you have a JavaScript object with a `save` method.\n\nIt would be nice to be able to declare code that runs before `save` and after `save`.\nFor example, you might want to run validation code before every `save`,\nand you might want to dispatch a job to a background job queue after `save`.\n\nOne might have an urge to hard code this all into `save`, but that turns out to\ncouple all these pieces of functionality (validation, save, and job creation) more\ntightly than is necessary. For example, what if someone does not want to do background\njob creation after the logical save? \n\nIt is nicer to tack on functionality using what we call `pre` and `post` hooks. These\nare functions that you define and that you direct to execute before or after particular\nmethods.\n\n## Example\nWe can use `hooks` to add validation and background jobs in the following way:\n\n var hooks = require('hooks')\n , Document = require('./path/to/some/document/constructor');\n\n // Add hooks' methods: `hook`, `pre`, and `post` \n for (var k in hooks) {\n Document[k] = hooks[k];\n }\n\n // Define a new method that is able to invoke pre and post middleware\n Document.hook('save', Document.prototype.save);\n\n // Define a middleware function to be invoked before 'save'\n Document.pre('save', function validate (next) {\n // The `this` context inside of `pre` and `post` functions\n // is the Document instance\n if (this.isValid()) next(); // next() passes control to the next middleware\n // or to the target method itself\n else next(new Error(\"Invalid\")); // next(error) invokes an error callback\n });\n\n // Define a middleware function to be invoked after 'save'\n Document.post('save', function createJob () {\n this.sendToBackgroundQueue();\n });\n\nIf you already have defined `Document.prototype` methods for which you want pres and posts,\nthen you do not need to explicitly invoke `Document.hook(...)`. Invoking `Document.pre(methodName, fn)`\nor `Document.post(methodName, fn)` will automatically and lazily change `Document.prototype[methodName]`\nso that it plays well with `hooks`. An equivalent way to implement the previous example is:\n\n```javascript\nvar hooks = require('hooks')\n , Document = require('./path/to/some/document/constructor');\n\n// Add hooks' methods: `hook`, `pre`, and `post` \nfor (var k in hooks) {\n Document[k] = hooks[k];\n}\n\nDocument.prototype.save = function () {\n // ...\n};\n\n// Define a middleware function to be invoked before 'save'\nDocument.pre('save', function validate (next) {\n // The `this` context inside of `pre` and `post` functions\n // is the Document instance\n if (this.isValid()) next(); // next() passes control to the next middleware\n // or to the target method itself\n else next(new Error(\"Invalid\")); // next(error) invokes an error callback\n});\n\n// Define a middleware function to be invoked after 'save'\nDocument.post('save', function createJob () {\n this.sendToBackgroundQueue();\n});\n```\n\n## Pres and Posts as Middleware\nWe structure pres and posts as middleware to give you maximum flexibility:\n\n1. You can define **multiple** pres (or posts) for a single method.\n2. These pres (or posts) are then executed as a chain of methods.\n3. Any functions in this middleware chain can choose to halt the chain's execution by `next`ing an Error from that middleware function. If this occurs, then none of the other middleware in the chain will execute, and the main method (e.g., `save`) will not execute. This is nice, for example, when we don't want a document to save if it is invalid.\n\n## Defining multiple pres (or posts)\n`pre` is chainable, so you can define multiple pres via:\n Document.pre('save', function (next, halt) {\n console.log(\"hello\");\n }).pre('save', function (next, halt) {\n console.log(\"world\");\n });\n\nAs soon as one pre finishes executing, the next one will be invoked, and so on.\n\n## Error Handling\nYou can define a default error handler by passing a 2nd function as the 3rd argument to `hook`:\n Document.hook('set', function (path, val) {\n this[path] = val;\n }, function (err) {\n // Handler the error here\n console.error(err);\n });\n\nThen, we can pass errors to this handler from a pre or post middleware function:\n Document.pre('set', function (next, path, val) {\n next(new Error());\n });\n\nIf you do not set up a default handler, then `hooks` makes the default handler that just throws the `Error`.\n\nThe default error handler can be over-rided on a per method invocation basis.\n\nIf the main method that you are surrounding with pre and post middleware expects its last argument to be a function\nwith callback signature `function (error, ...)`, then that callback becomes the error handler, over-riding the default\nerror handler you may have set up.\n \n```javascript\nDocument.hook('save', function (callback) {\n // Save logic goes here\n ...\n});\n\nvar doc = new Document();\ndoc.save( function (err, saved) {\n // We can pass err via `next` in any of our pre or post middleware functions\n if (err) console.error(err);\n \n // Rest of callback logic follows ...\n});\n```\n\n## Mutating Arguments via Middleware\n`pre` and `post` middleware can also accept the intended arguments for the method\nthey augment. This is useful if you want to mutate the arguments before passing\nthem along to the next middleware and eventually pass a mutated arguments list to\nthe main method itself.\n\nAs a simple example, let's define a method `set` that just sets a key, value pair.\nIf we want to namespace the key, we can do so by adding a `pre` middleware hook\nthat runs before `set`, alters the arguments by namespacing the `key` argument, and passes them onto `set`:\n\n Document.hook('set', function (key, val) {\n this[key] = val;\n });\n Document.pre('set', function (next, key, val) {\n next('namespace-' + key, val);\n });\n var doc = new Document();\n doc.set('hello', 'world');\n console.log(doc.hello); // undefined\n console.log(doc['namespace-hello']); // 'world'\n\nAs you can see above, we pass arguments via `next`.\n\nIf you are not mutating the arguments, then you can pass zero arguments\nto `next`, and the next middleware function will still have access\nto the arguments.\n\n Document.hook('set', function (key, val) {\n this[key] = val;\n });\n Document.pre('set', function (next, key, val) {\n // I have access to key and val here\n next(); // We don't need to pass anything to next\n });\n Document.pre('set', function (next, key, val) {\n // And I still have access to the original key and val here\n next();\n });\n\nFinally, you can add arguments that downstream middleware can also see:\n\n // Note that in the definition of `set`, there is no 3rd argument, options\n Document.hook('set', function (key, val) {\n // But...\n var options = arguments[2]; // ...I have access to an options argument\n // because of pre function pre2 (defined below)\n console.log(options); // '{debug: true}'\n this[key] = val;\n });\n Document.pre('set', function pre1 (next, key, val) {\n // I only have access to key and val arguments\n console.log(arguments.length); // 3\n next(key, val, {debug: true});\n });\n Document.pre('set', function pre2 (next, key, val, options) {\n console.log(arguments.length); // 4\n console.log(options); // '{ debug: true}'\n next();\n });\n Document.pre('set', function pre3 (next, key, val, options) {\n // I still have access to key, val, AND the options argument introduced via the preceding middleware\n console.log(arguments.length); // 4\n console.log(options); // '{ debug: true}'\n next();\n });\n \n var doc = new Document()\n doc.set('hey', 'there');\n\n## Parallel `pre` middleware\n\nAll middleware up to this point has been \"serial\" middleware -- i.e., middleware whose logic\nis executed as a serial chain.\n\nSome scenarios call for parallel middleware -- i.e., middleware that can wait for several\nasynchronous services at once to respond.\n\nFor instance, you may only want to save a Document only after you have checked\nthat the Document is valid according to two different remote services.\n\nWe accomplish asynchronous middleware by adding a second kind of flow control callback\n(the only flow control callback so far has been `next`), called `done`.\n\n- `next` passes control to the next middleware in the chain\n- `done` keeps track of how many parallel middleware have invoked `done` and passes\n control to the target method when ALL parallel middleware have invoked `done`. If\n you pass an `Error` to `done`, then the error is handled, and the main method that is\n wrapped by pres and posts will not get invoked.\n\nWe declare pre middleware that is parallel by passing a 3rd boolean argument to our `pre`\ndefinition method.\n\nWe illustrate via the parallel validation example mentioned above:\n\n Document.hook('save', function targetFn (callback) {\n // Save logic goes here\n // ...\n // This only gets run once the two `done`s are both invoked via preOne and preTwo.\n });\n\n // true marks this as parallel middleware\n Document.pre('save', true, function preOne (next, doneOne, callback) {\n remoteServiceOne.validate(this.serialize(), function (err, isValid) {\n // The code in here will probably be run after the `next` below this block\n // and could possibly be run after the console.log(\"Hola\") in `preTwo\n if (err) return doneOne(err);\n if (isValid) doneOne();\n });\n next(); // Pass control to the next middleware\n });\n \n // We will suppose that we need 2 different remote services to validate our document\n Document.pre('save', true, function preTwo (next, doneTwo, callback) {\n remoteServiceTwo.validate(this.serialize(), function (err, isValid) {\n if (err) return doneTwo(err);\n if (isValid) doneTwo();\n });\n next();\n });\n \n // While preOne and preTwo are parallel, preThree is a serial pre middleware\n Document.pre('save', function preThree (next, callback) {\n next();\n });\n \n var doc = new Document();\n doc.save( function (err, doc) {\n // Do stuff with the saved doc here...\n });\n\nIn the above example, flow control may happen in the following way:\n\n(1) doc.save -> (2) preOne --(next)--> (3) preTwo --(next)--> (4) preThree --(next)--> (wait for dones to invoke) -> (5) doneTwo -> (6) doneOne -> (7) targetFn\n\nSo what's happening is that:\n\n1. You call `doc.save(...)`\n2. First, your preOne middleware gets executed. It makes a remote call to the validation service and `next()`s to the preTwo middleware.\n3. Now, your preTwo middleware gets executed. It makes a remote call to another validation service and `next()`s to the preThree middleware.\n4. Your preThree middleware gets executed. It immediately `next()`s. But nothing else gets executing until both `doneOne` and `doneTwo` are invoked inside the callbacks handling the response from the two valiation services.\n5. We will suppose that validation remoteServiceTwo returns a response to us first. In this case, we call `doneTwo` inside the callback to remoteServiceTwo.\n6. Some fractions of a second later, remoteServiceOne returns a response to us. In this case, we call `doneOne` inside the callback to remoteServiceOne.\n7. `hooks` implementation keeps track of how many parallel middleware has been defined per target function. It detects that both asynchronous pre middlewares (`preOne` and `preTwo`) have finally called their `done` functions (`doneOne` and `doneTwo`), so the implementation finally invokes our `targetFn` (i.e., our core `save` business logic).\n\n## Removing Pres\n\nYou can remove a particular pre associated with a hook:\n\n Document.pre('set', someFn);\n Document.removePre('set', someFn);\n\nAnd you can also remove all pres associated with a hook:\n Document.removePre('set'); // Removes all declared `pre`s on the hook 'set'\n\n## Tests\nTo run the tests:\n make test\n\n### Contributors\n- [Brian Noguchi](https://github.com/bnoguchi)\n\n### License\nMIT License\n\n---\n### Author\nBrian Noguchi\n", + "readmeFilename": "README.md", + "_id": "hooks@0.2.1", + "dist": { + "shasum": "57f4546b5b35085089593f0bf2a28abf13d0f803" + }, + "_from": "hooks@0.2.1", + "_resolved": "https://registry.npmjs.org/hooks/-/hooks-0.2.1.tgz" +} diff --git a/node_modules/mongoose/node_modules/hooks/test.js b/node_modules/mongoose/node_modules/hooks/test.js new file mode 100644 index 0000000..efe2f3e --- /dev/null +++ b/node_modules/mongoose/node_modules/hooks/test.js @@ -0,0 +1,691 @@ +var hooks = require('./hooks') + , should = require('should') + , assert = require('assert') + , _ = require('underscore'); + +// TODO Add in test for making sure all pres get called if pre is defined directly on an instance. +// TODO Test for calling `done` twice or `next` twice in the same function counts only once +module.exports = { + 'should be able to assign multiple hooks at once': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook({ + hook1: function (a) {}, + hook2: function (b) {} + }); + var a = new A(); + assert.equal(typeof a.hook1, 'function'); + assert.equal(typeof a.hook2, 'function'); + }, + 'should run without pres and posts when not present': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + var a = new A(); + a.save(); + a.value.should.equal(1); + }, + 'should run with pres when present': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.pre('save', function (next) { + this.preValue = 2; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(1); + a.preValue.should.equal(2); + }, + 'should run with posts when present': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.post('save', function (next) { + this.value = 2; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(2); + }, + 'should run pres and posts when present': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.pre('save', function (next) { + this.preValue = 2; + next(); + }); + A.post('save', function (next) { + this.value = 3; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(3); + a.preValue.should.equal(2); + }, + 'should run posts after pres': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.pre('save', function (next) { + this.override = 100; + next(); + }); + A.post('save', function (next) { + this.override = 200; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(1); + a.override.should.equal(200); + }, + 'should not run a hook if a pre fails': function () { + var A = function () {}; + _.extend(A, hooks); + var counter = 0; + A.hook('save', function () { + this.value = 1; + }, function (err) { + counter++; + }); + A.pre('save', true, function (next, done) { + next(new Error()); + }); + var a = new A(); + a.save(); + counter.should.equal(1); + assert.equal(typeof a.value, 'undefined'); + }, + 'should be able to run multiple pres': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.pre('save', function (next) { + this.v1 = 1; + next(); + }).pre('save', function (next) { + this.v2 = 2; + next(); + }); + var a = new A(); + a.save(); + a.v1.should.equal(1); + a.v2.should.equal(2); + }, + 'should run multiple pres until a pre fails and not call the hook': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }, function (err) {}); + A.pre('save', function (next) { + this.v1 = 1; + next(); + }).pre('save', function (next) { + next(new Error()); + }).pre('save', function (next) { + this.v3 = 3; + next(); + }); + var a = new A(); + a.save(); + a.v1.should.equal(1); + assert.equal(typeof a.v3, 'undefined'); + assert.equal(typeof a.value, 'undefined'); + }, + 'should be able to run multiple posts': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.post('save', function (next) { + this.value = 2; + next(); + }).post('save', function (next) { + this.value = 3.14; + next(); + }).post('save', function (next) { + this.v3 = 3; + next(); + }); + var a = new A(); + a.save(); + assert.equal(a.value, 3.14); + assert.equal(a.v3, 3); + }, + 'should run only posts up until an error': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }, function (err) {}); + A.post('save', function (next) { + this.value = 2; + next(); + }).post('save', function (next) { + this.value = 3; + next(new Error()); + }).post('save', function (next) { + this.value = 4; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(3); + }, + "should fall back first to the hook method's last argument as the error handler if it is a function of arity 1 or 2": function () { + var A = function () {}; + _.extend(A, hooks); + var counter = 0; + A.hook('save', function (callback) { + this.value = 1; + }); + A.pre('save', true, function (next, done) { + next(new Error()); + }); + var a = new A(); + a.save( function (err) { + if (err instanceof Error) counter++; + }); + counter.should.equal(1); + should.deepEqual(undefined, a.value); + }, + 'should fall back second to the default error handler if specified': function () { + var A = function () {}; + _.extend(A, hooks); + var counter = 0; + A.hook('save', function (callback) { + this.value = 1; + }, function (err) { + if (err instanceof Error) counter++; + }); + A.pre('save', true, function (next, done) { + next(new Error()); + }); + var a = new A(); + a.save(); + counter.should.equal(1); + should.deepEqual(undefined, a.value); + }, + 'fallback default error handler should scope to the object': function () { + var A = function () { + this.counter = 0; + }; + _.extend(A, hooks); + var counter = 0; + A.hook('save', function (callback) { + this.value = 1; + }, function (err) { + if (err instanceof Error) this.counter++; + }); + A.pre('save', true, function (next, done) { + next(new Error()); + }); + var a = new A(); + a.save(); + a.counter.should.equal(1); + should.deepEqual(undefined, a.value); + }, + 'should fall back last to throwing the error': function () { + var A = function () {}; + _.extend(A, hooks); + var counter = 0; + A.hook('save', function (err) { + if (err instanceof Error) return counter++; + this.value = 1; + }); + A.pre('save', true, function (next, done) { + next(new Error()); + }); + var a = new A(); + var didCatch = false; + try { + a.save(); + } catch (e) { + didCatch = true; + e.should.be.an.instanceof(Error); + counter.should.equal(0); + assert.equal(typeof a.value, 'undefined'); + } + didCatch.should.be.true; + }, + "should proceed without mutating arguments if `next(null|undefined)` is called in a serial pre, and the last argument of the target method is a callback with node-like signature function (err, obj) {...} or function (err) {...}": function () { + var A = function () {}; + _.extend(A, hooks); + var counter = 0; + A.prototype.save = function (callback) { + this.value = 1; + callback(); + }; + A.pre('save', function (next) { + next(null); + }); + A.pre('save', function (next) { + next(undefined); + }); + var a = new A(); + a.save( function (err) { + if (err instanceof Error) counter++; + else counter--; + }); + counter.should.equal(-1); + a.value.should.eql(1); + }, + "should proceed with mutating arguments if `next(null|undefined)` is callback in a serial pre, and the last argument of the target method is not a function": function () { + var A = function () {}; + _.extend(A, hooks); + A.prototype.set = function (v) { + this.value = v; + }; + A.pre('set', function (next) { + next(undefined); + }); + A.pre('set', function (next) { + next(null); + }); + var a = new A(); + a.set(1); + should.strictEqual(null, a.value); + }, + 'should not run any posts if a pre fails': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 2; + }, function (err) {}); + A.pre('save', function (next) { + this.value = 1; + next(new Error()); + }).post('save', function (next) { + this.value = 3; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(1); + }, + + "can pass the hook's arguments verbatim to pres": function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val) { + this[path] = val; + }); + A.pre('set', function (next, path, val) { + path.should.equal('hello'); + val.should.equal('world'); + next(); + }); + var a = new A(); + a.set('hello', 'world'); + a.hello.should.equal('world'); + }, +// "can pass the hook's arguments as an array to pres": function () { +// // Great for dynamic arity - e.g., slice(...) +// var A = function () {}; +// _.extend(A, hooks); +// A.hook('set', function (path, val) { +// this[path] = val; +// }); +// A.pre('set', function (next, hello, world) { +// hello.should.equal('hello'); +// world.should.equal('world'); +// next(); +// }); +// var a = new A(); +// a.set('hello', 'world'); +// assert.equal(a.hello, 'world'); +// }, + "can pass the hook's arguments verbatim to posts": function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val) { + this[path] = val; + }); + A.post('set', function (next, path, val) { + path.should.equal('hello'); + val.should.equal('world'); + next(); + }); + var a = new A(); + a.set('hello', 'world'); + assert.equal(a.hello, 'world'); + }, +// "can pass the hook's arguments as an array to posts": function () { +// var A = function () {}; +// _.extend(A, hooks); +// A.hook('set', function (path, val) { +// this[path] = val; +// }); +// A.post('set', function (next, halt, args) { +// assert.equal(args[0], 'hello'); +// assert.equal(args[1], 'world'); +// next(); +// }); +// var a = new A(); +// a.set('hello', 'world'); +// assert.equal(a.hello, 'world'); +// }, + "pres should be able to modify and pass on a modified version of the hook's arguments": function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val) { + this[path] = val; + assert.equal(arguments[2], 'optional'); + }); + A.pre('set', function (next, path, val) { + next('foo', 'bar'); + }); + A.pre('set', function (next, path, val) { + assert.equal(path, 'foo'); + assert.equal(val, 'bar'); + next('rock', 'says', 'optional'); + }); + A.pre('set', function (next, path, val, opt) { + assert.equal(path, 'rock'); + assert.equal(val, 'says'); + assert.equal(opt, 'optional'); + next(); + }); + var a = new A(); + a.set('hello', 'world'); + assert.equal(typeof a.hello, 'undefined'); + a.rock.should.equal('says'); + }, + 'posts should see the modified version of arguments if the pres modified them': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val) { + this[path] = val; + }); + A.pre('set', function (next, path, val) { + next('foo', 'bar'); + }); + A.post('set', function (next, path, val) { + path.should.equal('foo'); + val.should.equal('bar'); + }); + var a = new A(); + a.set('hello', 'world'); + assert.equal(typeof a.hello, 'undefined'); + a.foo.should.equal('bar'); + }, + 'should pad missing arguments (relative to expected arguments of the hook) with null': function () { + // Otherwise, with hookFn = function (a, b, next, ), + // if we use hookFn(a), then because the pre functions are of the form + // preFn = function (a, b, next, ), then it actually gets executed with + // preFn(a, next, ), so when we call next() from within preFn, we are actually + // calling () + + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val, opts) { + this[path] = val; + }); + A.pre('set', function (next, path, val, opts) { + next('foo', 'bar'); + assert.equal(typeof opts, 'undefined'); + }); + var a = new A(); + a.set('hello', 'world'); + }, + + 'should not invoke the target method until all asynchronous middleware have invoked dones': function () { + var counter = 0; + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val) { + counter++; + this[path] = val; + counter.should.equal(7); + }); + A.pre('set', function (next, path, val) { + counter++; + next(); + }); + A.pre('set', true, function (next, done, path, val) { + counter++; + setTimeout(function () { + counter++; + done(); + }, 1000); + next(); + }); + A.pre('set', function (next, path, val) { + counter++; + next(); + }); + A.pre('set', true, function (next, done, path, val) { + counter++; + setTimeout(function () { + counter++; + done(); + }, 500); + next(); + }); + var a = new A(); + a.set('hello', 'world'); + }, + + 'invoking a method twice should run its async middleware twice': function () { + var counter = 0; + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val) { + this[path] = val; + if (path === 'hello') counter.should.equal(1); + if (path === 'foo') counter.should.equal(2); + }); + A.pre('set', true, function (next, done, path, val) { + setTimeout(function () { + counter++; + done(); + }, 1000); + next(); + }); + var a = new A(); + a.set('hello', 'world'); + a.set('foo', 'bar'); + }, + + 'calling the same done multiple times should have the effect of only calling it once': function () { + var A = function () { + this.acked = false; + }; + _.extend(A, hooks); + A.hook('ack', function () { + console.log("UH OH, YOU SHOULD NOT BE SEEING THIS"); + this.acked = true; + }); + A.pre('ack', true, function (next, done) { + next(); + done(); + done(); + }); + A.pre('ack', true, function (next, done) { + next(); + // Notice that done() is not invoked here + }); + var a = new A(); + a.ack(); + setTimeout( function () { + a.acked.should.be.false; + }, 1000); + }, + + 'calling the same next multiple times should have the effect of only calling it once': function (beforeExit) { + var A = function () { + this.acked = false; + }; + _.extend(A, hooks); + A.hook('ack', function () { + console.log("UH OH, YOU SHOULD NOT BE SEEING THIS"); + this.acked = true; + }); + A.pre('ack', function (next) { + // force a throw to re-exec next() + try { + next(new Error('bam')); + } catch (err) { + next(); + } + }); + A.pre('ack', function (next) { + next(); + }); + var a = new A(); + a.ack(); + beforeExit( function () { + a.acked.should.be.false; + }); + }, + + 'asynchronous middleware should be able to pass an error via `done`, stopping the middleware chain': function () { + var counter = 0; + var A = function () {}; + _.extend(A, hooks); + A.hook('set', function (path, val, fn) { + counter++; + this[path] = val; + fn(null); + }); + A.pre('set', true, function (next, done, path, val, fn) { + setTimeout(function () { + counter++; + done(new Error); + }, 1000); + next(); + }); + var a = new A(); + a.set('hello', 'world', function (err) { + err.should.be.an.instanceof(Error); + should.strictEqual(undefined, a['hello']); + counter.should.eql(1); + }); + }, + + 'should be able to remove a particular pre': function () { + var A = function () {} + , preTwo; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.pre('save', function (next) { + this.preValueOne = 2; + next(); + }); + A.pre('save', preTwo = function (next) { + this.preValueTwo = 4; + next(); + }); + A.removePre('save', preTwo); + var a = new A(); + a.save(); + a.value.should.equal(1); + a.preValueOne.should.equal(2); + should.strictEqual(undefined, a.preValueTwo); + }, + + 'should be able to remove all pres associated with a hook': function () { + var A = function () {}; + _.extend(A, hooks); + A.hook('save', function () { + this.value = 1; + }); + A.pre('save', function (next) { + this.preValueOne = 2; + next(); + }); + A.pre('save', function (next) { + this.preValueTwo = 4; + next(); + }); + A.removePre('save'); + var a = new A(); + a.save(); + a.value.should.equal(1); + should.strictEqual(undefined, a.preValueOne); + should.strictEqual(undefined, a.preValueTwo); + }, + + '#pre should lazily make a method hookable': function () { + var A = function () {}; + _.extend(A, hooks); + A.prototype.save = function () { + this.value = 1; + }; + A.pre('save', function (next) { + this.preValue = 2; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(1); + a.preValue.should.equal(2); + }, + + '#pre lazily making a method hookable should be able to provide a default errorHandler as the last argument': function () { + var A = function () {}; + var preValue = ""; + _.extend(A, hooks); + A.prototype.save = function () { + this.value = 1; + }; + A.pre('save', function (next) { + next(new Error); + }, function (err) { + preValue = 'ERROR'; + }); + var a = new A(); + a.save(); + should.strictEqual(undefined, a.value); + preValue.should.equal('ERROR'); + }, + + '#post should lazily make a method hookable': function () { + var A = function () {}; + _.extend(A, hooks); + A.prototype.save = function () { + this.value = 1; + }; + A.post('save', function (next) { + this.value = 2; + next(); + }); + var a = new A(); + a.save(); + a.value.should.equal(2); + }, + + "a lazy hooks setup should handle errors via a method's last argument, if it's a callback": function () { + var A = function () {}; + _.extend(A, hooks); + A.prototype.save = function (fn) {}; + A.pre('save', function (next) { + next(new Error("hi there")); + }); + var a = new A(); + a.save( function (err) { + err.should.be.an.instanceof(Error); + }); + } +}; diff --git a/node_modules/mongoose/node_modules/mongodb/.travis.yml b/node_modules/mongoose/node_modules/mongodb/.travis.yml new file mode 100644 index 0000000..0140117 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.10 # development version of 0.8, may be unstable \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md b/node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md new file mode 100644 index 0000000..2a1c52e --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md @@ -0,0 +1,23 @@ +## Contributing to the driver + +### Bugfixes + +- Before starting to write code, look for existing [tickets](https://github.com/mongodb/node-mongodb-native/issues) or [create one](https://github.com/mongodb/node-mongodb-native/issues/new) for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. +- Fork the [repo](https://github.com/mongodb/node-mongodb-native) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. +- Follow the general coding style of the rest of the project: + - 2 space tabs + - no trailing whitespace + - comma last + - inline documentation for new methods, class members, etc + - 0 space between conditionals/functions, and their parenthesis and curly braces + - `if(..) {` + - `for(..) {` + - `while(..) {` + - `function(err) {` +- Write tests and make sure they pass (execute `make test` from the cmd line to run the test suite). + +### Documentation + +To contribute to the [API documentation](http://mongodb.github.com/node-mongodb-native/) just make your changes to the inline documentation of the appropriate [source code](https://github.com/mongodb/node-mongodb-native/tree/master/docs) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + +If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make generate_docs`. Make sure you have the python documentation framework sphinx installed `easy_install sphinx`. The docs are generated under `docs/build'. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes. \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/LICENSE b/node_modules/mongoose/node_modules/mongodb/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/mongoose/node_modules/mongodb/Makefile b/node_modules/mongoose/node_modules/mongodb/Makefile new file mode 100644 index 0000000..59d2bfe --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/Makefile @@ -0,0 +1,28 @@ +NODE = node +NPM = npm +NODEUNIT = node_modules/nodeunit/bin/nodeunit +DOX = node_modules/dox/bin/dox +name = all + +total: build_native + +test_functional: + node test/runner.js -t functional + +test_ssl: + node test/runner.js -t ssl + +test_replicaset: + node test/runner.js -t replicaset + +test_sharded: + node test/runner.js -t sharded + +test_auth: + node test/runner.js -t auth + +generate_docs: + $(NODE) dev/tools/build-docs.js + make --directory=./docs/sphinx-docs --file=Makefile html + +.PHONY: total diff --git a/node_modules/mongoose/node_modules/mongodb/Readme.md b/node_modules/mongoose/node_modules/mongodb/Readme.md new file mode 100644 index 0000000..29f2d2d --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/Readme.md @@ -0,0 +1,421 @@ +Up to date documentation +======================== + +[Documentation](http://mongodb.github.com/node-mongodb-native/) + +Install +======= + +To install the most recent release from npm, run: + + npm install mongodb + +That may give you a warning telling you that bugs['web'] should be bugs['url'], it would be safe to ignore it (this has been fixed in the development version) + +To install the latest from the repository, run:: + + npm install path/to/node-mongodb-native + +Community +========= +Check out the google group [node-mongodb-native](http://groups.google.com/group/node-mongodb-native) for questions/answers from users of the driver. + +Live Examples +============ + + +Introduction +============ + +This is a node.js driver for MongoDB. It's a port (or close to a port) of the library for ruby at http://github.com/mongodb/mongo-ruby-driver/. + +A simple example of inserting a document. + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + var collection = db.collection('test_insert'); + collection.insert({a:2}, function(err, docs) { + + collection.count(function(err, count) { + console.log(format("count = %s", count)); + }); + + // Locate all the entries using find + collection.find().toArray(function(err, results) { + console.dir(results); + // Let's close the db + db.close(); + }); + }); + }) +``` + +Data types +========== + +To store and retrieve the non-JSON MongoDb primitives ([ObjectID](http://www.mongodb.org/display/DOCS/Object+IDs), Long, Binary, [Timestamp](http://www.mongodb.org/display/DOCS/Timestamp+data+type), [DBRef](http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef), Code). + +In particular, every document has a unique `_id` which can be almost any type, and by default a 12-byte ObjectID is created. ObjectIDs can be represented as 24-digit hexadecimal strings, but you must convert the string back into an ObjectID before you can use it in the database. For example: + +```javascript + // Get the objectID type + var ObjectID = require('mongodb').ObjectID; + + var idString = '4e4e1638c85e808431000003'; + collection.findOne({_id: new ObjectID(idString)}, console.log) // ok + collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined +``` + +Here are the constructors the non-Javascript BSON primitive types: + +```javascript + // Fetch the library + var mongo = require('mongodb'); + // Create new instances of BSON types + new mongo.Long(numberString) + new mongo.ObjectID(hexString) + new mongo.Timestamp() // the actual unique number is generated on insert. + new mongo.DBRef(collectionName, id, dbName) + new mongo.Binary(buffer) // takes a string or Buffer + new mongo.Code(code, [context]) + new mongo.Symbol(string) + new mongo.MinKey() + new mongo.MaxKey() + new mongo.Double(number) // Force double storage +``` + +The C/C++ bson parser/serializer +-------------------------------- + +If you are running a version of this library has the C/C++ parser compiled, to enable the driver to use the C/C++ bson parser pass it the option native_parser:true like below + +```javascript + // using native_parser: + MongoClient.connect('mongodb://127.0.0.1:27017/test' + , {db: {native_parser: true}}, function(err, db) {}) +``` + +The C++ parser uses the js objects both for serialization and deserialization. + +GitHub information +================== + +The source code is available at http://github.com/mongodb/node-mongodb-native. +You can either clone the repository or download a tarball of the latest release. + +Once you have the source you can test the driver by running + + $ make test + +in the main directory. You will need to have a mongo instance running on localhost for the integration tests to pass. + +Examples +======== + +For examples look in the examples/ directory. You can execute the examples using node. + + $ cd examples + $ node queries.js + +GridStore +========= + +The GridStore class allows for storage of binary files in mongoDB using the mongoDB defined files and chunks collection definition. + +For more information have a look at [Gridstore](https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md) + +Replicasets +=========== +For more information about how to connect to a replicaset have a look at [Replicasets](https://github.com/mongodb/node-mongodb-native/blob/master/docs/replicaset.md) + +Primary Key Factories +--------------------- + +Defining your own primary key factory allows you to generate your own series of id's +(this could f.ex be to use something like ISBN numbers). The generated the id needs to be a 12 byte long "string". + +Simple example below + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + // Custom factory (need to provide a 12 byte array); + CustomPKFactory = function() {} + CustomPKFactory.prototype = new Object(); + CustomPKFactory.createPk = function() { + return new ObjectID("aaaaaaaaaaaa"); + } + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + db.dropDatabase(function(err, done) { + + db.createCollection('test_custom_key', function(err, collection) { + + collection.insert({'a':1}, function(err, docs) { + + collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}).toArray(function(err, items) { + console.dir(items); + // Let's close the db + db.close(); + }); + }); + }); + }); + }); +``` + +Documentation +============= + +If this document doesn't answer your questions, see the source of +[Collection](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/collection.js) +or [Cursor](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/cursor.js), +or the documentation at MongoDB for query and update formats. + +Find +---- + +The find method is actually a factory method to create +Cursor objects. A Cursor lazily uses the connection the first time +you call `nextObject`, `each`, or `toArray`. + +The basic operation on a cursor is the `nextObject` method +that fetches the next matching document from the database. The convenience +methods `each` and `toArray` call `nextObject` until the cursor is exhausted. + +Signatures: + +```javascript + var cursor = collection.find(query, [fields], options); + cursor.sort(fields).limit(n).skip(m). + + cursor.nextObject(function(err, doc) {}); + cursor.each(function(err, doc) {}); + cursor.toArray(function(err, docs) {}); + + cursor.rewind() // reset the cursor to its initial state. +``` + +Useful chainable methods of cursor. These can optionally be options of `find` instead of method calls: + + * `.limit(n).skip(m)` to control paging. + * `.sort(fields)` Order by the given fields. There are several equivalent syntaxes: + * `.sort({field1: -1, field2: 1})` descending by field1, then ascending by field2. + * `.sort([['field1', 'desc'], ['field2', 'asc']])` same as above + * `.sort([['field1', 'desc'], 'field2'])` same as above + * `.sort('field1')` ascending by field1 + +Other options of `find`: + +* `fields` the fields to fetch (to avoid transferring the entire document) +* `tailable` if true, makes the cursor [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors). +* `batchSize` The number of the subset of results to request the database +to return for every request. This should initially be greater than 1 otherwise +the database will automatically close the cursor. The batch size can be set to 1 +with `batchSize(n, function(err){})` after performing the initial query to the database. +* `hint` See [Optimization: hint](http://www.mongodb.org/display/DOCS/Optimization#Optimization-Hint). +* `explain` turns this into an explain query. You can also call +`explain()` on any cursor to fetch the explanation. +* `snapshot` prevents documents that are updated while the query is active +from being returned multiple times. See more +[details about query snapshots](http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database). +* `timeout` if false, asks MongoDb not to time out this cursor after an +inactivity period. + + +For information on how to create queries, see the +[MongoDB section on querying](http://www.mongodb.org/display/DOCS/Querying). + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + var collection = db + .collection('test') + .find({}) + .limit(10) + .toArray(function(err, docs) { + console.dir(docs); + }); + }); +``` + +Insert +------ + +Signature: + +```javascript + collection.insert(docs, options, [callback]); +``` + +where `docs` can be a single document or an array of documents. + +Useful options: + +* `safe:true` Should always set if you have a callback. + +See also: [MongoDB docs for insert](http://www.mongodb.org/display/DOCS/Inserting). + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + db.collection('test').insert({hello: 'world'}, {w:1}, function(err, objects) { + if (err) console.warn(err.message); + if (err && err.message.indexOf('E11000 ') !== -1) { + // this _id was already inserted in the database + } + }); + }); +``` + +Note that there's no reason to pass a callback to the insert or update commands +unless you use the `safe:true` option. If you don't specify `safe:true`, then +your callback will be called immediately. + +Update; update and insert (upsert) +---------------------------------- + +The update operation will update the first document that matches your query +(or all documents that match if you use `multi:true`). +If `safe:true`, `upsert` is not set, and no documents match, your callback will return 0 documents updated. + +See the [MongoDB docs](http://www.mongodb.org/display/DOCS/Updating) for +the modifier (`$inc`, `$set`, `$push`, etc.) formats. + +Signature: + +```javascript + collection.update(criteria, objNew, options, [callback]); +``` + +Useful options: + +* `safe:true` Should always set if you have a callback. +* `multi:true` If set, all matching documents are updated, not just the first. +* `upsert:true` Atomically inserts the document if no documents matched. + +Example for `update`: + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + db.collection('test').update({hi: 'here'}, {$set: {hi: 'there'}}, {w:1}, function(err) { + if (err) console.warn(err.message); + else console.log('successfully updated'); + }); + }); +``` + +Find and modify +--------------- + +`findAndModify` is like `update`, but it also gives the updated document to +your callback. But there are a few key differences between findAndModify and +update: + + 1. The signatures differ. + 2. You can only findAndModify a single item, not multiple items. + +Signature: + +```javascript + collection.findAndModify(query, sort, update, options, callback) +``` + +The sort parameter is used to specify which object to operate on, if more than +one document matches. It takes the same format as the cursor sort (see +Connection.find above). + +See the +[MongoDB docs for findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) +for more details. + +Useful options: + +* `remove:true` set to a true to remove the object before returning +* `new:true` set to true if you want to return the modified object rather than the original. Ignored for remove. +* `upsert:true` Atomically inserts the document if no documents matched. + +Example for `findAndModify`: + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + db.collection('test').findAndModify({hello: 'world'}, [['_id','asc']], {$set: {hi: 'there'}}, {}, function(err, object) { + if (err) console.warn(err.message); + else console.dir(object); // undefined if no matching object exists. + }); + }); +``` + +Save +---- + +The `save` method is a shorthand for upsert if the document contains an +`_id`, or an insert if there is no `_id`. + +Sponsors +======== +Just as Felix Geisendörfer I'm also working on the driver for my own startup and this driver is a big project that also benefits other companies who are using MongoDB. + +If your company could benefit from a even better-engineered node.js mongodb driver I would appreciate any type of sponsorship you may be able to provide. All the sponsors will get a lifetime display in this readme, priority support and help on problems and votes on the roadmap decisions for the driver. If you are interested contact me on [christkv AT g m a i l.com](mailto:christkv@gmail.com) for details. + +And I'm very thankful for code contributions. If you are interested in working on features please contact me so we can discuss API design and testing. + +Release Notes +============= + +See HISTORY + +Credits +======= + +1. [10gen](http://github.com/mongodb/mongo-ruby-driver/) +2. [Google Closure Library](http://code.google.com/closure/library/) +3. [Jonas Raoni Soares Silva](http://jsfromhell.com/classes/binary-parser) + +Contributors +============ + +Aaron Heckmann, Christoph Pojer, Pau Ramon Revilla, Nathan White, Emmerman, Seth LaForge, Boris Filipov, Stefan Schärmeli, Tedde Lundgren, renctan, Sergey Ukustov, Ciaran Jessup, kuno, srimonti, Erik Abele, Pratik Daga, Slobodan Utvic, Kristina Chodorow, Yonathan Randolph, Brian Noguchi, Sam Epstein, James Harrison Fisher, Vladimir Dronnikov, Ben Hockey, Henrik Johansson, Simon Weare, Alex Gorbatchev, Shimon Doodkin, Kyle Mueller, Eran Hammer-Lahav, Marcin Ciszak, François de Metz, Vinay Pulim, nstielau, Adam Wiggins, entrinzikyl, Jeremy Selier, Ian Millington, Public Keating, andrewjstone, Christopher Stott, Corey Jewett, brettkiefer, Rob Holland, Senmiao Liu, heroic, gitfy + +License +======= + + Copyright 2009 - 2012 Christian Amor Kvalheim. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/node_modules/mongoose/node_modules/mongodb/index.js b/node_modules/mongoose/node_modules/mongodb/index.js new file mode 100755 index 0000000..4f59e9d --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/mongodb'); diff --git a/node_modules/mongoose/node_modules/mongodb/install.js b/node_modules/mongoose/node_modules/mongodb/install.js new file mode 100644 index 0000000..f9f2a57 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/install.js @@ -0,0 +1,40 @@ +var spawn = require('child_process').spawn, + exec = require('child_process').exec; + +process.stdout.write("================================================================================\n"); +process.stdout.write("= =\n"); +process.stdout.write("= To install with C++ bson parser do =\n"); +process.stdout.write("= =\n"); +process.stdout.write("================================================================================\n"); + +// Check if we want to build the native code +var build_native = process.env['npm_package_config_native'] != null ? process.env['npm_package_config_native'] : 'false'; +build_native = build_native == 'true' ? true : false; +// If we are building the native bson extension ensure we use gmake if available +if(build_native) { + // Check if we need to use gmake + exec('which gmake', function(err, stdout, stderr) { + // Set up spawn command + var make = null; + // No gmake build using make + if(err != null) { + make = spawn('make', ['total']); + } else { + make = spawn('gmake', ['total']); + } + + // Execute spawn + make.stdout.on('data', function(data) { + process.stdout.write(data); + }) + + make.stderr.on('data', function(data) { + process.stdout.write(data); + }) + + make.on('exit', function(code) { + process.stdout.write('child process exited with code ' + code + "\n"); + }) + }); +} + diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js new file mode 100644 index 0000000..6e9cd30 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js @@ -0,0 +1,339 @@ +/*! + * Module dependencies. + */ +var Collection = require('./collection').Collection, + Cursor = require('./cursor').Cursor, + DbCommand = require('./commands/db_command').DbCommand, + utils = require('./utils'); + +/** + * Allows the user to access the admin functionality of MongoDB + * + * @class Represents the Admin methods of MongoDB. + * @param {Object} db Current db instance we wish to perform Admin operations on. + * @return {Function} Constructor for Admin type. + */ +function Admin(db) { + if(!(this instanceof Admin)) return new Admin(db); + this.db = db; +}; + +/** + * Retrieve the server information for the current + * instance of the db client + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from buildInfo or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.buildInfo = function(callback) { + this.serverInfo(callback); +} + +/** + * Retrieve the server information for the current + * instance of the db client + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverInfo or null if an error occured. + * @return {null} Returns no result + * @api private + */ +Admin.prototype.serverInfo = function(callback) { + this.db.executeDbAdminCommand({buildinfo:1}, function(err, doc) { + if(err != null) return callback(err, null); + return callback(null, doc.documents[0]); + }); +} + +/** + * Retrieve this db's server status. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverStatus or null if an error occured. + * @return {null} + * @api public + */ +Admin.prototype.serverStatus = function(callback) { + var self = this; + + this.db.executeDbAdminCommand({serverStatus: 1}, function(err, doc) { + if(err == null && doc.documents[0].ok === 1) { + callback(null, doc.documents[0]); + } else { + if(err) return callback(err, false); + return callback(utils.toError(doc.documents[0]), false); + } + }); +}; + +/** + * Retrieve the current profiling Level for MongoDB + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingLevel or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.profilingLevel = function(callback) { + var self = this; + + this.db.executeDbAdminCommand({profile:-1}, function(err, doc) { + doc = doc.documents[0]; + + if(err == null && doc.ok === 1) { + var was = doc.was; + if(was == 0) return callback(null, "off"); + if(was == 1) return callback(null, "slow_only"); + if(was == 2) return callback(null, "all"); + return callback(new Error("Error: illegal profiling level value " + was), null); + } else { + err != null ? callback(err, null) : callback(new Error("Error with profile command"), null); + } + }); +}; + +/** + * Ping the MongoDB server and retrieve results + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ping or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.ping = function(options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + + this.db.executeDbAdminCommand({ping: 1}, callback); +} + +/** + * Authenticate against MongoDB + * + * @param {String} username The user name for the authentication. + * @param {String} password The password for the authentication. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authenticate or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.authenticate = function(username, password, callback) { + this.db.authenticate(username, password, {authdb: 'admin'}, function(err, doc) { + return callback(err, doc); + }) +} + +/** + * Logout current authenticated user + * + * @param {Object} [options] Optional parameters to the command. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.logout = function(callback) { + this.db.logout({authdb: 'admin'}, function(err, doc) { + return callback(err, doc); + }) +} + +/** + * Add a user to the MongoDB server, if the user exists it will + * overwrite the current password + * + * Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} username The user name for the authentication. + * @param {String} password The password for the authentication. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.addUser = function(username, password, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() : {}; + + options.dbName = 'admin'; + // Add user + this.db.addUser(username, password, options, function(err, doc) { + return callback(err, doc); + }) +} + +/** + * Remove a user from the MongoDB server + * + * Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} username The user name for the authentication. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.removeUser = function(username, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + options.dbName = 'admin'; + + this.db.removeUser(username, options, function(err, doc) { + return callback(err, doc); + }) +} + +/** + * Set the current profiling level of MongoDB + * + * @param {String} level The new profiling level (off, slow_only, all) + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from setProfilingLevel or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.setProfilingLevel = function(level, callback) { + var self = this; + var command = {}; + var profile = 0; + + if(level == "off") { + profile = 0; + } else if(level == "slow_only") { + profile = 1; + } else if(level == "all") { + profile = 2; + } else { + return callback(new Error("Error: illegal profiling level value " + level)); + } + + // Set up the profile number + command['profile'] = profile; + + this.db.executeDbAdminCommand(command, function(err, doc) { + doc = doc.documents[0]; + + if(err == null && doc.ok === 1) + return callback(null, level); + return err != null ? callback(err, null) : callback(new Error("Error with profile command"), null); + }); +}; + +/** + * Retrive the current profiling information for MongoDB + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingInfo or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.profilingInfo = function(callback) { + try { + new Cursor(this.db, new Collection(this.db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) { + return callback(err, items); + }); + } catch (err) { + return callback(err, null); + } +}; + +/** + * Execute a db command against the Admin database + * + * @param {Object} command A command object `{ping:1}`. + * @param {Object} [options] Optional parameters to the command. + * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.command = function(command, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + + // Execute a command + this.db.executeDbAdminCommand(command, options, function(err, doc) { + // Ensure change before event loop executes + return callback != null ? callback(err, doc) : null; + }); +} + +/** + * Validate an existing collection + * + * @param {String} collectionName The name of the collection to validate. + * @param {Object} [options] Optional parameters to the command. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from validateCollection or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.validateCollection = function(collectionName, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + + var self = this; + var command = {validate: collectionName}; + var keys = Object.keys(options); + + // Decorate command with extra options + for(var i = 0; i < keys.length; i++) { + if(options.hasOwnProperty(keys[i])) { + command[keys[i]] = options[keys[i]]; + } + } + + this.db.executeDbCommand(command, function(err, doc) { + if(err != null) return callback(err, null); + doc = doc.documents[0]; + + if(doc.ok === 0) + return callback(new Error("Error with validate command"), null); + if(doc.result != null && doc.result.constructor != String) + return callback(new Error("Error with validation data"), null); + if(doc.result != null && doc.result.match(/exception|corrupt/) != null) + return callback(new Error("Error: invalid collection " + collectionName), null); + if(doc.valid != null && !doc.valid) + return callback(new Error("Error: invalid collection " + collectionName), null); + + return callback(null, doc); + }); +}; + +/** + * List the available databases + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from listDatabases or null if an error occured. + * @return {null} Returns no result + * @api public + */ +Admin.prototype.listDatabases = function(callback) { + // Execute the listAllDatabases command + this.db.executeDbAdminCommand({listDatabases:1}, {}, function(err, doc) { + if(err != null) return callback(err, null); + return callback(null, doc.documents[0]); + }); +} + +/** + * Get ReplicaSet status + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from replSetGetStatus or null if an error occured. + * @return {null} + * @api public + */ +Admin.prototype.replSetGetStatus = function(callback) { + var self = this; + + this.db.executeDbAdminCommand({replSetGetStatus:1}, function(err, doc) { + if(err == null && doc.documents[0].ok === 1) + return callback(null, doc.documents[0]); + if(err) return callback(err, false); + return callback(utils.toError(doc.documents[0]), false); + }); +}; + +/** + * @ignore + */ +exports.Admin = Admin; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js new file mode 100644 index 0000000..51b09b1 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js @@ -0,0 +1,53 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils'); + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Execute all four + db._executeQueryCommand(DbCommand.createGetNonceCommand(db), options, function(err, result, connection) { + // Execute on all the connections + if(err == null) { + // Nonce used to make authentication request with md5 hash + var nonce = result.documents[0].nonce; + // Execute command + db._executeQueryCommand(DbCommand.createAuthenticationCommand(db, username, password, nonce, authdb), {connection:connection}, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + // Ensure we save any error + if(err) { + errorObject = err; + } else if(result.documents[0].err != null || result.documents[0].errmsg != null){ + errorObject = utils.toError(result.documents[0]); + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + if(errorObject == null && result.documents[0].ok == 1) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb); + // Return callback + internalCallback(errorObject, true); + } else { + internalCallback(errorObject, false); + } + } + }); + } + }); +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js new file mode 100644 index 0000000..47b5155 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js @@ -0,0 +1,149 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , format = require('util').format; + +// Kerberos class +var Kerberos = null; +var MongoAuthProcess = null; +// Try to grab the Kerberos class +try { + Kerberos = require('kerberos').Kerberos + // Authentication process for Mongo + MongoAuthProcess = require('kerberos').processes.MongoAuthProcess +} catch(err) {} + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + // We don't have the Kerberos library + if(Kerberos == null) return callback(new Error("Kerberos library is not installed")); + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Grab all the connections + var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); + var gssapiServiceName = options['gssapiServiceName'] || 'mongodb'; + var error = null; + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + + // Start Auth process for a connection + GSSAPIInitialize(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) { + // Adjust number of connections left to connect + numberOfConnections = numberOfConnections - 1; + // If we have an error save it + if(err) error = err; + + // We are done + if(numberOfConnections == 0) { + if(err) return callback(error, false); + // We authenticated correctly save the credentials + db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); + // Return valid callback + return callback(null, true); + } + }); + } +} + +// +// Initialize step +var GSSAPIInitialize = function(db, username, password, authdb, gssapiServiceName, connection, callback) { + // Create authenticator + var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, gssapiServiceName); + + // Perform initialization + mongo_auth_process.init(username, password, function(err, context) { + if(err) return callback(err, false); + + // Perform the first step + mongo_auth_process.transition('', function(err, payload) { + if(err) return callback(err, false); + + // Call the next db step + MongoDBGSSAPIFirstStep(mongo_auth_process, payload, db, username, password, authdb, connection, callback); + }); + }); +} + +// +// Perform first step against mongodb +var MongoDBGSSAPIFirstStep = function(mongo_auth_process, payload, db, username, password, authdb, connection, callback) { + // Build the sasl start command + var command = { + saslStart: 1 + , mechanism: 'GSSAPI' + , payload: payload + , autoAuthorize: 1 + }; + + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err, false); + // Get the payload + doc = doc.documents[0]; + var db_payload = doc.payload; + + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err, false); + + // MongoDB API Second Step + MongoDBGSSAPISecondStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback); + }); + }); +} + +// +// Perform first step against mongodb +var MongoDBGSSAPISecondStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) { + // Build Authentication command to send to MongoDB + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err, false); + + // Get the result document + doc = doc.documents[0]; + + // Call next transition for kerberos + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err, false); + + // Call the last and third step + MongoDBGSSAPIThirdStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback); + }); + }); +} + +var MongoDBGSSAPIThirdStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) { + // Build final command + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Let's finish the auth process against mongodb + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err, false); + + mongo_auth_process.transition(null, function(err, payload) { + if(err) return callback(err, false); + callback(null, true); + }); + }); +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js new file mode 100644 index 0000000..594181d --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js @@ -0,0 +1,66 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , Binary = require('bson').Binary + , format = require('util').format; + +var authenticate = function(db, username, password, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Create payload + var payload = new Binary(format("\x00%s\x00%s", username, password)); + + // Let's start the sasl process + var command = { + saslStart: 1 + , mechanism: 'PLAIN' + , payload: payload + , autoAuthorize: 1 + }; + + // Grab all the connections + var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); + + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + var connection = connections[i]; + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + + // Ensure we save any error + if(err) { + errorObject = err; + } else if(result.documents[0].err != null || result.documents[0].errmsg != null){ + errorObject = utils.toError(result.documents[0]); + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + if(errorObject == null && result.documents[0].ok == 1) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('PLAIN', db.databaseName, username, password); + // Return callback + internalCallback(errorObject, true); + } else { + internalCallback(errorObject, false); + } + } + }); + } +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js new file mode 100644 index 0000000..c5ac150 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js @@ -0,0 +1,135 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , format = require('util').format; + +// Kerberos class +var Kerberos = null; +var MongoAuthProcess = null; +// Try to grab the Kerberos class +try { + Kerberos = require('kerberos').Kerberos + // Authentication process for Mongo + MongoAuthProcess = require('kerberos').processes.MongoAuthProcess +} catch(err) {} + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + // We don't have the Kerberos library + if(Kerberos == null) return callback(new Error("Kerberos library is not installed")); + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + var connection = db.serverConfig.allRawConnections()[0]; + var gssapiServiceName = options['gssapiServiceName'] || 'mongodb'; + + // Grab all the connections + var connections = db.serverConfig.allRawConnections(); + var error = null; + + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + // Start Auth process for a connection + SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) { + // Adjust number of connections left to connect + numberOfConnections = numberOfConnections - 1; + // If we have an error save it + if(err) error = err; + + // We are done + if(numberOfConnections == 0) { + if(err) return callback(err, false); + // We authenticated correctly save the credentials + db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); + // Return valid callback + return callback(null, true); + } + }); + } +} + +var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) { + // -------------------------------------------------------------- + // Async Version + // -------------------------------------------------------------- + var command = { + saslStart: 1 + , mechanism: 'GSSAPI' + , payload: '' + , autoAuthorize: 1 + }; + + // Create authenticator + var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name); + + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + mongo_auth_process.init(username, password, function(err) { + if(err) return callback(err); + + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err); + + // Perform the next step against mongod + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err); + + // Perform the next step against mongod + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + mongo_auth_process.transition(doc.payload, function(err, payload) { + // Perform the next step against mongod + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + if(doc.done) return callback(null, true); + callback(new Error("Authentication failed"), false); + }); + }); + }); + }); + }); + }); + }); + }); +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js new file mode 100644 index 0000000..72a78e5 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js @@ -0,0 +1,1780 @@ +/** + * Module dependencies. + * @ignore + */ +var InsertCommand = require('./commands/insert_command').InsertCommand + , QueryCommand = require('./commands/query_command').QueryCommand + , DeleteCommand = require('./commands/delete_command').DeleteCommand + , UpdateCommand = require('./commands/update_command').UpdateCommand + , DbCommand = require('./commands/db_command').DbCommand + , ObjectID = require('bson').ObjectID + , Code = require('bson').Code + , Cursor = require('./cursor').Cursor + , utils = require('./utils'); + +/** + * Precompiled regexes + * @ignore +**/ +const eErrorMessages = /No matching object found/; + +/** + * toString helper. + * @ignore + */ +var toString = Object.prototype.toString; + +/** + * Create a new Collection instance (INTERNAL TYPE) + * + * Options + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **slaveOk** {Boolean, default:false}, Allow reads from secondaries. + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * + * @class Represents a Collection + * @param {Object} db db instance. + * @param {String} collectionName collection name. + * @param {Object} [pkFactory] alternative primary key factory. + * @param {Object} [options] additional options for the collection. + * @return {Object} a collection instance. + */ +function Collection (db, collectionName, pkFactory, options) { + if(!(this instanceof Collection)) return new Collection(db, collectionName, pkFactory, options); + + checkCollectionName(collectionName); + + this.db = db; + this.collectionName = collectionName; + this.internalHint = null; + this.opts = options != null && ('object' === typeof options) ? options : {}; + this.slaveOk = options == null || options.slaveOk == null ? db.slaveOk : options.slaveOk; + this.serializeFunctions = options == null || options.serializeFunctions == null ? db.serializeFunctions : options.serializeFunctions; + this.raw = options == null || options.raw == null ? db.raw : options.raw; + + this.readPreference = options == null || options.readPreference == null ? db.serverConfig.options.readPreference : options.readPreference; + this.readPreference = this.readPreference == null ? 'primary' : this.readPreference; + + this.pkFactory = pkFactory == null + ? ObjectID + : pkFactory; + + var self = this; +} + +/** + * Inserts a single document or a an array of documents into MongoDB. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **continueOnError/keepGoing** {Boolean, default:false}, keep inserting documents even if one document has an error, *mongodb 1.9.1 >*. + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **forceServerObjectId** {Boolean, default:false}, let server assign ObjectId instead of the driver + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Array|Object} docs + * @param {Object} [options] optional options for insert command + * @param {Function} [callback] optional callback for the function, must be provided when using a writeconcern + * @return {null} + * @api public + */ +Collection.prototype.insert = function insert (docs, options, callback) { + if ('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + var self = this; + insertAll(self, Array.isArray(docs) ? docs : [docs], options, callback); + return this; +}; + +/** + * @ignore + */ +var checkCollectionName = function checkCollectionName (collectionName) { + if ('string' !== typeof collectionName) { + throw Error("collection name must be a String"); + } + + if (!collectionName || collectionName.indexOf('..') != -1) { + throw Error("collection names cannot be empty"); + } + + if (collectionName.indexOf('$') != -1 && + collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) { + throw Error("collection names must not contain '$'"); + } + + if (collectionName.match(/^\.|\.$/) != null) { + throw Error("collection names must not start or end with '.'"); + } +}; + +/** + * Removes documents specified by `selector` from the db. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **single** {Boolean, default:false}, removes the first document found. + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} [selector] optional select, no selector is equivalent to removing all documents. + * @param {Object} [options] additional options during remove. + * @param {Function} [callback] must be provided if you performing a remove with a writeconcern + * @return {null} + * @api public + */ +Collection.prototype.remove = function remove(selector, options, callback) { + if ('function' === typeof selector) { + callback = selector; + selector = options = {}; + } else if ('function' === typeof options) { + callback = options; + options = {}; + } + + // Ensure options + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + // Ensure we have at least an empty selector + selector = selector == null ? {} : selector; + // Set up flags for the command, if we have a single document remove + var flags = 0 | (options.single ? 1 : 0); + + // DbName + var dbName = options['dbName']; + // If no dbname defined use the db one + if(dbName == null) { + dbName = this.db.databaseName; + } + + // Create a delete command + var deleteCommand = new DeleteCommand( + this.db + , dbName + "." + this.collectionName + , selector + , flags); + + var self = this; + var errorOptions = _getWriteConcern(self, options, callback); + // Execute the command, do not add a callback as it's async + if(_hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + var commandOptions = {read:false}; + // If we have safe set set async to false + if(errorOptions == null) commandOptions['async'] = true; + // Set safe option + commandOptions['safe'] = true; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) + this.db._executeRemoveCommand(deleteCommand, commandOptions, function (err, error) { + error = error && error.documents; + if(!callback) return; + + if(err) { + callback(err); + } else if(error[0].err || error[0].errmsg) { + callback(utils.toError(error[0])); + } else { + callback(null, error[0].n); + } + }); + } else if(_hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + var result = this.db._executeRemoveCommand(deleteCommand); + // If no callback just return + if (!callback) return; + // If error return error + if (result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(); + } +}; + +/** + * Renames the collection. + * + * Options + * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists. + * + * @param {String} newName the new name of the collection. + * @param {Object} [options] returns option results. + * @param {Function} callback the callback accepting the result + * @return {null} + * @api public + */ +Collection.prototype.rename = function rename (newName, options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {} + } + + // Ensure the new name is valid + checkCollectionName(newName); + // Execute the command, return the new renamed collection if successful + self.db._executeQueryCommand(DbCommand.createRenameCollectionCommand(self.db, self.collectionName, newName, options), function(err, result) { + if(err == null && result.documents[0].ok == 1) { + if(callback != null) { + // Set current object to point to the new name + self.collectionName = newName; + // Return the current collection + callback(null, self); + } + } else if(result.documents[0].errmsg != null) { + if(null != callback) { + if (null == err) { + err = utils.toError(result.documents[0]); + } + callback(err, null); + } + } + }); +}; + +/** + * @ignore + */ +var insertAll = function insertAll (self, docs, options, callback) { + if('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // Insert options (flags for insert) + var insertFlags = {}; + // If we have a mongodb version >= 1.9.1 support keepGoing attribute + if(options['keepGoing'] != null) { + insertFlags['keepGoing'] = options['keepGoing']; + } + + // If we have a mongodb version >= 1.9.1 support keepGoing attribute + if(options['continueOnError'] != null) { + insertFlags['continueOnError'] = options['continueOnError']; + } + + // DbName + var dbName = options['dbName']; + // If no dbname defined use the db one + if(dbName == null) { + dbName = self.db.databaseName; + } + + // Either use override on the function, or go back to default on either the collection + // level or db + if(options['serializeFunctions'] != null) { + insertFlags['serializeFunctions'] = options['serializeFunctions']; + } else { + insertFlags['serializeFunctions'] = self.serializeFunctions; + } + + // Pass in options + var insertCommand = new InsertCommand( + self.db + , dbName + "." + self.collectionName, true, insertFlags); + + // Add the documents and decorate them with id's if they have none + for(var index = 0, len = docs.length; index < len; ++index) { + var doc = docs[index]; + + // Add id to each document if it's not already defined + if (!(Buffer.isBuffer(doc)) + && doc['_id'] == null + && self.db.forceServerObjectId != true + && options.forceServerObjectId != true) { + doc['_id'] = self.pkFactory.createPk(); + } + + insertCommand.add(doc); + } + + // Collect errorOptions + var errorOptions = _getWriteConcern(self, options, callback); + // Default command options + var commandOptions = {}; + // If safe is defined check for error message + if(_hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + commandOptions['read'] = false; + // If we have safe set set async to false + if(errorOptions == null) commandOptions['async'] = true; + + // Set safe option + commandOptions['safe'] = errorOptions; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) + self.db._executeInsertCommand(insertCommand, commandOptions, function (err, error) { + error = error && error.documents; + if(!callback) return; + + if (err) { + callback(err); + } else if(error[0].err || error[0].errmsg) { + callback(utils.toError(error[0])); + } else { + callback(null, docs); + } + }); + } else if(_hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + // Execute the call without a write concern + var result = self.db._executeInsertCommand(insertCommand, commandOptions); + // If no callback just return + if(!callback) return; + // If error return error + if(result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(null, docs); + } +}; + +/** + * Save a document. Simple full document replacement function. Not recommended for efficiency, use atomic + * operators and update instead for more efficient operations. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} [doc] the document to save + * @param {Object} [options] additional options during remove. + * @param {Function} [callback] must be provided if you performing a safe save + * @return {null} + * @api public + */ +Collection.prototype.save = function save(doc, options, callback) { + if('function' === typeof options) callback = options, options = null; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + // Throw an error if attempting to perform a bulk operation + if(Array.isArray(doc)) throw new Error("doc parameter must be a single document"); + // Extract the id, if we have one we need to do a update command + var id = doc['_id']; + var commandOptions = _getWriteConcern(this, options, callback); + + if(id) { + commandOptions.upsert = true; + this.update({ _id: id }, doc, commandOptions, callback); + } else { + this.insert(doc, commandOptions, callback && function (err, docs) { + if (err) return callback(err, null); + + if (Array.isArray(docs)) { + callback(err, docs[0]); + } else { + callback(err, docs); + } + }); + } +}; + +/** + * Updates documents. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **upsert** {Boolean, default:false}, perform an upsert operation. + * - **multi** {Boolean, default:false}, update all documents matching the selector. + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} selector the query to select the document/documents to be updated + * @param {Object} document the fields/vals to be updated, or in the case of an upsert operation, inserted. + * @param {Object} [options] additional options during update. + * @param {Function} [callback] must be provided if you performing an update with a writeconcern + * @return {null} + * @api public + */ +Collection.prototype.update = function update(selector, document, options, callback) { + if('function' === typeof options) callback = options, options = null; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // DbName + var dbName = options['dbName']; + // If no dbname defined use the db one + if(dbName == null) { + dbName = this.db.databaseName; + } + + // If we are not providing a selector or document throw + if(selector == null || typeof selector != 'object') return callback(new Error("selector must be a valid JavaScript object")); + if(document == null || typeof document != 'object') return callback(new Error("document must be a valid JavaScript object")); + + // Either use override on the function, or go back to default on either the collection + // level or db + if(options['serializeFunctions'] != null) { + options['serializeFunctions'] = options['serializeFunctions']; + } else { + options['serializeFunctions'] = this.serializeFunctions; + } + + var updateCommand = new UpdateCommand( + this.db + , dbName + "." + this.collectionName + , selector + , document + , options); + + var self = this; + // Unpack the error options if any + var errorOptions = _getWriteConcern(this, options, callback); + // If safe is defined check for error message + if(_hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + var commandOptions = {read:false}; + // If we have safe set set async to false + if(errorOptions == null) commandOptions['async'] = true; + // Set safe option + commandOptions['safe'] = errorOptions; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) + this.db._executeUpdateCommand(updateCommand, commandOptions, function (err, error) { + error = error && error.documents; + if(!callback) return; + + if(err) { + callback(err); + } else if(error[0].err || error[0].errmsg) { + callback(utils.toError(error[0])); + } else { + // Perform the callback + callback(null, error[0].n, error[0]); + } + }); + } else if(_hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + // Execute update + var result = this.db._executeUpdateCommand(updateCommand); + // If no callback just return + if (!callback) return; + // If error return error + if (result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(); + } +}; + +/** + * The distinct command returns returns a list of distinct values for the given key across a collection. + * + * Options + * - **readPreference** {String}, the preferred read preference (Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {String} key key to run distinct against. + * @param {Object} [query] option query to narrow the returned objects. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from distinct or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.distinct = function distinct(key, query, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + query = args.length ? args.shift() || {} : {}; + options = args.length ? args.shift() || {} : {}; + + var mapCommandHash = { + 'distinct': this.collectionName + , 'query': query + , 'key': key + }; + + // Set read preference if we set one + var readPreference = options['readPreference'] ? options['readPreference'] : false; + // Create the command + var cmd = DbCommand.createDbSlaveOkCommand(this.db, mapCommandHash); + + this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) { + if(err) + return callback(err); + if(result.documents[0].ok != 1) + return callback(new Error(result.documents[0].errmsg)); + callback(null, result.documents[0].values); + }); +}; + +/** + * Count number of matching documents in the db to a query. + * + * Options + * - **skip** {Number}, The number of documents to skip for the count. + * - **limit** {Number}, The limit of documents to count. + * - **readPreference** {String}, the preferred read preference (Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Object} [query] query to filter by before performing count. + * @param {Object} [options] additional options during count. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the count method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.count = function count (query, options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + query = args.length ? args.shift() || {} : {}; + options = args.length ? args.shift() || {} : {}; + var skip = options.skip; + var limit = options.limit; + + // Final query + var commandObject = { + 'count': this.collectionName + , 'query': query + , 'fields': null + }; + + // Add limit and skip if defined + if(typeof skip == 'number') commandObject.skip = skip; + if(typeof limit == 'number') commandObject.limit = limit; + + // Set read preference if we set one + options.readPreference = _getReadConcern(this, options); + + // Execute the command + this.db.command(commandObject, options, function(err, result) { + if(err) return callback(err, null); + return callback(null, result.n); + }); +}; + + +/** + * Drop the collection + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the drop method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.drop = function drop(callback) { + this.db.dropCollection(this.collectionName, callback); +}; + +/** + * Find and update a document. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **remove** {Boolean, default:false}, set to true to remove the object before returning. + * - **upsert** {Boolean, default:false}, perform an upsert operation. + * - **new** {Boolean, default:false}, set to true if you want to return the modified object rather than the original. Ignored for remove. + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} query query object to locate the object to modify + * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate + * @param {Object} doc - the fields/vals to be updated + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndModify method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.findAndModify = function findAndModify (query, sort, doc, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + sort = args.length ? args.shift() || [] : []; + doc = args.length ? args.shift() : null; + options = args.length ? args.shift() || {} : {}; + var self = this; + + var queryObject = { + 'findandmodify': this.collectionName + , 'query': query + , 'sort': utils.formattedOrderClause(sort) + }; + + queryObject.new = options.new ? 1 : 0; + queryObject.remove = options.remove ? 1 : 0; + queryObject.upsert = options.upsert ? 1 : 0; + + if (options.fields) { + queryObject.fields = options.fields; + } + + if (doc && !options.remove) { + queryObject.update = doc; + } + + // Either use override on the function, or go back to default on either the collection + // level or db + if(options['serializeFunctions'] != null) { + options['serializeFunctions'] = options['serializeFunctions']; + } else { + options['serializeFunctions'] = this.serializeFunctions; + } + + // Unpack the error options if any + var errorOptions = _getWriteConcern(this, options, callback); + // If we have j, w or something else do the getLast Error path + if(errorOptions != null + && typeof errorOptions == 'object' + && (errorOptions.w != 0 && errorOptions.w != 1 && errorOptions.safe != false)) { + // Commands to send + var commands = []; + // Add the find and modify command + commands.push(DbCommand.createDbCommand(this.db, queryObject, options)); + // If we have safe defined we need to return both call results + var chainedCommands = errorOptions != null ? true : false; + // Add error command if we have one + if(chainedCommands) { + commands.push(DbCommand.createGetLastErrorCommand(errorOptions, this.db)); + } + + // Fire commands and + this.db._executeQueryCommand(commands, {read:false}, function(err, result) { + if(err != null) return callback(err); + result = result && result.documents; + + if(result[0].err != null) { + return callback(utils.toError(result[0]), null); + } + + // Workaround due to 1.8.X returning an error on no matching object + // while 2.0.X does not not, making 2.0.X behaviour standard + if(result[0].errmsg != null && !result[0].errmsg.match(eErrorMessages)) { + return callback(utils.toError(result[0]), null, result[0]); + } + + return callback(null, result[0].value, result[0]); + }); + } else { + // Only run command and rely on getLastError command + var command = DbCommand.createDbCommand(this.db, queryObject, options) + // Execute command + this.db._executeQueryCommand(command, {read:false}, function(err, result) { + if(err != null) return callback(err); + + result = result && result.documents; + + if(result[0].errmsg != null && !result[0].errmsg.match(eErrorMessages)) { + return callback(utils.toError(result[0]), null, result[0]); + } + + // If we have an error return it + if(result[0].lastErrorObject && result[0].lastErrorObject.err != null) { + return callback(utils.toError(result[0].lastErrorObject), null); + } + + return callback(null, result[0].value, result[0]); + }); + } +} + +/** + * Find and remove a document + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} query query object to locate the object to modify + * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndRemove method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.findAndRemove = function(query, sort, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + sort = args.length ? args.shift() || [] : []; + options = args.length ? args.shift() || {} : {}; + // Add the remove option + options['remove'] = true; + // Execute the callback + this.findAndModify(query, sort, null, options, callback); +} + +var testForFields = { + limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1 + , numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1 + , comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1 +}; + +/** + * Creates a cursor for a query that can be used to iterate over results from MongoDB + * + * Various argument possibilities + * - callback? + * - selector, callback?, + * - selector, fields, callback? + * - selector, options, callback? + * - selector, fields, options, callback? + * - selector, fields, skip, limit, callback? + * - selector, fields, skip, limit, timeout, callback? + * + * Options + * - **limit** {Number, default:0}, sets the limit of documents returned in the query. + * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. + * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1} + * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination). + * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1} + * - **explain** {Boolean, default:false}, explain the query instead of returning the data. + * - **snapshot** {Boolean, default:false}, snapshot query. + * - **timeout** {Boolean, default:false}, specify if the cursor can timeout. + * - **tailable** {Boolean, default:false}, specify if the cursor is tailable. + * - **tailableRetryInterval** {Number, default:100}, specify the miliseconds between getMores on tailable cursor. + * - **numberOfRetries** {Number, default:5}, specify the number of times to retry the tailable cursor. + * - **awaitdata** {Boolean, default:false} allow the cursor to wait for data, only applicable for tailable cursor. + * - **exhaust** {Boolean, default:false} have the server send all the documents at once as getMore packets, not recommended. + * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. + * - **returnKey** {Boolean, default:false}, only return the index key. + * - **maxScan** {Number}, Limit the number of items to scan. + * - **min** {Number}, Set index bounds. + * - **max** {Number}, Set index bounds. + * - **showDiskLoc** {Boolean, default:false}, Show disk location of results. + * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler. + * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * - **numberOfRetries** {Number, default:5}, if using awaidata specifies the number of times to retry on timeout. + * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system + * + * @param {Object|ObjectID} query query object to locate the object to modify + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the find method or null if an error occured. + * @return {Cursor} returns a cursor to the query + * @api public + */ +Collection.prototype.find = function find () { + var options + , args = Array.prototype.slice.call(arguments, 0) + , has_callback = typeof args[args.length - 1] === 'function' + , has_weird_callback = typeof args[0] === 'function' + , callback = has_callback ? args.pop() : (has_weird_callback ? args.shift() : null) + , len = args.length + , selector = len >= 1 ? args[0] : {} + , fields = len >= 2 ? args[1] : undefined; + + if(len === 1 && has_weird_callback) { + // backwards compat for callback?, options case + selector = {}; + options = args[0]; + } + + if(len === 2 && !Array.isArray(fields)) { + var fieldKeys = Object.getOwnPropertyNames(fields); + var is_option = false; + + for(var i = 0; i < fieldKeys.length; i++) { + if(testForFields[fieldKeys[i]] != null) { + is_option = true; + break; + } + } + + if(is_option) { + options = fields; + fields = undefined; + } else { + options = {}; + } + } else if(len === 2 && Array.isArray(fields) && !Array.isArray(fields[0])) { + var newFields = {}; + // Rewrite the array + for(var i = 0; i < fields.length; i++) { + newFields[fields[i]] = 1; + } + // Set the fields + fields = newFields; + } + + if(3 === len) { + options = args[2]; + } + + // Ensure selector is not null + selector = selector == null ? {} : selector; + // Validate correctness off the selector + var object = selector; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + // Validate correctness of the field selector + var object = fields; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + // Check special case where we are using an objectId + if(selector instanceof ObjectID || (selector != null && selector._bsontype == 'ObjectID')) { + selector = {_id:selector}; + } + + // If it's a serialized fields field we need to just let it through + // user be warned it better be good + if(options && options.fields && !(Buffer.isBuffer(options.fields))) { + fields = {}; + + if(Array.isArray(options.fields)) { + if(!options.fields.length) { + fields['_id'] = 1; + } else { + for (var i = 0, l = options.fields.length; i < l; i++) { + fields[options.fields[i]] = 1; + } + } + } else { + fields = options.fields; + } + } + + if (!options) options = {}; + options.skip = len > 3 ? args[2] : options.skip ? options.skip : 0; + options.limit = len > 3 ? args[3] : options.limit ? options.limit : 0; + options.raw = options.raw != null && typeof options.raw === 'boolean' ? options.raw : this.raw; + options.hint = options.hint != null ? normalizeHintField(options.hint) : this.internalHint; + options.timeout = len == 5 ? args[4] : typeof options.timeout === 'undefined' ? undefined : options.timeout; + // If we have overridden slaveOk otherwise use the default db setting + options.slaveOk = options.slaveOk != null ? options.slaveOk : this.db.slaveOk; + + // Set option + var o = options; + // Support read/readPreference + if(o["read"] != null) o["readPreference"] = o["read"]; + // Set the read preference + o.read = o["readPreference"] ? o.readPreference : this.readPreference; + // Adjust slave ok if read preference is secondary or secondary only + if(o.read == "secondary" || o.read == "secondaryOnly") options.slaveOk = true; + + // callback for backward compatibility + if(callback) { + // TODO refactor Cursor args + callback(null, new Cursor(this.db, this, selector, fields, o)); + } else { + return new Cursor(this.db, this, selector, fields, o); + } +}; + +/** + * Normalizes a `hint` argument. + * + * @param {String|Object|Array} hint + * @return {Object} + * @api private + */ +var normalizeHintField = function normalizeHintField(hint) { + var finalHint = null; + + if(typeof hint == 'string') { + finalHint = hint; + } else if(Array.isArray(hint)) { + finalHint = {}; + + hint.forEach(function(param) { + finalHint[param] = 1; + }); + } else if(hint != null && typeof hint == 'object') { + finalHint = {}; + for (var name in hint) { + finalHint[name] = hint[name]; + } + } + + return finalHint; +}; + +/** + * Finds a single document based on the query + * + * Various argument possibilities + * - callback? + * - selector, callback?, + * - selector, fields, callback? + * - selector, options, callback? + * - selector, fields, options, callback? + * - selector, fields, skip, limit, callback? + * - selector, fields, skip, limit, timeout, callback? + * + * Options + * - **limit** {Number, default:0}, sets the limit of documents returned in the query. + * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. + * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1} + * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination). + * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1} + * - **explain** {Boolean, default:false}, explain the query instead of returning the data. + * - **snapshot** {Boolean, default:false}, snapshot query. + * - **timeout** {Boolean, default:false}, specify if the cursor can timeout. + * - **tailable** {Boolean, default:false}, specify if the cursor is tailable. + * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. + * - **returnKey** {Boolean, default:false}, only return the index key. + * - **maxScan** {Number}, Limit the number of items to scan. + * - **min** {Number}, Set index bounds. + * - **max** {Number}, Set index bounds. + * - **showDiskLoc** {Boolean, default:false}, Show disk location of results. + * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler. + * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents. + * - **readPreference** {String}, the preferred read preference (Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system + * + * @param {Object|ObjectID} query query object to locate the object to modify + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findOne method or null if an error occured. + * @return {Cursor} returns a cursor to the query + * @api public + */ +Collection.prototype.findOne = function findOne () { + var self = this; + var args = Array.prototype.slice.call(arguments, 0); + var callback = args.pop(); + var cursor = this.find.apply(this, args).limit(-1).batchSize(1); + // Return the item + cursor.nextObject(function(err, item) { + if(err != null) return callback(utils.toError(err), null); + callback(null, item); + }); +}; + +/** + * Creates an index on the collection. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the createIndex method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.createIndex = function createIndex (fieldOrSpec, options, callback) { + // Clean up call + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + options = typeof callback === 'function' ? options : callback; + options = options == null ? {} : options; + + // Collect errorOptions + var errorOptions = _getWriteConcern(this, options, callback); + // Execute create index + this.db.createIndex(this.collectionName, fieldOrSpec, options, callback); +}; + +/** + * Ensures that an index exists, if it does not it creates it + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the ensureIndex method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.ensureIndex = function ensureIndex (fieldOrSpec, options, callback) { + // Clean up call + if (typeof callback === 'undefined' && typeof options === 'function') { + callback = options; + options = {}; + } + + if (options == null) { + options = {}; + } + + // Execute create index + this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback); +}; + +/** + * Retrieves this collections index info. + * + * Options + * - **full** {Boolean, default:false}, returns the full raw index information. + * + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexInformation method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.indexInformation = function indexInformation (options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + // Call the index information + this.db.indexInformation(this.collectionName, options, callback); +}; + +/** + * Drops an index from this collection. + * + * @param {String} name + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndex method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.dropIndex = function dropIndex (name, callback) { + this.db.dropIndex(this.collectionName, name, callback); +}; + +/** + * Drops all indexes from this collection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropAllIndexes method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.dropAllIndexes = function dropIndexes (callback) { + this.db.dropIndex(this.collectionName, '*', function (err, result) { + if(err != null) { + callback(err, false); + } else if(result.documents[0].errmsg == null) { + callback(null, true); + } else { + callback(new Error(result.documents[0].errmsg), false); + } + }); +}; + +/** + * Drops all indexes from this collection. + * + * @deprecated + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndexes method or null if an error occured. + * @return {null} + * @api private + */ +Collection.prototype.dropIndexes = Collection.prototype.dropAllIndexes; + +/** + * Reindex all indexes on the collection + * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the reIndex method or null if an error occured. + * @return {null} + * @api public +**/ +Collection.prototype.reIndex = function(callback) { + this.db.reIndex(this.collectionName, callback); +} + +/** + * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection. + * + * Options + * - **out** {Object}, sets the output target for the map reduce job. *{inline:1} | {replace:'collectionName'} | {merge:'collectionName'} | {reduce:'collectionName'}* + * - **query** {Object}, query filter object. + * - **sort** {Object}, sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces. + * - **limit** {Number}, number of objects to return from collection. + * - **keeptemp** {Boolean, default:false}, keep temporary data. + * - **finalize** {Function | String}, finalize function. + * - **scope** {Object}, can pass in variables that can be access from map/reduce/finalize. + * - **jsMode** {Boolean, default:false}, it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X. + * - **verbose** {Boolean, default:false}, provide statistics on job execution time. + * - **readPreference** {String, only for inline results}, the preferred read preference (Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Function|String} map the mapping function. + * @param {Function|String} reduce the reduce function. + * @param {Objects} [options] options for the map reduce job. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the mapReduce method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.mapReduce = function mapReduce (map, reduce, options, callback) { + if ('function' === typeof options) callback = options, options = {}; + // Out must allways be defined (make sure we don't break weirdly on pre 1.8+ servers) + if(null == options.out) { + throw new Error("the out option parameter must be defined, see mongodb docs for possible values"); + } + + if ('function' === typeof map) { + map = map.toString(); + } + + if ('function' === typeof reduce) { + reduce = reduce.toString(); + } + + if ('function' === typeof options.finalize) { + options.finalize = options.finalize.toString(); + } + + var mapCommandHash = { + mapreduce: this.collectionName + , map: map + , reduce: reduce + }; + + // Add any other options passed in + for (var name in options) { + if ('scope' == name) { + mapCommandHash[name] = processScope(options[name]); + } else { + mapCommandHash[name] = options[name]; + } + } + + // Set read preference if we set one + var readPreference = _getReadConcern(this, options); + + // If we have a read preference and inline is not set as output fail hard + if((readPreference != false && readPreference != 'primary') + && options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) { + throw new Error("a readPreference can only be provided when performing an inline mapReduce"); + } + + // self + var self = this; + var cmd = DbCommand.createDbCommand(this.db, mapCommandHash); + + this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) { + if (err) { + return callback(err); + } + + // + if (1 != result.documents[0].ok || result.documents[0].err || result.documents[0].errmsg) { + return callback(utils.toError(result.documents[0])); + } + + // Create statistics value + var stats = {}; + if(result.documents[0].timeMillis) stats['processtime'] = result.documents[0].timeMillis; + if(result.documents[0].counts) stats['counts'] = result.documents[0].counts; + if(result.documents[0].timing) stats['timing'] = result.documents[0].timing; + + // invoked with inline? + if(result.documents[0].results) { + return callback(null, result.documents[0].results, stats); + } + + // The returned collection + var collection = null; + + // If we have an object it's a different db + if(result.documents[0].result != null && typeof result.documents[0].result == 'object') { + var doc = result.documents[0].result; + collection = self.db.db(doc.db).collection(doc.collection); + } else { + // Create a collection object that wraps the result collection + collection = self.db.collection(result.documents[0].result) + } + + // If we wish for no verbosity + if(options['verbose'] == null || !options['verbose']) { + return callback(err, collection); + } + + // Return stats as third set of values + callback(err, collection, stats); + }); +}; + +/** + * Functions that are passed as scope args must + * be converted to Code instances. + * @ignore + */ +function processScope (scope) { + if (!utils.isObject(scope)) { + return scope; + } + + var keys = Object.keys(scope); + var i = keys.length; + var key; + + while (i--) { + key = keys[i]; + if ('function' == typeof scope[key]) { + scope[key] = new Code(String(scope[key])); + } + } + + return scope; +} + +/** + * Group function helper + * @ignore + */ +var groupFunction = function () { + var c = db[ns].find(condition); + var map = new Map(); + var reduce_function = reduce; + + while (c.hasNext()) { + var obj = c.next(); + var key = {}; + + for (var i = 0, len = keys.length; i < len; ++i) { + var k = keys[i]; + key[k] = obj[k]; + } + + var aggObj = map.get(key); + + if (aggObj == null) { + var newObj = Object.extend({}, key); + aggObj = Object.extend(newObj, initial); + map.put(key, aggObj); + } + + reduce_function(obj, aggObj); + } + + return { "result": map.values() }; +}.toString(); + +/** + * Run a group command across a collection + * + * Options + * - **readPreference** {String}, the preferred read preference (Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Object|Array|Function|Code} keys an object, array or function expressing the keys to group by. + * @param {Object} condition an optional condition that must be true for a row to be considered. + * @param {Object} initial initial value of the aggregation counter object. + * @param {Function|Code} reduce the reduce function aggregates (reduces) the objects iterated + * @param {Function|Code} finalize an optional function to be run on each item in the result set just before the item is returned. + * @param {Boolean} command specify if you wish to run using the internal group command or using eval, default is true. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the group method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.group = function group(keys, condition, initial, reduce, finalize, command, options, callback) { + var args = Array.prototype.slice.call(arguments, 3); + callback = args.pop(); + // Fetch all commands + reduce = args.length ? args.shift() : null; + finalize = args.length ? args.shift() : null; + command = args.length ? args.shift() : null; + options = args.length ? args.shift() || {} : {}; + + // Make sure we are backward compatible + if(!(typeof finalize == 'function')) { + command = finalize; + finalize = null; + } + + if (!Array.isArray(keys) && keys instanceof Object && typeof(keys) !== 'function' && !(keys instanceof Code)) { + keys = Object.keys(keys); + } + + if(typeof reduce === 'function') { + reduce = reduce.toString(); + } + + if(typeof finalize === 'function') { + finalize = finalize.toString(); + } + + // Set up the command as default + command = command == null ? true : command; + + // Execute using the command + if(command) { + var reduceFunction = reduce instanceof Code + ? reduce + : new Code(reduce); + + var selector = { + group: { + 'ns': this.collectionName + , '$reduce': reduceFunction + , 'cond': condition + , 'initial': initial + , 'out': "inline" + } + }; + + // if finalize is defined + if(finalize != null) selector.group['finalize'] = finalize; + // Set up group selector + if ('function' === typeof keys || keys instanceof Code) { + selector.group.$keyf = keys instanceof Code + ? keys + : new Code(keys); + } else { + var hash = {}; + keys.forEach(function (key) { + hash[key] = 1; + }); + selector.group.key = hash; + } + + var cmd = DbCommand.createDbSlaveOkCommand(this.db, selector); + // Set read preference if we set one + var readPreference = _getReadConcern(this, options); + + this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) { + if(err != null) return callback(err); + + var document = result.documents[0]; + if (null == document.retval) { + return callback(new Error("group command failed: " + document.errmsg)); + } + + callback(null, document.retval); + }); + + } else { + // Create execution scope + var scope = reduce != null && reduce instanceof Code + ? reduce.scope + : {}; + + scope.ns = this.collectionName; + scope.keys = keys; + scope.condition = condition; + scope.initial = initial; + + // Pass in the function text to execute within mongodb. + var groupfn = groupFunction.replace(/ reduce;/, reduce.toString() + ';'); + + this.db.eval(new Code(groupfn, scope), function (err, results) { + if (err) return callback(err, null); + callback(null, results.result || results); + }); + } +}; + +/** + * Returns the options of the collection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the options method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.options = function options(callback) { + this.db.collectionsInfo(this.collectionName, function (err, cursor) { + if (err) return callback(err); + cursor.nextObject(function (err, document) { + callback(err, document && document.options || null); + }); + }); +}; + +/** + * Returns if the collection is a capped collection + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the isCapped method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.isCapped = function isCapped(callback) { + this.options(function(err, document) { + if(err != null) { + callback(err); + } else { + callback(null, document && document.capped); + } + }); +}; + +/** + * Checks if one or more indexes exist on the collection + * + * @param {String|Array} indexNames check if one or more indexes exist on the collection. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexExists method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.indexExists = function indexExists(indexes, callback) { + this.indexInformation(function(err, indexInformation) { + // If we have an error return + if(err != null) return callback(err, null); + // Let's check for the index names + if(Array.isArray(indexes)) { + for(var i = 0; i < indexes.length; i++) { + if(indexInformation[indexes[i]] == null) { + return callback(null, false); + } + } + + // All keys found return true + return callback(null, true); + } else { + return callback(null, indexInformation[indexes] != null); + } + }); +} + +/** + * Execute the geoNear command to search for items in the collection + * + * Options + * - **num** {Number}, max number of results to return. + * - **maxDistance** {Number}, include results up to maxDistance from the point. + * - **distanceMultiplier** {Number}, include a value to multiply the distances with allowing for range conversions. + * - **query** {Object}, filter the results by a query. + * - **spherical** {Boolean, default:false}, perform query using a spherical model. + * - **uniqueDocs** {Boolean, default:false}, the closest location in a document to the center of the search region will always be returned MongoDB > 2.X. + * - **includeLocs** {Boolean, default:false}, include the location data fields in the top level of the results MongoDB > 2.X. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. + * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. + * @param {Objects} [options] options for the map reduce job. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.geoNear = function geoNear(x, y, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + geoNear:this.collectionName, + near: [x, y] + } + + // Decorate object if any with known properties + if(options['num'] != null) commandObject['num'] = options['num']; + if(options['maxDistance'] != null) commandObject['maxDistance'] = options['maxDistance']; + if(options['distanceMultiplier'] != null) commandObject['distanceMultiplier'] = options['distanceMultiplier']; + if(options['query'] != null) commandObject['query'] = options['query']; + if(options['spherical'] != null) commandObject['spherical'] = options['spherical']; + if(options['uniqueDocs'] != null) commandObject['uniqueDocs'] = options['uniqueDocs']; + if(options['includeLocs'] != null) commandObject['includeLocs'] = options['includeLocs']; + + // Ensure we have the right read preference inheritance + options.readPreference = _getReadConcern(this, options); + + // Execute the command + this.db.command(commandObject, options, function (err, res) { + if (err) { + callback(err); + } else if (res.err || res.errmsg) { + callback(utils.toError(res)); + } else { + // should we only be returning res.results here? Not sure if the user + // should see the other return information + callback(null, res); + } + }); +} + +/** + * Execute a geo search using a geo haystack index on a collection. + * + * Options + * - **maxDistance** {Number}, include results up to maxDistance from the point. + * - **search** {Object}, filter the results by a query. + * - **limit** {Number}, max number of results to return. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. + * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. + * @param {Objects} [options] options for the map reduce job. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoHaystackSearch method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.geoHaystackSearch = function geoHaystackSearch(x, y, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + geoSearch:this.collectionName, + near: [x, y] + } + + // Decorate object if any with known properties + if(options['maxDistance'] != null) commandObject['maxDistance'] = options['maxDistance']; + if(options['query'] != null) commandObject['search'] = options['query']; + if(options['search'] != null) commandObject['search'] = options['search']; + if(options['limit'] != null) commandObject['limit'] = options['limit']; + + // Ensure we have the right read preference inheritance + options.readPreference = _getReadConcern(this, options); + + // Execute the command + this.db.command(commandObject, options, function (err, res) { + if (err) { + callback(err); + } else if (res.err || res.errmsg) { + callback(utils.toError(res)); + } else { + // should we only be returning res.results here? Not sure if the user + // should see the other return information + callback(null, res); + } + }); +} + +/** + * Retrieve all the indexes on the collection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexes method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.indexes = function indexes(callback) { + // Return all the index information + this.db.indexInformation(this.collectionName, {full:true}, callback); +} + +/** + * Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.1 + * + * Options + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Array} array containing all the aggregation framework commands for the execution. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the aggregate method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.aggregate = function(pipeline, options, callback) { + // * - **explain** {Boolean}, return the query plan for the aggregation pipeline instead of the results. 2.3, 2.4 + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + var self = this; + + // If we have any of the supported options in the options object + var opts = args[args.length - 1]; + options = opts.readPreference || opts.explain ? args.pop() : {} + + // Convert operations to an array + if(!Array.isArray(args[0])) { + pipeline = []; + // Push all the operations to the pipeline + for(var i = 0; i < args.length; i++) pipeline.push(args[i]); + } + + // Build the command + var command = { aggregate : this.collectionName, pipeline : pipeline}; + + // Ensure we have the right read preference inheritance + options.readPreference = _getReadConcern(this, options); + + // Execute the command + this.db.command(command, options, function(err, result) { + if(err) { + callback(err); + } else if(result['err'] || result['errmsg']) { + callback(utils.toError(result)); + } else if(typeof result == 'object' && result['serverPipeline']) { + callback(null, result); + } else { + callback(null, result.result); + } + }); +} + +/** + * Get all the collection statistics. + * + * Options + * - **scale** {Number}, divide the returned sizes by scale value. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Objects} [options] options for the stats command. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the stats method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.stats = function stats(options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + collStats:this.collectionName, + } + + // Check if we have the scale value + if(options['scale'] != null) commandObject['scale'] = options['scale']; + + // Ensure we have the right read preference inheritance + options.readPreference = _getReadConcern(this, options); + + // Execute the command + this.db.command(commandObject, options, callback); +} + +/** + * @ignore + */ +Object.defineProperty(Collection.prototype, "hint", { + enumerable: true + , get: function () { + return this.internalHint; + } + , set: function (v) { + this.internalHint = normalizeHintField(v); + } +}); + +var _getReadConcern = function(self, options) { + if(options.readPreference) return options.readPreference; + if(self.readPreference) return self.readPreference; + if(self.db.readPreference) return self.readPreference; + return 'primary'; +} + +/** + * @ignore + */ +var _hasWriteConcern = function(errorOptions) { + return errorOptions == true + || errorOptions.w > 0 + || errorOptions.w == 'majority' + || errorOptions.j == true + || errorOptions.journal == true + || errorOptions.fsync == true +} + +/** + * @ignore + */ +var _setWriteConcernHash = function(options) { + var finalOptions = {}; + if(options.w != null) finalOptions.w = options.w; + if(options.journal == true) finalOptions.j = options.journal; + if(options.j == true) finalOptions.j = options.j; + if(options.fsync == true) finalOptions.fsync = options.fsync; + if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; + return finalOptions; +} + +/** + * @ignore + */ +var _getWriteConcern = function(self, options, callback) { + // Final options + var finalOptions = {w:1}; + // Local options verification + if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(options); + } else if(typeof options.safe == "boolean") { + finalOptions = {w: (options.safe ? 1 : 0)}; + } else if(options.safe != null && typeof options.safe == 'object') { + finalOptions = _setWriteConcernHash(options.safe); + } else if(self.opts.w != null || typeof self.opts.j == 'boolean' || typeof self.opts.journal == 'boolean' || typeof self.opts.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.opts); + } else if(typeof self.opts.safe == "boolean") { + finalOptions = {w: (self.opts.safe ? 1 : 0)}; + } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.db.safe); + } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.db.options); + } else if(typeof self.db.safe == "boolean") { + finalOptions = {w: (self.db.safe ? 1 : 0)}; + } + + // Ensure we don't have an invalid combination of write concerns + if(finalOptions.w < 1 + && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true"); + + // Return the options + return finalOptions; +} + +/** + * Expose. + */ +exports.Collection = Collection; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js new file mode 100644 index 0000000..9558582 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js @@ -0,0 +1,29 @@ +/** + Base object used for common functionality +**/ +var BaseCommand = exports.BaseCommand = function BaseCommand() { +}; + +var id = 1; +BaseCommand.prototype.getRequestId = function getRequestId() { + if (!this.requestId) this.requestId = id++; + return this.requestId; +}; + +BaseCommand.prototype.setMongosReadPreference = function setMongosReadPreference(readPreference, tags) {} + +BaseCommand.prototype.updateRequestId = function() { + this.requestId = id++; + return this.requestId; +}; + +// OpCodes +BaseCommand.OP_REPLY = 1; +BaseCommand.OP_MSG = 1000; +BaseCommand.OP_UPDATE = 2001; +BaseCommand.OP_INSERT = 2002; +BaseCommand.OP_GET_BY_OID = 2003; +BaseCommand.OP_QUERY = 2004; +BaseCommand.OP_GET_MORE = 2005; +BaseCommand.OP_DELETE = 2006; +BaseCommand.OP_KILL_CURSORS = 2007; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js new file mode 100644 index 0000000..b7019c8 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js @@ -0,0 +1,245 @@ +var QueryCommand = require('./query_command').QueryCommand, + InsertCommand = require('./insert_command').InsertCommand, + inherits = require('util').inherits, + utils = require('../utils'), + crypto = require('crypto'); + +/** + Db Command +**/ +var DbCommand = exports.DbCommand = function(dbInstance, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) { + QueryCommand.call(this); + this.collectionName = collectionName; + this.queryOptions = queryOptions; + this.numberToSkip = numberToSkip; + this.numberToReturn = numberToReturn; + this.query = query; + this.returnFieldSelector = returnFieldSelector; + this.db = dbInstance; + + if(this.db && this.db.slaveOk) { + this.queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Make sure we don't get a null exception + options = options == null ? {} : options; + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(DbCommand, QueryCommand); + +// Constants +DbCommand.SYSTEM_NAMESPACE_COLLECTION = "system.namespaces"; +DbCommand.SYSTEM_INDEX_COLLECTION = "system.indexes"; +DbCommand.SYSTEM_PROFILE_COLLECTION = "system.profile"; +DbCommand.SYSTEM_USER_COLLECTION = "system.users"; +DbCommand.SYSTEM_COMMAND_COLLECTION = "$cmd"; +DbCommand.SYSTEM_JS_COLLECTION = "system.js"; + +// New commands +DbCommand.NcreateIsMasterCommand = function(db, databaseName) { + return new DbCommand(db, databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null); +}; + +// Provide constructors for different db commands +DbCommand.createIsMasterCommand = function(db) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null); +}; + +DbCommand.createCollectionInfoCommand = function(db, selector) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_NAMESPACE_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, 0, selector, null); +}; + +DbCommand.createGetNonceCommand = function(db, options) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getnonce':1}, null); +}; + +DbCommand.createAuthenticationCommand = function(db, username, password, nonce, authdb) { + // Use node md5 generator + var md5 = crypto.createHash('md5'); + // Generate keys used for authentication + md5.update(username + ":mongo:" + password); + var hash_password = md5.digest('hex'); + // Final key + md5 = crypto.createHash('md5'); + md5.update(nonce + username + hash_password); + var key = md5.digest('hex'); + // Creat selector + var selector = {'authenticate':1, 'user':username, 'nonce':nonce, 'key':key}; + // Create db command + return new DbCommand(db, authdb + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NONE, 0, -1, selector, null); +}; + +DbCommand.createLogoutCommand = function(db) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'logout':1}, null); +}; + +DbCommand.createCreateCollectionCommand = function(db, collectionName, options) { + var selector = {'create':collectionName}; + // Modify the options to ensure correct behaviour + for(var name in options) { + if(options[name] != null && options[name].constructor != Function) selector[name] = options[name]; + } + // Execute the command + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, selector, null); +}; + +DbCommand.createDropCollectionCommand = function(db, collectionName) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'drop':collectionName}, null); +}; + +DbCommand.createRenameCollectionCommand = function(db, fromCollectionName, toCollectionName, options) { + var renameCollection = db.databaseName + "." + fromCollectionName; + var toCollection = db.databaseName + "." + toCollectionName; + var dropTarget = options && options.dropTarget ? options.dropTarget : false; + return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget}, null); +}; + +DbCommand.createGetLastErrorCommand = function(options, db) { + + if (typeof db === 'undefined') { + db = options; + options = {}; + } + // Final command + var command = {'getlasterror':1}; + // If we have an options Object let's merge in the fields (fsync/wtimeout/w) + if('object' === typeof options) { + for(var name in options) { + command[name] = options[name] + } + } + + // Special case for w == 1, remove the w + if(1 == command.w) { + delete command.w; + } + + // Execute command + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null); +}; + +DbCommand.createGetLastStatusCommand = DbCommand.createGetLastErrorCommand; + +DbCommand.createGetPreviousErrorsCommand = function(db) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getpreverror':1}, null); +}; + +DbCommand.createResetErrorHistoryCommand = function(db) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reseterror':1}, null); +}; + +DbCommand.createCreateIndexCommand = function(db, collectionName, fieldOrSpec, options) { + var fieldHash = {}; + var indexes = []; + var keys; + + // Get all the fields accordingly + if('string' == typeof fieldOrSpec) { + // 'type' + indexes.push(fieldOrSpec + '_' + 1); + fieldHash[fieldOrSpec] = 1; + + } else if(utils.isArray(fieldOrSpec)) { + + fieldOrSpec.forEach(function(f) { + if('string' == typeof f) { + // [{location:'2d'}, 'type'] + indexes.push(f + '_' + 1); + fieldHash[f] = 1; + } else if(utils.isArray(f)) { + // [['location', '2d'],['type', 1]] + indexes.push(f[0] + '_' + (f[1] || 1)); + fieldHash[f[0]] = f[1] || 1; + } else if(utils.isObject(f)) { + // [{location:'2d'}, {type:1}] + keys = Object.keys(f); + keys.forEach(function(k) { + indexes.push(k + '_' + f[k]); + fieldHash[k] = f[k]; + }); + } else { + // undefined (ignore) + } + }); + + } else if(utils.isObject(fieldOrSpec)) { + // {location:'2d', type:1} + keys = Object.keys(fieldOrSpec); + keys.forEach(function(key) { + indexes.push(key + '_' + fieldOrSpec[key]); + fieldHash[key] = fieldOrSpec[key]; + }); + } + + // Generate the index name + var indexName = typeof options.name == 'string' + ? options.name + : indexes.join("_"); + + var selector = { + 'ns': db.databaseName + "." + collectionName, + 'key': fieldHash, + 'name': indexName + } + + // Ensure we have a correct finalUnique + var finalUnique = options == null || 'object' === typeof options + ? false + : options; + + // Set up options + options = options == null || typeof options == 'boolean' + ? {} + : options; + + // Add all the options + var keys = Object.keys(options); + for(var i = 0; i < keys.length; i++) { + selector[keys[i]] = options[keys[i]]; + } + + if(selector['unique'] == null) + selector['unique'] = finalUnique; + + var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION; + var cmd = new InsertCommand(db, name, false); + return cmd.add(selector); +}; + +DbCommand.logoutCommand = function(db, command_hash, options) { + var dbName = options != null && options['authdb'] != null ? options['authdb'] : db.databaseName; + return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null); +} + +DbCommand.createDropIndexCommand = function(db, collectionName, indexName) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'deleteIndexes':collectionName, 'index':indexName}, null); +}; + +DbCommand.createReIndexCommand = function(db, collectionName) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reIndex':collectionName}, null); +}; + +DbCommand.createDropDatabaseCommand = function(db) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'dropDatabase':1}, null); +}; + +DbCommand.createDbCommand = function(db, command_hash, options, auth_db) { + var db_name = (auth_db ? auth_db : db.databaseName) + "." + DbCommand.SYSTEM_COMMAND_COLLECTION; + return new DbCommand(db, db_name, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null, options); +}; + +DbCommand.createAdminDbCommand = function(db, command_hash) { + return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null); +}; + +DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) { + return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null); +}; + +DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null, options); +}; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js new file mode 100644 index 0000000..e6ae20a --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js @@ -0,0 +1,114 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Insert Document Command +**/ +var DeleteCommand = exports.DeleteCommand = function(db, collectionName, selector, flags) { + BaseCommand.call(this); + + // Validate correctness off the selector + var object = selector; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("delete raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + this.flags = flags; + this.collectionName = collectionName; + this.selector = selector; + this.db = db; +}; + +inherits(DeleteCommand, BaseCommand); + +DeleteCommand.OP_DELETE = 2006; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + cstring fullCollectionName; // "dbname.collectionname" + int32 ZERO; // 0 - reserved for future use + mongo.BSON selector; // query object. See below for details. +} +*/ +DeleteCommand.prototype.toBinary = function() { + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.selector, false, true) + (4 * 4); + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (DeleteCommand.OP_DELETE >> 24) & 0xff; + _command[_index + 2] = (DeleteCommand.OP_DELETE >> 16) & 0xff; + _command[_index + 1] = (DeleteCommand.OP_DELETE >> 8) & 0xff; + _command[_index] = DeleteCommand.OP_DELETE & 0xff; + // Adjust index + _index = _index + 4; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write the flags + _command[_index + 3] = (this.flags >> 24) & 0xff; + _command[_index + 2] = (this.flags >> 16) & 0xff; + _command[_index + 1] = (this.flags >> 8) & 0xff; + _command[_index] = this.flags & 0xff; + // Adjust index + _index = _index + 4; + + // Document binary length + var documentLength = 0 + + // Serialize the selector + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(this.selector)) { + documentLength = this.selector.length; + // Copy the data into the current buffer + this.selector.copy(_command, _index); + } else { + documentLength = this.db.bson.serializeWithBufferAndIndex(this.selector, this.checkKeys, _command, _index) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + return _command; +}; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js new file mode 100644 index 0000000..d3aac02 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js @@ -0,0 +1,83 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits, + binaryutils = require('../utils'); + +/** + Get More Document Command +**/ +var GetMoreCommand = exports.GetMoreCommand = function(db, collectionName, numberToReturn, cursorId) { + BaseCommand.call(this); + + this.collectionName = collectionName; + this.numberToReturn = numberToReturn; + this.cursorId = cursorId; + this.db = db; +}; + +inherits(GetMoreCommand, BaseCommand); + +GetMoreCommand.OP_GET_MORE = 2005; + +GetMoreCommand.prototype.toBinary = function() { + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 8 + (4 * 4); + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index++] = totalLengthOfCommand & 0xff; + _command[_index++] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index++] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index++] = (totalLengthOfCommand >> 24) & 0xff; + + // Write the request ID + _command[_index++] = this.requestId & 0xff; + _command[_index++] = (this.requestId >> 8) & 0xff; + _command[_index++] = (this.requestId >> 16) & 0xff; + _command[_index++] = (this.requestId >> 24) & 0xff; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the op_code for the command + _command[_index++] = GetMoreCommand.OP_GET_MORE & 0xff; + _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 8) & 0xff; + _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 16) & 0xff; + _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 24) & 0xff; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Number of documents to return + _command[_index++] = this.numberToReturn & 0xff; + _command[_index++] = (this.numberToReturn >> 8) & 0xff; + _command[_index++] = (this.numberToReturn >> 16) & 0xff; + _command[_index++] = (this.numberToReturn >> 24) & 0xff; + + // Encode the cursor id + var low_bits = this.cursorId.getLowBits(); + // Encode low bits + _command[_index++] = low_bits & 0xff; + _command[_index++] = (low_bits >> 8) & 0xff; + _command[_index++] = (low_bits >> 16) & 0xff; + _command[_index++] = (low_bits >> 24) & 0xff; + + var high_bits = this.cursorId.getHighBits(); + // Encode high bits + _command[_index++] = high_bits & 0xff; + _command[_index++] = (high_bits >> 8) & 0xff; + _command[_index++] = (high_bits >> 16) & 0xff; + _command[_index++] = (high_bits >> 24) & 0xff; + // Return command + return _command; +}; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js new file mode 100644 index 0000000..d6a2100 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js @@ -0,0 +1,147 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Insert Document Command +**/ +var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKeys, options) { + BaseCommand.call(this); + + this.collectionName = collectionName; + this.documents = []; + this.checkKeys = checkKeys == null ? true : checkKeys; + this.db = db; + this.flags = 0; + this.serializeFunctions = false; + + // Ensure valid options hash + options = options == null ? {} : options; + + // Check if we have keepGoing set -> set flag if it's the case + if(options['keepGoing'] != null && options['keepGoing']) { + // This will finish inserting all non-index violating documents even if it returns an error + this.flags = 1; + } + + // Check if we have keepGoing set -> set flag if it's the case + if(options['continueOnError'] != null && options['continueOnError']) { + // This will finish inserting all non-index violating documents even if it returns an error + this.flags = 1; + } + + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(InsertCommand, BaseCommand); + +// OpCodes +InsertCommand.OP_INSERT = 2002; + +InsertCommand.prototype.add = function(document) { + if(Buffer.isBuffer(document)) { + var object_size = document[0] | document[1] << 8 | document[2] << 16 | document[3] << 24; + if(object_size != document.length) { + var error = new Error("insert raw message size does not match message header size [" + document.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + this.documents.push(document); + return this; +}; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + cstring fullCollectionName; // "dbname.collectionname" + BSON[] documents; // one or more documents to insert into the collection +} +*/ +InsertCommand.prototype.toBinary = function() { + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4); + // var docLength = 0 + for(var i = 0; i < this.documents.length; i++) { + if(Buffer.isBuffer(this.documents[i])) { + totalLengthOfCommand += this.documents[i].length; + } else { + // Calculate size of document + totalLengthOfCommand += this.db.bson.calculateObjectSize(this.documents[i], this.serializeFunctions, true); + } + } + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (InsertCommand.OP_INSERT >> 24) & 0xff; + _command[_index + 2] = (InsertCommand.OP_INSERT >> 16) & 0xff; + _command[_index + 1] = (InsertCommand.OP_INSERT >> 8) & 0xff; + _command[_index] = InsertCommand.OP_INSERT & 0xff; + // Adjust index + _index = _index + 4; + // Write flags if any + _command[_index + 3] = (this.flags >> 24) & 0xff; + _command[_index + 2] = (this.flags >> 16) & 0xff; + _command[_index + 1] = (this.flags >> 8) & 0xff; + _command[_index] = this.flags & 0xff; + // Adjust index + _index = _index + 4; + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write all the bson documents to the buffer at the index offset + for(var i = 0; i < this.documents.length; i++) { + // Document binary length + var documentLength = 0 + var object = this.documents[i]; + + // Serialize the selector + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(object)) { + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + // Serialize the document straight to the buffer + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + } + + return _command; +}; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js new file mode 100644 index 0000000..d8ccb0c --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js @@ -0,0 +1,98 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits, + binaryutils = require('../utils'); + +/** + Insert Document Command +**/ +var KillCursorCommand = exports.KillCursorCommand = function(db, cursorIds) { + BaseCommand.call(this); + + this.cursorIds = cursorIds; + this.db = db; +}; + +inherits(KillCursorCommand, BaseCommand); + +KillCursorCommand.OP_KILL_CURSORS = 2007; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + int32 numberOfCursorIDs; // number of cursorIDs in message + int64[] cursorIDs; // array of cursorIDs to close +} +*/ +KillCursorCommand.prototype.toBinary = function() { + // Calculate total length of the document + var totalLengthOfCommand = 4 + 4 + (4 * 4) + (this.cursorIds.length * 8); + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (KillCursorCommand.OP_KILL_CURSORS >> 24) & 0xff; + _command[_index + 2] = (KillCursorCommand.OP_KILL_CURSORS >> 16) & 0xff; + _command[_index + 1] = (KillCursorCommand.OP_KILL_CURSORS >> 8) & 0xff; + _command[_index] = KillCursorCommand.OP_KILL_CURSORS & 0xff; + // Adjust index + _index = _index + 4; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Number of cursors to kill + var numberOfCursors = this.cursorIds.length; + _command[_index + 3] = (numberOfCursors >> 24) & 0xff; + _command[_index + 2] = (numberOfCursors >> 16) & 0xff; + _command[_index + 1] = (numberOfCursors >> 8) & 0xff; + _command[_index] = numberOfCursors & 0xff; + // Adjust index + _index = _index + 4; + + // Encode all the cursors + for(var i = 0; i < this.cursorIds.length; i++) { + // Encode the cursor id + var low_bits = this.cursorIds[i].getLowBits(); + // Encode low bits + _command[_index + 3] = (low_bits >> 24) & 0xff; + _command[_index + 2] = (low_bits >> 16) & 0xff; + _command[_index + 1] = (low_bits >> 8) & 0xff; + _command[_index] = low_bits & 0xff; + // Adjust index + _index = _index + 4; + + var high_bits = this.cursorIds[i].getHighBits(); + // Encode high bits + _command[_index + 3] = (high_bits >> 24) & 0xff; + _command[_index + 2] = (high_bits >> 16) & 0xff; + _command[_index + 1] = (high_bits >> 8) & 0xff; + _command[_index] = high_bits & 0xff; + // Adjust index + _index = _index + 4; + } + + return _command; +}; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js new file mode 100644 index 0000000..c1d2e5c --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js @@ -0,0 +1,266 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Insert Document Command +**/ +var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) { + BaseCommand.call(this); + + // Validate correctness off the selector + var object = query, + object_size; + if(Buffer.isBuffer(object)) { + object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + object = returnFieldSelector; + if(Buffer.isBuffer(object)) { + object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + // Make sure we don't get a null exception + options = options == null ? {} : options; + // Set up options + this.collectionName = collectionName; + this.queryOptions = queryOptions; + this.numberToSkip = numberToSkip; + this.numberToReturn = numberToReturn; + + // Ensure we have no null query + query = query == null ? {} : query; + // Wrap query in the $query parameter so we can add read preferences for mongos + this.query = query; + this.returnFieldSelector = returnFieldSelector; + this.db = db; + + // Force the slave ok flag to be set if we are not using primary read preference + if(this.db && this.db.slaveOk) { + this.queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(QueryCommand, BaseCommand); + +QueryCommand.OP_QUERY = 2004; + +/* + * Adds the read prefrence to the current command + */ +QueryCommand.prototype.setMongosReadPreference = function(readPreference, tags) { + // If we have readPreference set to true set to secondary prefered + if(readPreference == true) { + readPreference = 'secondaryPreferred'; + } else if(readPreference == 'false') { + readPreference = 'primary'; + } + + // Force the slave ok flag to be set if we are not using primary read preference + if(readPreference != false && readPreference != 'primary') { + this.queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Backward compatibility, ensure $query only set on read preference so 1.8.X works + if((readPreference != null || tags != null) && this.query['$query'] == null) { + this.query = {'$query': this.query}; + } + + // If we have no readPreference set and no tags, check if the slaveOk bit is set + if(readPreference == null && tags == null) { + // If we have a slaveOk bit set the read preference for MongoS + if(this.queryOptions & QueryCommand.OPTS_SLAVE) { + this.query['$readPreference'] = {mode: 'secondary'} + } else { + this.query['$readPreference'] = {mode: 'primary'} + } + } + + // Build read preference object + if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') { + this.query['$readPreference'] = readPreference.toObject(); + } else if(readPreference != null) { + // Add the read preference + this.query['$readPreference'] = {mode: readPreference}; + + // If we have tags let's add them + if(tags != null) { + this.query['$readPreference']['tags'] = tags; + } + } +} + +/* +struct { + MsgHeader header; // standard message header + int32 opts; // query options. See below for details. + cstring fullCollectionName; // "dbname.collectionname" + int32 numberToSkip; // number of documents to skip when returning results + int32 numberToReturn; // number of documents to return in the first OP_REPLY + BSON query ; // query object. See below for details. + [ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details. +} +*/ +QueryCommand.prototype.toBinary = function() { + // Total length of the command + var totalLengthOfCommand = 0; + // Calculate total length of the document + if(Buffer.isBuffer(this.query)) { + totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.query.length + (4 * 4); + } else { + totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson.calculateObjectSize(this.query, this.serializeFunctions, true) + (4 * 4); + } + + // Calculate extra fields size + if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) { + if(Object.keys(this.returnFieldSelector).length > 0) { + totalLengthOfCommand += this.db.bson.calculateObjectSize(this.returnFieldSelector, this.serializeFunctions, true); + } + } else if(Buffer.isBuffer(this.returnFieldSelector)) { + totalLengthOfCommand += this.returnFieldSelector.length; + } + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff; + _command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff; + _command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff; + _command[_index] = QueryCommand.OP_QUERY & 0xff; + // Adjust index + _index = _index + 4; + + // Write the query options + _command[_index + 3] = (this.queryOptions >> 24) & 0xff; + _command[_index + 2] = (this.queryOptions >> 16) & 0xff; + _command[_index + 1] = (this.queryOptions >> 8) & 0xff; + _command[_index] = this.queryOptions & 0xff; + // Adjust index + _index = _index + 4; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write the number of documents to skip + _command[_index + 3] = (this.numberToSkip >> 24) & 0xff; + _command[_index + 2] = (this.numberToSkip >> 16) & 0xff; + _command[_index + 1] = (this.numberToSkip >> 8) & 0xff; + _command[_index] = this.numberToSkip & 0xff; + // Adjust index + _index = _index + 4; + + // Write the number of documents to return + _command[_index + 3] = (this.numberToReturn >> 24) & 0xff; + _command[_index + 2] = (this.numberToReturn >> 16) & 0xff; + _command[_index + 1] = (this.numberToReturn >> 8) & 0xff; + _command[_index] = this.numberToReturn & 0xff; + // Adjust index + _index = _index + 4; + + // Document binary length + var documentLength = 0 + var object = this.query; + + // Serialize the selector + if(Buffer.isBuffer(object)) { + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + // Serialize the document straight to the buffer + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + + // Push field selector if available + if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) { + if(Object.keys(this.returnFieldSelector).length > 0) { + var documentLength = this.db.bson.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + } + } if(this.returnFieldSelector != null && Buffer.isBuffer(this.returnFieldSelector)) { + // Document binary length + var documentLength = 0 + var object = this.returnFieldSelector; + + // Serialize the selector + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + } + + // Return finished command + return _command; +}; + +// Constants +QueryCommand.OPTS_NONE = 0; +QueryCommand.OPTS_TAILABLE_CURSOR = 2; +QueryCommand.OPTS_SLAVE = 4; +QueryCommand.OPTS_OPLOG_REPLY = 8; +QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16; +QueryCommand.OPTS_AWAIT_DATA = 32; +QueryCommand.OPTS_EXHAUST = 64; +QueryCommand.OPTS_PARTIAL = 128; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js new file mode 100644 index 0000000..9829dea --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js @@ -0,0 +1,174 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Update Document Command +**/ +var UpdateCommand = exports.UpdateCommand = function(db, collectionName, spec, document, options) { + BaseCommand.call(this); + + var object = spec; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("update spec raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + var object = document; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("update document raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + this.collectionName = collectionName; + this.spec = spec; + this.document = document; + this.db = db; + this.serializeFunctions = false; + + // Generate correct flags + var db_upsert = 0; + var db_multi_update = 0; + db_upsert = options != null && options['upsert'] != null ? (options['upsert'] == true ? 1 : 0) : db_upsert; + db_multi_update = options != null && options['multi'] != null ? (options['multi'] == true ? 1 : 0) : db_multi_update; + + // Flags + this.flags = parseInt(db_multi_update.toString() + db_upsert.toString(), 2); + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(UpdateCommand, BaseCommand); + +UpdateCommand.OP_UPDATE = 2001; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + cstring fullCollectionName; // "dbname.collectionname" + int32 flags; // bit vector. see below + BSON spec; // the query to select the document + BSON document; // the document data to update with or insert +} +*/ +UpdateCommand.prototype.toBinary = function() { + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.spec, false, true) + + this.db.bson.calculateObjectSize(this.document, this.serializeFunctions, true) + (4 * 4); + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (UpdateCommand.OP_UPDATE >> 24) & 0xff; + _command[_index + 2] = (UpdateCommand.OP_UPDATE >> 16) & 0xff; + _command[_index + 1] = (UpdateCommand.OP_UPDATE >> 8) & 0xff; + _command[_index] = UpdateCommand.OP_UPDATE & 0xff; + // Adjust index + _index = _index + 4; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write the update flags + _command[_index + 3] = (this.flags >> 24) & 0xff; + _command[_index + 2] = (this.flags >> 16) & 0xff; + _command[_index + 1] = (this.flags >> 8) & 0xff; + _command[_index] = this.flags & 0xff; + // Adjust index + _index = _index + 4; + + // Document binary length + var documentLength = 0 + var object = this.spec; + + // Serialize the selector + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, false) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + + // Document binary length + var documentLength = 0 + var object = this.document; + + // Serialize the document + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + + return _command; +}; + +// Constants +UpdateCommand.DB_UPSERT = 0; +UpdateCommand.DB_MULTI_UPDATE = 1; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js new file mode 100644 index 0000000..9696562 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js @@ -0,0 +1,466 @@ +var EventEmitter = require('events').EventEmitter + , inherits = require('util').inherits + , mongodb_cr_authenticate = require('../auth/mongodb_cr.js').authenticate + , mongodb_gssapi_authenticate = require('../auth/mongodb_gssapi.js').authenticate + , mongodb_sspi_authenticate = require('../auth/mongodb_sspi.js').authenticate; + +var id = 0; + +/** + * Internal class for callback storage + * @ignore + */ +var CallbackStore = function() { + // Make class an event emitter + EventEmitter.call(this); + // Add a info about call variable + this._notReplied = {}; + this.id = id++; +} + +/** + * @ignore + */ +inherits(CallbackStore, EventEmitter); + +CallbackStore.prototype.notRepliedToIds = function() { + return Object.keys(this._notReplied); +} + +CallbackStore.prototype.callbackInfo = function(id) { + return this._notReplied[id]; +} + +/** + * Internal class for holding non-executed commands + * @ignore + */ +var NonExecutedOperationStore = function(config) { + this.config = config; + this.commands = { + read: [] + , write_reads: [] + , write: [] + }; +} + +NonExecutedOperationStore.prototype.write = function(op) { + this.commands.write.push(op); +} + +NonExecutedOperationStore.prototype.read_from_writer = function(op) { + this.commands.write_reads.push(op); +} + +NonExecutedOperationStore.prototype.read = function(op) { + this.commands.read.push(op); +} + +NonExecutedOperationStore.prototype.execute_queries = function(executeInsertCommand) { + var connection = this.config.checkoutReader(); + if(connection == null || connection instanceof Error) return; + + // Write out all the queries + while(this.commands.read.length > 0) { + // Get the next command + var command = this.commands.read.shift(); + // command['options'].connection = this.config.checkoutReader(); + command.options.connection = connection; + // Execute the next command + command.executeQueryCommand(command.db, command.db_command, command.options, command.callback); + } +} + +NonExecutedOperationStore.prototype.execute_writes = function() { + var connection = this.config.checkoutWriter(); + if(connection == null || connection instanceof Error) return; + + // Write out all the queries to the primary + while(this.commands.write_reads.length > 0) { + // Get the next command + var command = this.commands.write_reads.shift(); + command.options.connection = connection; + // Execute the next command + command.executeQueryCommand(command.db, command.db_command, command.options, command.callback); + } + + // Execute all write operations + while(this.commands.write.length > 0) { + // Get the next command + var command = this.commands.write.shift(); + // Set the connection + command.options.connection = connection; + // Execute the next command + command.executeInsertCommand(command.db, command.db_command, command.options, command.callback); + } +} + +/** + * Internal class for authentication storage + * @ignore + */ +var AuthStore = function() { + this._auths = []; +} + +AuthStore.prototype.add = function(authMechanism, dbName, username, password, authdbName, gssapiServiceName) { + // Check for duplicates + if(!this.contains(dbName)) { + // Base config + var config = { + 'username':username + , 'password':password + , 'db': dbName + , 'authMechanism': authMechanism + , 'gssapiServiceName': gssapiServiceName + }; + + // Add auth source if passed in + if(typeof authdbName == 'string') { + config['authdb'] = authdbName; + } + + // Push the config + this._auths.push(config); + } +} + +AuthStore.prototype.contains = function(dbName) { + for(var i = 0; i < this._auths.length; i++) { + if(this._auths[i].db == dbName) return true; + } + + return false; +} + +AuthStore.prototype.remove = function(dbName) { + var newAuths = []; + + // Filter out all the login details + for(var i = 0; i < this._auths.length; i++) { + if(this._auths[i].db != dbName) newAuths.push(this._auths[i]); + } + + // Set the filtered list + this._auths = newAuths; +} + +AuthStore.prototype.get = function(index) { + return this._auths[index]; +} + +AuthStore.prototype.length = function() { + return this._auths.length; +} + +AuthStore.prototype.toArray = function() { + return this._auths.slice(0); +} + +/** + * Internal class for storing db references + * @ignore + */ +var DbStore = function() { + this._dbs = []; +} + +DbStore.prototype.add = function(db) { + // this._dbs.push(db); + var found = false; + // Only add if it does not exist already + for(var i = 0; i < this._dbs.length; i++) { + if(db.databaseName == this._dbs[i].databaseName) found = true; + } + + if(!found) this._dbs.push(db); +} + +DbStore.prototype.reset = function() { + this._dbs = []; +} + +DbStore.prototype.emit = function(event, message, object, reset, filterDb) { + if(reset) { + while(this._dbs.length > 0) { + var db = this._dbs.shift(); + // Only emit if there is a listener + if(db.listeners(event).length > 0) { + if(filterDb == null || filterDb.databaseName !== db.databaseName + || filterDb.tag !== db.tag) { + db.emit(event, message, object); + } + } + } + } else { + for(var i = 0; i < this._dbs.length; i++) { + if(this._dbs[i].listeners(event).length > 0) { + if(filterDb == null || filterDb.databaseName !== this._dbs[i].databaseName + || filterDb.tag !== this._dbs[i].tag) { + this._dbs[i].emit(event, message, object); + } + } + } + } +} + +var Base = function Base() { + EventEmitter.call(this); + + // Callback store is part of connection specification + if(Base._callBackStore == null) { + Base._callBackStore = new CallbackStore(); + } + + // Create a new callback store + this._callBackStore = new CallbackStore(); + // All commands not being executed + this._commandsStore = new NonExecutedOperationStore(this); + // Create a new auth store + this.auth = new AuthStore(); + // Contains all the dbs attached to this server config + this._dbStore = new DbStore(); +} + +/** + * @ignore + */ +inherits(Base, EventEmitter); + +/** + * @ignore + */ +Base.prototype._apply_auths = function(db, callback) { + _apply_auths_serially(this, db, this.auth.toArray(), callback); +} + +var _apply_auths_serially = function(self, db, auths, callback) { + if(auths.length == 0) return callback(null, null); + // Get the first auth + var auth = auths.shift(); + var connections = self.allRawConnections(); + var connectionsLeft = connections.length; + + // Let's apply it to all raw connections + for(var i = 0; i < connections.length; i++) { + var options = {connection: connections[i]}; + + if(auth.authMechanism == 'GSSAPI') { + var connectionHandler = function(err, result) { + connectionsLeft = connectionsLeft - 1; + // If no more connections are left return + if(connectionsLeft == 0) { + return _apply_auths_serially(self, db, auths, callback); + } + } + + // We have the kerberos library, execute auth process + if(process.platform == 'win32') { + mongodb_sspi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } else { + mongodb_gssapi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } + } else if(auth.authMechanism == 'MONGODB-CR') { + mongodb_cr_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } + } +} + +/** + * Fire all the errors + * @ignore + */ +Base.prototype.__executeAllCallbacksWithError = function(err) { + // Check all callbacks + var keys = Object.keys(this._callBackStore._notReplied); + // For each key check if it's a callback that needs to be returned + for(var j = 0; j < keys.length; j++) { + var info = this._callBackStore._notReplied[keys[j]]; + // Check if we have a chained command (findAndModify) + if(info && info['chained'] && Array.isArray(info['chained']) && info['chained'].length > 0) { + var chained = info['chained']; + // Only callback once and the last one is the right one + var finalCallback = chained.pop(); + // Emit only the last event + this._callBackStore.emit(finalCallback, err, null); + + // Put back the final callback to ensure we don't call all commands in the chain + chained.push(finalCallback); + + // Remove all chained callbacks + for(var i = 0; i < chained.length; i++) { + delete this._callBackStore._notReplied[chained[i]]; + } + // Remove the key + delete this._callBackStore._notReplied[keys[j]]; + } else { + this._callBackStore.emit(keys[j], err, null); + // Remove the key + delete this._callBackStore._notReplied[keys[j]]; + } + } +} + +/** + * Fire all the errors + * @ignore + */ +Base.prototype.__executeAllServerSpecificErrorCallbacks = function(host, port, err) { + // Check all callbacks + var keys = Object.keys(this._callBackStore._notReplied); + // For each key check if it's a callback that needs to be returned + for(var j = 0; j < keys.length; j++) { + var info = this._callBackStore._notReplied[keys[j]]; + + if(info.connection) { + // Unpack the connection settings + var _host = info.connection.socketOptions.host; + var _port = info.connection.socketOptions.port; + // Check if we have a chained command (findAndModify) + if(info && info['chained'] + && Array.isArray(info['chained']) + && info['chained'].length > 0 + && _port == port && _host == host) { + var chained = info['chained']; + // Only callback once and the last one is the right one + var finalCallback = chained.pop(); + // Emit only the last event + this._callBackStore.emit(finalCallback, err, null); + + // Put back the final callback to ensure we don't call all commands in the chain + chained.push(finalCallback); + + // Remove all chained callbacks + for(var i = 0; i < chained.length; i++) { + delete this._callBackStore._notReplied[chained[i]]; + } + // Remove the key + delete this._callBackStore._notReplied[keys[j]]; + } else if(_port == port && _host == host) { + this._callBackStore.emit(keys[j], err, null); + // Remove the key + delete this._callBackStore._notReplied[keys[j]]; + } + } + } +} + +/** + * Register a handler + * @ignore + * @api private + */ +Base.prototype._registerHandler = function(db_command, raw, connection, exhaust, callback) { + // If we have an array of commands, chain them + var chained = Array.isArray(db_command); + + // Check if we have exhausted + if(typeof exhaust == 'function') { + callback = exhaust; + exhaust = false; + } + + // If they are chained we need to add a special handler situation + if(chained) { + // List off chained id's + var chainedIds = []; + // Add all id's + for(var i = 0; i < db_command.length; i++) chainedIds.push(db_command[i].getRequestId().toString()); + // Register all the commands together + for(var i = 0; i < db_command.length; i++) { + var command = db_command[i]; + // Add the callback to the store + this._callBackStore.once(command.getRequestId(), callback); + // Add the information about the reply + this._callBackStore._notReplied[command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, chained:chainedIds, connection:connection, exhaust:false}; + } + } else { + // Add the callback to the list of handlers + this._callBackStore.once(db_command.getRequestId(), callback); + // Add the information about the reply + this._callBackStore._notReplied[db_command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, connection:connection, exhaust:exhaust}; + } +} + +/** + * Re-Register a handler, on the cursor id f.ex + * @ignore + * @api private + */ +Base.prototype._reRegisterHandler = function(newId, object, callback) { + // Add the callback to the list of handlers + this._callBackStore.once(newId, object.callback.listener); + // Add the information about the reply + this._callBackStore._notReplied[newId] = object.info; +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._callHandler = function(id, document, err) { + // If there is a callback peform it + if(this._callBackStore.listeners(id).length >= 1) { + // Get info object + var info = this._callBackStore._notReplied[id]; + // Delete the current object + delete this._callBackStore._notReplied[id]; + // Emit to the callback of the object + this._callBackStore.emit(id, err, document, info.connection); + } +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._hasHandler = function(id) { + // If there is a callback peform it + return this._callBackStore.listeners(id).length >= 1; +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._removeHandler = function(id) { + // Remove the information + if(this._callBackStore._notReplied[id] != null) delete this._callBackStore._notReplied[id]; + // Remove the callback if it's registered + this._callBackStore.removeAllListeners(id); + // Force cleanup _events, node.js seems to set it as a null value + if(this._callBackStore._events != null) delete this._callBackStore._events[id]; +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._findHandler = function(id) { + var info = this._callBackStore._notReplied[id]; + // Return the callback + return {info:info, callback:(this._callBackStore.listeners(id).length >= 1) ? this._callBackStore.listeners(id)[0] : null} +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._emitAcrossAllDbInstances = function(server, filterDb, event, message, object, resetConnection) { + if(resetConnection) { + for(var i = 0; i < this._dbStore._dbs.length; i++) { + if(typeof this._dbStore._dbs[i].openCalled != 'undefined') + this._dbStore._dbs[i].openCalled = false; + } + } + + // Fire event + this._dbStore.emit(event, message, object, resetConnection, filterDb); +} + +exports.Base = Base; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js new file mode 100644 index 0000000..6753fd2 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js @@ -0,0 +1,505 @@ +var utils = require('./connection_utils'), + inherits = require('util').inherits, + net = require('net'), + EventEmitter = require('events').EventEmitter, + inherits = require('util').inherits, + binaryutils = require('../utils'), + tls = require('tls'); + +var Connection = exports.Connection = function(id, socketOptions) { + // Set up event emitter + EventEmitter.call(this); + // Store all socket options + this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017, domainSocket:false}; + // Set keep alive default if not overriden + if(this.socketOptions.keepAlive == null && (process.platform !== "sunos" || process.platform !== "win32")) this.socketOptions.keepAlive = 100; + // Id for the connection + this.id = id; + // State of the connection + this.connected = false; + // Set if this is a domain socket + this.domainSocket = this.socketOptions.domainSocket; + + // + // Connection parsing state + // + this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE; + this.maxMessageSizeBytes = socketOptions.maxMessageSizeBytes ? socketOptions.maxMessageSizeBytes : Connection.DEFAULT_MAX_MESSAGE_SIZE; + // Contains the current message bytes + this.buffer = null; + // Contains the current message size + this.sizeOfMessage = 0; + // Contains the readIndex for the messaage + this.bytesRead = 0; + // Contains spill over bytes from additional messages + this.stubBuffer = 0; + + // Just keeps list of events we allow + this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]}; + + // Just keeps list of events we allow + resetHandlers(this, false); +} + +// Set max bson size +Connection.DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4; +// Set default to max bson to avoid overflow or bad guesses +Connection.DEFAULT_MAX_MESSAGE_SIZE = Connection.DEFAULT_MAX_BSON_SIZE; + +// Inherit event emitter so we can emit stuff wohoo +inherits(Connection, EventEmitter); + +Connection.prototype.start = function() { + var self = this; + + // If we have a normal connection + if(this.socketOptions.ssl) { + // Create new connection instance + if(this.domainSocket) { + this.connection = net.createConnection(this.socketOptions.host); + } else { + this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host); + } + if(this.logger != null && this.logger.doDebug){ + this.logger.debug("opened connection", this.socketOptions); + } + // Set options on the socket + this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout); + // Work around for 0.4.X + if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay); + // Set keep alive if defined + if(process.version.indexOf("v0.4") == -1) { + if(this.socketOptions.keepAlive > 0) { + this.connection.setKeepAlive(true, this.socketOptions.keepAlive); + } else { + this.connection.setKeepAlive(false); + } + } + + // Check if the driver should validate the certificate + var validate_certificates = this.socketOptions.sslValidate == true ? true : false; + + // Create options for the tls connection + var tls_options = { + socket: this.connection + , rejectUnauthorized: false + } + + // If we wish to validate the certificate we have provided a ca store + if(validate_certificates) { + tls_options.ca = this.socketOptions.sslCA; + } + + // If we have a certificate to present + if(this.socketOptions.sslCert) { + tls_options.cert = this.socketOptions.sslCert; + tls_options.key = this.socketOptions.sslKey; + } + + // If the driver has been provided a private key password + if(this.socketOptions.sslPass) { + tls_options.passphrase = this.socketOptions.sslPass; + } + + // Contains the cleartext stream + var cleartext = null; + // Attempt to establish a TLS connection to the server + try { + cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() { + // If we have a ssl certificate validation error return an error + if(cleartext.authorizationError && validate_certificates) { + // Emit an error + return self.emit("error", cleartext.authorizationError, self, {ssl:true}); + } + + // Connect to the server + connectHandler(self)(); + }) + } catch(err) { + return self.emit("error", "SSL connection failed", self, {ssl:true}); + } + + // Save the output stream + this.writeSteam = cleartext; + + // Set up data handler for the clear stream + cleartext.on("data", createDataHandler(this)); + // Do any handling of end event of the stream + cleartext.on("end", endHandler(this)); + cleartext.on("error", errorHandler(this)); + + // Handle any errors + this.connection.on("error", errorHandler(this)); + // Handle timeout + this.connection.on("timeout", timeoutHandler(this)); + // Handle drain event + this.connection.on("drain", drainHandler(this)); + // Handle the close event + this.connection.on("close", closeHandler(this)); + } else { + // Create new connection instance + if(this.domainSocket) { + this.connection = net.createConnection(this.socketOptions.host); + } else { + this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host); + } + if(this.logger != null && this.logger.doDebug){ + this.logger.debug("opened connection", this.socketOptions); + } + + // Set options on the socket + this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout); + // Work around for 0.4.X + if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay); + // Set keep alive if defined + if(process.version.indexOf("v0.4") == -1) { + if(this.socketOptions.keepAlive > 0) { + this.connection.setKeepAlive(true, this.socketOptions.keepAlive); + } else { + this.connection.setKeepAlive(false); + } + } + + // Set up write stream + this.writeSteam = this.connection; + // Add handlers + this.connection.on("error", errorHandler(this)); + // Add all handlers to the socket to manage it + this.connection.on("connect", connectHandler(this)); + // this.connection.on("end", endHandler(this)); + this.connection.on("data", createDataHandler(this)); + this.connection.on("timeout", timeoutHandler(this)); + this.connection.on("drain", drainHandler(this)); + this.connection.on("close", closeHandler(this)); + } +} + +// Check if the sockets are live +Connection.prototype.isConnected = function() { + return this.connected && !this.connection.destroyed && this.connection.writable && this.connection.readable; +} + +// Write the data out to the socket +Connection.prototype.write = function(command, callback) { + try { + // If we have a list off commands to be executed on the same socket + if(Array.isArray(command)) { + for(var i = 0; i < command.length; i++) { + var binaryCommand = command[i].toBinary() + + if(!this.socketOptions['disableDriverBSONSizeCheck'] && binaryCommand.length > this.maxBsonSize) + return callback(new Error("Document exceeds maximum allowed bson size of " + this.maxBsonSize + " bytes")); + + if(this.socketOptions['disableDriverBSONSizeCheck'] && binaryCommand.length > this.maxMessageSizeBytes) { + return callback(new Error("Command exceeds maximum message size of " + this.maxMessageSizeBytes + " bytes")); + } + + if(this.logger != null && this.logger.doDebug) + this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]}); + + var r = this.writeSteam.write(binaryCommand); + } + } else { + var binaryCommand = command.toBinary() + + if(!this.socketOptions['disableDriverBSONSizeCheck'] && binaryCommand.length > this.maxBsonSize) + return callback(new Error("Document exceeds maximum allowed bson size of " + this.maxBsonSize + " bytes")); + + if(this.socketOptions['disableDriverBSONSizeCheck'] && binaryCommand.length > this.maxMessageSizeBytes) { + return callback(new Error("Command exceeds maximum message size of " + this.maxMessageSizeBytes + " bytes")); + } + + if(this.logger != null && this.logger.doDebug) + this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command}); + + var r = this.writeSteam.write(binaryCommand); + } + } catch (err) { + if(typeof callback === 'function') callback(err); + } +} + +// Force the closure of the connection +Connection.prototype.close = function() { + // clear out all the listeners + resetHandlers(this, true); + // Add a dummy error listener to catch any weird last moment errors (and ignore them) + this.connection.on("error", function() {}) + // destroy connection + this.connection.destroy(); + if(this.logger != null && this.logger.doDebug){ + this.logger.debug("closed connection", this.connection); + } +} + +// Reset all handlers +var resetHandlers = function(self, clearListeners) { + self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]}; + + // If we want to clear all the listeners + if(clearListeners && self.connection != null) { + var keys = Object.keys(self.eventHandlers); + // Remove all listeners + for(var i = 0; i < keys.length; i++) { + self.connection.removeAllListeners(keys[i]); + } + } +} + +// +// Handlers +// + +// Connect handler +var connectHandler = function(self) { + return function(data) { + // Set connected + self.connected = true; + // Now that we are connected set the socket timeout + self.connection.setTimeout(self.socketOptions.socketTimeoutMS != null ? self.socketOptions.socketTimeoutMS : self.socketOptions.timeout); + // Emit the connect event with no error + self.emit("connect", null, self); + } +} + +var createDataHandler = exports.Connection.createDataHandler = function(self) { + // We need to handle the parsing of the data + // and emit the messages when there is a complete one + return function(data) { + // Parse until we are done with the data + while(data.length > 0) { + // If we still have bytes to read on the current message + if(self.bytesRead > 0 && self.sizeOfMessage > 0) { + // Calculate the amount of remaining bytes + var remainingBytesToRead = self.sizeOfMessage - self.bytesRead; + // Check if the current chunk contains the rest of the message + if(remainingBytesToRead > data.length) { + // Copy the new data into the exiting buffer (should have been allocated when we know the message size) + data.copy(self.buffer, self.bytesRead); + // Adjust the number of bytes read so it point to the correct index in the buffer + self.bytesRead = self.bytesRead + data.length; + + // Reset state of buffer + data = new Buffer(0); + } else { + // Copy the missing part of the data into our current buffer + data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead); + // Slice the overflow into a new buffer that we will then re-parse + data = data.slice(remainingBytesToRead); + + // Emit current complete message + try { + var emitBuffer = self.buffer; + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Emit the buffer + self.emit("message", emitBuffer, self); + } catch(err) { + var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ + sizeOfMessage:self.sizeOfMessage, + bytesRead:self.bytesRead, + stubBuffer:self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + } + } + } else { + // Stub buffer is kept in case we don't get enough bytes to determine the + // size of the message (< 4 bytes) + if(self.stubBuffer != null && self.stubBuffer.length > 0) { + + // If we have enough bytes to determine the message size let's do it + if(self.stubBuffer.length + data.length > 4) { + // Prepad the data + var newData = new Buffer(self.stubBuffer.length + data.length); + self.stubBuffer.copy(newData, 0); + data.copy(newData, self.stubBuffer.length); + // Reassign for parsing + data = newData; + + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + + } else { + + // Add the the bytes to the stub buffer + var newStubBuffer = new Buffer(self.stubBuffer.length + data.length); + // Copy existing stub buffer + self.stubBuffer.copy(newStubBuffer, 0); + // Copy missing part of the data + data.copy(newStubBuffer, self.stubBuffer.length); + // Exit parsing loop + data = new Buffer(0); + } + } else { + if(data.length > 4) { + // Retrieve the message size + var sizeOfMessage = binaryutils.decodeUInt32(data, 0); + // If we have a negative sizeOfMessage emit error and return + if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) { + var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{ + sizeOfMessage: sizeOfMessage, + bytesRead: self.bytesRead, + stubBuffer: self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + return; + } + + // Ensure that the size of message is larger than 0 and less than the max allowed + if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage > data.length) { + self.buffer = new Buffer(sizeOfMessage); + // Copy all the data into the buffer + data.copy(self.buffer, 0); + // Update bytes read + self.bytesRead = data.length; + // Update sizeOfMessage + self.sizeOfMessage = sizeOfMessage; + // Ensure stub buffer is null + self.stubBuffer = null; + // Exit parsing loop + data = new Buffer(0); + + } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage == data.length) { + try { + var emitBuffer = data; + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Exit parsing loop + data = new Buffer(0); + // Emit the message + self.emit("message", emitBuffer, self); + } catch (err) { + var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ + sizeOfMessage:self.sizeOfMessage, + bytesRead:self.bytesRead, + stubBuffer:self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + } + } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxBsonSize) { + var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{ + sizeOfMessage:sizeOfMessage, + bytesRead:0, + buffer:null, + stubBuffer:null}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + + // Clear out the state of the parser + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Exit parsing loop + data = new Buffer(0); + + } else { + try { + var emitBuffer = data.slice(0, sizeOfMessage); + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Copy rest of message + data = data.slice(sizeOfMessage); + // Emit the message + self.emit("message", emitBuffer, self); + } catch (err) { + var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ + sizeOfMessage:sizeOfMessage, + bytesRead:self.bytesRead, + stubBuffer:self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + } + + } + } else { + // Create a buffer that contains the space for the non-complete message + self.stubBuffer = new Buffer(data.length) + // Copy the data to the stub buffer + data.copy(self.stubBuffer, 0); + // Exit parsing loop + data = new Buffer(0); + } + } + } + } + } +} + +var endHandler = function(self) { + return function() { + // Set connected to false + self.connected = false; + // Emit end event + self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } +} + +var timeoutHandler = function(self) { + return function() { + // Set connected to false + self.connected = false; + // Emit timeout event + self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self); + } +} + +var drainHandler = function(self) { + return function() { + } +} + +var errorHandler = function(self) { + return function(err) { + self.connection.destroy(); + // Set connected to false + self.connected = false; + // Emit error + self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } +} + +var closeHandler = function(self) { + return function(hadError) { + // If we have an error during the connection phase + if(hadError && !self.connected) { + // Set disconnected + self.connected = false; + // Emit error + self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } else { + // Set disconnected + self.connected = false; + // Emit close + self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } + } +} + +// Some basic defaults +Connection.DEFAULT_PORT = 27017; + + + + + + + diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js new file mode 100644 index 0000000..94cf754 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js @@ -0,0 +1,294 @@ +var utils = require('./connection_utils'), + inherits = require('util').inherits, + net = require('net'), + timers = require('timers'), + EventEmitter = require('events').EventEmitter, + inherits = require('util').inherits, + MongoReply = require("../responses/mongo_reply").MongoReply, + Connection = require("./connection").Connection; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; +processor = process.nextTick + +var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) { + if(typeof host !== 'string') { + throw new Error("host must be specified [" + host + "]"); + } + + // Set up event emitter + EventEmitter.call(this); + + // Keep all options for the socket in a specific collection allowing the user to specify the + // Wished upon socket connection parameters + this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {}; + this.socketOptions.host = host; + this.socketOptions.port = port; + this.socketOptions.domainSocket = false; + this.bson = bson; + // PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc) + this.poolSize = poolSize; + this.minPoolSize = Math.floor(this.poolSize / 2) + 1; + + // Check if the host is a socket + if(host.match(/^\//)) { + this.socketOptions.domainSocket = true; + } else if(typeof port === 'string') { + try { + port = parseInt(port, 10); + } catch(err) { + new Error("port must be specified or valid integer[" + port + "]"); + } + } else if(typeof port !== 'number') { + throw new Error("port must be specified [" + port + "]"); + } + + // Set default settings for the socket options + utils.setIntegerParameter(this.socketOptions, 'timeout', 0); + // Delay before writing out the data to the server + utils.setBooleanParameter(this.socketOptions, 'noDelay', true); + // Delay before writing out the data to the server + utils.setIntegerParameter(this.socketOptions, 'keepAlive', 0); + // Set the encoding of the data read, default is binary == null + utils.setStringParameter(this.socketOptions, 'encoding', null); + // Allows you to set a throttling bufferSize if you need to stop overflows + utils.setIntegerParameter(this.socketOptions, 'bufferSize', 0); + + // Internal structures + this.openConnections = []; + // Assign connection id's + this.connectionId = 0; + + // Current index for selection of pool connection + this.currentConnectionIndex = 0; + // The pool state + this._poolState = 'disconnected'; + // timeout control + this._timeout = false; + // Time to wait between connections for the pool + this._timeToWait = 10; +} + +inherits(ConnectionPool, EventEmitter); + +ConnectionPool.prototype.setMaxBsonSize = function(maxBsonSize) { + if(maxBsonSize == null){ + maxBsonSize = Connection.DEFAULT_MAX_BSON_SIZE; + } + + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].maxBsonSize = maxBsonSize; + } +} + +ConnectionPool.prototype.setMaxMessageSizeBytes = function(maxMessageSizeBytes) { + if(maxMessageSizeBytes == null){ + maxMessageSizeBytes = Connection.DEFAULT_MAX_MESSAGE_SIZE; + } + + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].maxMessageSizeBytes = maxMessageSizeBytes; + } +} + +// Start a function +var _connect = function(_self) { + // return new function() { + // Create a new connection instance + var connection = new Connection(_self.connectionId++, _self.socketOptions); + // Set logger on pool + connection.logger = _self.logger; + // Connect handler + connection.on("connect", function(err, connection) { + // Add connection to list of open connections + _self.openConnections.push(connection); + // If the number of open connections is equal to the poolSize signal ready pool + if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') { + // Set connected + _self._poolState = 'connected'; + // Emit pool ready + _self.emit("poolReady"); + } else if(_self.openConnections.length < _self.poolSize) { + // Wait a little bit of time to let the close event happen if the server closes the connection + // so we don't leave hanging connections around + if(typeof _self._timeToWait == 'number') { + setTimeout(function() { + // If we are still connecting (no close events fired in between start another connection) + if(_self._poolState == 'connecting') { + _connect(_self); + } + }, _self._timeToWait); + } else { + processor(function() { + // If we are still connecting (no close events fired in between start another connection) + if(_self._poolState == 'connecting') { + _connect(_self); + } + }); + } + } + }); + + var numberOfErrors = 0 + + // Error handler + connection.on("error", function(err, connection, error_options) { + numberOfErrors++; + // If we are already disconnected ignore the event + if(_self._poolState != 'disconnected' && _self.listeners("error").length > 0) { + _self.emit("error", err, connection, error_options); + } + + // Close the connection + connection.close(); + // Set pool as disconnected + _self._poolState = 'disconnected'; + // Stop the pool + _self.stop(); + }); + + // Close handler + connection.on("close", function() { + // If we are already disconnected ignore the event + if(_self._poolState !== 'disconnected' && _self.listeners("close").length > 0) { + _self.emit("close"); + } + + // Set disconnected + _self._poolState = 'disconnected'; + // Stop + _self.stop(); + }); + + // Timeout handler + connection.on("timeout", function(err, connection) { + // If we are already disconnected ignore the event + if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) { + _self.emit("timeout", err); + } + + // Close the connection + connection.close(); + // Set disconnected + _self._poolState = 'disconnected'; + _self.stop(); + }); + + // Parse error, needs a complete shutdown of the pool + connection.on("parseError", function() { + // If we are already disconnected ignore the event + if(_self._poolState !== 'disconnected' && _self.listeners("parseError").length > 0) { + _self.emit("parseError", new Error("parseError occured")); + } + + // Set disconnected + _self._poolState = 'disconnected'; + _self.stop(); + }); + + connection.on("message", function(message) { + _self.emit("message", message); + }); + + // Start connection in the next tick + connection.start(); + // }(); +} + + +// Start method, will throw error if no listeners are available +// Pass in an instance of the listener that contains the api for +// finding callbacks for a given message etc. +ConnectionPool.prototype.start = function() { + var markerDate = new Date().getTime(); + var self = this; + + if(this.listeners("poolReady").length == 0) { + throw "pool must have at least one listener ready that responds to the [poolReady] event"; + } + + // Set pool state to connecting + this._poolState = 'connecting'; + this._timeout = false; + + _connect(self); +} + +// Restart a connection pool (on a close the pool might be in a wrong state) +ConnectionPool.prototype.restart = function() { + // Close all connections + this.stop(false); + // Now restart the pool + this.start(); +} + +// Stop the connections in the pool +ConnectionPool.prototype.stop = function(removeListeners) { + removeListeners = removeListeners == null ? true : removeListeners; + // Set disconnected + this._poolState = 'disconnected'; + + // Clear all listeners if specified + if(removeListeners) { + this.removeAllEventListeners(); + } + + // Close all connections + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].close(); + } + + // Clean up + this.openConnections = []; +} + +// Check the status of the connection +ConnectionPool.prototype.isConnected = function() { + // return this._poolState === 'connected'; + return this.openConnections.length > 0 && this.openConnections[0].isConnected(); +} + +// Checkout a connection from the pool for usage, or grab a specific pool instance +ConnectionPool.prototype.checkoutConnection = function(id) { + var index = (this.currentConnectionIndex++ % (this.openConnections.length)); + var connection = this.openConnections[index]; + return connection; +} + +ConnectionPool.prototype.getAllConnections = function() { + return this.openConnections; +} + +// Remove all non-needed event listeners +ConnectionPool.prototype.removeAllEventListeners = function() { + this.removeAllListeners("close"); + this.removeAllListeners("error"); + this.removeAllListeners("timeout"); + this.removeAllListeners("connect"); + this.removeAllListeners("end"); + this.removeAllListeners("parseError"); + this.removeAllListeners("message"); + this.removeAllListeners("poolReady"); +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js new file mode 100644 index 0000000..5910924 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js @@ -0,0 +1,23 @@ +exports.setIntegerParameter = function(object, field, defaultValue) { + if(object[field] == null) { + object[field] = defaultValue; + } else if(typeof object[field] !== "number" && object[field] !== parseInt(object[field], 10)) { + throw "object field [" + field + "] must be a numeric integer value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; + } +} + +exports.setBooleanParameter = function(object, field, defaultValue) { + if(object[field] == null) { + object[field] = defaultValue; + } else if(typeof object[field] !== "boolean") { + throw "object field [" + field + "] must be a boolean value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; + } +} + +exports.setStringParameter = function(object, field, defaultValue) { + if(object[field] == null) { + object[field] = defaultValue; + } else if(typeof object[field] !== "string") { + throw "object field [" + field + "] must be a string value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; + } +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js new file mode 100644 index 0000000..6122a50 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js @@ -0,0 +1,474 @@ +var ReadPreference = require('./read_preference').ReadPreference + , Base = require('./base').Base + , Server = require('./server').Server + , inherits = require('util').inherits; + +/** + * Mongos constructor provides a connection to a mongos proxy including failover to additional servers + * + * Options + * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) + * - **ha** {Boolean, default:true}, turn on high availability, attempts to reconnect to down proxies + * - **haInterval** {Number, default:2000}, time between each replicaset status check. + * + * @class Represents a Mongos connection with failover to backup proxies + * @param {Array} list of mongos server objects + * @param {Object} [options] additional options for the mongos connection + */ +var Mongos = function Mongos(servers, options) { + // Set up basic + if(!(this instanceof Mongos)) + return new Mongos(servers, options); + + // Set up event emitter + Base.call(this); + + // Throw error on wrong setup + if(servers == null || !Array.isArray(servers) || servers.length == 0) + throw new Error("At least one mongos proxy must be in the array"); + + // Ensure we have at least an empty options object + this.options = options == null ? {} : options; + // Set default connection pool options + this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {}; + // Enabled ha + this.haEnabled = this.options['ha'] == null ? true : this.options['ha']; + this._haInProgress = false; + // How often are we checking for new servers in the replicaset + this.mongosStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval']; + // Save all the server connections + this.servers = servers; + // Servers we need to attempt reconnect with + this.downServers = []; + // Emit open setup + this.emitOpen = this.options.emitOpen || true; + // Just contains the current lowest ping time and server + this.lowestPingTimeServer = null; + this.lowestPingTime = 0; + // Connection timeout + this._connectTimeoutMS = this.socketOptions.connectTimeoutMS + ? this.socketOptions.connectTimeoutMS + : 1000; + + // Add options to servers + for(var i = 0; i < this.servers.length; i++) { + var server = this.servers[i]; + server._callBackStore = this._callBackStore; + server.auto_reconnect = false; + // Default empty socket options object + var socketOptions = {host: server.host, port: server.port}; + // If a socket option object exists clone it + if(this.socketOptions != null) { + var keys = Object.keys(this.socketOptions); + for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = this.socketOptions[keys[i]]; + } + + // Set socket options + server.socketOptions = socketOptions; + } +} + +/** + * @ignore + */ +inherits(Mongos, Base); + +/** + * @ignore + */ +Mongos.prototype.isMongos = function() { + return true; +} + +/** + * @ignore + */ +Mongos.prototype.connect = function(db, options, callback) { + if('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + var self = this; + + // Keep reference to parent + this.db = db; + // Set server state to connecting + this._serverState = 'connecting'; + // Number of total servers that need to initialized (known servers) + this._numberOfServersLeftToInitialize = this.servers.length; + // Connect handler + var connectHandler = function(_server) { + return function(err, result) { + self._numberOfServersLeftToInitialize = self._numberOfServersLeftToInitialize - 1; + + if(self._numberOfServersLeftToInitialize == 0) { + // Start ha function if it exists + if(self.haEnabled) { + // Setup the ha process + if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId); + self._replicasetTimeoutId = setInterval(self.mongosCheckFunction, self.mongosStatusCheckInterval); + } + + // Set the mongos to connected + self._serverState = "connected"; + + // Emit the open event + if(self.emitOpen) + self.db.emit("open", null, self.db); + + // Callback + callback(null, self.db); + } + } + }; + + // Error handler + var errorOrCloseHandler = function(_server) { + return function(err, result) { + var validServers = []; + // Execute all the callbacks with errors + self.__executeAllCallbacksWithError(err); + // Check if we have the server + var found = false; + // Save the down server if it does not already exists + for(var i = 0; i < self.downServers.length; i++) { + if(self.downServers[i].host == _server.host && self.downServers[i].port == _server.port) { + found = true; + break; + } + } + + if(!found) + self.downServers.push(_server); + + // Remove the current server from the list + for(var i = 0; i < self.servers.length; i++) { + if(!(self.servers[i].host == _server.host && self.servers[i].port == _server.port) && self.servers[i].isConnected()) { + validServers.push(self.servers[i]); + } + } + + // Set current list of servers + self.servers = validServers; + + // Emit close across all the attached db instances + if(self.servers.length == 0) { + self._dbStore.emit("close", new Error("mongos disconnected, no valid proxies contactable over tcp"), null, true); + } + } + } + + // Mongo function + this.mongosCheckFunction = function() { + if(self._haInProgress) return; + // If all servers are down we are done + if(self.servers.length == 0) return; + + // Check that at least one server is available + var alldown = true; + for(var i = 0; i < self.servers.length; i++) { + if(self.servers[i].isConnected()) { + alldown = false; + break; + } + } + + // All servers are down + if(alldown) return; + + // Set as not waiting for check event + self._haInProgress = true; + // Check downed servers + if(self.downServers.length > 0) { + var numberOfServersLeft = self.downServers.length; + + // Iterate over all the downed servers + for(var i = 0; i < self.downServers.length; i++) { + // Pop a downed server + var downServer = self.downServers.pop(); + + // Set up the connection options for a Mongos + var options = { + auto_reconnect: false, + returnIsMasterResults: true, + slaveOk: true, + poolSize: downServer.poolSize, + socketOptions: { + connectTimeoutMS: self._connectTimeoutMS, + socketTimeoutMS: self._socketTimeoutMS + } + } + + // Create a new server object + var newServer = new Server(downServer.host, downServer.port, options); + // Setup the connection function + var connectFunction = function(_db, _server, _options, _callback) { + return function() { + // Attempt to connect + _server.connect(_db, _options, function(err, result) { + numberOfServersLeft = numberOfServersLeft - 1; + + if(err) { + return _callback(err, _server); + } else { + // Set the new server settings + _server._callBackStore = self._callBackStore; + + // Add server event handlers + _server.on("close", errorOrCloseHandler(_server)); + _server.on("timeout", errorOrCloseHandler(_server)); + _server.on("error", errorOrCloseHandler(_server)); + + // Get a read connection + var _connection = _server.checkoutReader(); + // Get the start time + var startTime = new Date().getTime(); + + // Execute ping command to mark each server with the expected times + self.db.command({ping:1} + , {failFast:true, connection:_connection}, function(err, result) { + // Get the start time + var endTime = new Date().getTime(); + // Mark the server with the ping time + _server.runtimeStats['pingMs'] = endTime - startTime; + // Sort the servers on runtime so the first server always is the closest one + self.servers.sort(function(a, b) { + return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs']; + }); + + // Callback + return _callback(null, _server); + }); + } + }); + } + } + + // Attempt to connect to the database + connectFunction(self.db, newServer, options, function(err, _server) { + // If we have an error + if(err) { + self.downServers.push(_server); + } + + // Connection function + var connectionFunction = function(_auth, _connection, _callback) { + var pending = _auth.length(); + + for(var j = 0; j < pending; j++) { + // Get the auth object + var _auth = _auth.get(j); + // Unpack the parameter + var username = _auth.username; + var password = _auth.password; + var options = { + authMechanism: _auth.authMechanism + , authSource: _auth.authdb + , connection: _connection + }; + + // If we have changed the service name + if(_auth.gssapiServiceName) + options.gssapiServiceName = _auth.gssapiServiceName; + + // Hold any error + var _error = null; + // Authenticate against the credentials + self.db.authenticate(username, password, options, function(err, result) { + _error = err != null ? err : _error; + // Adjust the pending authentication + pending = pending - 1; + // Finished up + if(pending == 0) _callback(_error ? _error : null, _error ? false : true); + }); + } + } + + // Run auths against the connections + if(self.auth.length() > 0) { + var connections = _server.allRawConnections(); + var pendingAuthConn = connections.length; + + // No connections we are done + if(connections.length == 0) { + // Set ha done + if(numberOfServersLeft == 0) { + self._haInProgress = false; + } + } + + // Final error object + var finalError = null; + // Go over all the connections + for(var j = 0; j < connections.length; j++) { + + // Execute against all the connections + connectionFunction(self.auth, connections[j], function(err, result) { + // Pending authentication + pendingAuthConn = pendingAuthConn - 1 ; + + // Save error if any + finalError = err ? err : finalError; + + // If we are done let's finish up + if(pendingAuthConn == 0) { + // Set ha done + if(numberOfServersLeft == 0) { + self._haInProgress = false; + } + + if(finalError) { + return self.downServers.push(_server); + } + + // Push to list of valid server + self.servers.push(_server); + } + }); + } + } else { + self.servers.push(_server); + // Set ha done + if(numberOfServersLeft == 0) { + self._haInProgress = false; + } + } + })(); + } + } else { + self._haInProgress = false; + } + } + + // Connect all the server instances + for(var i = 0; i < this.servers.length; i++) { + // Get the connection + var server = this.servers[i]; + server.mongosInstance = this; + // Add server event handlers + server.on("close", errorOrCloseHandler(server)); + server.on("timeout", errorOrCloseHandler(server)); + server.on("error", errorOrCloseHandler(server)); + + // Configuration + var options = { + slaveOk: true, + poolSize: server.poolSize, + socketOptions: { connectTimeoutMS: self._connectTimeoutMS }, + returnIsMasterResults: true + } + + // Connect the instance + server.connect(self.db, options, connectHandler(server)); + } +} + +/** + * @ignore + * Just return the currently picked active connection + */ +Mongos.prototype.allServerInstances = function() { + return this.servers; +} + +/** + * Always ourselves + * @ignore + */ +Mongos.prototype.setReadPreference = function() {} + +/** + * @ignore + */ +Mongos.prototype.allRawConnections = function() { + // Neeed to build a complete list of all raw connections, start with master server + var allConnections = []; + // Add all connections + for(var i = 0; i < this.servers.length; i++) { + allConnections = allConnections.concat(this.servers[i].allRawConnections()); + } + + // Return all the conections + return allConnections; +} + +/** + * @ignore + */ +Mongos.prototype.isConnected = function() { + return this._serverState == "connected"; +} + +/** + * @ignore + */ +Mongos.prototype.canWrite = Mongos.prototype.isConnected; + +/** + * @ignore + */ +Mongos.prototype.canRead = Mongos.prototype.isConnected; + +/** + * @ignore + */ +Mongos.prototype.isDestroyed = function() { + return this._serverState == 'destroyed'; +} + +/** + * @ignore + */ +Mongos.prototype.checkoutWriter = function() { + if(this.servers.length == 0) return null; + return this.servers[0].checkoutWriter(); +} + +/** + * @ignore + */ +Mongos.prototype.checkoutReader = function(read) { + // If we have a read preference object unpack it + if(read != null && typeof read == 'object' && read['_type'] == 'ReadPreference') { + // Validate if the object is using a valid mode + if(!read.isValid()) throw new Error("Illegal readPreference mode specified, " + read.mode); + } else if(!ReadPreference.isValid(read)) { + throw new Error("Illegal readPreference mode specified, " + read); + } + + if(this.servers.length == 0) return null; + return this.servers[0].checkoutWriter(); +} + +/** + * @ignore + */ +Mongos.prototype.close = function(callback) { + var self = this; + // Set server status as disconnected + this._serverState = 'destroyed'; + // Number of connections to close + var numberOfConnectionsToClose = self.servers.length; + // If we have a ha process running kill it + if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId); + self._replicasetTimeoutId = null; + // Close all proxy connections + for(var i = 0; i < self.servers.length; i++) { + self.servers[i].close(function(err, result) { + numberOfConnectionsToClose = numberOfConnectionsToClose - 1; + // Callback if we have one defined + if(numberOfConnectionsToClose == 0 && typeof callback == 'function') { + callback(null); + } + }); + } +} + +/** + * @ignore + * Return the used state + */ +Mongos.prototype._isUsed = function() { + return this._used; +} + +exports.Mongos = Mongos; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js new file mode 100644 index 0000000..6845171 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js @@ -0,0 +1,67 @@ +/** + * A class representation of the Read Preference. + * + * Read Preferences + * - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.). + * - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary. + * - **ReadPreference.SECONDARY**, Read from secondary if available, otherwise error. + * - **ReadPreference.SECONDARY_PREFERRED**, Read from a secondary if available, otherwise read from the primary. + * - **ReadPreference.NEAREST**, All modes read from among the nearest candidates, but unlike other modes, NEAREST will include both the primary and all secondaries in the random selection. + * + * @class Represents a Read Preference. + * @param {String} the read preference type + * @param {Object} tags + * @return {ReadPreference} + */ +var ReadPreference = function(mode, tags) { + if(!(this instanceof ReadPreference)) + return new ReadPreference(mode, tags); + this._type = 'ReadPreference'; + this.mode = mode; + this.tags = tags; +} + +/** + * @ignore + */ +ReadPreference.isValid = function(_mode) { + return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED + || _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED + || _mode == ReadPreference.NEAREST + || _mode == true || _mode == false); +} + +/** + * @ignore + */ +ReadPreference.prototype.isValid = function(mode) { + var _mode = typeof mode == 'string' ? mode : this.mode; + return ReadPreference.isValid(_mode); +} + +/** + * @ignore + */ +ReadPreference.prototype.toObject = function() { + var object = {mode:this.mode}; + + if(this.tags != null) { + object['tags'] = this.tags; + } + + return object; +} + +/** + * @ignore + */ +ReadPreference.PRIMARY = 'primary'; +ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred'; +ReadPreference.SECONDARY = 'secondary'; +ReadPreference.SECONDARY_PREFERRED = 'secondaryPreferred'; +ReadPreference.NEAREST = 'nearest' + +/** + * @ignore + */ +exports.ReadPreference = ReadPreference; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js new file mode 100644 index 0000000..0791f70 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js @@ -0,0 +1,411 @@ +var DbCommand = require('../../commands/db_command').DbCommand + , format = require('util').format; + +var HighAvailabilityProcess = function(replset, options) { + this.replset = replset; + this.options = options; + this.server = null; + this.state = HighAvailabilityProcess.INIT; + this.selectedIndex = 0; +} + +HighAvailabilityProcess.INIT = 'init'; +HighAvailabilityProcess.RUNNING = 'running'; +HighAvailabilityProcess.STOPPED = 'stopped'; + +HighAvailabilityProcess.prototype.start = function() { + var self = this; + if(this.replset._state + && Object.keys(this.replset._state.addresses).length == 0) { + if(this.server) this.server.close(); + this.state = HighAvailabilityProcess.STOPPED; + return; + } + + if(this.server) this.server.close(); + // Start the running + this._haProcessInProcess = false; + this.state = HighAvailabilityProcess.RUNNING; + + // Get all possible reader servers + var candidate_servers = this.replset._state.getAllReadServers(); + if(candidate_servers.length == 0) { + return; + } + + // Select a candidate server for the connection + var server = candidate_servers[this.selectedIndex % candidate_servers.length]; + this.selectedIndex = this.selectedIndex + 1; + + // Unpack connection options + var connectTimeoutMS = self.options.connectTimeoutMS || 10000; + var socketTimeoutMS = self.options.socketTimeoutMS || 30000; + + // Just ensure we don't have a full cycle dependency + var Db = require('../../db').Db + var Server = require('../server').Server; + + // Set up a new server instance + var newServer = new Server(server.host, server.port, { + auto_reconnect: false + , returnIsMasterResults: true + , poolSize: 1 + , socketOptions: { + connectTimeoutMS: connectTimeoutMS, + socketTimeoutMS: socketTimeoutMS, + keepAlive: 100 + } + , ssl: this.options.ssl + , sslValidate: this.options.sslValidate + , sslCA: this.options.sslCA + , sslCert: this.options.sslCert + , sslKey: this.options.sslKey + , sslPass: this.options.sslPass + }); + + // Create new dummy db for app + self.db = new Db('local', newServer, {w:1}); + + // Set up the event listeners + newServer.once("error", _handle(this, newServer)); + newServer.once("close", _handle(this, newServer)); + newServer.once("timeout", _handle(this, newServer)); + newServer.name = format("%s:%s", server.host, server.port); + + // Let's attempt a connection over here + newServer.connect(self.db, function(err, result, _server) { + if(self.state == HighAvailabilityProcess.STOPPED) { + _server.close(); + } + + if(err) { + // Close the server + _server.close(); + // Check if we can even do HA (is there anything running) + if(Object.keys(self.replset._state.addresses).length == 0) { + return; + } + + // Let's boot the ha timeout settings + setTimeout(function() { + self.start(); + }, self.options.haInterval); + } else { + self.server = _server; + // Let's boot the ha timeout settings + setTimeout(_timeoutHandle(self), self.options.haInterval); + } + }); +} + +HighAvailabilityProcess.prototype.stop = function() { + this.state = HighAvailabilityProcess.STOPPED; + if(this.server) this.server.close(); +} + +var _timeoutHandle = function(self) { + return function() { + if(self.state == HighAvailabilityProcess.STOPPED) { + // Stop all server instances + for(var name in self.replset._state.addresses) { + self.replset._state.addresses[name].close(); + delete self.replset._state.addresses[name]; + } + + // Finished pinging + return; + } + + // If the server is connected + if(self.server.isConnected() && !self._haProcessInProcess) { + // Start HA process + self._haProcessInProcess = true; + // Execute is master command + self.db._executeQueryCommand(DbCommand.createIsMasterCommand(self.db), + {failFast:true, connection: self.server.checkoutReader()} + , function(err, res) { + if(err) { + self.server.close(); + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + + // Master document + var master = res.documents[0]; + var hosts = master.hosts || []; + var reconnect_servers = []; + var state = self.replset._state; + + // console.log("==================================== HA ISMASTER") + // console.dir(master) + + // We are in recovery mode, let's remove the current server + if(!master.ismaster + && !master.secondary + && state.addresses[master.me]) { + self.server.close(); + state.addresses[master.me].close(); + delete state.secondaries[master.me]; + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + + // For all the hosts let's check that we have connections + for(var i = 0; i < hosts.length; i++) { + var host = hosts[i]; + + // Check if we need to reconnect to a server + if(state.addresses[host] == null) { + reconnect_servers.push(host); + } else if(state.addresses[host] && !state.addresses[host].isConnected()) { + state.addresses[host].close(); + delete state.secondaries[host]; + reconnect_servers.push(host); + } + + if((master.primary && state.master == null) + || (master.primary && state.master.name != master.primary)) { + + // Locate the primary and set it + if(state.addresses[master.primary]) { + if(state.master) state.master.close(); + delete state.secondaries[master.primary]; + state.master = state.addresses[master.primary]; + } + + // Set up the changes + if(state.master != null && state.master.isMasterDoc != null) { + state.master.isMasterDoc.ismaster = true; + state.master.isMasterDoc.secondary = false; + } else if(state.master != null) { + state.master.isMasterDoc = master; + state.master.isMasterDoc.ismaster = true; + state.master.isMasterDoc.secondary = false; + } + + // Execute any waiting commands (queries or writes) + self.replset._commandsStore.execute_queries(); + self.replset._commandsStore.execute_writes(); + } + } + + // Let's reconnect to any server needed + if(reconnect_servers.length > 0) { + _reconnect_servers(self, reconnect_servers); + } else { + self._haProcessInProcess = false + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + }); + } else if(!self.server.isConnected()) { + setTimeout(function() { + return self.start(); + }, self.options.haInterval); + } else { + setTimeout(_timeoutHandle(self), self.options.haInterval); + } + } +} + +var _reconnect_servers = function(self, reconnect_servers) { + if(reconnect_servers.length == 0) { + self._haProcessInProcess = false + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + + // Unpack connection options + var connectTimeoutMS = self.options.connectTimeoutMS || 10000; + var socketTimeoutMS = self.options.socketTimeoutMS || 30000; + + // Server class + var Db = require('../../db').Db + var Server = require('../server').Server; + // Get the host + var host = reconnect_servers.shift(); + // Split it up + var _host = host.split(":")[0]; + var _port = parseInt(host.split(":")[1], 10); + + // Set up a new server instance + var newServer = new Server(_host, _port, { + auto_reconnect: false + , returnIsMasterResults: true + , poolSize: self.options.poolSize + , socketOptions: { + connectTimeoutMS: connectTimeoutMS, + socketTimeoutMS: socketTimeoutMS + } + , ssl: self.options.ssl + , sslValidate: self.options.sslValidate + , sslCA: self.options.sslCA + , sslCert: self.options.sslCert + , sslKey: self.options.sslKey + , sslPass: self.options.sslPass + }); + + // Create new dummy db for app + var db = new Db('local', newServer, {w:1}); + var state = self.replset._state; + + // Set up the event listeners + newServer.once("error", _repl_set_handler("error", self.replset, newServer)); + newServer.once("close", _repl_set_handler("close", self.replset, newServer)); + newServer.once("timeout", _repl_set_handler("timeout", self.replset, newServer)); + + // Set shared state + newServer.name = host; + newServer._callBackStore = self.replset._callBackStore; + newServer.replicasetInstance = self.replset; + newServer.enableRecordQueryStats(self.replset.recordQueryStats); + + // Let's attempt a connection over here + newServer.connect(db, function(err, result, _server) { + if(self.state == HighAvailabilityProcess.STOPPED) { + _server.close(); + } + + // If we connected let's check what kind of server we have + if(!err) { + _apply_auths(self, db, _server, function(err, result) { + if(err) { + _server.close(); + // Process the next server + return setTimeout(function() { + _reconnect_servers(self, reconnect_servers); + }, self.options.haInterval); + } + var doc = _server.isMasterDoc; + // Fire error on any unknown callbacks for this server + self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err); + + if(doc.ismaster) { + if(state.secondaries[doc.me]) { + delete state.secondaries[doc.me]; + } + + // Override any server in list of addresses + state.addresses[doc.me] = _server; + // Set server as master + state.master = _server; + // Execute any waiting writes + self.replset._commandsStore.execute_writes(); + } else if(doc.secondary) { + state.secondaries[doc.me] = _server; + // Override any server in list of addresses + state.addresses[doc.me] = _server; + // Execute any waiting reads + self.replset._commandsStore.execute_queries(); + } else { + _server.close(); + } + + // Set any tags on the instance server + _server.name = doc.me; + _server.tags = doc.tags; + // Process the next server + setTimeout(function() { + _reconnect_servers(self, reconnect_servers); + }, self.options.haInterval); + }); + } else { + _server.close(); + self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err); + + setTimeout(function() { + _reconnect_servers(self, reconnect_servers); + }, self.options.haInterval); + } + }); +} + +var _apply_auths = function(self, _db, _server, _callback) { + if(self.replset.auth.length() == 0) return _callback(null); + // Apply any authentication needed + if(self.replset.auth.length() > 0) { + var pending = self.replset.auth.length(); + var connections = _server.allRawConnections(); + var pendingAuthConn = connections.length; + + // Connection function + var connectionFunction = function(_auth, _connection, __callback) { + var pending = _auth.length(); + + for(var j = 0; j < pending; j++) { + // Get the auth object + var _auth = _auth.get(j); + // Unpack the parameter + var username = _auth.username; + var password = _auth.password; + var options = { + authMechanism: _auth.authMechanism + , authSource: _auth.authdb + , connection: _connection + }; + + // If we have changed the service name + if(_auth.gssapiServiceName) + options.gssapiServiceName = _auth.gssapiServiceName; + + // Hold any error + var _error = null; + + // Authenticate against the credentials + _db.authenticate(username, password, options, function(err, result) { + _error = err != null ? err : _error; + // Adjust the pending authentication + pending = pending - 1; + // Finished up + if(pending == 0) __callback(_error ? _error : null, _error ? false : true); + }); + } + } + + // Final error object + var finalError = null; + // Iterate over all the connections + for(var i = 0; i < connections.length; i++) { + connectionFunction(self.replset.auth, connections[i], function(err, result) { + // Pending authentication + pendingAuthConn = pendingAuthConn - 1 ; + + // Save error if any + finalError = err ? err : finalError; + + // If we are done let's finish up + if(pendingAuthConn == 0) { + _callback(null); + } + }); + } + } +} + +var _handle = function(self, server) { + return function(err) { + server.close(); + } +} + +var _repl_set_handler = function(event, self, server) { + var ReplSet = require('./repl_set').ReplSet; + + return function(err, doc) { + server.close(); + + // The event happened to a primary + // Remove it from play + if(self._state.isPrimary(server)) { + self._state.master == null; + self._serverState = ReplSet.REPLSET_READ_ONLY; + } else if(self._state.isSecondary(server)) { + delete self._state.secondaries[server.name]; + } + + // Unpack variables + var host = server.socketOptions.host; + var port = server.socketOptions.port; + + // Fire error on any unknown callbacks + self.__executeAllServerSpecificErrorCallbacks(host, port, err); + } +} + +exports.HighAvailabilityProcess = HighAvailabilityProcess; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js new file mode 100644 index 0000000..a5658e3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js @@ -0,0 +1,126 @@ +var PingStrategy = require('./strategies/ping_strategy').PingStrategy + , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy + , ReadPreference = require('../read_preference').ReadPreference; + +var Options = function(options) { + options = options || {}; + this._options = options; + this.ha = options.ha || true; + this.haInterval = options.haInterval || 2000; + this.reconnectWait = options.reconnectWait || 1000; + this.retries = options.retries || 30; + this.rs_name = options.rs_name; + this.socketOptions = options.socketOptions || {}; + this.readPreference = options.readPreference; + this.readSecondary = options.read_secondary; + this.poolSize = options.poolSize == null ? 5 : options.poolSize; + this.strategy = options.strategy || 'ping'; + this.secondaryAcceptableLatencyMS = options.secondaryAcceptableLatencyMS || 15; + this.connectArbiter = options.connectArbiter || false; + this.connectWithNoPrimary = options.connectWithNoPrimary || false; + this.logger = options.logger; + this.ssl = options.ssl || false; + this.sslValidate = options.sslValidate || false; + this.sslCA = options.sslCA; + this.sslCert = options.sslCert; + this.sslKey = options.sslKey; + this.sslPass = options.sslPass; + this.emitOpen = options.emitOpen || true; +} + +Options.prototype.init = function() { + if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) { + throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate"); + } + + // Make sure strategy is one of the two allowed + if(this.strategy != null && (this.strategy != 'ping' && this.strategy != 'statistical' && this.strategy != 'none')) + throw new Error("Only ping or statistical strategies allowed"); + + if(this.strategy == null) this.strategy = 'ping'; + + // Set logger if strategy exists + if(this.strategyInstance) this.strategyInstance.logger = this.logger; + + // Unpack read Preference + var readPreference = this.readPreference; + // Validate correctness of Read preferences + if(readPreference != null) { + if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.PRIMARY_PREFERRED + && readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.SECONDARY_PREFERRED + && readPreference != ReadPreference.NEAREST && typeof readPreference != 'object' && readPreference['_type'] != 'ReadPreference') { + throw new Error("Illegal readPreference mode specified, " + readPreference); + } + + this.readPreference = readPreference; + } else { + this.readPreference = null; + } + + // Ensure read_secondary is set correctly + if(this.readSecondary != null) + this.readSecondary = this.readPreference == ReadPreference.PRIMARY + || this.readPreference == false + || this.readPreference == null ? false : true; + + // Ensure correct slave set + if(this.readSecondary) this.slaveOk = true; + + // Set up logger if any set + this.logger = this.logger != null + && (typeof this.logger.debug == 'function') + && (typeof this.logger.error == 'function') + && (typeof this.logger.debug == 'function') + ? this.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; + + // Connection timeout + this.connectTimeoutMS = this.socketOptions.connectTimeoutMS + ? this.socketOptions.connectTimeoutMS + : 1000; + + // Socket connection timeout + this.socketTimeoutMS = this.socketOptions.socketTimeoutMS + ? this.socketOptions.socketTimeoutMS + : 30000; +} + +Options.prototype.decorateAndClean = function(servers, callBackStore) { + var self = this; + + // var de duplicate list + var uniqueServers = {}; + // De-duplicate any servers in the seed list + for(var i = 0; i < servers.length; i++) { + var server = servers[i]; + // If server does not exist set it + if(uniqueServers[server.host + ":" + server.port] == null) { + uniqueServers[server.host + ":" + server.port] = server; + } + } + + // Let's set the deduplicated list of servers + var finalServers = []; + // Add the servers + for(var key in uniqueServers) { + finalServers.push(uniqueServers[key]); + } + + finalServers.forEach(function(server) { + // Ensure no server has reconnect on + server.options.auto_reconnect = false; + // Set up ssl options + server.ssl = self.ssl; + server.sslValidate = self.sslValidate; + server.sslCA = self.sslCA; + server.sslCert = self.sslCert; + server.sslKey = self.sslKey; + server.sslPass = self.sslPass; + server.poolSize = self.poolSize; + // Set callback store + server._callBackStore = callBackStore; + }); + + return finalServers; +} + +exports.Options = Options; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js new file mode 100644 index 0000000..136615e --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js @@ -0,0 +1,777 @@ +var ReadPreference = require('../read_preference').ReadPreference + , DbCommand = require('../../commands/db_command').DbCommand + , inherits = require('util').inherits + , format = require('util').format + , timers = require('timers') + , Server = require('../server').Server + , utils = require('../../utils') + , PingStrategy = require('./strategies/ping_strategy').PingStrategy + , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy + , Options = require('./options').Options + , ReplSetState = require('./repl_set_state').ReplSetState + , HighAvailabilityProcess = require('./ha').HighAvailabilityProcess + , Base = require('../base').Base; + +const STATE_STARTING_PHASE_1 = 0; +const STATE_PRIMARY = 1; +const STATE_SECONDARY = 2; +const STATE_RECOVERING = 3; +const STATE_FATAL_ERROR = 4; +const STATE_STARTING_PHASE_2 = 5; +const STATE_UNKNOWN = 6; +const STATE_ARBITER = 7; +const STATE_DOWN = 8; +const STATE_ROLLBACK = 9; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; + +/** + * ReplSet constructor provides replicaset functionality + * + * Options + * - **ha** {Boolean, default:true}, turn on high availability. + * - **haInterval** {Number, default:2000}, time between each replicaset status check. + * - **reconnectWait** {Number, default:1000}, time to wait in miliseconds before attempting reconnect. + * - **retries** {Number, default:30}, number of times to attempt a replicaset reconnect. + * - **rs_name** {String}, the name of the replicaset to connect to. + * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **strategy** {String, default:'ping'}, selection strategy for reads choose between (ping, statistical and none, default is ping) + * - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms) + * - **connectWithNoPrimary** {Boolean, default:false}, sets if the driver should connect even if no primary is available + * - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not. + * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. + * - **poolSize** {Number, default:5}, number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons. + * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support) + * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher) + * + * @class Represents a Replicaset Configuration + * @param {Array} list of server objects participating in the replicaset. + * @param {Object} [options] additional options for the replicaset connection. + */ +var ReplSet = exports.ReplSet = function(servers, options) { + // Set up basic + if(!(this instanceof ReplSet)) + return new ReplSet(servers, options); + + // Set up event emitter + Base.call(this); + + // Ensure we have a list of servers + if(!Array.isArray(servers)) throw Error("The parameter must be an array of servers and contain at least one server"); + // Ensure no Mongos's + for(var i = 0; i < servers.length; i++) { + if(!(servers[i] instanceof Server)) throw new Error("list of servers must be of type Server"); + } + + // Save the options + this.options = new Options(options); + // Ensure basic validation of options + this.options.init(); + + // Server state + this._serverState = ReplSet.REPLSET_DISCONNECTED; + // Add high availability process + this._haProcess = new HighAvailabilityProcess(this, this.options); + + + // Let's iterate over all the provided server objects and decorate them + this.servers = this.options.decorateAndClean(servers, this._callBackStore); + // Throw error if no seed servers + if(this.servers.length == 0) throw new Error("No valid seed servers in the array"); + + // Let's set up our strategy object for picking secondaries + if(this.options.strategy == 'ping') { + // Create a new instance + this.strategyInstance = new PingStrategy(this, this.options.secondaryAcceptableLatencyMS); + } else if(this.options.strategy == 'statistical') { + // Set strategy as statistical + this.strategyInstance = new StatisticsStrategy(this); + // Add enable query information + this.enableRecordQueryStats(true); + } + + this.emitOpen = this.options.emitOpen || true; + // Set up a clean state + this._state = new ReplSetState(); + // Current round robin selected server + this._currentServerChoice = 0; + // Ensure up the server callbacks + for(var i = 0; i < this.servers.length; i++) { + this.servers[i]._callBackStore = this._callBackStore; + this.servers[i].name = format("%s:%s", this.servers[i].host, this.servers[i].port) + this.servers[i].replicasetInstance = this; + this.servers[i].options.auto_reconnect = false; + this.servers[i].inheritReplSetOptionsFrom(this); + } +} + +/** + * @ignore + */ +inherits(ReplSet, Base); + +// Replicaset states +ReplSet.REPLSET_CONNECTING = 'connecting'; +ReplSet.REPLSET_DISCONNECTED = 'disconnected'; +ReplSet.REPLSET_CONNECTED = 'connected'; +ReplSet.REPLSET_RECONNECTING = 'reconnecting'; +ReplSet.REPLSET_DESTROYED = 'destroyed'; +ReplSet.REPLSET_READ_ONLY = 'readonly'; + +ReplSet.prototype.isAutoReconnect = function() { + return true; +} + +ReplSet.prototype.canWrite = function() { + return this._state.master && this._state.master.isConnected(); +} + +ReplSet.prototype.canRead = function(read) { + if((read == ReadPreference.PRIMARY + || read == null || read == false) && (this._state.master == null || !this._state.master.isConnected())) return false; + return Object.keys(this._state.secondaries).length > 0; +} + +/** + * @ignore + */ +ReplSet.prototype.enableRecordQueryStats = function(enable) { + // Set the global enable record query stats + this.recordQueryStats = enable; + + // Enable all the servers + for(var i = 0; i < this.servers.length; i++) { + this.servers[i].enableRecordQueryStats(enable); + } +} + +/** + * @ignore + */ +ReplSet.prototype.setReadPreference = function(preference) { + this.options.readPreference = preference; +} + +ReplSet.prototype.connect = function(parent, options, callback) { + if(this._serverState != ReplSet.REPLSET_DISCONNECTED) + return callback(new Error("in process of connection")); + + // If no callback throw + if(!(typeof callback == 'function')) + throw new Error("cannot call ReplSet.prototype.connect with no callback function"); + + var self = this; + // Save db reference + this.options.db = parent; + // Set replicaset as connecting + this._serverState = ReplSet.REPLSET_CONNECTING + // Copy all the servers to our list of seeds + var candidateServers = this.servers.slice(0); + // Pop the first server + var server = candidateServers.pop(); + server.name = format("%s:%s", server.host, server.port); + // Set up the options + var opts = { + returnIsMasterResults: true, + eventReceiver: server + } + + // Register some event listeners + this.once("fullsetup", function(err, db, replset) { + // Set state to connected + self._serverState = ReplSet.REPLSET_CONNECTED; + // Stop any process running + if(self._haProcess) self._haProcess.stop(); + // Start the HA process + self._haProcess.start(); + + // Emit fullsetup + processor(function() { + if(self.emitOpen) + parent.emit("open", null, self.options.db, self); + + parent.emit("fullsetup", null, self.options.db, self); + }); + + // If we have a strategy defined start it + if(self.strategyInstance) { + self.strategyInstance.start(); + } + + // Finishing up the call + callback(err, db, replset); + }); + + // Errors + this.once("connectionError", function(err, result) { + callback(err, result); + }); + + // Attempt to connect to the server + server.connect(this.options.db, opts, _connectHandler(this, candidateServers, server)); +} + +ReplSet.prototype.close = function(callback) { + var self = this; + // Set as destroyed + this._serverState = ReplSet.REPLSET_DESTROYED; + // Stop the ha + this._haProcess.stop(); + + // If we have a strategy stop it + if(this.strategyInstance) { + this.strategyInstance.stop(); + } + + // Kill all servers available + for(var name in this._state.addresses) { + this._state.addresses[name].close(); + } + + // Clean out the state + this._state = new ReplSetState(); + + // Emit close event + processor(function() { + self._emitAcrossAllDbInstances(self, null, "close", null, null, true) + }); + + // Callback + if(typeof callback == 'function') + return callback(null, null); +} + +/** + * Creates a new server for the `replset` based on `host`. + * + * @param {String} host - host:port pair (localhost:27017) + * @param {ReplSet} replset - the ReplSet instance + * @return {Server} + * @ignore + */ +var createServer = function(self, host, options) { + // copy existing socket options to new server + var socketOptions = {} + if(options.socketOptions) { + var keys = Object.keys(options.socketOptions); + for(var k = 0; k < keys.length; k++) { + socketOptions[keys[k]] = options.socketOptions[keys[k]]; + } + } + + var parts = host.split(/:/); + if(1 === parts.length) { + parts[1] = Connection.DEFAULT_PORT; + } + + socketOptions.host = parts[0]; + socketOptions.port = parseInt(parts[1], 10); + + var serverOptions = { + readPreference: options.readPreference, + socketOptions: socketOptions, + poolSize: options.poolSize, + logger: options.logger, + auto_reconnect: false, + ssl: options.ssl, + sslValidate: options.sslValidate, + sslCA: options.sslCA, + sslCert: options.sslCert, + sslKey: options.sslKey, + sslPass: options.sslPass + } + + var server = new Server(socketOptions.host, socketOptions.port, serverOptions); + // Set up shared state + server._callBackStore = self._callBackStore; + server.replicasetInstance = self; + server.enableRecordQueryStats(self.recordQueryStats); + // Set up event handlers + server.on("close", _handler("close", self, server)); + server.on("error", _handler("error", self, server)); + server.on("timeout", _handler("timeout", self, server)); + return server; +} + +var _handler = function(event, self, server) { + return function(err, doc) { + // The event happened to a primary + // Remove it from play + if(self._state.isPrimary(server)) { + var current_master = self._state.master; + self._state.master = null; + self._serverState = ReplSet.REPLSET_READ_ONLY; + + if(current_master != null) { + // Unpack variables + var host = current_master.socketOptions.host; + var port = current_master.socketOptions.port; + + // Fire error on any unknown callbacks + self.__executeAllServerSpecificErrorCallbacks(host, port, err); + } + } else if(self._state.isSecondary(server)) { + delete self._state.secondaries[server.name]; + } + + // If there is no more connections left and the setting is not destroyed + // set to disconnected + if(Object.keys(self._state.addresses).length == 0 + && self._serverState != ReplSet.REPLSET_DESTROYED) { + self._serverState = ReplSet.REPLSET_DISCONNECTED; + + // Emit close across all the attached db instances + self._dbStore.emit("close", new Error("replicaset disconnected, no valid servers contactable over tcp"), null, true); + } + + // Unpack variables + var host = server.socketOptions.host; + var port = server.socketOptions.port; + + // Fire error on any unknown callbacks + self.__executeAllServerSpecificErrorCallbacks(host, port, err); + } +} + +var locateNewServers = function(self, state, candidateServers, ismaster) { + // Retrieve the host + var hosts = ismaster.hosts; + // In candidate servers + var inCandidateServers = function(name, candidateServers) { + for(var i = 0; i < candidateServers.length; i++) { + if(candidateServers[i].name == name) return true; + } + + return false; + } + + // New servers + var newServers = []; + if(Array.isArray(hosts)) { + // Let's go over all the hosts + for(var i = 0; i < hosts.length; i++) { + if(!state.contains(hosts[i]) + && !inCandidateServers(hosts[i], candidateServers)) { + newServers.push(createServer(self, hosts[i], self.options)); + } + } + } + + // Return list of possible new servers + return newServers; +} + +var _connectHandler = function(self, candidateServers, instanceServer) { + return function(err, doc) { + // If we have an error add to the list + if(err) self._state.errors[instanceServer.name] = instanceServer; + + // No error let's analyse the ismaster command + if(!err) { + var ismaster = doc.documents[0] + // console.dir(ismaster) + // If no replicaset name exists set the current one + if(self.options.rs_name == null) { + self.options.rs_name = ismaster.setName; + } + + // If we have a member that is not part of the set let's finish up + if(typeof ismaster.setName == 'string' && ismaster.setName != self.options.rs_name) { + return self.emit("connectionError", new Error("Replicaset name " + ismaster.setName + " does not match specified name " + self.options.rs_name)); + } + + // Add the error handlers + instanceServer.on("close", _handler("close", self, instanceServer)); + instanceServer.on("error", _handler("error", self, instanceServer)); + instanceServer.on("timeout", _handler("timeout", self, instanceServer)); + + // Set any tags on the instance server + instanceServer.name = ismaster.me; + instanceServer.tags = ismaster.tags; + + // Add the server to the list + self._state.addServer(instanceServer, ismaster); + + // Check if we have more servers to add (only check when done with initial set) + if(candidateServers.length == 0) { + // Get additional new servers that are not currently in set + var new_servers = locateNewServers(self, self._state, candidateServers, ismaster); + + // If we have new servers join them + if(new_servers.length > 0) { + candidateServers = candidateServers.concat(new_servers); + } + } + } + + // If the candidate server list is empty and no valid servers + if(candidateServers.length == 0 && + !self._state.hasValidServers()) { + return self.emit("connectionError", new Error("No valid replicaset instance servers found")); + } else if(candidateServers.length == 0) { + if(!self.options.connectWithNoPrimary && (self._state.master == null || !self._state.master.isConnected())) { + return self.emit("connectionError", new Error("No primary found in set")); + } + return self.emit("fullsetup", null, self.options.db, self); + } + + // Let's connect the next server + var nextServer = candidateServers.pop(); + + // Set up the options + var opts = { + returnIsMasterResults: true, + eventReceiver: nextServer + } + + // Attempt to connect to the server + nextServer.connect(self.options.db, opts, _connectHandler(self, candidateServers, nextServer)); + } +} + +ReplSet.prototype.isDestroyed = function() { + return this._serverState == ReplSet.REPLSET_DESTROYED; +} + +ReplSet.prototype.isConnected = function(read) { + var isConnected = false; + + if(read == null || read == ReadPreference.PRIMARY || read == false) + isConnected = this._state.master != null && this._state.master.isConnected(); + + if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST) + && ((this._state.master != null && this._state.master.isConnected()) + || (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) { + isConnected = true; + } else if(read == ReadPreference.SECONDARY) { + isConnected = this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0; + } + + // No valid connection return false + return isConnected; +} + +ReplSet.prototype.isMongos = function() { + return false; +} + +ReplSet.prototype.checkoutWriter = function() { + if(this._state.master) return this._state.master.checkoutWriter(); + return new Error("no writer connection available"); +} + +ReplSet.prototype.allRawConnections = function() { + var connections = []; + + for(var name in this._state.addresses) { + connections = connections.concat(this._state.addresses[name].allRawConnections()); + } + + return connections; +} + +/** + * @ignore + */ +ReplSet.prototype.allServerInstances = function() { + var self = this; + // If no state yet return empty + if(!self._state) return []; + // Close all the servers (concatenate entire list of servers first for ease) + var allServers = self._state.master != null ? [self._state.master] : []; + + // Secondary keys + var keys = Object.keys(self._state.secondaries); + // Add all secondaries + for(var i = 0; i < keys.length; i++) { + allServers.push(self._state.secondaries[keys[i]]); + } + + // Return complete list of all servers + return allServers; +} + +/** + * @ignore + */ +ReplSet.prototype.checkoutReader = function(readPreference, tags) { + // console.log("============= ReplSet.prototype.checkoutReader") + var connection = null; + + // If we have a read preference object unpack it + if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') { + // Validate if the object is using a valid mode + if(!readPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + readPreference.mode); + // Set the tag + tags = readPreference.tags; + readPreference = readPreference.mode; + } else if(typeof readPreference == 'object' && readPreference['_type'] != 'ReadPreference') { + return new Error("read preferences must be either a string or an instance of ReadPreference"); + } + + // Set up our read Preference, allowing us to override the readPreference + var finalReadPreference = readPreference != null ? readPreference : this.options.readPreference; + + // Ensure we unpack a reference + if(finalReadPreference != null && typeof finalReadPreference == 'object' && finalReadPreference['_type'] == 'ReadPreference') { + // Validate if the object is using a valid mode + if(!finalReadPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + finalReadPreference.mode); + // Set the tag + tags = finalReadPreference.tags; + readPreference = finalReadPreference.mode; + } + + // Finalize the read preference setup + finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference; + finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference; + + // If we are reading from a primary + if(finalReadPreference == 'primary') { + // If we provide a tags set send an error + if(typeof tags == 'object' && tags != null) { + return new Error("PRIMARY cannot be combined with tags"); + } + + // If we provide a tags set send an error + if(this._state.master == null) { + return new Error("No replica set primary available for query with ReadPreference PRIMARY"); + } + + // Checkout a writer + return this.checkoutWriter(); + } + + // If we have specified to read from a secondary server grab a random one and read + // from it, otherwise just pass the primary connection + if((this.options.readSecondary || finalReadPreference == ReadPreference.SECONDARY_PREFERRED || finalReadPreference == ReadPreference.SECONDARY) && Object.keys(this._state.secondaries).length > 0) { + // If we have tags, look for servers matching the specific tag + if(this.strategyInstance != null) { + // Only pick from secondaries + var _secondaries = []; + for(var key in this._state.secondaries) { + _secondaries.push(this._state.secondaries[key]); + } + + if(finalReadPreference == ReadPreference.SECONDARY) { + // Check out the nearest from only the secondaries + connection = this.strategyInstance.checkoutConnection(tags, _secondaries); + } else { + connection = this.strategyInstance.checkoutConnection(tags, _secondaries); + // No candidate servers that match the tags, error + if(connection == null || connection instanceof Error) { + // No secondary server avilable, attemp to checkout a primary server + connection = this.checkoutWriter(); + // If no connection return an error + if(connection == null || connection instanceof Error) { + return new Error("No replica set members available for query"); + } + } + } + } else if(tags != null && typeof tags == 'object') { + // Get connection + connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { + // No candidate servers that match the tags, error + if(connection == null) { + return new Error("No replica set members available for query"); + } + } else { + // console.log("+++++++++++++++++++++++++++++++++ ReadPreference.SECONDARY :: 0") + connection = _roundRobin(this, tags); + } + } else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) { + // Check if there is a primary available and return that if possible + connection = this.checkoutWriter(); + // If no connection available checkout a secondary + if(connection == null || connection instanceof Error) { + // If we have tags, look for servers matching the specific tag + if(tags != null && typeof tags == 'object') { + // Get connection + connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { + // No candidate servers that match the tags, error + if(connection == null) { + return new Error("No replica set members available for query"); + } + } else { + connection = _roundRobin(this, tags); + } + } + } else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED) { + // If we have tags, look for servers matching the specific tag + if(this.strategyInstance != null) { + connection = this.strategyInstance.checkoutConnection(tags); + + // No candidate servers that match the tags, error + if(connection == null || connection instanceof Error) { + // No secondary server avilable, attemp to checkout a primary server + connection = this.checkoutWriter(); + // If no connection return an error + if(connection == null || connection instanceof Error) { + var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; + return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); + } + } + } else if(tags != null && typeof tags == 'object') { + // Get connection + connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { + // No candidate servers that match the tags, error + if(connection == null) { + // No secondary server avilable, attemp to checkout a primary server + connection = this.checkoutWriter(); + // If no connection return an error + if(connection == null || connection instanceof Error) { + var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; + return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); + } + } + } + } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance != null) { + connection = this.strategyInstance.checkoutConnection(tags); + } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) { + return new Error("A strategy for calculating nearness must be enabled such as ping or statistical"); + } else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) { + if(tags != null && typeof tags == 'object') { + var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; + return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); + } else { + return new Error("No replica set secondary available for query with ReadPreference SECONDARY"); + } + } else { + connection = this.checkoutWriter(); + } + + // if(connection && connection.socketOptions) { + // console.log("============================ checking out :: " + connection.socketOptions.port); + // console.dir(finalReadPreference) + // } + // Return the connection + return connection; +} + +/** + * @ignore + */ +var _pickFromTags = function(self, tags) { + // If we have an array or single tag selection + var tagObjects = Array.isArray(tags) ? tags : [tags]; + // Iterate over all tags until we find a candidate server + for(var _i = 0; _i < tagObjects.length; _i++) { + // Grab a tag object + var tagObject = tagObjects[_i]; + // Matching keys + var matchingKeys = Object.keys(tagObject); + // Match all the servers that match the provdided tags + var keys = Object.keys(self._state.secondaries); + var candidateServers = []; + + for(var i = 0; i < keys.length; i++) { + var server = self._state.secondaries[keys[i]]; + // If we have tags match + if(server.tags != null) { + var matching = true; + // Ensure we have all the values + for(var j = 0; j < matchingKeys.length; j++) { + if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { + matching = false; + break; + } + } + + // If we have a match add it to the list of matching servers + if(matching) { + candidateServers.push(server); + } + } + } + + // If we have a candidate server return + if(candidateServers.length > 0) { + if(self.strategyInstance) return self.strategyInstance.checkoutConnection(tags, candidateServers); + // Set instance to return + return candidateServers[Math.floor(Math.random() * candidateServers.length)].checkoutReader(); + } + } + + // No connection found + return null; +} + +/** + * Pick a secondary using round robin + * + * @ignore + */ +function _roundRobin (replset, tags) { + var keys = Object.keys(replset._state.secondaries); + // console.log("+++++++++++++++++++++++++++ _roundRobin") + // console.dir(keys) + // Update index + replset._currentServerChoice = replset._currentServerChoice + 1; + // Pick a server + var key = keys[replset._currentServerChoice % keys.length]; + // console.log("selected :: " + key) + + var conn = null != replset._state.secondaries[key] + ? replset._state.secondaries[key].checkoutReader() + : null; + + // If connection is null fallback to first available secondary + if(null == conn) { + conn = pickFirstConnectedSecondary(replset, tags); + } + + return conn; +} + +/** + * @ignore + */ +var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) { + var keys = Object.keys(self._state.secondaries); + var connection; + + // Find first available reader if any + for(var i = 0; i < keys.length; i++) { + connection = self._state.secondaries[keys[i]].checkoutReader(); + if(connection) return connection; + } + + // If we still have a null, read from primary if it's not secondary only + if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) { + connection = self._state.master.checkoutReader(); + if(connection) return connection; + } + + var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED + ? 'secondary' + : self._readPreference; + + return new Error("No replica set member available for query with ReadPreference " + + preferenceName + " and tags " + JSON.stringify(tags)); +} + +/** + * Get list of secondaries + * @ignore + */ +Object.defineProperty(ReplSet.prototype, "secondaries", {enumerable: true + , get: function() { + return utils.objectToArray(this._state.secondaries); + } +}); + +/** + * Get list of secondaries + * @ignore + */ +Object.defineProperty(ReplSet.prototype, "arbiters", {enumerable: true + , get: function() { + return utils.objectToArray(this._state.arbiters); + } +}); + diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js new file mode 100644 index 0000000..6f9e143 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js @@ -0,0 +1,70 @@ +/** + * Interval state object constructor + * + * @ignore + */ +var ReplSetState = function ReplSetState () { + this.errorMessages = []; + this.secondaries = {}; + this.addresses = {}; + this.arbiters = {}; + this.passives = {}; + this.members = []; + this.errors = {}; + this.setName = null; + this.master = null; +} + +ReplSetState.prototype.hasValidServers = function() { + var validServers = []; + if(this.master && this.master.isConnected()) return true; + + if(this.secondaries) { + var keys = Object.keys(this.secondaries) + for(var i = 0; i < keys.length; i++) { + if(this.secondaries[keys[i]].isConnected()) + return true; + } + } + + return false; +} + +ReplSetState.prototype.getAllReadServers = function() { + var candidate_servers = []; + for(var name in this.addresses) { + candidate_servers.push(this.addresses[name]); + } + + // Return all possible read candidates + return candidate_servers; +} + +ReplSetState.prototype.addServer = function(server, master) { + server.name = master.me; + + if(master.ismaster) { + this.master = server; + this.addresses[server.name] = server; + } else if(master.secondary) { + this.secondaries[server.name] = server; + this.addresses[server.name] = server; + } else if(master.arbiters) { + this.arbiters[server.name] = server; + this.addresses[server.name] = server; + } +} + +ReplSetState.prototype.contains = function(host) { + return this.addresses[host] != null; +} + +ReplSetState.prototype.isPrimary = function(server) { + return this.master && this.master.name == server.name; +} + +ReplSetState.prototype.isSecondary = function(server) { + return this.secondaries[server.name] != null; +} + +exports.ReplSetState = ReplSetState; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js new file mode 100644 index 0000000..e5a7367 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js @@ -0,0 +1,304 @@ +var Server = require("../../server").Server + , format = require('util').format; + +// The ping strategy uses pings each server and records the +// elapsed time for the server so it can pick a server based on lowest +// return time for the db command {ping:true} +var PingStrategy = exports.PingStrategy = function(replicaset, secondaryAcceptableLatencyMS) { + this.replicaset = replicaset; + this.secondaryAcceptableLatencyMS = secondaryAcceptableLatencyMS; + this.state = 'disconnected'; + this.pingInterval = 5000; + // Class instance + this.Db = require("../../../db").Db; + // Active db connections + this.dbs = {}; + // Current server index + this.index = 0; + // Logger api + this.Logger = null; +} + +// Starts any needed code +PingStrategy.prototype.start = function(callback) { + // already running? + if ('connected' == this.state) return; + + this.state = 'connected'; + + // Start ping server + this._pingServer(callback); +} + +// Stops and kills any processes running +PingStrategy.prototype.stop = function(callback) { + // Stop the ping process + this.state = 'disconnected'; + + // Stop all the server instances + for(var key in this.dbs) { + this.dbs[key].close(); + } + + // optional callback + callback && callback(null, null); +} + +PingStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) { + // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS + // Create a list of candidat servers, containing the primary if available + var candidateServers = []; + var self = this; + + // If we have not provided a list of candidate servers use the default setup + if(!Array.isArray(secondaryCandidates)) { + candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : []; + // Add all the secondaries + var keys = Object.keys(this.replicaset._state.secondaries); + for(var i = 0; i < keys.length; i++) { + candidateServers.push(this.replicaset._state.secondaries[keys[i]]) + } + } else { + candidateServers = secondaryCandidates; + } + + // Final list of eligable server + var finalCandidates = []; + + // If we have tags filter by tags + if(tags != null && typeof tags == 'object') { + // If we have an array or single tag selection + var tagObjects = Array.isArray(tags) ? tags : [tags]; + // Iterate over all tags until we find a candidate server + for(var _i = 0; _i < tagObjects.length; _i++) { + // Grab a tag object + var tagObject = tagObjects[_i]; + // Matching keys + var matchingKeys = Object.keys(tagObject); + // Remove any that are not tagged correctly + for(var i = 0; i < candidateServers.length; i++) { + var server = candidateServers[i]; + // If we have tags match + if(server.tags != null) { + var matching = true; + + // Ensure we have all the values + for(var j = 0; j < matchingKeys.length; j++) { + if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { + matching = false; + break; + } + } + + // If we have a match add it to the list of matching servers + if(matching) { + finalCandidates.push(server); + } + } + } + } + } else { + // Final array candidates + var finalCandidates = candidateServers; + } + + // Sort by ping time + finalCandidates.sort(function(a, b) { + return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs']; + }); + + if(0 === finalCandidates.length) + return new Error("No replica set members available for query"); + + // find lowest server with a ping time + var lowest = finalCandidates.filter(function (server) { + return undefined != server.runtimeStats.pingMs; + })[0]; + + if(!lowest) { + lowest = finalCandidates[0]; + } + + // convert to integer + var lowestPing = lowest.runtimeStats.pingMs | 0; + + // determine acceptable latency + var acceptable = lowestPing + this.secondaryAcceptableLatencyMS; + + // remove any server responding slower than acceptable + var len = finalCandidates.length; + while(len--) { + if(finalCandidates[len].runtimeStats['pingMs'] > acceptable) { + finalCandidates.splice(len, 1); + } + } + + if(self.logger && self.logger.debug) { + self.logger.debug("Ping strategy selection order for tags", tags); + finalCandidates.forEach(function(c) { + self.logger.debug(format("%s:%s = %s ms", c.host, c.port, c.runtimeStats['pingMs']), null); + }) + } + + // If no candidates available return an error + if(finalCandidates.length == 0) + return new Error("No replica set members available for query"); + + // Ensure no we don't overflow + this.index = this.index % finalCandidates.length + // Pick a random acceptable server + var connection = finalCandidates[this.index].checkoutReader(); + // Point to next candidate (round robin style) + this.index = this.index + 1; + + if(self.logger && self.logger.debug) { + if(connection) + self.logger.debug("picked server %s:%s", connection.socketOptions.host, connection.socketOptions.port); + } + + return connection; +} + +PingStrategy.prototype._pingServer = function(callback) { + var self = this; + + // Ping server function + var pingFunction = function() { + // Our state changed to disconnected or destroyed return + if(self.state == 'disconnected' || self.state == 'destroyed') return; + // If the replicaset is destroyed return + if(self.replicaset.isDestroyed() || self.replicaset._serverState == 'disconnected') return + + // Create a list of all servers we can send the ismaster command to + var allServers = self.replicaset._state.master != null ? [self.replicaset._state.master] : []; + + // Secondary keys + var keys = Object.keys(self.replicaset._state.secondaries); + // Add all secondaries + for(var i = 0; i < keys.length; i++) { + allServers.push(self.replicaset._state.secondaries[keys[i]]); + } + + // Number of server entries + var numberOfEntries = allServers.length; + + // We got keys + for(var i = 0; i < allServers.length; i++) { + + // We got a server instance + var server = allServers[i]; + + // Create a new server object, avoid using internal connections as they might + // be in an illegal state + new function(serverInstance) { + var _db = self.dbs[serverInstance.host + ":" + serverInstance.port]; + // If we have a db + if(_db != null) { + // Startup time of the command + var startTime = Date.now(); + + // Execute ping command in own scope + var _ping = function(__db, __serverInstance) { + // Execute ping on this connection + __db.executeDbCommand({ping:1}, {failFast:true}, function(err) { + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { + __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime; + } + + done(); + }); + }; + // Ping + _ping(_db, serverInstance); + } else { + var connectTimeoutMS = self.replicaset.options.socketOptions + ? self.replicaset.options.socketOptions.connectTimeoutMS : 0 + + // Create a new master connection + var _server = new Server(serverInstance.host, serverInstance.port, { + auto_reconnect: false, + returnIsMasterResults: true, + slaveOk: true, + poolSize: 1, + socketOptions: { connectTimeoutMS: connectTimeoutMS }, + ssl: self.replicaset.ssl, + sslValidate: self.replicaset.sslValidate, + sslCA: self.replicaset.sslCA, + sslCert: self.replicaset.sslCert, + sslKey: self.replicaset.sslKey, + sslPass: self.replicaset.sslPass + }); + + // Create Db instance + var _db = new self.Db('local', _server, { safe: true }); + _db.on("close", function() { + delete self.dbs[this.serverConfig.host + ":" + this.serverConfig.port]; + }) + + var _ping = function(__db, __serverInstance) { + if(self.state == 'disconnected') { + self.stop(); + return; + } + + __db.open(function(err, db) { + if(self.state == 'disconnected' && __db != null) { + return __db.close(); + } + + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + // Save instance + self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port] = __db; + + // Startup time of the command + var startTime = Date.now(); + + // Execute ping on this connection + __db.executeDbCommand({ping:1}, {failFast:true}, function(err) { + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { + __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime; + } + + done(); + }); + }); + }; + + _ping(_db, serverInstance); + } + + function done() { + // Adjust the number of checks + numberOfEntries--; + + // If we are done with all results coming back trigger ping again + if(0 === numberOfEntries && 'connected' == self.state) { + setTimeout(pingFunction, self.pingInterval); + } + } + }(server); + } + } + + // Start pingFunction + pingFunction(); + + callback && callback(null); +} diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js new file mode 100644 index 0000000..f9b8c46 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js @@ -0,0 +1,80 @@ +// The Statistics strategy uses the measure of each end-start time for each +// query executed against the db to calculate the mean, variance and standard deviation +// and pick the server which the lowest mean and deviation +var StatisticsStrategy = exports.StatisticsStrategy = function(replicaset) { + this.replicaset = replicaset; + // Logger api + this.Logger = null; +} + +// Starts any needed code +StatisticsStrategy.prototype.start = function(callback) { + callback && callback(null, null); +} + +StatisticsStrategy.prototype.stop = function(callback) { + callback && callback(null, null); +} + +StatisticsStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) { + // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS + // Create a list of candidat servers, containing the primary if available + var candidateServers = []; + + // If we have not provided a list of candidate servers use the default setup + if(!Array.isArray(secondaryCandidates)) { + candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : []; + // Add all the secondaries + var keys = Object.keys(this.replicaset._state.secondaries); + for(var i = 0; i < keys.length; i++) { + candidateServers.push(this.replicaset._state.secondaries[keys[i]]) + } + } else { + candidateServers = secondaryCandidates; + } + + // Final list of eligable server + var finalCandidates = []; + + // If we have tags filter by tags + if(tags != null && typeof tags == 'object') { + // If we have an array or single tag selection + var tagObjects = Array.isArray(tags) ? tags : [tags]; + // Iterate over all tags until we find a candidate server + for(var _i = 0; _i < tagObjects.length; _i++) { + // Grab a tag object + var tagObject = tagObjects[_i]; + // Matching keys + var matchingKeys = Object.keys(tagObject); + // Remove any that are not tagged correctly + for(var i = 0; i < candidateServers.length; i++) { + var server = candidateServers[i]; + // If we have tags match + if(server.tags != null) { + var matching = true; + + // Ensure we have all the values + for(var j = 0; j < matchingKeys.length; j++) { + if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { + matching = false; + break; + } + } + + // If we have a match add it to the list of matching servers + if(matching) { + finalCandidates.push(server); + } + } + } + } + } else { + // Final array candidates + var finalCandidates = candidateServers; + } + + // If no candidates available return an error + if(finalCandidates.length == 0) return new Error("No replica set members available for query"); + // Pick a random server + return finalCandidates[Math.round(Math.random(1000000) * (finalCandidates.length - 1))].checkoutReader(); +} diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js new file mode 100644 index 0000000..b84702a --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js @@ -0,0 +1,1010 @@ +var Connection = require('./connection').Connection, + ReadPreference = require('./read_preference').ReadPreference, + DbCommand = require('../commands/db_command').DbCommand, + MongoReply = require('../responses/mongo_reply').MongoReply, + ConnectionPool = require('./connection_pool').ConnectionPool, + EventEmitter = require('events').EventEmitter, + Base = require('./base').Base, + utils = require('../utils'), + timers = require('timers'), + inherits = require('util').inherits; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; + +/** + * Class representing a single MongoDB Server connection + * + * Options + * - **readPreference** {String, default:null}, set's the read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST) + * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support) + * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher) + * - **poolSize** {Number, default:5}, number of connections in the connection pool, set to 5 as default for legacy reasons. + * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) + * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. + * - **auto_reconnect** {Boolean, default:false}, reconnect on error. + * - **disableDriverBSONSizeCheck** {Boolean, default:false}, force the server to error if the BSON message is to big + * + * @class Represents a Server connection. + * @param {String} host the server host + * @param {Number} port the server port + * @param {Object} [options] optional options for insert command + */ +function Server(host, port, options) { + // Set up Server instance + if(!(this instanceof Server)) return new Server(host, port, options); + + // Set up event emitter + Base.call(this); + + // Ensure correct values + if(port != null && typeof port == 'object') { + options = port; + port = Connection.DEFAULT_PORT; + } + + var self = this; + this.host = host; + this.port = port; + this.options = options == null ? {} : options; + this.internalConnection; + this.internalMaster = false; + this.connected = false; + this.poolSize = this.options.poolSize == null ? 5 : this.options.poolSize; + this.disableDriverBSONSizeCheck = this.options.disableDriverBSONSizeCheck != null ? this.options.disableDriverBSONSizeCheck : false; + this._used = false; + this.replicasetInstance = null; + + // Emit open setup + this.emitOpen = this.options.emitOpen || true; + // Set ssl as connection method + this.ssl = this.options.ssl == null ? false : this.options.ssl; + // Set ssl validation + this.sslValidate = this.options.sslValidate == null ? false : this.options.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.sslCA = Array.isArray(this.options.sslCA) ? this.options.sslCA : null; + // Certificate to present to the server + this.sslCert = this.options.sslCert; + // Certificate private key if in separate file + this.sslKey = this.options.sslKey; + // Password to unlock private key + this.sslPass = this.options.sslPass; + + // Ensure we are not trying to validate with no list of certificates + if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) { + throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate"); + } + + // Get the readPreference + var readPreference = this.options['readPreference']; + // If readPreference is an object get the mode string + var validateReadPreference = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference; + // Read preference setting + if(validateReadPreference != null) { + if(validateReadPreference != ReadPreference.PRIMARY && validateReadPreference != ReadPreference.SECONDARY && validateReadPreference != ReadPreference.NEAREST + && validateReadPreference != ReadPreference.SECONDARY_PREFERRED && validateReadPreference != ReadPreference.PRIMARY_PREFERRED) { + throw new Error("Illegal readPreference mode specified, " + validateReadPreference); + } + + // Set read Preference + this._readPreference = readPreference; + } else { + this._readPreference = null; + } + + // Contains the isMaster information returned from the server + this.isMasterDoc; + + // Set default connection pool options + this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {}; + if(this.disableDriverBSONSizeCheck) this.socketOptions.disableDriverBSONSizeCheck = this.disableDriverBSONSizeCheck; + + // Set ssl up if it's defined + if(this.ssl) { + this.socketOptions.ssl = true; + // Set ssl validation + this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null; + // Set certificate to present + this.socketOptions.sslCert = this.sslCert; + // Set certificate to present + this.socketOptions.sslKey = this.sslKey; + // Password to unlock private key + this.socketOptions.sslPass = this.sslPass; + } + + // Set up logger if any set + this.logger = this.options.logger != null + && (typeof this.options.logger.debug == 'function') + && (typeof this.options.logger.error == 'function') + && (typeof this.options.logger.log == 'function') + ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; + + // Just keeps list of events we allow + this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[]}; + // Internal state of server connection + this._serverState = 'disconnected'; + // Contains state information about server connection + this._state = {'runtimeStats': {'queryStats':new RunningStats()}}; + // Do we record server stats or not + this.recordQueryStats = false; +}; + +/** + * @ignore + */ +inherits(Server, Base); + +// +// Deprecated, USE ReadPreferences class +// +Server.READ_PRIMARY = ReadPreference.PRIMARY; +Server.READ_SECONDARY = ReadPreference.SECONDARY_PREFERRED; +Server.READ_SECONDARY_ONLY = ReadPreference.SECONDARY; + +/** + * Always ourselves + * @ignore + */ +Server.prototype.setReadPreference = function(readPreference) { + this._readPreference = readPreference; +} + +/** + * @ignore + */ +Server.prototype.isMongos = function() { + return this.isMasterDoc != null && this.isMasterDoc['msg'] == "isdbgrid" ? true : false; +} + +/** + * @ignore + */ +Server.prototype._isUsed = function() { + return this._used; +} + +/** + * @ignore + */ +Server.prototype.close = function(callback) { + // Set server status as disconnected + this._serverState = 'destroyed'; + // Remove all local listeners + this.removeAllListeners(); + + if(this.connectionPool != null) { + // Remove all the listeners on the pool so it does not fire messages all over the place + this.connectionPool.removeAllEventListeners(); + // Close the connection if it's open + this.connectionPool.stop(true); + } + + // Emit close event + if(this.db && !this.isSetMember()) { + var self = this; + processor(function() { + self._emitAcrossAllDbInstances(self, null, "close", null, null, true) + }) + } + + // Peform callback if present + if(typeof callback === 'function') callback(null); +}; + +Server.prototype.isDestroyed = function() { + return this._serverState == 'destroyed'; +} + +/** + * @ignore + */ +Server.prototype.isConnected = function() { + return this.connectionPool.isConnected(); +} + +/** + * @ignore + */ +Server.prototype.canWrite = Server.prototype.isConnected; +Server.prototype.canRead = Server.prototype.isConnected; + +Server.prototype.isAutoReconnect = function() { + if(this.isSetMember()) return false; + return this.options.auto_reconnect != null ? this.options.auto_reconnect : true; +} + +/** + * @ignore + */ +Server.prototype.allServerInstances = function() { + return [this]; +} + +/** + * @ignore + */ +Server.prototype.isSetMember = function() { + return this.replicasetInstance != null || this.mongosInstance != null; +} + +/** + * Assigns a replica set to this `server`. + * + * @param {ReplSet} replset + * @ignore + */ +Server.prototype.assignReplicaSet = function (replset) { + this.replicasetInstance = replset; + this.inheritReplSetOptionsFrom(replset); + this.enableRecordQueryStats(replset.recordQueryStats); +} + +/** + * Takes needed options from `replset` and overwrites + * our own options. + * + * @param {ReplSet} replset + * @ignore + */ +Server.prototype.inheritReplSetOptionsFrom = function (replset) { + this.socketOptions = {}; + this.socketOptions.connectTimeoutMS = replset.options.socketOptions.connectTimeoutMS || 30000; + + if(replset.options.ssl) { + // Set ssl on + this.socketOptions.ssl = true; + // Set ssl validation + this.socketOptions.sslValidate = replset.options.sslValidate == null ? false : replset.options.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.socketOptions.sslCA = Array.isArray(replset.options.sslCA) ? replset.options.sslCA : null; + // Set certificate to present + this.socketOptions.sslCert = replset.options.sslCert; + // Set certificate to present + this.socketOptions.sslKey = replset.options.sslKey; + // Password to unlock private key + this.socketOptions.sslPass = replset.options.sslPass; + } + + // If a socket option object exists clone it + if(utils.isObject(replset.options.socketOptions)) { + var keys = Object.keys(replset.options.socketOptions); + for(var i = 0; i < keys.length; i++) + this.socketOptions[keys[i]] = replset.options.socketOptions[keys[i]]; + } +} + +/** + * Opens this server connection. + * + * @ignore + */ +Server.prototype.connect = function(dbInstance, options, callback) { + if('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + var self = this; + // Save the options + this.options = options; + + // Currently needed to work around problems with multiple connections in a pool with ssl + // TODO fix if possible + if(this.ssl == true) { + // Set up socket options for ssl + this.socketOptions.ssl = true; + // Set ssl validation + this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null; + // Set certificate to present + this.socketOptions.sslCert = this.sslCert; + // Set certificate to present + this.socketOptions.sslKey = this.sslKey; + // Password to unlock private key + this.socketOptions.sslPass = this.sslPass; + } + + // Let's connect + var server = this; + // Let's us override the main receiver of events + var eventReceiver = options.eventReceiver != null ? options.eventReceiver : this; + // Save reference to dbInstance + this.db = dbInstance; // `db` property matches ReplSet and Mongos + this.dbInstances = [dbInstance]; + + // Force connection pool if there is one + if(server.connectionPool) server.connectionPool.stop(); + // Set server state to connecting + this._serverState = 'connecting'; + + if(server.connectionPool != null) { + // Remove all the listeners on the pool so it does not fire messages all over the place + this.connectionPool.removeAllEventListeners(); + // Close the connection if it's open + this.connectionPool.stop(true); + } + + this.connectionPool = new ConnectionPool(this.host, this.port, this.poolSize, dbInstance.bson, this.socketOptions); + var connectionPool = this.connectionPool; + // If ssl is not enabled don't wait between the pool connections + if(this.ssl == null || !this.ssl) connectionPool._timeToWait = null; + // Set logger on pool + connectionPool.logger = this.logger; + connectionPool.bson = dbInstance.bson; + + // Set basic parameters passed in + var returnIsMasterResults = options.returnIsMasterResults == null ? false : options.returnIsMasterResults; + + // Create a default connect handler, overriden when using replicasets + var connectCallback = function(_server) { + return function(err, reply) { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Assign the server + _server = _server != null ? _server : server; + + // If something close down the connection and removed the callback before + // proxy killed connection etc, ignore the erorr as close event was isssued + if(err != null && internalCallback == null) return; + // Internal callback + if(err != null) return internalCallback(err, null, _server); + _server.master = reply.documents[0].ismaster == 1 ? true : false; + _server.connectionPool.setMaxBsonSize(reply.documents[0].maxBsonObjectSize); + _server.connectionPool.setMaxMessageSizeBytes(reply.documents[0].maxMessageSizeBytes); + // Set server state to connEcted + _server._serverState = 'connected'; + // Set server as connected + _server.connected = true; + // Save document returned so we can query it + _server.isMasterDoc = reply.documents[0]; + + if(self.emitOpen) + _server._emitAcrossAllDbInstances(_server, eventReceiver, "open", null, returnIsMasterResults ? reply : dbInstance, null); + + // If we have it set to returnIsMasterResults + if(returnIsMasterResults) { + internalCallback(null, reply, _server); + } else { + internalCallback(null, dbInstance, _server); + } + } + }; + + // Let's us override the main connect callback + var connectHandler = options.connectHandler == null ? connectCallback(server) : options.connectHandler; + + // Set up on connect method + connectionPool.on("poolReady", function() { + // Create db command and Add the callback to the list of callbacks by the request id (mapping outgoing messages to correct callbacks) + var db_command = DbCommand.NcreateIsMasterCommand(dbInstance, dbInstance.databaseName); + // Check out a reader from the pool + var connection = connectionPool.checkoutConnection(); + // Register handler for messages + server._registerHandler(db_command, false, connection, connectHandler); + // Write the command out + connection.write(db_command); + }) + + // Set up item connection + connectionPool.on("message", function(message) { + // Attempt to parse the message + try { + // Create a new mongo reply + var mongoReply = new MongoReply() + // Parse the header + mongoReply.parseHeader(message, connectionPool.bson) + + // If message size is not the same as the buffer size + // something went terribly wrong somewhere + if(mongoReply.messageLength != message.length) { + // Emit the error + if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", new Error("bson length is different from message length"), server); + // Remove all listeners + server.removeAllListeners(); + } else { + var startDate = new Date().getTime(); + + // Callback instance + var callbackInfo = server._findHandler(mongoReply.responseTo.toString()); + + // The command executed another request, log the handler again under that request id + if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0" + && callbackInfo && callbackInfo.info && callbackInfo.info.exhaust) { + server._reRegisterHandler(mongoReply.requestId, callbackInfo); + } + + // Only execute callback if we have a caller + // chained is for findAndModify as it does not respect write concerns + if(callbackInfo && callbackInfo.callback && callbackInfo.info && Array.isArray(callbackInfo.info.chained)) { + // Check if callback has already been fired (missing chain command) + var chained = callbackInfo.info.chained; + var numberOfFoundCallbacks = 0; + for(var i = 0; i < chained.length; i++) { + if(server._hasHandler(chained[i])) numberOfFoundCallbacks++; + } + + // If we have already fired then clean up rest of chain and move on + if(numberOfFoundCallbacks != chained.length) { + for(var i = 0; i < chained.length; i++) { + server._removeHandler(chained[i]); + } + + // Just return from function + return; + } + + // Parse the body + mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) { + if(err != null) { + // If pool connection is already closed + if(server._serverState === 'disconnected') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // Remove all listeners and close the connection pool + server.removeAllListeners(); + connectionPool.stop(true); + + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(new Error("connection closed due to parseError"), null, server); + } else if(server.isSetMember()) { + if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", new Error("connection closed due to parseError"), server); + } else { + if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", new Error("connection closed due to parseError"), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(new Error("connection closed due to parseError")); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); + } + // Short cut + return; + } + + // Fetch the callback + var callbackInfo = server._findHandler(mongoReply.responseTo.toString()); + // If we have an error let's execute the callback and clean up all other + // chained commands + var firstResult = mongoReply && mongoReply.documents; + + // Check for an error, if we have one let's trigger the callback and clean up + // The chained callbacks + if(firstResult[0].err != null || firstResult[0].errmsg != null) { + // Cleanup the remaining callback + if(Array.isArray(callbackInfo.info.chained)) { + for(var i = 0; i < callbackInfo.info.chained.length; i++) { + if(callbackInfo.info.chained[i] != mongoReply.responseTo) + server._removeHandler(callbackInfo.info.chained[i]); + } + } + + // Trigger the callback for the error + server._callHandler(mongoReply.responseTo, mongoReply, null); + + // If we have an error about the server not being master or primary + if((mongoReply.responseFlag & (1 << 1)) != 0 + && mongoReply.documents[0].code + && mongoReply.documents[0].code == 13436) { + server.close(); + } + // server._callHandler(mongoReply.responseTo, mongoReply, null); + } else { + var chainedIds = callbackInfo.info.chained; + + if(chainedIds.length > 0 && chainedIds[chainedIds.length - 1] == mongoReply.responseTo) { + // Cleanup all other chained calls + chainedIds.pop(); + // Remove listeners + for(var i = 0; i < chainedIds.length; i++) server._removeHandler(chainedIds[i]); + + // Call the handler + server._callHandler(mongoReply.responseTo, callbackInfo.info.results.shift(), null); + + // If we have an error about the server not being master or primary + if((mongoReply.responseFlag & (1 << 1)) != 0 + && mongoReply.documents[0].code + && mongoReply.documents[0].code == 13436) { + server.close(); + } + } else{ + // Add the results to all the results + for(var i = 0; i < chainedIds.length; i++) { + var handler = server._findHandler(chainedIds[i]); + // Check if we have an object, if it's the case take the current object commands and + // and add this one + if(handler.info != null) { + handler.info.results = Array.isArray(callbackInfo.info.results) ? callbackInfo.info.results : []; + handler.info.results.push(mongoReply); + } + } + } + } + }); + } else if(callbackInfo && callbackInfo.callback && callbackInfo.info) { + // Parse the body + mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) { + if(err != null) { + // If pool connection is already closed + if(server._serverState === 'disconnected') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // Remove all listeners and close the connection pool + server.removeAllListeners(); + connectionPool.stop(true); + + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(new Error("connection closed due to parseError"), null, server); + } else if(server.isSetMember()) { + if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", new Error("connection closed due to parseError"), server); + } else { + if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", new Error("connection closed due to parseError"), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(new Error("connection closed due to parseError")); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); + } + // Short cut + return; + } + + // Let's record the stats info if it's enabled + if(server.recordQueryStats == true && server._state['runtimeStats'] != null + && server._state.runtimeStats['queryStats'] instanceof RunningStats) { + // Add data point to the running statistics object + server._state.runtimeStats.queryStats.push(new Date().getTime() - callbackInfo.info.start); + } + + // Dispatch the call + server._callHandler(mongoReply.responseTo, mongoReply, null); + + // If we have an error about the server not being master or primary + if((mongoReply.responseFlag & (1 << 1)) != 0 + && mongoReply.documents[0].code + && mongoReply.documents[0].code == 13436) { + server.close(); + } + }); + } + } + } catch (err) { + // Throw error in next tick + processor(function() { + throw err; + }) + } + }); + + // Handle timeout + connectionPool.on("timeout", function(err) { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(err, null, server); + } else if(server.isSetMember()) { + if(server.listeners("timeout") && server.listeners("timeout").length > 0) server.emit("timeout", err, server); + } else { + if(eventReceiver.listeners("timeout") && eventReceiver.listeners("timeout").length > 0) eventReceiver.emit("timeout", err, server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(err); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "timeout", err, server, true); + } + }); + + // Handle errors + connectionPool.on("error", function(message, connection, error_options) { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // Error message + var error_message = new Error(message && message.err ? message.err : message); + // Error message coming from ssl + if(error_options && error_options.ssl) error_message.ssl = true; + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(error_message, null, server); + } else if(server.isSetMember()) { + if(server.listeners("error") && server.listeners("error").length > 0) server.emit("error", error_message, server); + } else { + if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", error_message, server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(error_message); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "error", error_message, server, true); + } + + // If we have autoConnect enabled let's fire up an attempt to reconnect + if(server.isAutoReconnect() + && !server.isSetMember() + && (server._serverState != 'destroyed') + && !server._reconnectInProgreess) { + + // Set the number of retries + server._reconnect_retries = server.db.numberOfRetries; + // Attempt reconnect + server._reconnectInProgreess = true; + setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + }); + + // Handle close events + connectionPool.on("close", function() { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // If we have a callback return the error + if(typeof callback == 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(new Error("connection closed"), null, server); + } else if(server.isSetMember()) { + if(server.listeners("close") && server.listeners("close").length > 0) server.emit("close", new Error("connection closed"), server); + } else { + if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(new Error("connection closed")); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "close", server, null, true); + } + + // If we have autoConnect enabled let's fire up an attempt to reconnect + if(server.isAutoReconnect() + && !server.isSetMember() + && (server._serverState != 'destroyed') + && !server._reconnectInProgreess) { + + // Set the number of retries + server._reconnect_retries = server.db.numberOfRetries; + // Attempt reconnect + server._reconnectInProgreess = true; + setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + }); + + /** + * @ignore + */ + var __attemptReconnect = function(server) { + return function() { + // Attempt reconnect + server.connect(server.db, server.options, function(err, result) { + server._reconnect_retries = server._reconnect_retries - 1; + + if(err) { + // Retry + if(server._reconnect_retries == 0 || server._serverState == 'destroyed') { + server._serverState = 'connected'; + server._reconnectInProgreess = false + // Fire all callback errors + return server.__executeAllCallbacksWithError(new Error("failed to reconnect to server")); + } else { + return setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + } else { + // Set as authenticating (isConnected will be false) + server._serverState = 'authenticating'; + // Apply any auths, we don't try to catch any errors here + // as there are nowhere to simply propagate them to + self._apply_auths(server.db, function(err, result) { + server._serverState = 'connected'; + server._reconnectInProgreess = false; + server._commandsStore.execute_queries(); + server._commandsStore.execute_writes(); + }); + } + }); + } + } + + // If we have a parser error we are in an unknown state, close everything and emit + // error + connectionPool.on("parseError", function(message) { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(new Error("connection closed due to parseError"), null, server); + } else if(server.isSetMember()) { + if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", new Error("connection closed due to parseError"), server); + } else { + if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", new Error("connection closed due to parseError"), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(new Error("connection closed due to parseError")); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); + } + }); + + // Boot up connection poole, pass in a locator of callbacks + connectionPool.start(); +} + +/** + * @ignore + */ +Server.prototype.allRawConnections = function() { + return this.connectionPool.getAllConnections(); +} + +/** + * Check if a writer can be provided + * @ignore + */ +var canCheckoutWriter = function(self, read) { + // We cannot write to an arbiter or secondary server + if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) { + return new Error("Cannot write to an arbiter"); + } if(self.isMasterDoc['secondary'] == true) { + return new Error("Cannot write to a secondary"); + } else if(read == true && self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc['ismaster'] == true) { + return new Error("Cannot read from primary when secondary only specified"); + } + + // Return no error + return null; +} + +/** + * @ignore + */ +Server.prototype.checkoutWriter = function(read) { + if(read == true) return this.connectionPool.checkoutConnection(); + // Check if are allowed to do a checkout (if we try to use an arbiter f.ex) + var result = canCheckoutWriter(this, read); + // If the result is null check out a writer + if(result == null && this.connectionPool != null) { + return this.connectionPool.checkoutConnection(); + } else if(result == null) { + return null; + } else { + return result; + } +} + +/** + * Check if a reader can be provided + * @ignore + */ +var canCheckoutReader = function(self) { + // We cannot write to an arbiter or secondary server + if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) { + return new Error("Cannot write to an arbiter"); + } else if(self._readPreference != null) { + // If the read preference is Primary and the instance is not a master return an error + if((self._readPreference == ReadPreference.PRIMARY) && self.isMasterDoc['ismaster'] != true) { + return new Error("Read preference is Server.PRIMARY and server is not master"); + } else if(self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc['ismaster'] == true) { + return new Error("Cannot read from primary when secondary only specified"); + } + } + + // Return no error + return null; +} + +/** + * @ignore + */ +Server.prototype.checkoutReader = function(read) { + // Check if are allowed to do a checkout (if we try to use an arbiter f.ex) + var result = canCheckoutReader(this); + // If the result is null check out a writer + if(result == null && this.connectionPool != null) { + return this.connectionPool.checkoutConnection(); + } else if(result == null) { + return null; + } else { + return result; + } +} + +/** + * @ignore + */ +Server.prototype.enableRecordQueryStats = function(enable) { + this.recordQueryStats = enable; +} + +/** + * Internal statistics object used for calculating average and standard devitation on + * running queries + * @ignore + */ +var RunningStats = function() { + var self = this; + this.m_n = 0; + this.m_oldM = 0.0; + this.m_oldS = 0.0; + this.m_newM = 0.0; + this.m_newS = 0.0; + + // Define getters + Object.defineProperty(this, "numDataValues", { enumerable: true + , get: function () { return this.m_n; } + }); + + Object.defineProperty(this, "mean", { enumerable: true + , get: function () { return (this.m_n > 0) ? this.m_newM : 0.0; } + }); + + Object.defineProperty(this, "variance", { enumerable: true + , get: function () { return ((this.m_n > 1) ? this.m_newS/(this.m_n - 1) : 0.0); } + }); + + Object.defineProperty(this, "standardDeviation", { enumerable: true + , get: function () { return Math.sqrt(this.variance); } + }); + + Object.defineProperty(this, "sScore", { enumerable: true + , get: function () { + var bottom = this.mean + this.standardDeviation; + if(bottom == 0) return 0; + return ((2 * this.mean * this.standardDeviation)/(bottom)); + } + }); +} + +/** + * @ignore + */ +RunningStats.prototype.push = function(x) { + // Update the number of samples + this.m_n = this.m_n + 1; + // See Knuth TAOCP vol 2, 3rd edition, page 232 + if(this.m_n == 1) { + this.m_oldM = this.m_newM = x; + this.m_oldS = 0.0; + } else { + this.m_newM = this.m_oldM + (x - this.m_oldM) / this.m_n; + this.m_newS = this.m_oldS + (x - this.m_oldM) * (x - this.m_newM); + + // set up for next iteration + this.m_oldM = this.m_newM; + this.m_oldS = this.m_newS; + } +} + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "autoReconnect", { enumerable: true + , get: function () { + return this.options['auto_reconnect'] == null ? false : this.options['auto_reconnect']; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "connection", { enumerable: true + , get: function () { + return this.internalConnection; + } + , set: function(connection) { + this.internalConnection = connection; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "master", { enumerable: true + , get: function () { + return this.internalMaster; + } + , set: function(value) { + this.internalMaster = value; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "primary", { enumerable: true + , get: function () { + return this; + } +}); + +/** + * Getter for query Stats + * @ignore + */ +Object.defineProperty(Server.prototype, "queryStats", { enumerable: true + , get: function () { + return this._state.runtimeStats.queryStats; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "runtimeStats", { enumerable: true + , get: function () { + return this._state.runtimeStats; + } +}); + +/** + * Get Read Preference method + * @ignore + */ +Object.defineProperty(Server.prototype, "readPreference", { enumerable: true + , get: function () { + if(this._readPreference == null && this.readSecondary) { + return Server.READ_SECONDARY; + } else if(this._readPreference == null && !this.readSecondary) { + return Server.READ_PRIMARY; + } else { + return this._readPreference; + } + } +}); + +/** + * @ignore + */ +exports.Server = Server; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/url_parser.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/url_parser.js new file mode 100644 index 0000000..347aee0 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/url_parser.js @@ -0,0 +1,251 @@ +var fs = require('fs'), + ReadPreference = require('./read_preference').ReadPreference; + +exports.parse = function(url, options) { + // Ensure we have a default options object if none set + options = options || {}; + // Variables + var connection_part = ''; + var auth_part = ''; + var query_string_part = ''; + var dbName = 'admin'; + + // Must start with mongodb + if(url.indexOf("mongodb://") != 0) + throw Error("URL must be in the format mongodb://user:pass@host:port/dbname"); + // If we have a ? mark cut the query elements off + if(url.indexOf("?") != -1) { + query_string_part = url.substr(url.indexOf("?") + 1); + connection_part = url.substring("mongodb://".length, url.indexOf("?")) + } else { + connection_part = url.substring("mongodb://".length); + } + + // Check if we have auth params + if(connection_part.indexOf("@") != -1) { + auth_part = connection_part.split("@")[0]; + connection_part = connection_part.split("@")[1]; + } + + // Check if the connection string has a db + if(connection_part.indexOf(".sock") != -1) { + if(connection_part.indexOf(".sock/") != -1) { + dbName = connection_part.split(".sock/")[1]; + connection_part = connection_part.split("/", connection_part.indexOf(".sock") + ".sock".length); + } + } else if(connection_part.indexOf("/") != -1) { + dbName = connection_part.split("/")[1]; + connection_part = connection_part.split("/")[0]; + } + + // Result object + var object = {}; + + // Pick apart the authentication part of the string + var authPart = auth_part || ''; + var auth = authPart.split(':', 2); + if(options['uri_decode_auth']){ + auth[0] = decodeURIComponent(auth[0]); + if(auth[1]){ + auth[1] = decodeURIComponent(auth[1]); + } + } + + // Add auth to final object if we have 2 elements + if(auth.length == 2) object.auth = {user: auth[0], password: auth[1]}; + + // Variables used for temporary storage + var hostPart; + var urlOptions; + var servers; + var serverOptions = {socketOptions: {}}; + var dbOptions = {read_preference_tags: []}; + var replSetServersOptions = {socketOptions: {}}; + // Add server options to final object + object.server_options = serverOptions; + object.db_options = dbOptions; + object.rs_options = replSetServersOptions; + object.mongos_options = {}; + + // Let's check if we are using a domain socket + if(url.match(/\.sock/)) { + // Split out the socket part + var domainSocket = url.substring( + url.indexOf("mongodb://") + "mongodb://".length + , url.lastIndexOf(".sock") + ".sock".length); + // Clean out any auth stuff if any + if(domainSocket.indexOf("@") != -1) domainSocket = domainSocket.split("@")[1]; + servers = [{domain_socket: domainSocket}]; + } else { + // Split up the db + hostPart = connection_part; + // Parse all server results + servers = hostPart.split(',').map(function(h) { + var hostPort = h.split(':', 2); + var _host = hostPort[0] || 'localhost'; + var _port = hostPort[1] != null ? parseInt(hostPort[1], 10) : 27017; + // Check for localhost?safe=true style case + if(_host.indexOf("?") != -1) _host = _host.split(/\?/)[0]; + + // Return the mapped object + return {host: _host, port: _port}; + }); + } + + // Get the db name + object.dbName = dbName || 'admin'; + // Split up all the options + urlOptions = (query_string_part || '').split(/[&;]/); + // Ugh, we have to figure out which options go to which constructor manually. + urlOptions.forEach(function(opt) { + if(!opt) return; + var splitOpt = opt.split('='), name = splitOpt[0], value = splitOpt[1]; + // Options implementations + switch(name) { + case 'slaveOk': + case 'slave_ok': + serverOptions.slave_ok = (value == 'true'); + dbOptions.slaveOk = (value == 'true'); + break; + case 'maxPoolSize': + case 'poolSize': + serverOptions.poolSize = parseInt(value, 10); + replSetServersOptions.poolSize = parseInt(value, 10); + break; + case 'autoReconnect': + case 'auto_reconnect': + serverOptions.auto_reconnect = (value == 'true'); + break; + case 'minPoolSize': + throw new Error("minPoolSize not supported"); + case 'maxIdleTimeMS': + throw new Error("maxIdleTimeMS not supported"); + case 'waitQueueMultiple': + throw new Error("waitQueueMultiple not supported"); + case 'waitQueueTimeoutMS': + throw new Error("waitQueueTimeoutMS not supported"); + case 'uuidRepresentation': + throw new Error("uuidRepresentation not supported"); + case 'ssl': + if(value == 'prefer') { + serverOptions.ssl = value; + replSetServersOptions.ssl = value; + break; + } + serverOptions.ssl = (value == 'true'); + replSetServersOptions.ssl = (value == 'true'); + break; + case 'replicaSet': + case 'rs_name': + replSetServersOptions.rs_name = value; + break; + case 'reconnectWait': + replSetServersOptions.reconnectWait = parseInt(value, 10); + break; + case 'retries': + replSetServersOptions.retries = parseInt(value, 10); + break; + case 'readSecondary': + case 'read_secondary': + replSetServersOptions.read_secondary = (value == 'true'); + break; + case 'fsync': + dbOptions.fsync = (value == 'true'); + break; + case 'journal': + dbOptions.journal = (value == 'true'); + break; + case 'safe': + dbOptions.safe = (value == 'true'); + break; + case 'nativeParser': + case 'native_parser': + dbOptions.native_parser = (value == 'true'); + break; + case 'connectTimeoutMS': + serverOptions.socketOptions.connectTimeoutMS = parseInt(value, 10); + replSetServersOptions.socketOptions.connectTimeoutMS = parseInt(value, 10); + break; + case 'socketTimeoutMS': + serverOptions.socketOptions.socketTimeoutMS = parseInt(value, 10); + replSetServersOptions.socketOptions.socketTimeoutMS = parseInt(value, 10); + break; + case 'w': + dbOptions.w = parseInt(value, 10); + break; + case 'authSource': + dbOptions.authSource = value; + break; + case 'gssapiServiceName': + dbOptions.gssapiServiceName = value; + break; + case 'authMechanism': + if(value == 'GSSAPI') { + // If no password provided decode only the principal + if(object.auth == null) { + var urlDecodeAuthPart = decodeURIComponent(authPart); + if(urlDecodeAuthPart.indexOf("@") == -1) throw new Error("GSSAPI requires a provided principal"); + object.auth = {user: urlDecodeAuthPart, password: null}; + } else { + object.auth.user = decodeURIComponent(object.auth.user); + } + } + + // Only support GSSAPI or MONGODB-CR for now + if(value != 'GSSAPI' + && value != 'MONGODB-CR' + && value != 'PLAIN') + throw new Error("only GSSAPI, PLAIN or MONGODB-CR is supported by authMechanism"); + + // Authentication mechanism + dbOptions.authMechanism = value; + break; + case 'wtimeoutMS': + dbOptions.wtimeoutMS = parseInt(value, 10); + break; + case 'readPreference': + if(!ReadPreference.isValid(value)) throw new Error("readPreference must be either primary/primaryPreferred/secondary/secondaryPreferred/nearest"); + dbOptions.read_preference = value; + break; + case 'readPreferenceTags': + // Contains the tag object + var tagObject = {}; + if(value == null || value == '') { + dbOptions.read_preference_tags.push(tagObject); + break; + } + + // Split up the tags + var tags = value.split(/\,/); + for(var i = 0; i < tags.length; i++) { + var parts = tags[i].trim().split(/\:/); + tagObject[parts[0]] = parts[1]; + } + + // Set the preferences tags + dbOptions.read_preference_tags.push(tagObject); + break; + default: + break; + } + }); + + // No tags: should be null (not []) + if(dbOptions.read_preference_tags.length === 0) { + dbOptions.read_preference_tags = null; + } + + // Validate if there are an invalid write concern combinations + if((dbOptions.w == -1 || dbOptions.w == 0) && ( + dbOptions.journal == true + || dbOptions.fsync == true + || dbOptions.safe == true)) throw new Error("w set to -1 or 0 cannot be combined with safe/w/journal/fsync") + + // If no read preference set it to primary + if(!dbOptions.read_preference) dbOptions.read_preference = 'primary'; + + // Add servers to result + object.servers = servers; + // Returned parsed object + return object; +} diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js new file mode 100644 index 0000000..da645cb --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js @@ -0,0 +1,948 @@ +var QueryCommand = require('./commands/query_command').QueryCommand, + GetMoreCommand = require('./commands/get_more_command').GetMoreCommand, + KillCursorCommand = require('./commands/kill_cursor_command').KillCursorCommand, + Long = require('bson').Long, + ReadPreference = require('./connection/read_preference').ReadPreference, + CursorStream = require('./cursorstream'), + timers = require('timers'), + utils = require('./utils'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; + +/** + * Constructor for a cursor object that handles all the operations on query result + * using find. This cursor object is unidirectional and cannot traverse backwards. Clients should not be creating a cursor directly, + * but use find to acquire a cursor. (INTERNAL TYPE) + * + * Options + * - **skip** {Number} skip number of documents to skip. + * - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1. + * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. + * - **hint** {Object}, hint force the query to use a specific index. + * - **explain** {Boolean}, explain return the explaination of the query. + * - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned. + * - **timeout** {Boolean}, timeout allow the query to timeout. + * - **tailable** {Boolean}, tailable allow the cursor to be tailable. + * - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor. + * - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database. + * - **raw** {Boolean}, raw return all query documents as raw buffers (default false). + * - **read** {Boolean}, read specify override of read from source (primary/secondary). + * - **returnKey** {Boolean}, returnKey only return the index key. + * - **maxScan** {Number}, maxScan limit the number of items to scan. + * - **min** {Number}, min set index bounds. + * - **max** {Number}, max set index bounds. + * - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results. + * - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler. + * - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout. + * - **dbName** {String}, dbName override the default dbName. + * - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor. + * - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets. + * - **partial** {Boolean}, partial have the sharded system return a partial result from mongos. + * + * @class Represents a Cursor. + * @param {Db} db the database object to work with. + * @param {Collection} collection the collection to query. + * @param {Object} selector the query selector. + * @param {Object} fields an object containing what fields to include or exclude from objects returned. + * @param {Object} [options] additional options for the collection. +*/ +function Cursor(db, collection, selector, fields, options) { + this.db = db; + this.collection = collection; + this.selector = selector; + this.fields = fields; + options = !options ? {} : options; + + this.skipValue = options.skip == null ? 0 : options.skip; + this.limitValue = options.limit == null ? 0 : options.limit; + this.sortValue = options.sort; + this.hint = options.hint; + this.explainValue = options.explain; + this.snapshot = options.snapshot; + this.timeout = options.timeout == null ? true : options.timeout; + this.tailable = options.tailable; + this.awaitdata = options.awaitdata; + this.numberOfRetries = options.numberOfRetries == null ? 5 : options.numberOfRetries; + this.currentNumberOfRetries = this.numberOfRetries; + this.batchSizeValue = options.batchSize == null ? 0 : options.batchSize; + this.raw = options.raw == null ? false : options.raw; + this.read = options.read == null ? ReadPreference.PRIMARY : options.read; + this.returnKey = options.returnKey; + this.maxScan = options.maxScan; + this.min = options.min; + this.max = options.max; + this.showDiskLoc = options.showDiskLoc; + this.comment = options.comment; + this.tailableRetryInterval = options.tailableRetryInterval || 100; + this.exhaust = options.exhaust || false; + this.partial = options.partial || false; + this.slaveOk = options.slaveOk || false; + + this.totalNumberOfRecords = 0; + this.items = []; + this.cursorId = Long.fromInt(0); + + // This name + this.dbName = options.dbName; + + // State variables for the cursor + this.state = Cursor.INIT; + // Keep track of the current query run + this.queryRun = false; + this.getMoreTimer = false; + + // If we are using a specific db execute against it + if(this.dbName != null) { + this.collectionName = this.dbName + "." + this.collection.collectionName; + } else { + this.collectionName = (this.db.databaseName ? this.db.databaseName + "." : '') + this.collection.collectionName; + } +}; + +/** + * Resets this cursor to its initial state. All settings like the query string, + * tailable, batchSizeValue, skipValue and limits are preserved. + * + * @return {Cursor} returns itself with rewind applied. + * @api public + */ +Cursor.prototype.rewind = function() { + var self = this; + + if (self.state != Cursor.INIT) { + if (self.state != Cursor.CLOSED) { + self.close(function() {}); + } + + self.numberOfReturned = 0; + self.totalNumberOfRecords = 0; + self.items = []; + self.cursorId = Long.fromInt(0); + self.state = Cursor.INIT; + self.queryRun = false; + } + + return self; +}; + + +/** + * Returns an array of documents. The caller is responsible for making sure that there + * is enough memory to store the results. Note that the array only contain partial + * results when this cursor had been previouly accessed. In that case, + * cursor.rewind() can be used to reset the cursor. + * + * @param {Function} callback This will be called after executing this method successfully. The first parameter will contain the Error object if an error occured, or null otherwise. The second parameter will contain an array of BSON deserialized objects as a result of the query. + * @return {null} + * @api public + */ +Cursor.prototype.toArray = function(callback) { + var self = this; + + if(!callback) { + throw new Error('callback is mandatory'); + } + + if(this.tailable) { + callback(new Error("Tailable cursor cannot be converted to array"), null); + } else if(this.state != Cursor.CLOSED) { + // return toArrayExhaust(self, callback); + // If we are using exhaust we can't use the quick fire method + if(self.exhaust) return toArrayExhaust(self, callback); + // Quick fire using trampoline to avoid nextTick + self.nextObject({noReturn: true}, function(err, result) { + if(err) return callback(utils.toError(err), null); + if(self.cursorId.toString() == "0") { + self.state = Cursor.CLOSED; + return callback(null, self.items); + } + + // Let's issue getMores until we have no more records waiting + getAllByGetMore(self, function(err, done) { + self.state = Cursor.CLOSED; + if(err) return callback(utils.toError(err), null); + // Let's release the internal list + var items = self.items; + self.items = null; + // Return all the items + callback(null, items); + }); + }) + + } else { + callback(new Error("Cursor is closed"), null); + } +} + +var toArrayExhaust = function(self, callback) { + var items = []; + + self.each(function(err, item) { + if(err != null) { + return callback(utils.toError(err), null); + } + + if(item != null && Array.isArray(items)) { + items.push(item); + } else { + var resultItems = items; + items = null; + self.items = []; + callback(null, resultItems); + } + }); +} + +var getAllByGetMore = function(self, callback) { + getMore(self, {noReturn: true}, function(err, result) { + if(err) return callback(utils.toError(err)); + if(result == null) return callback(null, null); + if(self.cursorId.toString() == "0") return callback(null, null); + getAllByGetMore(self, callback); + }) +} + +/** + * Iterates over all the documents for this cursor. As with **{cursor.toArray}**, + * not all of the elements will be iterated if this cursor had been previouly accessed. + * In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike + * **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements + * at any given time if batch size is specified. Otherwise, the caller is responsible + * for making sure that the entire result can fit the memory. + * + * @param {Function} callback this will be called for while iterating every document of the query result. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the document. + * @return {null} + * @api public + */ +Cursor.prototype.each = function(callback) { + var self = this; + var fn; + + if (!callback) { + throw new Error('callback is mandatory'); + } + + if(this.state != Cursor.CLOSED) { + // If we are using exhaust we can't use the quick fire method + if(self.exhaust) return eachExhaust(self, callback); + // Quick fire using trampoline to avoid nextTick + if(this.items.length > 0) { + // Trampoline all the entries + while(fn = loop(self, callback)) fn(self, callback); + // Call each again + self.each(callback); + } else { + self.nextObject(function(err, item) { + + if(err) { + self.state = Cursor.CLOSED; + return callback(utils.toError(err), item); + } + + if(item == null) return callback(null, null); + callback(null, item); + self.each(callback); + }) + } + } else { + callback(new Error("Cursor is closed"), null); + } +} + +// Special for exhaust command as we don't initiate the actual result sets +// the server just sends them as they arrive meaning we need to get the IO event +// loop happen so we can receive more data from the socket or we return to early +// after the first fetch and loose all the incoming getMore's automatically issued +// from the server. +var eachExhaust = function(self, callback) { + //FIX: stack overflow (on deep callback) (cred: https://github.com/limp/node-mongodb-native/commit/27da7e4b2af02035847f262b29837a94bbbf6ce2) + processor(function(){ + // Fetch the next object until there is no more objects + self.nextObject(function(err, item) { + if(err != null) return callback(err, null); + if(item != null) { + callback(null, item); + eachExhaust(self, callback); + } else { + // Close the cursor if done + self.state = Cursor.CLOSED; + callback(err, null); + } + }); + }); +} + +// Trampoline emptying the number of retrieved items +// without incurring a nextTick operation +var loop = function(self, callback) { + // No more items we are done + if(self.items.length == 0) return; + // Get the next document + var doc = self.items.shift(); + // Callback + callback(null, doc); + // Loop + return loop; +} + +/** + * Determines how many result the query for this cursor will return + * + * @param {Boolean} applySkipLimit if set to true will apply the skip and limits set on the cursor. Defaults to false. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the number of results or null if an error occured. + * @return {null} + * @api public + */ +Cursor.prototype.count = function(applySkipLimit, callback) { + if(typeof applySkipLimit == 'function') { + callback = applySkipLimit; + applySkipLimit = false; + } + + var options = {}; + if(applySkipLimit) { + if(typeof this.skipValue == 'number') options.skip = this.skipValue; + if(typeof this.limitValue == 'number') options.limit = this.limitValue; + } + + // Call count command + this.collection.count(this.selector, options, callback); +}; + +/** + * Sets the sort parameter of this cursor to the given value. + * + * This method has the following method signatures: + * (keyOrList, callback) + * (keyOrList, direction, callback) + * + * @param {String|Array|Object} keyOrList This can be a string or an array. If passed as a string, the string will be the field to sort. If passed an array, each element will represent a field to be sorted and should be an array that contains the format [string, direction]. + * @param {String|Number} direction this determines how the results are sorted. "asc", "ascending" or 1 for asceding order while "desc", "desceding or -1 for descending order. Note that the strings are case insensitive. + * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.sort = function(keyOrList, direction, callback) { + callback = callback || function(){}; + if(typeof direction === "function") { callback = direction; direction = null; } + + if(this.tailable) { + callback(new Error("Tailable cursor doesn't support sorting"), null); + } else if(this.queryRun == true || this.state == Cursor.CLOSED) { + callback(new Error("Cursor is closed"), null); + } else { + var order = keyOrList; + + if(direction != null) { + order = [[keyOrList, direction]]; + } + + this.sortValue = order; + callback(null, this); + } + return this; +}; + +/** + * Sets the limit parameter of this cursor to the given value. + * + * @param {Number} limit the new limit. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.limit = function(limit, callback) { + if(this.tailable) { + if(callback) { + callback(new Error("Tailable cursor doesn't support limit"), null); + } else { + throw new Error("Tailable cursor doesn't support limit"); + } + } else if(this.queryRun == true || this.state == Cursor.CLOSED) { + if(callback) { + callback(new Error("Cursor is closed"), null); + } else { + throw new Error("Cursor is closed"); + } + } else { + if(limit != null && limit.constructor != Number) { + if(callback) { + callback(new Error("limit requires an integer"), null); + } else { + throw new Error("limit requires an integer"); + } + } else { + this.limitValue = limit; + if(callback) return callback(null, this); + } + } + + return this; +}; + +/** + * Sets the read preference for the cursor + * + * @param {String} the read preference for the cursor, one of Server.READ_PRIMARY, Server.READ_SECONDARY, Server.READ_SECONDARY_ONLY + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the read preference given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.setReadPreference = function(readPreference, tags, callback) { + if(typeof tags == 'function') callback = tags; + + var _mode = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference; + + if(this.queryRun == true || this.state == Cursor.CLOSED) { + if(callback == null) throw new Error("Cannot change read preference on executed query or closed cursor"); + callback(new Error("Cannot change read preference on executed query or closed cursor")); + } else if(_mode != null && _mode != 'primary' + && _mode != 'secondaryOnly' && _mode != 'secondary' + && _mode != 'nearest' && _mode != 'primaryPreferred' && _mode != 'secondaryPreferred') { + if(callback == null) throw new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported"); + callback(new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported")); + } else { + this.read = readPreference; + if(callback != null) callback(null, this); + } + + return this; +} + +/** + * Sets the skip parameter of this cursor to the given value. + * + * @param {Number} skip the new skip value. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.skip = function(skip, callback) { + callback = callback || function(){}; + + if(this.tailable) { + callback(new Error("Tailable cursor doesn't support skip"), null); + } else if(this.queryRun == true || this.state == Cursor.CLOSED) { + callback(new Error("Cursor is closed"), null); + } else { + if(skip != null && skip.constructor != Number) { + callback(new Error("skip requires an integer"), null); + } else { + this.skipValue = skip; + callback(null, this); + } + } + + return this; +}; + +/** + * Sets the batch size parameter of this cursor to the given value. + * + * @param {Number} batchSize the new batch size. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.batchSize = function(batchSize, callback) { + if(this.state == Cursor.CLOSED) { + if(callback != null) { + return callback(new Error("Cursor is closed"), null); + } else { + throw new Error("Cursor is closed"); + } + } else if(batchSize != null && batchSize.constructor != Number) { + if(callback != null) { + return callback(new Error("batchSize requires an integer"), null); + } else { + throw new Error("batchSize requires an integer"); + } + } else { + this.batchSizeValue = batchSize; + if(callback != null) return callback(null, this); + } + + return this; +}; + +/** + * The limit used for the getMore command + * + * @return {Number} The number of records to request per batch. + * @ignore + * @api private + */ +var limitRequest = function(self) { + var requestedLimit = self.limitValue; + var absLimitValue = Math.abs(self.limitValue); + var absBatchValue = Math.abs(self.batchSizeValue); + + if(absLimitValue > 0) { + if (absBatchValue > 0) { + requestedLimit = Math.min(absLimitValue, absBatchValue); + } + } else { + requestedLimit = self.batchSizeValue; + } + + return requestedLimit; +}; + + +/** + * Generates a QueryCommand object using the parameters of this cursor. + * + * @return {QueryCommand} The command object + * @ignore + * @api private + */ +var generateQueryCommand = function(self) { + // Unpack the options + var queryOptions = QueryCommand.OPTS_NONE; + if(!self.timeout) { + queryOptions |= QueryCommand.OPTS_NO_CURSOR_TIMEOUT; + } + + if(self.tailable != null) { + queryOptions |= QueryCommand.OPTS_TAILABLE_CURSOR; + self.skipValue = self.limitValue = 0; + + // if awaitdata is set + if(self.awaitdata != null) { + queryOptions |= QueryCommand.OPTS_AWAIT_DATA; + } + } + + if(self.exhaust) { + queryOptions |= QueryCommand.OPTS_EXHAUST; + } + + // Unpack the read preference to set slave ok correctly + var read = self.read instanceof ReadPreference ? self.read.mode : self.read; + + // if(self.read == 'secondary') + if(read == ReadPreference.PRIMARY_PREFERRED + || read == ReadPreference.SECONDARY + || read == ReadPreference.SECONDARY_PREFERRED + || read == ReadPreference.NEAREST) { + queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Override slaveOk from the user + if(self.slaveOk) { + queryOptions |= QueryCommand.OPTS_SLAVE; + } + + if(self.partial) { + queryOptions |= QueryCommand.OPTS_PARTIAL; + } + + // limitValue of -1 is a special case used by Db#eval + var numberToReturn = self.limitValue == -1 ? -1 : limitRequest(self); + + // Check if we need a special selector + if(self.sortValue != null || self.explainValue != null || self.hint != null || self.snapshot != null + || self.returnKey != null || self.maxScan != null || self.min != null || self.max != null + || self.showDiskLoc != null || self.comment != null) { + + // Build special selector + var specialSelector = {'$query':self.selector}; + if(self.sortValue != null) specialSelector['orderby'] = utils.formattedOrderClause(self.sortValue); + if(self.hint != null && self.hint.constructor == Object) specialSelector['$hint'] = self.hint; + if(self.snapshot != null) specialSelector['$snapshot'] = true; + if(self.returnKey != null) specialSelector['$returnKey'] = self.returnKey; + if(self.maxScan != null) specialSelector['$maxScan'] = self.maxScan; + if(self.min != null) specialSelector['$min'] = self.min; + if(self.max != null) specialSelector['$max'] = self.max; + if(self.showDiskLoc != null) specialSelector['$showDiskLoc'] = self.showDiskLoc; + if(self.comment != null) specialSelector['$comment'] = self.comment; + // If we have explain set only return a single document with automatic cursor close + if(self.explainValue != null) { + numberToReturn = (-1)*Math.abs(numberToReturn); + specialSelector['$explain'] = true; + } + + // Return the query + return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, specialSelector, self.fields); + } else { + return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, self.selector, self.fields); + } +}; + +/** + * @return {Object} Returns an object containing the sort value of this cursor with + * the proper formatting that can be used internally in this cursor. + * @ignore + * @api private + */ +Cursor.prototype.formattedOrderClause = function() { + return utils.formattedOrderClause(this.sortValue); +}; + +/** + * Converts the value of the sort direction into its equivalent numerical value. + * + * @param sortDirection {String|number} Range of acceptable values: + * 'ascending', 'descending', 'asc', 'desc', 1, -1 + * + * @return {number} The equivalent numerical value + * @throws Error if the given sortDirection is invalid + * @ignore + * @api private + */ +Cursor.prototype.formatSortValue = function(sortDirection) { + return utils.formatSortValue(sortDirection); +}; + +/** + * Gets the next document from the cursor. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results. + * @api public + */ +Cursor.prototype.nextObject = function(options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + if(self.state == Cursor.INIT) { + var cmd; + try { + cmd = generateQueryCommand(self); + } catch (err) { + return callback(err, null); + } + + var queryOptions = {exhaust: self.exhaust, raw:self.raw, read:self.read, connection:self.connection}; + // Execute command + var commandHandler = function(err, result) { + // If on reconnect, the command got given a different connection, switch + // the whole cursor to it. + self.connection = queryOptions.connection; + self.state = Cursor.OPEN; + if(err != null && result == null) return callback(utils.toError(err), null); + + if(err == null && (result == null || result.documents == null)) { + return self.close(function() {callback(null, null);}); + } + + if(err == null && result && result.documents[0] && result.documents[0]['$err']) { + return self.close(function() {callback(utils.toError(result.documents[0]['$err']), null);}); + } + + self.queryRun = true; + self.state = Cursor.OPEN; // Adjust the state of the cursor + self.cursorId = result.cursorId; + self.totalNumberOfRecords = result.numberReturned; + + // Add the new documents to the list of items, using forloop to avoid + // new array allocations and copying + for(var i = 0; i < result.documents.length; i++) { + self.items.push(result.documents[i]); + } + + // If we have noReturn set just return (not modifying the internal item list) + // used for toArray + if(options.noReturn) { + return callback(null, true); + } + + // Ignore callbacks until the cursor is dead for exhausted + if(self.exhaust && result.cursorId.toString() == "0") { + self.nextObject(callback); + } else if(self.exhaust == false || self.exhaust == null) { + self.nextObject(callback); + } + }; + + // If we have no connection set on this cursor check one out + if(self.connection == null) { + try { + // self.connection = this.read == null ? self.db.serverConfig.checkoutWriter() : self.db.serverConfig.checkoutReader(this.read); + // console.log("++++++++++++++++++++++++++++++ checkoutReader :: CURSOR") + self.connection = self.db.serverConfig.checkoutReader(this.read); + // Add to the query options + queryOptions.connection = self.connection; + } catch(err) { + return callback(utils.toError(err), null); + } + } + + // Execute the command + self.db._executeQueryCommand(cmd, queryOptions, commandHandler); + // Set the command handler to null + commandHandler = null; + } else if(self.items.length) { + callback(null, self.items.shift()); + } else if(self.cursorId.greaterThan(Long.fromInt(0))) { + getMore(self, callback); + } else { + // Force cursor to stay open + return self.close(function() {callback(null, null);}); + } +} + +/** + * Gets more results from the database if any. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results. + * @ignore + * @api private + */ +var getMore = function(self, options, callback) { + var limit = 0; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + if(self.state == Cursor.GET_MORE) return callback(null, null); + + // Set get more in progress + self.state = Cursor.GET_MORE; + + // Set options + if (!self.tailable && self.limitValue > 0) { + limit = self.limitValue - self.totalNumberOfRecords; + if (limit < 1) { + self.close(function() {callback(null, null);}); + return; + } + } + + try { + var getMoreCommand = new GetMoreCommand( + self.db + , self.collectionName + , limitRequest(self) + , self.cursorId + ); + + // Set up options + var command_options = {read: self.read, raw: self.raw, connection:self.connection }; + + // Execute the command + self.db._executeQueryCommand(getMoreCommand, command_options, function(err, result) { + var cbValue; + + // Get more done + self.state = Cursor.OPEN; + + if(err != null) { + self.state = Cursor.CLOSED; + return callback(utils.toError(err), null); + } + + // If the QueryFailure flag is set + if((result.responseFlag & (1 << 1)) != 0) { + self.state = Cursor.CLOSED; + return callback(utils.toError("QueryFailure flag set on getmore command"), null); + } + + try { + var isDead = 1 === result.responseFlag && result.cursorId.isZero(); + + self.cursorId = result.cursorId; + self.totalNumberOfRecords += result.numberReturned; + + // Determine if there's more documents to fetch + if(result.numberReturned > 0) { + if (self.limitValue > 0) { + var excessResult = self.totalNumberOfRecords - self.limitValue; + + if (excessResult > 0) { + result.documents.splice(-1 * excessResult, excessResult); + } + } + + // Reset the tries for awaitdata if we are using it + self.currentNumberOfRetries = self.numberOfRetries; + // Get the documents + for(var i = 0; i < result.documents.length; i++) { + self.items.push(result.documents[i]); + } + + // Don's shift a document out as we need it for toArray + if(options.noReturn) { + cbValue = true; + } else { + cbValue = self.items.shift(); + } + } else if(self.tailable && !isDead && self.awaitdata) { + // Excute the tailable cursor once more, will timeout after ~4 sec if awaitdata used + self.currentNumberOfRetries = self.currentNumberOfRetries - 1; + if(self.currentNumberOfRetries == 0) { + self.close(function() { + callback(new Error("tailable cursor timed out"), null); + }); + } else { + getMore(self, callback); + } + } else if(self.tailable && !isDead) { + self.getMoreTimer = setTimeout(function() { getMore(self, callback); }, self.tailableRetryInterval); + } else { + self.close(function() {callback(null, null); }); + } + + result = null; + } catch(err) { + callback(utils.toError(err), null); + } + if (cbValue != null) callback(null, cbValue); + }); + + getMoreCommand = null; + } catch(err) { + // Get more done + self.state = Cursor.OPEN; + + var handleClose = function() { + callback(utils.toError(err), null); + }; + + self.close(handleClose); + handleClose = null; + } +} + +/** + * Gets a detailed information about how the query is performed on this cursor and how + * long it took the database to process it. + * + * @param {Function} callback this will be called after executing this method. The first parameter will always be null while the second parameter will be an object containing the details. + * @api public + */ +Cursor.prototype.explain = function(callback) { + var limit = (-1)*Math.abs(this.limitValue); + + // Create a new cursor and fetch the plan + var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, { + skip: this.skipValue + , limit:limit + , sort: this.sortValue + , hint: this.hint + , explain: true + , snapshot: this.snapshot + , timeout: this.timeout + , tailable: this.tailable + , batchSize: this.batchSizeValue + , slaveOk: this.slaveOk + , raw: this.raw + , read: this.read + , returnKey: this.returnKey + , maxScan: this.maxScan + , min: this.min + , max: this.max + , showDiskLoc: this.showDiskLoc + , comment: this.comment + , awaitdata: this.awaitdata + , numberOfRetries: this.numberOfRetries + , dbName: this.dbName + }); + + // Fetch the explaination document + cursor.nextObject(function(err, item) { + if(err != null) return callback(utils.toError(err), null); + // close the cursor + cursor.close(function(err, result) { + if(err != null) return callback(utils.toError(err), null); + callback(null, item); + }); + }); +}; + +/** + * Returns a Node ReadStream interface for this cursor. + * + * Options + * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting. + * + * @return {CursorStream} returns a stream object. + * @api public + */ +Cursor.prototype.stream = function stream(options) { + return new CursorStream(this, options); +} + +/** + * Close the cursor. + * + * @param {Function} callback this will be called after executing this method. The first parameter will always contain null while the second parameter will contain a reference to this cursor. + * @return {null} + * @api public + */ +Cursor.prototype.close = function(callback) { + var self = this + this.getMoreTimer && clearTimeout(this.getMoreTimer); + // Close the cursor if not needed + if(this.cursorId instanceof Long && this.cursorId.greaterThan(Long.fromInt(0))) { + try { + var command = new KillCursorCommand(this.db, [this.cursorId]); + // Added an empty callback to ensure we don't throw any null exceptions + this.db._executeQueryCommand(command, {read:self.read, raw:self.raw, connection:self.connection}, function() {}); + } catch(err) {} + } + + // Null out the connection + self.connection = null; + // Reset cursor id + this.cursorId = Long.fromInt(0); + // Set to closed status + this.state = Cursor.CLOSED; + + if(callback) { + callback(null, self); + self.items = []; + } + + return this; +}; + +/** + * Check if the cursor is closed or open. + * + * @return {Boolean} returns the state of the cursor. + * @api public + */ +Cursor.prototype.isClosed = function() { + return this.state == Cursor.CLOSED ? true : false; +}; + +/** + * Init state + * + * @classconstant INIT + **/ +Cursor.INIT = 0; + +/** + * Cursor open + * + * @classconstant OPEN + **/ +Cursor.OPEN = 1; + +/** + * Cursor closed + * + * @classconstant CLOSED + **/ +Cursor.CLOSED = 2; + +/** + * Cursor performing a get more + * + * @classconstant OPEN + **/ +Cursor.GET_MORE = 3; + +/** + * @ignore + * @api private + */ +exports.Cursor = Cursor; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursorstream.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursorstream.js new file mode 100644 index 0000000..2752091 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursorstream.js @@ -0,0 +1,164 @@ +var timers = require('timers'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; + +/** + * Module dependecies. + */ +var Stream = require('stream').Stream; + +/** + * CursorStream + * + * Returns a stream interface for the **cursor**. + * + * Options + * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting. + * + * Events + * - **data** {function(item) {}} the data event triggers when a document is ready. + * - **error** {function(err) {}} the error event triggers if an error happens. + * - **close** {function() {}} the end event triggers when there is no more documents available. + * + * @class Represents a CursorStream. + * @param {Cursor} cursor a cursor object that the stream wraps. + * @return {Stream} + */ +function CursorStream(cursor, options) { + if(!(this instanceof CursorStream)) return new CursorStream(cursor); + options = options ? options : {}; + + Stream.call(this); + + this.readable = true; + this.paused = false; + this._cursor = cursor; + this._destroyed = null; + this.options = options; + + // give time to hook up events + var self = this; + process.nextTick(function() { + self._init(); + }); +} + +/** + * Inherit from Stream + * @ignore + * @api private + */ +CursorStream.prototype.__proto__ = Stream.prototype; + +/** + * Flag stating whether or not this stream is readable. + */ +CursorStream.prototype.readable; + +/** + * Flag stating whether or not this stream is paused. + */ +CursorStream.prototype.paused; + +/** + * Initialize the cursor. + * @ignore + * @api private + */ +CursorStream.prototype._init = function () { + if (this._destroyed) return; + this._next(); +} + +/** + * Pull the next document from the cursor. + * @ignore + * @api private + */ +CursorStream.prototype._next = function () { + if(this.paused || this._destroyed) return; + + var self = this; + // Get the next object + processor(function() { + if(self.paused || self._destroyed) return; + + self._cursor.nextObject(function (err, doc) { + self._onNextObject(err, doc); + }); + }); +} + +/** + * Handle each document as its returned from the cursor. + * @ignore + * @api private + */ +CursorStream.prototype._onNextObject = function (err, doc) { + if(err) return this.destroy(err); + + // when doc is null we hit the end of the cursor + if(!doc && (this._cursor.state == 1 || this._cursor.state == 2)) { + this.emit('end') + return this.destroy(); + } else if(doc) { + var data = typeof this.options.transform == 'function' ? this.options.transform(doc) : doc; + this.emit('data', data); + this._next(); + } +} + +/** + * Pauses the stream. + * + * @api public + */ +CursorStream.prototype.pause = function () { + this.paused = true; +} + +/** + * Resumes the stream. + * + * @api public + */ +CursorStream.prototype.resume = function () { + var self = this; + + // Don't do anything if we are not paused + if(!this.paused) return; + if(!this._cursor.state == 3) return; + + process.nextTick(function() { + self.paused = false; + // Only trigger more fetching if the cursor is open + self._next(); + }) +} + +/** + * Destroys the stream, closing the underlying + * cursor. No more events will be emitted. + * + * @api public + */ +CursorStream.prototype.destroy = function (err) { + if (this._destroyed) return; + this._destroyed = true; + this.readable = false; + + this._cursor.close(); + + if(err) { + this.emit('error', err); + } + + this.emit('close'); +} + +// TODO - maybe implement the raw option to pass binary? +//CursorStream.prototype.setEncoding = function () { +//} + +module.exports = exports = CursorStream; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js new file mode 100644 index 0000000..db9790b --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js @@ -0,0 +1,1946 @@ +/** + * Module dependencies. + * @ignore + */ +var QueryCommand = require('./commands/query_command').QueryCommand + , DbCommand = require('./commands/db_command').DbCommand + , MongoReply = require('./responses/mongo_reply').MongoReply + , Admin = require('./admin').Admin + , Collection = require('./collection').Collection + , Server = require('./connection/server').Server + , ReplSet = require('./connection/repl_set/repl_set').ReplSet + , ReadPreference = require('./connection/read_preference').ReadPreference + , Mongos = require('./connection/mongos').Mongos + , Cursor = require('./cursor').Cursor + , EventEmitter = require('events').EventEmitter + , inherits = require('util').inherits + , crypto = require('crypto') + , timers = require('timers') + , utils = require('./utils') + , mongodb_cr_authenticate = require('./auth/mongodb_cr.js').authenticate + , mongodb_gssapi_authenticate = require('./auth/mongodb_gssapi.js').authenticate + , mongodb_sspi_authenticate = require('./auth/mongodb_sspi.js').authenticate + , mongodb_plain_authenticate = require('./auth/mongodb_plain.js').authenticate; + +var hasKerberos = false; +// Check if we have a the kerberos library +try { + require('kerberos'); + hasKerberos = true; +} catch(err) {} + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; + +/** + * Create a new Db instance. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **native_parser** {Boolean, default:false}, use c++ bson parser. + * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **serializeFunctions** {Boolean, default:false}, serialize functions. + * - **raw** {Boolean, default:false}, peform operations using raw bson buffers. + * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution. + * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries. + * - **numberOfRetries** {Number, default:5}, number of retries off connection. + * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. + * - **slaveOk** {Number, default:null}, force setting of SlaveOk flag on queries (only use when explicitly connecting to a secondary server). + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @class Represents a Db + * @param {String} databaseName name of the database. + * @param {Object} serverConfig server config object. + * @param {Object} [options] additional options for the collection. + */ +function Db(databaseName, serverConfig, options) { + if(!(this instanceof Db)) return new Db(databaseName, serverConfig, options); + EventEmitter.call(this); + + var self = this; + this.databaseName = databaseName; + this.serverConfig = serverConfig; + this.options = options == null ? {} : options; + // State to check against if the user force closed db + this._applicationClosed = false; + // Fetch the override flag if any + var overrideUsedFlag = this.options['override_used_flag'] == null ? false : this.options['override_used_flag']; + + // Verify that nobody is using this config + if(!overrideUsedFlag && this.serverConfig != null && typeof this.serverConfig == 'object' && this.serverConfig._isUsed && this.serverConfig._isUsed()) { + throw new Error("A Server or ReplSet instance cannot be shared across multiple Db instances"); + } else if(!overrideUsedFlag && typeof this.serverConfig == 'object'){ + // Set being used + this.serverConfig._used = true; + } + + // Allow slaveOk override + this.slaveOk = this.options["slave_ok"] == null ? false : this.options["slave_ok"]; + this.slaveOk = this.options["slaveOk"] == null ? this.slaveOk : this.options["slaveOk"]; + + // Ensure we have a valid db name + validateDatabaseName(databaseName); + + // Contains all the connections for the db + try { + this.native_parser = this.options.native_parser; + // The bson lib + var bsonLib = this.bsonLib = this.options.native_parser ? require('bson').BSONNative : require('bson').BSONPure; + // Fetch the serializer object + var BSON = bsonLib.BSON; + // Create a new instance + this.bson = new BSON([bsonLib.Long, bsonLib.ObjectID, bsonLib.Binary, bsonLib.Code, bsonLib.DBRef, bsonLib.Symbol, bsonLib.Double, bsonLib.Timestamp, bsonLib.MaxKey, bsonLib.MinKey]); + // Backward compatibility to access types + this.bson_deserializer = bsonLib; + this.bson_serializer = bsonLib; + } catch (err) { + // If we tried to instantiate the native driver + var msg = "Native bson parser not compiled, please compile " + + "or avoid using native_parser=true"; + throw Error(msg); + } + + // Internal state of the server + this._state = 'disconnected'; + + this.pkFactory = this.options.pk == null ? bsonLib.ObjectID : this.options.pk; + this.forceServerObjectId = this.options.forceServerObjectId != null ? this.options.forceServerObjectId : false; + + // Added safe + this.safe = this.options.safe == null ? false : this.options.safe; + + // If we have not specified a "safe mode" we just print a warning to the console + if(this.options.safe == null && this.options.w == null && this.options.journal == null && this.options.fsync == null) { + console.log("========================================================================================"); + console.log("= Please ensure that you set the default write concern for the database by setting ="); + console.log("= one of the options ="); + console.log("= ="); + console.log("= w: (value of > -1 or the string 'majority'), where < 1 means ="); + console.log("= no write acknowlegement ="); + console.log("= journal: true/false, wait for flush to journal before acknowlegement ="); + console.log("= fsync: true/false, wait for flush to file system before acknowlegement ="); + console.log("= ="); + console.log("= For backward compatibility safe is still supported and ="); + console.log("= allows values of [true | false | {j:true} | {w:n, wtimeout:n} | {fsync:true}] ="); + console.log("= the default value is false which means the driver receives does not ="); + console.log("= return the information of the success/error of the insert/update/remove ="); + console.log("= ="); + console.log("= ex: new Db(new Server('localhost', 27017), {safe:false}) ="); + console.log("= ="); + console.log("= http://www.mongodb.org/display/DOCS/getLastError+Command ="); + console.log("= ="); + console.log("= The default of no acknowlegement will change in the very near future ="); + console.log("= ="); + console.log("= This message will disappear when the default safe is set on the driver Db ="); + console.log("========================================================================================"); + } + + // Internal states variables + this.notReplied ={}; + this.isInitializing = true; + this.openCalled = false; + + // Command queue, keeps a list of incoming commands that need to be executed once the connection is up + this.commands = []; + + // Set up logger + this.logger = this.options.logger != null + && (typeof this.options.logger.debug == 'function') + && (typeof this.options.logger.error == 'function') + && (typeof this.options.logger.log == 'function') + ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; + + // Associate the logger with the server config + this.serverConfig.logger = this.logger; + if(this.serverConfig.strategyInstance) this.serverConfig.strategyInstance.logger = this.logger; + this.tag = new Date().getTime(); + // Just keeps list of events we allow + this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[]}; + + // Controls serialization options + this.serializeFunctions = this.options.serializeFunctions != null ? this.options.serializeFunctions : false; + + // Raw mode + this.raw = this.options.raw != null ? this.options.raw : false; + + // Record query stats + this.recordQueryStats = this.options.recordQueryStats != null ? this.options.recordQueryStats : false; + + // If we have server stats let's make sure the driver objects have it enabled + if(this.recordQueryStats == true) { + this.serverConfig.enableRecordQueryStats(true); + } + + // Retry information + this.retryMiliSeconds = this.options.retryMiliSeconds != null ? this.options.retryMiliSeconds : 1000; + this.numberOfRetries = this.options.numberOfRetries != null ? this.options.numberOfRetries : 60; + + // Set default read preference if any + this.readPreference = this.options.readPreference; + + // Set read preference on serverConfig if none is set + // but the db one was + if(this.serverConfig.options.readPreference == null + && this.readPreference != null) { + this.serverConfig.setReadPreference(this.readPreference); + } + + // Ensure we keep a reference to this db + this.serverConfig._dbStore.add(this); +}; + +/** + * @ignore + */ +function validateDatabaseName(databaseName) { + if(typeof databaseName !== 'string') throw new Error("database name must be a string"); + if(databaseName.length === 0) throw new Error("database name cannot be the empty string"); + if(databaseName == '$external') return; + + var invalidChars = [" ", ".", "$", "/", "\\"]; + for(var i = 0; i < invalidChars.length; i++) { + if(databaseName.indexOf(invalidChars[i]) != -1) throw new Error("database names cannot contain the character '" + invalidChars[i] + "'"); + } +} + +/** + * @ignore + */ +inherits(Db, EventEmitter); + +/** + * Initialize the database connection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the index information or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.open = function(callback) { + var self = this; + + // Check that the user has not called this twice + if(this.openCalled) { + // Close db + this.close(); + // Throw error + throw new Error("db object already connecting, open cannot be called multiple times"); + } + + // If we have a specified read preference + if(this.readPreference != null) this.serverConfig.setReadPreference(this.readPreference); + + // Set that db has been opened + this.openCalled = true; + + // Set the status of the server + self._state = 'connecting'; + + // Set up connections + if(self.serverConfig instanceof Server || self.serverConfig instanceof ReplSet || self.serverConfig instanceof Mongos) { + // Ensure we have the original options passed in for the server config + var connect_options = {}; + for(var name in self.serverConfig.options) { + connect_options[name] = self.serverConfig.options[name] + } + connect_options.firstCall = true; + + // Attempt to connect + self.serverConfig.connect(self, connect_options, function(err, result) { + if(err != null) { + // Set that db has been closed + self.openCalled = false; + // Return error from connection + return callback(err, null); + } + // Set the status of the server + self._state = 'connected'; + // If we have queued up commands execute a command to trigger replays + if(self.commands.length > 0) _execute_queued_command(self); + // Callback + return callback(null, self); + }); + } else { + return callback(Error("Server parameter must be of type Server, ReplSet or Mongos"), null); + } +}; + +/** + * Create a new Db instance sharing the current socket connections. + * + * @param {String} dbName the name of the database we want to use. + * @return {Db} a db instance using the new database. + * @api public + */ +Db.prototype.db = function(dbName) { + // Copy the options and add out internal override of the not shared flag + var options = {}; + for(var key in this.options) { + options[key] = this.options[key]; + } + + // Add override flag + options['override_used_flag'] = true; + // Create a new db instance + var newDbInstance = new Db(dbName, this.serverConfig, options); + // Add the instance to the list of approved db instances + this.serverConfig._dbStore.add(newDbInstance); + // Return new db object + return newDbInstance; +} + +/** + * Close the current db connection, including all the child db instances. Emits close event if no callback is provided. + * + * @param {Boolean} [forceClose] connection can never be reused. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.close = function(forceClose, callback) { + var self = this; + // Ensure we force close all connections + this._applicationClosed = false; + + if(typeof forceClose == 'function') { + callback = forceClose; + } else if(typeof forceClose == 'boolean') { + this._applicationClosed = forceClose; + } + + this.serverConfig.close(function(err, result) { + // You can reuse the db as everything is shut down + self.openCalled = false; + // If we have a callback call it + if(callback) callback(err, result); + }); +}; + +/** + * Access the Admin database + * + * @param {Function} [callback] returns the results. + * @return {Admin} the admin db object. + * @api public + */ +Db.prototype.admin = function(callback) { + if(callback == null) return new Admin(this); + callback(null, new Admin(this)); +}; + +/** + * Returns a cursor to all the collection information. + * + * @param {String} [collectionName] the collection name we wish to retrieve the information from. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the options or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.collectionsInfo = function(collectionName, callback) { + if(callback == null && typeof collectionName == 'function') { callback = collectionName; collectionName = null; } + // Create selector + var selector = {}; + // If we are limiting the access to a specific collection name + if(collectionName != null) selector.name = this.databaseName + "." + collectionName; + + // Return Cursor + // callback for backward compatibility + if(callback) { + callback(null, new Cursor(this, new Collection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector)); + } else { + return new Cursor(this, new Collection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector); + } +}; + +/** + * Get the list of all collection names for the specified db + * + * Options + * - **namesOnly** {String, default:false}, Return only the full collection namespace. + * + * @param {String} [collectionName] the collection name we wish to filter by. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the collection names or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.collectionNames = function(collectionName, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + collectionName = args.length ? args.shift() : null; + options = args.length ? args.shift() || {} : {}; + + // Ensure no breaking behavior + if(collectionName != null && typeof collectionName == 'object') { + options = collectionName; + collectionName = null; + } + + // Let's make our own callback to reuse the existing collections info method + self.collectionsInfo(collectionName, function(err, cursor) { + if(err != null) return callback(err, null); + + cursor.toArray(function(err, documents) { + if(err != null) return callback(err, null); + + // List of result documents that have been filtered + var filtered_documents = documents.filter(function(document) { + return !(document.name.indexOf(self.databaseName) == -1 || document.name.indexOf('$') != -1); + }); + + // If we are returning only the names + if(options.namesOnly) { + filtered_documents = filtered_documents.map(function(document) { return document.name }); + } + + // Return filtered items + callback(null, filtered_documents); + }); + }); +}; + +/** + * Fetch a specific collection (containing the actual collection information). If the application does not use strict mode you can + * can use it without a callback in the following way. var collection = db.collection('mycollection'); + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **strict**, (Boolean, default:false) returns an error if the collection does not exist + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} collectionName the collection name we wish to access. + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the collection or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.collection = function(collectionName, options, callback) { + var self = this; + if(typeof options === "function") { callback = options; options = {}; } + // Execute safe + + if(options && (options.strict)) { + self.collectionNames(collectionName, function(err, collections) { + if(err != null) return callback(err, null); + + if(collections.length == 0) { + return callback(new Error("Collection " + collectionName + " does not exist. Currently in safe mode."), null); + } else { + try { + var collection = new Collection(self, collectionName, self.pkFactory, options); + } catch(err) { + return callback(err, null); + } + return callback(null, collection); + } + }); + } else { + try { + var collection = new Collection(self, collectionName, self.pkFactory, options); + } catch(err) { + if(callback == null) { + throw err; + } else { + return callback(err, null); + } + } + + // If we have no callback return collection object + return callback == null ? collection : callback(null, collection); + } +}; + +/** + * Fetch all collections for the current db. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the collections or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.collections = function(callback) { + var self = this; + // Let's get the collection names + self.collectionNames(function(err, documents) { + if(err != null) return callback(err, null); + var collections = []; + documents.forEach(function(document) { + collections.push(new Collection(self, document.name.replace(self.databaseName + ".", ''), self.pkFactory)); + }); + // Return the collection objects + callback(null, collections); + }); +}; + +/** + * Evaluate javascript on the server + * + * Options + * - **nolock** {Boolean, default:false}, Tell MongoDB not to block on the evaulation of the javascript. + * + * @param {Code} code javascript to execute on server. + * @param {Object|Array} [parameters] the parameters for the call. + * @param {Object} [options] the options + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from eval or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.eval = function(code, parameters, options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + parameters = args.length ? args.shift() : parameters; + options = args.length ? args.shift() || {} : {}; + + var finalCode = code; + var finalParameters = []; + // If not a code object translate to one + if(!(finalCode instanceof this.bsonLib.Code)) { + finalCode = new this.bsonLib.Code(finalCode); + } + + // Ensure the parameters are correct + if(parameters != null && parameters.constructor != Array && typeof parameters !== 'function') { + finalParameters = [parameters]; + } else if(parameters != null && parameters.constructor == Array && typeof parameters !== 'function') { + finalParameters = parameters; + } + + // Create execution selector + var selector = {'$eval':finalCode, 'args':finalParameters}; + // Check if the nolock parameter is passed in + if(options['nolock']) { + selector['nolock'] = options['nolock']; + } + + // Set primary read preference + options.readPreference = ReadPreference.PRIMARY; + + // Execute the eval + this.collection(DbCommand.SYSTEM_COMMAND_COLLECTION).findOne(selector, options, function(err, result) { + if(err) return callback(err); + + if(result && result.ok == 1) { + callback(null, result.retval); + } else if(result) { + callback(new Error("eval failed: " + result.errmsg), null); return; + } else { + callback(err, result); + } + }); +}; + +/** + * Dereference a dbref, against a db + * + * @param {DBRef} dbRef db reference object we wish to resolve. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from dereference or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.dereference = function(dbRef, callback) { + var db = this; + // If we have a db reference then let's get the db first + if(dbRef.db != null) db = this.db(dbRef.db); + // Fetch the collection and find the reference + var collection = db.collection(dbRef.namespace); + collection.findOne({'_id':dbRef.oid}, function(err, result) { + callback(err, result); + }); +}; + +/** + * Logout user from server, fire off on all connections and remove all auth info + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.logout = function(options, callback) { + var self = this; + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // Number of connections we need to logout from + var numberOfConnections = this.serverConfig.allRawConnections().length; + + // Let's generate the logout command object + var logoutCommand = DbCommand.logoutCommand(self, {logout:1}, options); + self._executeQueryCommand(logoutCommand, {onAll:true}, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + // Remove the db from auths + self.serverConfig.auth.remove(self.databaseName); + + // Handle any errors + if(err == null && result.documents[0].ok == 1) { + internalCallback(null, true); + } else { + err != null ? internalCallback(err, false) : internalCallback(new Error(result.documents[0].errmsg), false); + } + } + }); +} + +/** + * Authenticate a user against the server. + * authMechanism + * Options + * - **authSource** {String}, The database that the credentials are for, + * different from the name of the current DB, for example admin + * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR + * + * @param {String} username username. + * @param {String} password password. + * @param {Object} [options] the options + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authentication or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.authenticate = function(username, password, options, callback) { + var self = this; + + if(typeof callback === 'undefined') { + callback = options; + options = {}; + } + + // Set default mechanism + if(!options.authMechanism) { + options.authMechanism = 'MONGODB-CR'; + } else if(options.authMechanism != 'GSSAPI' + && options.authMechanism != 'MONGODB-CR' + && options.authMechanism != 'PLAIN') { + return callback(new Error("only GSSAPI, PLAIN or MONGODB-CR is supported by authMechanism")); + } + + // the default db to authenticate against is 'this' + // if authententicate is called from a retry context, it may be another one, like admin + var authdb = options.authdb ? options.authdb : self.databaseName; + authdb = options.authSource ? options.authSource : authdb; + + // Callback + var _callback = function(err, result) { + if(self.listeners("authenticated").length > 9) { + self.emit("authenticated", err, result); + } + + // Return to caller + callback(err, result); + } + + // If classic auth delegate to auth command + if(options.authMechanism == 'MONGODB-CR') { + mongodb_cr_authenticate(self, username, password, authdb, options, _callback); + } else if(options.authMechanism == 'PLAIN') { + mongodb_plain_authenticate(self, username, password, options, _callback); + } else if(options.authMechanism == 'GSSAPI') { + // + // Kerberos library is not installed, throw and error + if(hasKerberos == false) { + console.log("========================================================================================"); + console.log("= Please make sure that you install the Kerberos library to use GSSAPI ="); + console.log("= ="); + console.log("= npm install -g kerberos ="); + console.log("= ="); + console.log("= The Kerberos package is not installed by default for simplicities sake ="); + console.log("= and needs to be global install ="); + console.log("========================================================================================"); + throw new Error("Kerberos library not installed"); + } + + if(process.platform == 'win32') { + mongodb_sspi_authenticate(self, username, password, authdb, options, _callback); + } else { + // We have the kerberos library, execute auth process + mongodb_gssapi_authenticate(self, username, password, authdb, options, _callback); + } + } +}; + +/** + * Add a user to the database. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} username username. + * @param {String} password password. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.addUser = function(username, password, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // Get the error options + var errorOptions = _getWriteConcern(this, options, callback); + errorOptions.w = errorOptions.w == null ? 1 : errorOptions.w; + // Use node md5 generator + var md5 = crypto.createHash('md5'); + // Generate keys used for authentication + md5.update(username + ":mongo:" + password); + var userPassword = md5.digest('hex'); + // Fetch a user collection + var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION); + // Check if we are inserting the first user + collection.count({}, function(err, count) { + // We got an error (f.ex not authorized) + if(err != null) return callback(err, null); + // Check if the user exists and update i + collection.find({user: username}, {dbName: options['dbName']}).toArray(function(err, documents) { + // We got an error (f.ex not authorized) + if(err != null) return callback(err, null); + // Add command keys + var commandOptions = errorOptions; + commandOptions.dbName = options['dbName']; + commandOptions.upsert = true; + + // We have a user, let's update the password or upsert if not + collection.update({user: username},{$set: {user: username, pwd: userPassword}}, commandOptions, function(err, results) { + if(count == 0 && err) { + callback(null, [{user:username, pwd:userPassword}]); + } else if(err) { + callback(err, null) + } else { + callback(null, [{user:username, pwd:userPassword}]); + } + }); + }); + }); +}; + +/** + * Remove a user from a database + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} username username. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.removeUser = function(username, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // Figure out the safe mode settings + var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe; + // Override with options passed in if applicable + safe = options != null && options['safe'] != null ? options['safe'] : safe; + // Ensure it's at least set to safe + safe = safe == null ? {w: 1} : safe; + + // Fetch a user collection + var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION); + collection.findOne({user: username}, {dbName: options['dbName']}, function(err, user) { + if(user != null) { + // Add command keys + var commandOptions = safe; + commandOptions.dbName = options['dbName']; + + collection.remove({user: username}, commandOptions, function(err, result) { + callback(err, true); + }); + } else { + callback(err, false); + } + }); +}; + +/** + * Creates a collection on a server pre-allocating space, need to create f.ex capped collections. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **capped** {Boolean, default:false}, create a capped collection. + * - **size** {Number}, the size of the capped collection in bytes. + * - **max** {Number}, the maximum number of documents in the capped collection. + * - **autoIndexId** {Boolean, default:true}, create an index on the _id field of the document, True by default on MongoDB 2.2 or higher off for version < 2.2. + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **strict**, (Boolean, default:false) throws an error if collection already exists + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} collectionName the collection name we wish to access. + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from createCollection or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.createCollection = function(collectionName, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : null; + var self = this; + + // Figure out the safe mode settings + var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe; + // Override with options passed in if applicable + safe = options != null && options['safe'] != null ? options['safe'] : safe; + // Ensure it's at least set to safe + safe = safe == null ? {w: 1} : safe; + + // Check if we have the name + this.collectionNames(collectionName, function(err, collections) { + if(err != null) return callback(err, null); + + var found = false; + collections.forEach(function(collection) { + if(collection.name == self.databaseName + "." + collectionName) found = true; + }); + + // If the collection exists either throw an exception (if db in safe mode) or return the existing collection + if(found && options && options.strict) { + return callback(new Error("Collection " + collectionName + " already exists. Currently in safe mode."), null); + } else if(found){ + try { + var collection = new Collection(self, collectionName, self.pkFactory, options); + } catch(err) { + return callback(err, null); + } + return callback(null, collection); + } + + // Create a new collection and return it + self._executeQueryCommand(DbCommand.createCreateCollectionCommand(self, collectionName, options), {read:false, safe:safe}, function(err, result) { + var document = result.documents[0]; + // If we have no error let's return the collection + if(err == null && document.ok == 1) { + try { + var collection = new Collection(self, collectionName, self.pkFactory, options); + } catch(err) { + return callback(err, null); + } + return callback(null, collection); + } else { + if (null == err) err = utils.toError(document); + callback(err, null); + } + }); + }); +}; + +/** + * Execute a command hash against MongoDB. This lets you acess any commands not available through the api on the server. + * + * @param {Object} selector the command hash to send to the server, ex: {ping:1}. + * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter. + * @return {null} + * @api public + */ +Db.prototype.command = function(selector, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + // Ignore command preference (I know what I'm doing) + var ignoreCommandFilter = options.ignoreCommandFilter ? options.ignoreCommandFilter : false; + + // Set up the options + var cursor = new Cursor(this + , new Collection(this, DbCommand.SYSTEM_COMMAND_COLLECTION), selector, {}, { + limit: -1, timeout: QueryCommand.OPTS_NO_CURSOR_TIMEOUT, dbName: options['dbName'] + }); + + // Set read preference if we set one + var readPreference = options['readPreference'] ? options['readPreference'] : false; + + // Ensure only commands who support read Prefrences are exeuted otherwise override and use Primary + if(readPreference != false && ignoreCommandFilter == false) { + if(selector['group'] || selector['aggregate'] || selector['collStats'] || selector['dbStats'] + || selector['count'] || selector['distinct'] || selector['geoNear'] || selector['geoSearch'] + || selector['geoWalk'] || selector['text'] + || (selector['mapreduce'] && (selector.out == 'inline' || selector.out.inline))) { + // Set the read preference + cursor.setReadPreference(readPreference); + } else { + cursor.setReadPreference(ReadPreference.PRIMARY); + } + } else if(readPreference != false) { + // Force setting the command filter + cursor.setReadPreference(readPreference); + } + + // Return the next object + cursor.nextObject(callback); +}; + +/** + * Drop a collection from the database, removing it permanently. New accesses will create a new collection. + * + * @param {String} collectionName the name of the collection we wish to drop. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from dropCollection or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.dropCollection = function(collectionName, callback) { + var self = this; + callback || (callback = function(){}); + + // Drop the collection + this._executeQueryCommand(DbCommand.createDropCollectionCommand(this, collectionName), function(err, result) { + if(err == null && result.documents[0].ok == 1) { + return callback(null, true); + } + + if(null == err) err = utils.toError(result.documents[0]); + callback(err, null); + }); +}; + +/** + * Rename a collection. + * + * Options + * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists. + * + * @param {String} fromCollection the name of the current collection we wish to rename. + * @param {String} toCollection the new name of the collection. + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from renameCollection or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.renameCollection = function(fromCollection, toCollection, options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {} + } + + callback || (callback = function(){}); + // Execute the command, return the new renamed collection if successful + this._executeQueryCommand(DbCommand.createRenameCollectionCommand(this, fromCollection, toCollection, options), function(err, result) { + if(err == null && result.documents[0].ok == 1) { + return callback(null, new Collection(self, toCollection, self.pkFactory)); + } + + if(null == err) err = utils.toError(result.documents[0]); + callback(err, null); + }); +}; + +/** + * Return last error message for the given connection, note options can be combined. + * + * Options + * - **fsync** {Boolean, default:false}, option forces the database to fsync all files before returning. + * - **j** {Boolean, default:false}, awaits the journal commit before returning, > MongoDB 2.0. + * - **w** {Number}, until a write operation has been replicated to N servers. + * - **wtimeout** {Number}, number of miliseconds to wait before timing out. + * + * Connection Options + * - **connection** {Connection}, fire the getLastError down a specific connection. + * + * @param {Object} [options] returns option results. + * @param {Object} [connectionOptions] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from lastError or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.lastError = function(options, connectionOptions, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + connectionOptions = args.length ? args.shift() || {} : {}; + + this._executeQueryCommand(DbCommand.createGetLastErrorCommand(options, this), connectionOptions, function(err, error) { + callback(err, error && error.documents); + }); +}; + +/** + * Legacy method calls. + * + * @ignore + * @api private + */ +Db.prototype.error = Db.prototype.lastError; +Db.prototype.lastStatus = Db.prototype.lastError; + +/** + * Return all errors up to the last time db reset_error_history was called. + * + * Options + * - **connection** {Connection}, fire the getLastError down a specific connection. + * + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from previousErrors or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.previousErrors = function(options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + this._executeQueryCommand(DbCommand.createGetPreviousErrorsCommand(this), options, function(err, error) { + callback(err, error.documents); + }); +}; + +/** + * Runs a command on the database. + * @ignore + * @api private + */ +Db.prototype.executeDbCommand = function(command_hash, options, callback) { + if(callback == null) { callback = options; options = {}; } + this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, command_hash, options), options, callback); +}; + +/** + * Runs a command on the database as admin. + * @ignore + * @api private + */ +Db.prototype.executeDbAdminCommand = function(command_hash, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {} + } + + if(options.readPreference) { + options.read = options.readPreference; + } + + this._executeQueryCommand(DbCommand.createAdminDbCommand(this, command_hash), options, callback); +}; + +/** + * Resets the error history of the mongo instance. + * + * Options + * - **connection** {Connection}, fire the getLastError down a specific connection. + * + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from resetErrorHistory or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.resetErrorHistory = function(options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + this._executeQueryCommand(DbCommand.createResetErrorHistoryCommand(this), options, function(err, error) { + callback(err, error.documents); + }); +}; + +/** + * Creates an index on the collection. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * + * @param {String} collectionName name of the collection to create the index on. + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from createIndex or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.createIndex = function(collectionName, fieldOrSpec, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + options = typeof callback === 'function' ? options : callback; + options = options == null ? {} : options; + + // Get the error options + var errorOptions = _getWriteConcern(this, options, callback); + // Create command + var command = DbCommand.createCreateIndexCommand(this, collectionName, fieldOrSpec, options); + // Default command options + var commandOptions = {}; + + // If we have error conditions set handle them + if(_hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + commandOptions['read'] = false; + // If we have safe set set async to false + if(errorOptions == null) commandOptions['async'] = true; + + // Set safe option + commandOptions['safe'] = errorOptions; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // Execute insert command + this._executeInsertCommand(command, commandOptions, function(err, result) { + if(err != null) return callback(err, null); + + result = result && result.documents; + if (result[0].err) { + callback(utils.toError(result[0])); + } else { + callback(null, command.documents[0].name); + } + }); + } else if(_hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + // Execute insert command + var result = this._executeInsertCommand(command, commandOptions); + // If no callback just return + if(!callback) return; + // If error return error + if(result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(null, null); + } +}; + +/** + * Ensures that an index exists, if it does not it creates it + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @param {String} collectionName name of the collection to create the index on. + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ensureIndex or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.ensureIndex = function(collectionName, fieldOrSpec, options, callback) { + var self = this; + + if (typeof callback === 'undefined' && typeof options === 'function') { + callback = options; + options = {}; + } + + if (options == null) { + options = {}; + } + + // Get the error options + var errorOptions = _getWriteConcern(this, options, callback); + // Make sure we don't try to do a write concern without a callback + if(_hasWriteConcern(errorOptions) && callback == null) + throw new Error("Cannot use a writeConcern without a provided callback"); + // Create command + var command = DbCommand.createCreateIndexCommand(this, collectionName, fieldOrSpec, options); + var index_name = command.documents[0].name; + + // Default command options + var commandOptions = {}; + // Check if the index allready exists + this.indexInformation(collectionName, function(err, collectionInfo) { + if(err != null) return callback(err, null); + + if(!collectionInfo[index_name]) { + // If we have error conditions set handle them + if(_hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + commandOptions['read'] = false; + // If we have safe set set async to false + if(errorOptions == null) commandOptions['async'] = true; + + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + if(typeof callback === 'function' + && commandOptions.w < 1 && !commandOptions.fsync && !commandOptions.journal) { + commandOptions.w = 1; + } + + self._executeInsertCommand(command, commandOptions, function(err, result) { + // Only callback if we have one specified + if(typeof callback === 'function') { + if(err != null) return callback(err, null); + + result = result && result.documents; + if (result[0].err) { + callback(utils.toError(result[0])); + } else { + callback(null, command.documents[0].name); + } + } + }); + } else { + // Execute insert command + var result = self._executeInsertCommand(command, commandOptions); + // If no callback just return + if(!callback) return; + // If error return error + if(result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(null, index_name); + } + } else { + if(typeof callback === 'function') return callback(null, index_name); + } + }); +}; + +/** + * Returns the information available on allocated cursors. + * + * Options + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from cursorInfo or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.cursorInfo = function(options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, {'cursorInfo':1}), options, function(err, result) { + callback(err, result.documents[0]); + }); +}; + +/** + * Drop an index on a collection. + * + * @param {String} collectionName the name of the collection where the command will drop an index. + * @param {String} indexName name of the index to drop. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from dropIndex or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.dropIndex = function(collectionName, indexName, callback) { + this._executeQueryCommand(DbCommand.createDropIndexCommand(this, collectionName, indexName), callback); +}; + +/** + * Reindex all indexes on the collection + * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. + * + * @param {String} collectionName the name of the collection. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from reIndex or null if an error occured. + * @api public +**/ +Db.prototype.reIndex = function(collectionName, callback) { + this._executeQueryCommand(DbCommand.createReIndexCommand(this, collectionName), function(err, result) { + if(err != null) { + callback(err, false); + } else if(result.documents[0].errmsg == null) { + callback(null, true); + } else { + callback(new Error(result.documents[0].errmsg), false); + } + }); +}; + +/** + * Retrieves this collections index info. + * + * Options + * - **full** {Boolean, default:false}, returns the full raw index information. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {String} collectionName the name of the collection. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from indexInformation or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.indexInformation = function(collectionName, options, callback) { + if(typeof callback === 'undefined') { + if(typeof options === 'undefined') { + callback = collectionName; + collectionName = null; + } else { + callback = options; + } + options = {}; + } + + // If we specified full information + var full = options['full'] == null ? false : options['full']; + // Build selector for the indexes + var selector = collectionName != null ? {ns: (this.databaseName + "." + collectionName)} : {}; + + // Set read preference if we set one + var readPreference = options['readPreference'] ? options['readPreference'] : ReadPreference.PRIMARY; + + // Iterate through all the fields of the index + this.collection(DbCommand.SYSTEM_INDEX_COLLECTION, function(err, collection) { + // Perform the find for the collection + collection.find(selector).setReadPreference(readPreference).toArray(function(err, indexes) { + if(err != null) return callback(err, null); + // Contains all the information + var info = {}; + + // if full defined just return all the indexes directly + if(full) return callback(null, indexes); + + // Process all the indexes + for(var i = 0; i < indexes.length; i++) { + var index = indexes[i]; + // Let's unpack the object + info[index.name] = []; + for(var name in index.key) { + info[index.name].push([name, index.key[name]]); + } + } + + // Return all the indexes + callback(null, info); + }); + }); +}; + +/** + * Drop a database. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from dropDatabase or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.dropDatabase = function(callback) { + var self = this; + + this._executeQueryCommand(DbCommand.createDropDatabaseCommand(this), function(err, result) { + if(err == null && result.documents[0].ok == 1) { + callback(null, true); + } else { + if(err) { + callback(err, false); + } else { + callback(utils.toError(result.documents[0]), false); + } + } + }); +}; + +/** + * Get all the db statistics. + * + * Options + * - **scale** {Number}, divide the returned sizes by scale value. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Objects} [options] options for the stats command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from stats or null if an error occured. + * @return {null} + * @api public + */ +Db.prototype.stats = function stats(options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + dbStats:this.collectionName, + } + + // Check if we have the scale value + if(options['scale'] != null) commandObject['scale'] = options['scale']; + + // Execute the command + this.command(commandObject, options, callback); +} + +/** + * @ignore + */ +var __executeQueryCommand = function(self, db_command, options, callback) { + // Options unpacking + var read = options['read'] != null ? options['read'] : false; + var raw = options['raw'] != null ? options['raw'] : self.raw; + var onAll = options['onAll'] != null ? options['onAll'] : false; + var specifiedConnection = options['connection'] != null ? options['connection'] : null; + + // Correct read preference to default primary if set to false, null or primary + if(!(typeof read == 'object') && read._type == 'ReadPreference') { + read = (read == null || read == 'primary' || read == false) ? ReadPreference.PRIMARY : read; + if(!ReadPreference.isValid(read)) return callback(new Error("Illegal readPreference mode specified, " + read)); + } else if(typeof read == 'object' && read._type == 'ReadPreference') { + if(!read.isValid()) return callback(new Error("Illegal readPreference mode specified, " + read.mode)); + } + + // If we have a read preference set and we are a mongos pass the read preference on to the mongos instance, + if(self.serverConfig.isMongos() && read != null && read != false) { + db_command.setMongosReadPreference(read); + } + + // If we got a callback object + if(typeof callback === 'function' && !onAll) { + // Override connection if we passed in a specific connection + var connection = specifiedConnection != null ? specifiedConnection : null; + + if(connection instanceof Error) return callback(connection, null); + + // Fetch either a reader or writer dependent on the specified read option if no connection + // was passed in + if(connection == null) { + connection = self.serverConfig.checkoutReader(read); + } + + if(connection == null) { + return callback(new Error("no open connections")); + } else if(connection instanceof Error || connection['message'] != null) { + return callback(connection); + } + + // Exhaust Option + var exhaust = options.exhaust || false; + + // Register the handler in the data structure + self.serverConfig._registerHandler(db_command, raw, connection, exhaust, callback); + + // Ensure the connection is valid + if(!connection.isConnected()) { + if(read == ReadPreference.PRIMARY + || read == ReadPreference.PRIMARY_PREFERRED + || (read != null && typeof read == 'object' && read.mode) + || read == null) { + + // Save the command + self.serverConfig._commandsStore.read_from_writer( + { type: 'query' + , db_command: db_command + , options: options + , callback: callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } else { + self.serverConfig._commandsStore.read( + { type: 'query' + , db_command: db_command + , options: options + , callback: callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } + } + + // Write the message out and handle any errors if there are any + connection.write(db_command, function(err) { + if(err != null) { + // Call the handler with an error + if(Array.isArray(db_command)) + self.serverConfig._callHandler(db_command[0].getRequestId(), null, err); + else + self.serverConfig._callHandler(db_command.getRequestId(), null, err); + } + }); + } else if(typeof callback === 'function' && onAll) { + var connections = self.serverConfig.allRawConnections(); + var numberOfEntries = connections.length; + // Go through all the connections + for(var i = 0; i < connections.length; i++) { + // Fetch a connection + var connection = connections[i]; + + // Ensure we have a valid connection + if(connection == null) { + return callback(new Error("no open connections")); + } else if(connection instanceof Error) { + return callback(connection); + } + + // Register the handler in the data structure + self.serverConfig._registerHandler(db_command, raw, connection, callback); + + // Write the message out + connection.write(db_command, function(err) { + // Adjust the number of entries we need to process + numberOfEntries = numberOfEntries - 1; + // Remove listener + if(err != null) { + // Clean up listener and return error + self.serverConfig._removeHandler(db_command.getRequestId()); + } + + // No more entries to process callback with the error + if(numberOfEntries <= 0) { + callback(err); + } + }); + + // Update the db_command request id + db_command.updateRequestId(); + } + } else { + // Fetch either a reader or writer dependent on the specified read option + // var connection = read == null || read == 'primary' || read == false ? self.serverConfig.checkoutWriter(true) : self.serverConfig.checkoutReader(read); + var connection = self.serverConfig.checkoutReader(read); + // Override connection if needed + connection = specifiedConnection != null ? specifiedConnection : connection; + // Ensure we have a valid connection + if(connection == null || connection instanceof Error || connection['message'] != null) return null; + // Write the message out + connection.write(db_command, function(err) { + if(err != null) { + // Emit the error + self.emit("error", err); + } + }); + } +} + +/** + * Execute db query command (not safe) + * @ignore + * @api private + */ +Db.prototype._executeQueryCommand = function(db_command, options, callback) { + var self = this; + + // Unpack the parameters + if (typeof callback === 'undefined') { + callback = options; + options = {}; + } + + // fast fail option used for HA, no retry + var failFast = options['failFast'] != null + ? options['failFast'] + : false; + + // Check if the user force closed the command + if(this._applicationClosed) { + var err = new Error("db closed by application"); + if('function' == typeof callback) { + return callback(err, null); + } else { + throw err; + } + } + + if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application")); + + // Get the configuration + var config = this.serverConfig; + var read = options.read; + + if(!config.canRead(read) && !config.canWrite() && config.isAutoReconnect()) { + if(read == ReadPreference.PRIMARY + || read == ReadPreference.PRIMARY_PREFERRED + || (read != null && typeof read == 'object' && read.mode) + || read == null) { + + // Save the command + self.serverConfig._commandsStore.read_from_writer( + { type: 'query' + , db_command: db_command + , options: options + , callback: callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } else { + self.serverConfig._commandsStore.read( + { type: 'query' + , db_command: db_command + , options: options + , callback: callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } + } else if(!config.canRead(read) && !config.canWrite() && !config.isAutoReconnect()) { + return callback(new Error("no open connections"), null); + } else { + // Execute the command + __executeQueryCommand(self, db_command, options, function (err, result, conn) { + if(callback) callback(err, result, conn); + }); + } +}; + +/** + * @ignore + */ +var __executeInsertCommand = function(self, db_command, options, callback) { + // Always checkout a writer for this kind of operations + var connection = self.serverConfig.checkoutWriter(); + // Get safe mode + var safe = options['safe'] != null ? options['safe'] : false; + var raw = options['raw'] != null ? options['raw'] : self.raw; + var specifiedConnection = options['connection'] != null ? options['connection'] : null; + // Override connection if needed + connection = specifiedConnection != null ? specifiedConnection : connection; + + // Ensure we have a valid connection + if(typeof callback === 'function') { + // Ensure we have a valid connection + /*if(connection == null && self.serverConfig.isAutoReconnect()) { + return self.serverConfig._commandsStore.write( + { type:'insert' + , 'db_command':db_command + , 'options':options + , 'callback':callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } else*/ if(connection == null) { + return callback(new Error("no open connections")); + } else if(connection instanceof Error) { + return callback(connection); + } + + var errorOptions = _getWriteConcern(self, options, callback); + if(errorOptions.w > 0 || errorOptions.w == 'majority' || errorOptions.j || errorOptions.journal || errorOptions.fsync) { + // db command is now an array of commands (original command + lastError) + db_command = [db_command, DbCommand.createGetLastErrorCommand(safe, self)]; + // Register the handler in the data structure + self.serverConfig._registerHandler(db_command[1], raw, connection, callback); + } + } + + // If we have no callback and there is no connection + if(connection == null) return null; + if(connection instanceof Error && typeof callback == 'function') return callback(connection, null); + if(connection instanceof Error) return null; + if(connection == null && typeof callback == 'function') return callback(new Error("no primary server found"), null); + + // Ensure we truly are connected + if(!connection.isConnected()) { + return self.serverConfig._commandsStore.write( + { type:'insert' + , 'db_command':db_command + , 'options':options + , 'callback':callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } + + // Write the message out + connection.write(db_command, function(err) { + // Return the callback if it's not a safe operation and the callback is defined + if(typeof callback === 'function' && (safe == null || safe == false)) { + // Perform the callback + callback(err, null); + } else if(typeof callback === 'function') { + // Call the handler with an error + self.serverConfig._callHandler(db_command[1].getRequestId(), null, err); + } else if(typeof callback == 'function' && safe && safe.w == -1) { + // Call the handler with no error + self.serverConfig._callHandler(db_command[1].getRequestId(), null, null); + } else if(!safe || safe.w == -1) { + self.emit("error", err); + } + }); +} + +/** + * Execute an insert Command + * @ignore + * @api private + */ +Db.prototype._executeInsertCommand = function(db_command, options, callback) { + var self = this; + + // Unpack the parameters + if(callback == null && typeof options === 'function') { + callback = options; + options = {}; + } + + // Ensure options are not null + options = options == null ? {} : options; + + // Check if the user force closed the command + if(this._applicationClosed) { + if(typeof callback == 'function') { + return callback(new Error("db closed by application"), null); + } else { + throw new Error("db closed by application"); + } + } + + if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application")); + + // Get config + var config = self.serverConfig; + // Check if we are connected + if(!config.canWrite() && config.isAutoReconnect()) { + self.serverConfig._commandsStore.write( + { type:'insert' + , 'db_command':db_command + , 'options':options + , 'callback':callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } else if(!config.canWrite() && !config.isAutoReconnect()) { + return callback(new Error("no open connections"), null); + } else { + // Execute write command + __executeInsertCommand(self, db_command, options, callback); + } +} + +/** + * Update command is the same + * @ignore + * @api private + */ +Db.prototype._executeUpdateCommand = Db.prototype._executeInsertCommand; +/** + * Remove command is the same + * @ignore + * @api private + */ +Db.prototype._executeRemoveCommand = Db.prototype._executeInsertCommand; + +/** + * Wrap a Mongo error document into an Error instance. + * Deprecated. Use utils.toError instead. + * + * @ignore + * @api private + * @deprecated + */ +Db.prototype.wrap = utils.toError; + +/** + * Default URL + * + * @classconstant DEFAULT_URL + **/ +Db.DEFAULT_URL = 'mongodb://localhost:27017/default'; + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Options + * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication + * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** + * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** + * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** + * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** + * + * @param {String} url connection url for MongoDB. + * @param {Object} [options] optional options for insert command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the db instance or null if an error occured. + * @return {null} + * @api public + */ +Db.connect = function(url, options, callback) { + // Ensure correct mapping of the callback + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Ensure same behavior as previous version w:0 + if(url.indexOf("safe") == -1 + && url.indexOf("w") == -1 + && url.indexOf("journal") == -1 && url.indexOf("j") == -1 + && url.indexOf("fsync") == -1) options.w = 0; + + // Avoid circular require problem + var MongoClient = require('./mongo_client.js').MongoClient; + // Attempt to connect + MongoClient.connect.call(MongoClient, url, options, callback); +} + +/** + * State of the db connection + * @ignore + */ +Object.defineProperty(Db.prototype, "state", { enumerable: true + , get: function () { + return this.serverConfig._serverState; + } +}); + +/** + * @ignore + */ +var _hasWriteConcern = function(errorOptions) { + return errorOptions == true + || errorOptions.w > 0 + || errorOptions.w == 'majority' + || errorOptions.j == true + || errorOptions.journal == true + || errorOptions.fsync == true +} + +/** + * @ignore + */ +var _setWriteConcernHash = function(options) { + var finalOptions = {}; + if(options.w != null) finalOptions.w = options.w; + if(options.journal == true) finalOptions.j = options.journal; + if(options.j == true) finalOptions.j = options.j; + if(options.fsync == true) finalOptions.fsync = options.fsync; + if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; + return finalOptions; +} + +/** + * @ignore + */ +var _getWriteConcern = function(self, options, callback) { + // Final options + var finalOptions = {w:1}; + // Local options verification + if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(options); + } else if(options.safe != null && typeof options.safe == 'object') { + finalOptions = _setWriteConcernHash(options.safe); + } else if(typeof options.safe == "boolean") { + finalOptions = {w: (options.safe ? 1 : 0)}; + } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.options); + } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.safe); + } else if(typeof self.safe == "boolean") { + finalOptions = {w: (self.safe ? 1 : 0)}; + } + + // Ensure we don't have an invalid combination of write concerns + if(finalOptions.w < 1 + && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true"); + + // Return the options + return finalOptions; +} + +/** + * Legacy support + * + * @ignore + * @api private + */ +exports.connect = Db.connect; +exports.Db = Db; + +/** + * Remove all listeners to the db instance. + * @ignore + * @api private + */ +Db.prototype.removeAllEventListeners = function() { + this.removeAllListeners("close"); + this.removeAllListeners("error"); + this.removeAllListeners("timeout"); + this.removeAllListeners("parseError"); + this.removeAllListeners("poolReady"); + this.removeAllListeners("message"); +} diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/chunk.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/chunk.js new file mode 100644 index 0000000..59c6a26 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/chunk.js @@ -0,0 +1,221 @@ +var Binary = require('bson').Binary, + ObjectID = require('bson').ObjectID; + +/** + * Class for representing a single chunk in GridFS. + * + * @class + * + * @param file {GridStore} The {@link GridStore} object holding this chunk. + * @param mongoObject {object} The mongo object representation of this chunk. + * + * @throws Error when the type of data field for {@link mongoObject} is not + * supported. Currently supported types for data field are instances of + * {@link String}, {@link Array}, {@link Binary} and {@link Binary} + * from the bson module + * + * @see Chunk#buildMongoObject + */ +var Chunk = exports.Chunk = function(file, mongoObject, writeConcern) { + if(!(this instanceof Chunk)) return new Chunk(file, mongoObject); + + this.file = file; + var self = this; + var mongoObjectFinal = mongoObject == null ? {} : mongoObject; + this.writeConcern = writeConcern || {w:1}; + this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id; + this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n; + this.data = new Binary(); + + if(mongoObjectFinal.data == null) { + } else if(typeof mongoObjectFinal.data == "string") { + var buffer = new Buffer(mongoObjectFinal.data.length); + buffer.write(mongoObjectFinal.data, 'binary', 0); + this.data = new Binary(buffer); + } else if(Array.isArray(mongoObjectFinal.data)) { + var buffer = new Buffer(mongoObjectFinal.data.length); + buffer.write(mongoObjectFinal.data.join(''), 'binary', 0); + this.data = new Binary(buffer); + } else if(mongoObjectFinal.data instanceof Binary || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") { + this.data = mongoObjectFinal.data; + } else if(Buffer.isBuffer(mongoObjectFinal.data)) { + } else { + throw Error("Illegal chunk format"); + } + // Update position + this.internalPosition = 0; +}; + +/** + * Writes a data to this object and advance the read/write head. + * + * @param data {string} the data to write + * @param callback {function(*, GridStore)} This will be called after executing + * this method. The first parameter will contain null and the second one + * will contain a reference to this object. + */ +Chunk.prototype.write = function(data, callback) { + this.data.write(data, this.internalPosition); + this.internalPosition = this.data.length(); + if(callback != null) return callback(null, this); + return this; +}; + +/** + * Reads data and advances the read/write head. + * + * @param length {number} The length of data to read. + * + * @return {string} The data read if the given length will not exceed the end of + * the chunk. Returns an empty String otherwise. + */ +Chunk.prototype.read = function(length) { + // Default to full read if no index defined + length = length == null || length == 0 ? this.length() : length; + + if(this.length() - this.internalPosition + 1 >= length) { + var data = this.data.read(this.internalPosition, length); + this.internalPosition = this.internalPosition + length; + return data; + } else { + return ''; + } +}; + +Chunk.prototype.readSlice = function(length) { + if ((this.length() - this.internalPosition) >= length) { + var data = null; + if (this.data.buffer != null) { //Pure BSON + data = this.data.buffer.slice(this.internalPosition, this.internalPosition + length); + } else { //Native BSON + data = new Buffer(length); + length = this.data.readInto(data, this.internalPosition); + } + this.internalPosition = this.internalPosition + length; + return data; + } else { + return null; + } +}; + +/** + * Checks if the read/write head is at the end. + * + * @return {boolean} Whether the read/write head has reached the end of this + * chunk. + */ +Chunk.prototype.eof = function() { + return this.internalPosition == this.length() ? true : false; +}; + +/** + * Reads one character from the data of this chunk and advances the read/write + * head. + * + * @return {string} a single character data read if the the read/write head is + * not at the end of the chunk. Returns an empty String otherwise. + */ +Chunk.prototype.getc = function() { + return this.read(1); +}; + +/** + * Clears the contents of the data in this chunk and resets the read/write head + * to the initial position. + */ +Chunk.prototype.rewind = function() { + this.internalPosition = 0; + this.data = new Binary(); +}; + +/** + * Saves this chunk to the database. Also overwrites existing entries having the + * same id as this chunk. + * + * @param callback {function(*, GridStore)} This will be called after executing + * this method. The first parameter will contain null and the second one + * will contain a reference to this object. + */ +Chunk.prototype.save = function(callback) { + var self = this; + + self.file.chunkCollection(function(err, collection) { + if(err) return callback(err); + + collection.remove({'_id':self.objectId}, self.writeConcern, function(err, result) { + if(err) return callback(err); + + if(self.data.length() > 0) { + self.buildMongoObject(function(mongoObject) { + var options = {forceServerObjectId:true}; + for(var name in self.writeConcern) { + options[name] = self.writeConcern[name]; + } + + collection.insert(mongoObject, options, function(err, collection) { + callback(err, self); + }); + }); + } else { + callback(null, self); + } + }); + }); +}; + +/** + * Creates a mongoDB object representation of this chunk. + * + * @param callback {function(Object)} This will be called after executing this + * method. The object will be passed to the first parameter and will have + * the structure: + * + *
    
    + *        {
    + *          '_id' : , // {number} id for this chunk
    + *          'files_id' : , // {number} foreign key to the file collection
    + *          'n' : , // {number} chunk number
    + *          'data' : , // {bson#Binary} the chunk data itself
    + *        }
    + *        
    + * + * @see MongoDB GridFS Chunk Object Structure + */ +Chunk.prototype.buildMongoObject = function(callback) { + var mongoObject = { + 'files_id': this.file.fileId, + 'n': this.chunkNumber, + 'data': this.data}; + // If we are saving using a specific ObjectId + if(this.objectId != null) mongoObject._id = this.objectId; + + callback(mongoObject); +}; + +/** + * @return {number} the length of the data + */ +Chunk.prototype.length = function() { + return this.data.length(); +}; + +/** + * The position of the read/write head + * @name position + * @lends Chunk# + * @field + */ +Object.defineProperty(Chunk.prototype, "position", { enumerable: true + , get: function () { + return this.internalPosition; + } + , set: function(value) { + this.internalPosition = value; + } +}); + +/** + * The default chunk size + * @constant + */ +Chunk.DEFAULT_CHUNK_SIZE = 1024 * 256; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js new file mode 100644 index 0000000..aa695b7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js @@ -0,0 +1,103 @@ +var GridStore = require('./gridstore').GridStore, + ObjectID = require('bson').ObjectID; + +/** + * A class representation of a simple Grid interface. + * + * @class Represents the Grid. + * @param {Db} db A database instance to interact with. + * @param {String} [fsName] optional different root collection for GridFS. + * @return {Grid} + */ +function Grid(db, fsName) { + + if(!(this instanceof Grid)) return new Grid(db, fsName); + + this.db = db; + this.fsName = fsName == null ? GridStore.DEFAULT_ROOT_COLLECTION : fsName; +} + +/** + * Puts binary data to the grid + * + * Options + * - **_id** {Any}, unique id for this file + * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**. + * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**. + * - **metadata** {Object}, arbitrary data the user wants to store. + * + * @param {Buffer} data buffer with Binary Data. + * @param {Object} [options] the options for the files. + * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +Grid.prototype.put = function(data, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + // If root is not defined add our default one + options['root'] = options['root'] == null ? this.fsName : options['root']; + + // Return if we don't have a buffer object as data + if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null); + // Get filename if we are using it + var filename = options['filename'] || null; + // Get id if we are using it + var id = options['_id'] || null; + // Create gridstore + var gridStore = new GridStore(this.db, id, filename, "w", options); + gridStore.open(function(err, gridStore) { + if(err) return callback(err, null); + + gridStore.write(data, function(err, result) { + if(err) return callback(err, null); + + gridStore.close(function(err, result) { + if(err) return callback(err, null); + callback(null, result); + }) + }) + }) +} + +/** + * Get binary data to the grid + * + * @param {Any} id for file. + * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +Grid.prototype.get = function(id, callback) { + // Create gridstore + var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName}); + gridStore.open(function(err, gridStore) { + if(err) return callback(err, null); + + // Return the data + gridStore.read(function(err, data) { + return callback(err, data) + }); + }) +} + +/** + * Delete file from grid + * + * @param {Any} id for file. + * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +Grid.prototype.delete = function(id, callback) { + // Create gridstore + GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) { + if(err) return callback(err, false); + return callback(null, true); + }); +} + +exports.Grid = Grid; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js new file mode 100644 index 0000000..2278de2 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js @@ -0,0 +1,1559 @@ +/** + * @fileOverview GridFS is a tool for MongoDB to store files to the database. + * Because of the restrictions of the object size the database can hold, a + * facility to split a file into several chunks is needed. The {@link GridStore} + * class offers a simplified api to interact with files while managing the + * chunks of split files behind the scenes. More information about GridFS can be + * found here. + */ +var Chunk = require('./chunk').Chunk, + DbCommand = require('../commands/db_command').DbCommand, + ObjectID = require('bson').ObjectID, + Buffer = require('buffer').Buffer, + fs = require('fs'), + timers = require('timers'), + util = require('util'), + inherits = util.inherits, + ReadStream = require('./readstream').ReadStream, + Stream = require('stream'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; +processor = process.nextTick + +var REFERENCE_BY_FILENAME = 0, + REFERENCE_BY_ID = 1; + +/** + * A class representation of a file stored in GridFS. + * + * Modes + * - **"r"** - read only. This is the default mode. + * - **"w"** - write in truncate mode. Existing data will be overwriten. + * - **w+"** - write in edit mode. + * + * Options + * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**. + * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**. + * - **metadata** {Object}, arbitrary data the user wants to store. + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * + * @class Represents the GridStore. + * @param {Db} db A database instance to interact with. + * @param {Any} [id] optional unique id for this file + * @param {String} [filename] optional filename for this file, no unique constrain on the field + * @param {String} mode set the mode for this file. + * @param {Object} options optional properties to specify. + * @return {GridStore} + */ +var GridStore = function GridStore(db, id, filename, mode, options) { + if(!(this instanceof GridStore)) return new GridStore(db, id, filename, mode, options); + + var self = this; + this.db = db; + + // Call stream constructor + if(typeof Stream == 'function') { + Stream.call(this); + } else { + // 0.4.X backward compatibility fix + Stream.Stream.call(this); + } + + // Handle options + if(typeof options === 'undefined') options = {}; + // Handle mode + if(typeof mode === 'undefined') { + mode = filename; + filename = undefined; + } else if(typeof mode == 'object') { + options = mode; + mode = filename; + filename = undefined; + } + + if(id instanceof ObjectID) { + this.referenceBy = REFERENCE_BY_ID; + this.fileId = id; + this.filename = filename; + } else if(typeof filename == 'undefined') { + this.referenceBy = REFERENCE_BY_FILENAME; + this.filename = id; + if (mode.indexOf('w') != null) { + this.fileId = new ObjectID(); + } + } else { + this.referenceBy = REFERENCE_BY_ID; + this.fileId = id; + this.filename = filename; + } + + // Set up the rest + this.mode = mode == null ? "r" : mode; + this.options = options == null ? {w:1} : options; + + // If we have no write concerns set w:1 as default + if(this.options.w == null + && this.options.j == null + && this.options.fsync == null) this.options.w = 1; + + // Set the root if overridden + this.root = this.options['root'] == null ? exports.GridStore.DEFAULT_ROOT_COLLECTION : this.options['root']; + this.position = 0; + this.readPreference = this.options.readPreference || 'primary'; + this.writeConcern = _getWriteConcern(this, this.options); + // Set default chunk size + this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize']; +} + +/** + * Code for the streaming capabilities of the gridstore object + * Most code from Aaron heckmanns project https://github.com/aheckmann/gridfs-stream + * Modified to work on the gridstore object itself + * @ignore + */ +if(typeof Stream == 'function') { + GridStore.prototype = { __proto__: Stream.prototype } +} else { + // Node 0.4.X compatibility code + GridStore.prototype = { __proto__: Stream.Stream.prototype } +} + +// Move pipe to _pipe +GridStore.prototype._pipe = GridStore.prototype.pipe; + +/** + * Opens the file from the database and initialize this object. Also creates a + * new one if file does not exist. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain an **{Error}** object and the second parameter will be null if an error occured. Otherwise, the first parameter will be null and the second will contain the reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.open = function(callback) { + if( this.mode != "w" && this.mode != "w+" && this.mode != "r"){ + callback(new Error("Illegal mode " + this.mode), null); + return; + } + + var self = this; + + if((self.mode == "w" || self.mode == "w+") && self.db.serverConfig.primary != null) { + // Get files collection + self.collection(function(err, collection) { + if(err) return callback(err); + + // Put index on filename + collection.ensureIndex([['filename', 1]], function(err, index) { + if(err) return callback(err); + + // Get chunk collection + self.chunkCollection(function(err, chunkCollection) { + if(err) return callback(err); + + // Ensure index on chunk collection + chunkCollection.ensureIndex([['files_id', 1], ['n', 1]], function(err, index) { + if(err) return callback(err); + _open(self, callback); + }); + }); + }); + }); + } else { + // Open the gridstore + _open(self, callback); + } +}; + +/** + * Hidding the _open function + * @ignore + * @api private + */ +var _open = function(self, callback) { + self.collection(function(err, collection) { + if(err!==null) { + callback(new Error("at collection: "+err), null); + return; + } + + // Create the query + var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename}; + query = null == self.fileId && this.filename == null ? null : query; + + // Fetch the chunks + if(query != null) { + collection.find(query, {readPreference:self.readPreference}, function(err, cursor) { + if(err) return error(err); + + // Fetch the file + cursor.nextObject(function(err, doc) { + if(err) return error(err); + + // Check if the collection for the files exists otherwise prepare the new one + if(doc != null) { + self.fileId = doc._id; + self.filename = doc.filename; + self.contentType = doc.contentType; + self.internalChunkSize = doc.chunkSize; + self.uploadDate = doc.uploadDate; + self.aliases = doc.aliases; + self.length = doc.length; + self.metadata = doc.metadata; + self.internalMd5 = doc.md5; + } else if (self.mode != 'r') { + self.fileId = self.fileId == null ? new ObjectID() : self.fileId; + self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE; + self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize; + self.length = 0; + } else { + self.length = 0; + var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId; + return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self)); + } + + // Process the mode of the object + if(self.mode == "r") { + nthChunk(self, 0, function(err, chunk) { + if(err) return error(err); + self.currentChunk = chunk; + self.position = 0; + callback(null, self); + }); + } else if(self.mode == "w") { + // Delete any existing chunks + deleteChunks(self, function(err, result) { + if(err) return error(err); + self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern); + self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type']; + self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size']; + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.position = 0; + callback(null, self); + }); + } else if(self.mode == "w+") { + nthChunk(self, lastChunkNumber(self), function(err, chunk) { + if(err) return error(err); + // Set the current chunk + self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk; + self.currentChunk.position = self.currentChunk.data.length(); + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.position = self.length; + callback(null, self); + }); + } + }); + }); + } else { + // Write only mode + self.fileId = null == self.fileId ? new ObjectID() : self.fileId; + self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE; + self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize; + self.length = 0; + + self.chunkCollection(function(err, collection2) { + if(err) return error(err); + + // No file exists set up write mode + if(self.mode == "w") { + // Delete any existing chunks + deleteChunks(self, function(err, result) { + if(err) return error(err); + self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern); + self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type']; + self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size']; + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.position = 0; + callback(null, self); + }); + } else if(self.mode == "w+") { + nthChunk(self, lastChunkNumber(self), function(err, chunk) { + if(err) return error(err); + // Set the current chunk + self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk; + self.currentChunk.position = self.currentChunk.data.length(); + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.position = self.length; + callback(null, self); + }); + } + }); + } + }); + + // only pass error to callback once + function error (err) { + if(error.err) return; + callback(error.err = err); + } +}; + +/** + * Stores a file from the file system to the GridFS database. + * + * @param {String|Buffer|FileHandle} file the file to store. + * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the the second will contain the reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.writeFile = function (file, callback) { + var self = this; + if (typeof file === 'string') { + fs.open(file, 'r', function (err, fd) { + if(err) return callback(err); + self.writeFile(fd, callback); + }); + return; + } + + self.open(function (err, self) { + if(err) return callback(err, self); + + fs.fstat(file, function (err, stats) { + if(err) return callback(err, self); + + var offset = 0; + var index = 0; + var numberOfChunksLeft = Math.min(stats.size / self.chunkSize); + + // Write a chunk + var writeChunk = function() { + fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) { + if(err) return callback(err, self); + + offset = offset + bytesRead; + + // Create a new chunk for the data + var chunk = new Chunk(self, {n:index++}, self.writeConcern); + chunk.write(data, function(err, chunk) { + if(err) return callback(err, self); + + chunk.save(function(err, result) { + if(err) return callback(err, self); + + self.position = self.position + data.length; + + // Point to current chunk + self.currentChunk = chunk; + + if(offset >= stats.size) { + fs.close(file); + self.close(function(err, result) { + if(err) return callback(err, self); + return callback(null, self); + }); + } else { + return processor(writeChunk); + } + }); + }); + }); + } + + // Process the first write + processor(writeChunk); + }); + }); +}; + +/** + * Writes some data. This method will work properly only if initialized with mode + * "w" or "w+". + * + * @param string {string} The data to write. + * @param close {boolean=false} opt_argument Closes this file after writing if + * true. + * @param callback {function(*, GridStore)} This will be called after executing + * this method. The first parameter will contain null and the second one + * will contain a reference to this object. + * + * @ignore + * @api private + */ +var writeBuffer = function(self, buffer, close, callback) { + if(typeof close === "function") { callback = close; close = null; } + var finalClose = (close == null) ? false : close; + + if(self.mode[0] != "w") { + callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null); + } else { + if(self.currentChunk.position + buffer.length >= self.chunkSize) { + // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left + // to a new chunk (recursively) + var previousChunkNumber = self.currentChunk.chunkNumber; + var leftOverDataSize = self.chunkSize - self.currentChunk.position; + var firstChunkData = buffer.slice(0, leftOverDataSize); + var leftOverData = buffer.slice(leftOverDataSize); + // A list of chunks to write out + var chunksToWrite = [self.currentChunk.write(firstChunkData)]; + // If we have more data left than the chunk size let's keep writing new chunks + while(leftOverData.length >= self.chunkSize) { + // Create a new chunk and write to it + var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern); + var firstChunkData = leftOverData.slice(0, self.chunkSize); + leftOverData = leftOverData.slice(self.chunkSize); + // Update chunk number + previousChunkNumber = previousChunkNumber + 1; + // Write data + newChunk.write(firstChunkData); + // Push chunk to save list + chunksToWrite.push(newChunk); + } + + // Set current chunk with remaining data + self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern); + // If we have left over data write it + if(leftOverData.length > 0) self.currentChunk.write(leftOverData); + + // Update the position for the gridstore + self.position = self.position + buffer.length; + // Total number of chunks to write + var numberOfChunksToWrite = chunksToWrite.length; + // Write out all the chunks and then return + for(var i = 0; i < chunksToWrite.length; i++) { + var chunk = chunksToWrite[i]; + chunk.save(function(err, result) { + if(err) return callback(err); + + numberOfChunksToWrite = numberOfChunksToWrite - 1; + + if(numberOfChunksToWrite <= 0) { + return callback(null, self); + } + }) + } + } else { + // Update the position for the gridstore + self.position = self.position + buffer.length; + // We have less data than the chunk size just write it and callback + self.currentChunk.write(buffer); + callback(null, self); + } + } +}; + +/** + * Creates a mongoDB object representation of this object. + * + * @param callback {function(object)} This will be called after executing this + * method. The object will be passed to the first parameter and will have + * the structure: + * + *
    
    + *        {
    + *          '_id' : , // {number} id for this file
    + *          'filename' : , // {string} name for this file
    + *          'contentType' : , // {string} mime type for this file
    + *          'length' : , // {number} size of this file?
    + *          'chunksize' : , // {number} chunk size used by this file
    + *          'uploadDate' : , // {Date}
    + *          'aliases' : , // {array of string}
    + *          'metadata' : , // {string}
    + *        }
    + *        
    + * + * @ignore + * @api private + */ +var buildMongoObject = function(self, callback) { + // // Keeps the final chunk number + // var chunkNumber = 0; + // var previousChunkSize = 0; + // // Get the correct chunk Number, if we have an empty chunk return the previous chunk number + // if(null != self.currentChunk && self.currentChunk.chunkNumber > 0 && self.currentChunk.position == 0) { + // chunkNumber = self.currentChunk.chunkNumber - 1; + // } else { + // chunkNumber = self.currentChunk.chunkNumber; + // previousChunkSize = self.currentChunk.position; + // } + + // // Calcuate the length + // var length = self.currentChunk != null ? (chunkNumber * self.chunkSize + previousChunkSize) : 0; + var mongoObject = { + '_id': self.fileId, + 'filename': self.filename, + 'contentType': self.contentType, + 'length': self.position ? self.position : 0, + 'chunkSize': self.chunkSize, + 'uploadDate': self.uploadDate, + 'aliases': self.aliases, + 'metadata': self.metadata + }; + + var md5Command = {filemd5:self.fileId, root:self.root}; + self.db.command(md5Command, function(err, results) { + mongoObject.md5 = results.md5; + callback(mongoObject); + }); +}; + +/** + * Saves this file to the database. This will overwrite the old entry if it + * already exists. This will work properly only if mode was initialized to + * "w" or "w+". + * + * @param {Function} callback this will be called after executing this method. Passes an **{Error}** object to the first parameter and null to the second if an error occured. Otherwise, passes null to the first and a reference to this object to the second. + * @return {null} + * @api public + */ +GridStore.prototype.close = function(callback) { + var self = this; + + if(self.mode[0] == "w") { + if(self.currentChunk != null && self.currentChunk.position > 0) { + self.currentChunk.save(function(err, chunk) { + if(err && typeof callback == 'function') return callback(err); + + self.collection(function(err, files) { + if(err && typeof callback == 'function') return callback(err); + + // Build the mongo object + if(self.uploadDate != null) { + files.remove({'_id':self.fileId}, {safe:true}, function(err, collection) { + if(err && typeof callback == 'function') return callback(err); + + buildMongoObject(self, function(mongoObject) { + files.save(mongoObject, self.writeConcern, function(err) { + if(typeof callback == 'function') + callback(err, mongoObject); + }); + }); + }); + } else { + self.uploadDate = new Date(); + buildMongoObject(self, function(mongoObject) { + files.save(mongoObject, self.writeConcern, function(err) { + if(typeof callback == 'function') + callback(err, mongoObject); + }); + }); + } + }); + }); + } else { + self.collection(function(err, files) { + if(err && typeof callback == 'function') return callback(err); + + self.uploadDate = new Date(); + buildMongoObject(self, function(mongoObject) { + files.save(mongoObject, self.writeConcern, function(err) { + if(typeof callback == 'function') + callback(err, mongoObject); + }); + }); + }); + } + } else if(self.mode[0] == "r") { + if(typeof callback == 'function') + callback(null, null); + } else { + if(typeof callback == 'function') + callback(new Error("Illegal mode " + self.mode), null); + } +}; + +/** + * Gets the nth chunk of this file. + * + * @param chunkNumber {number} The nth chunk to retrieve. + * @param callback {function(*, Chunk|object)} This will be called after + * executing this method. null will be passed to the first parameter while + * a new {@link Chunk} instance will be passed to the second parameter if + * the chunk was found or an empty object {} if not. + * + * @ignore + * @api private + */ +var nthChunk = function(self, chunkNumber, callback) { + self.chunkCollection(function(err, collection) { + if(err) return callback(err); + + collection.find({'files_id':self.fileId, 'n':chunkNumber}, {readPreference: self.readPreference}, function(err, cursor) { + if(err) return callback(err); + + cursor.nextObject(function(err, chunk) { + if(err) return callback(err); + + var finalChunk = chunk == null ? {} : chunk; + callback(null, new Chunk(self, finalChunk, self.writeConcern)); + }); + }); + }); +}; + +/** + * + * @ignore + * @api private + */ +GridStore.prototype._nthChunk = function(chunkNumber, callback) { + nthChunk(this, chunkNumber, callback); +} + +/** + * @return {Number} The last chunk number of this file. + * + * @ignore + * @api private + */ +var lastChunkNumber = function(self) { + return Math.floor(self.length/self.chunkSize); +}; + +/** + * Retrieve this file's chunks collection. + * + * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured. + * @return {null} + * @api public + */ +GridStore.prototype.chunkCollection = function(callback) { + this.db.collection((this.root + ".chunks"), callback); +}; + +/** + * Deletes all the chunks of this file in the database. + * + * @param callback {function(*, boolean)} This will be called after this method + * executes. Passes null to the first and true to the second argument. + * + * @ignore + * @api private + */ +var deleteChunks = function(self, callback) { + if(self.fileId != null) { + self.chunkCollection(function(err, collection) { + if(err) return callback(err, false); + collection.remove({'files_id':self.fileId}, {safe:true}, function(err, result) { + if(err) return callback(err, false); + callback(null, true); + }); + }); + } else { + callback(null, true); + } +}; + +/** + * Deletes all the chunks of this file in the database. + * + * @param {Function} callback this will be called after this method executes. Passes null to the first and true to the second argument. + * @return {null} + * @api public + */ +GridStore.prototype.unlink = function(callback) { + var self = this; + deleteChunks(this, function(err) { + if(err!==null) { + err.message = "at deleteChunks: " + err.message; + return callback(err); + } + + self.collection(function(err, collection) { + if(err!==null) { + err.message = "at collection: " + err.message; + return callback(err); + } + + collection.remove({'_id':self.fileId}, {safe:true}, function(err) { + callback(err, self); + }); + }); + }); +}; + +/** + * Retrieves the file collection associated with this object. + * + * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured. + * @return {null} + * @api public + */ +GridStore.prototype.collection = function(callback) { + this.db.collection(this.root + ".files", callback); +}; + +/** + * Reads the data of this file. + * + * @param {String} [separator] the character to be recognized as the newline separator. + * @param {Function} callback This will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character. + * @return {null} + * @api public + */ +GridStore.prototype.readlines = function(separator, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + separator = args.length ? args.shift() : "\n"; + + this.read(function(err, data) { + if(err) return callback(err); + + var items = data.toString().split(separator); + items = items.length > 0 ? items.splice(0, items.length - 1) : []; + for(var i = 0; i < items.length; i++) { + items[i] = items[i] + separator; + } + + callback(null, items); + }); +}; + +/** + * Deletes all the chunks of this file in the database if mode was set to "w" or + * "w+" and resets the read/write head to the initial position. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.rewind = function(callback) { + var self = this; + + if(this.currentChunk.chunkNumber != 0) { + if(this.mode[0] == "w") { + deleteChunks(self, function(err, gridStore) { + if(err) return callback(err); + self.currentChunk = new Chunk(self, {'n': 0}, self.writeConcern); + self.position = 0; + callback(null, self); + }); + } else { + self.currentChunk(0, function(err, chunk) { + if(err) return callback(err); + self.currentChunk = chunk; + self.currentChunk.rewind(); + self.position = 0; + callback(null, self); + }); + } + } else { + self.currentChunk.rewind(); + self.position = 0; + callback(null, self); + } +}; + +/** + * Retrieves the contents of this file and advances the read/write head. Works with Buffers only. + * + * There are 3 signatures for this method: + * + * (callback) + * (length, callback) + * (length, buffer, callback) + * + * @param {Number} [length] the number of characters to read. Reads all the characters from the read/write head to the EOF if not specified. + * @param {String|Buffer} [buffer] a string to hold temporary data. This is used for storing the string data read so far when recursively calling this method. + * @param {Function} callback this will be called after this method is executed. null will be passed to the first parameter and a string containing the contents of the buffer concatenated with the contents read from this file will be passed to the second. + * @return {null} + * @api public + */ +GridStore.prototype.read = function(length, buffer, callback) { + var self = this; + + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + length = args.length ? args.shift() : null; + buffer = args.length ? args.shift() : null; + + // The data is a c-terminated string and thus the length - 1 + var finalLength = length == null ? self.length - self.position : length; + var finalBuffer = buffer == null ? new Buffer(finalLength) : buffer; + // Add a index to buffer to keep track of writing position or apply current index + finalBuffer._index = buffer != null && buffer._index != null ? buffer._index : 0; + + if((self.currentChunk.length() - self.currentChunk.position + finalBuffer._index) >= finalLength) { + var slice = self.currentChunk.readSlice(finalLength - finalBuffer._index); + // Copy content to final buffer + slice.copy(finalBuffer, finalBuffer._index); + // Update internal position + self.position = self.position + finalBuffer.length; + // Check if we don't have a file at all + if(finalLength == 0 && finalBuffer.length == 0) return callback(new Error("File does not exist"), null); + // Else return data + callback(null, finalBuffer); + } else { + var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position); + // Copy content to final buffer + slice.copy(finalBuffer, finalBuffer._index); + // Update index position + finalBuffer._index += slice.length; + + // Load next chunk and read more + nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) { + if(err) return callback(err); + + if(chunk.length() > 0) { + self.currentChunk = chunk; + self.read(length, finalBuffer, callback); + } else { + if (finalBuffer._index > 0) { + callback(null, finalBuffer) + } else { + callback(new Error("no chunks found for file, possibly corrupt"), null); + } + } + }); + } +} + +/** + * Retrieves the position of the read/write head of this file. + * + * @param {Function} callback This gets called after this method terminates. null is passed to the first parameter and the position is passed to the second. + * @return {null} + * @api public + */ +GridStore.prototype.tell = function(callback) { + callback(null, this.position); +}; + +/** + * Moves the read/write head to a new location. + * + * There are 3 signatures for this method + * + * Seek Location Modes + * - **GridStore.IO_SEEK_SET**, **(default)** set the position from the start of the file. + * - **GridStore.IO_SEEK_CUR**, set the position from the current position in the file. + * - **GridStore.IO_SEEK_END**, set the position from the end of the file. + * + * @param {Number} [position] the position to seek to + * @param {Number} [seekLocation] seek mode. Use one of the Seek Location modes. + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.seek = function(position, seekLocation, callback) { + var self = this; + + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + seekLocation = args.length ? args.shift() : null; + + var seekLocationFinal = seekLocation == null ? exports.GridStore.IO_SEEK_SET : seekLocation; + var finalPosition = position; + var targetPosition = 0; + + // Calculate the position + if(seekLocationFinal == exports.GridStore.IO_SEEK_CUR) { + targetPosition = self.position + finalPosition; + } else if(seekLocationFinal == exports.GridStore.IO_SEEK_END) { + targetPosition = self.length + finalPosition; + } else { + targetPosition = finalPosition; + } + + // Get the chunk + var newChunkNumber = Math.floor(targetPosition/self.chunkSize); + if(newChunkNumber != self.currentChunk.chunkNumber) { + var seekChunk = function() { + nthChunk(self, newChunkNumber, function(err, chunk) { + self.currentChunk = chunk; + self.position = targetPosition; + self.currentChunk.position = (self.position % self.chunkSize); + callback(err, self); + }); + }; + + if(self.mode[0] == 'w') { + self.currentChunk.save(function(err) { + if(err) return callback(err); + seekChunk(); + }); + } else { + seekChunk(); + } + } else { + self.position = targetPosition; + self.currentChunk.position = (self.position % self.chunkSize); + callback(null, self); + } +}; + +/** + * Verify if the file is at EOF. + * + * @return {Boolean} true if the read/write head is at the end of this file. + * @api public + */ +GridStore.prototype.eof = function() { + return this.position == this.length ? true : false; +}; + +/** + * Retrieves a single character from this file. + * + * @param {Function} callback this gets called after this method is executed. Passes null to the first parameter and the character read to the second or null to the second if the read/write head is at the end of the file. + * @return {null} + * @api public + */ +GridStore.prototype.getc = function(callback) { + var self = this; + + if(self.eof()) { + callback(null, null); + } else if(self.currentChunk.eof()) { + nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) { + self.currentChunk = chunk; + self.position = self.position + 1; + callback(err, self.currentChunk.getc()); + }); + } else { + self.position = self.position + 1; + callback(null, self.currentChunk.getc()); + } +}; + +/** + * Writes a string to the file with a newline character appended at the end if + * the given string does not have one. + * + * @param {String} string the string to write. + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.puts = function(string, callback) { + var finalString = string.match(/\n$/) == null ? string + "\n" : string; + this.write(finalString, callback); +}; + +/** + * Returns read stream based on this GridStore file + * + * Events + * - **data** {function(item) {}} the data event triggers when a document is ready. + * - **end** {function() {}} the end event triggers when there is no more documents available. + * - **close** {function() {}} the close event triggers when the stream is closed. + * - **error** {function(err) {}} the error event triggers if an error happens. + * + * @param {Boolean} autoclose if true current GridStore will be closed when EOF and 'close' event will be fired + * @return {null} + * @api public + */ +GridStore.prototype.stream = function(autoclose) { + return new ReadStream(autoclose, this); +}; + +/** +* The collection to be used for holding the files and chunks collection. +* +* @classconstant DEFAULT_ROOT_COLLECTION +**/ +GridStore.DEFAULT_ROOT_COLLECTION = 'fs'; + +/** +* Default file mime type +* +* @classconstant DEFAULT_CONTENT_TYPE +**/ +GridStore.DEFAULT_CONTENT_TYPE = 'binary/octet-stream'; + +/** +* Seek mode where the given length is absolute. +* +* @classconstant IO_SEEK_SET +**/ +GridStore.IO_SEEK_SET = 0; + +/** +* Seek mode where the given length is an offset to the current read/write head. +* +* @classconstant IO_SEEK_CUR +**/ +GridStore.IO_SEEK_CUR = 1; + +/** +* Seek mode where the given length is an offset to the end of the file. +* +* @classconstant IO_SEEK_END +**/ +GridStore.IO_SEEK_END = 2; + +/** + * Checks if a file exists in the database. + * + * Options + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Db} db the database to query. + * @param {String} name the name of the file to look for. + * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * @param {Function} callback this will be called after this method executes. Passes null to the first and passes true to the second if the file exists and false otherwise. + * @return {null} + * @api public + */ +GridStore.exist = function(db, fileIdObject, rootCollection, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + rootCollection = args.length ? args.shift() : null; + options = args.length ? args.shift() : {}; + + // Establish read preference + var readPreference = options.readPreference || 'primary'; + // Fetch collection + var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION; + db.collection(rootCollectionFinal + ".files", function(err, collection) { + if(err) return callback(err); + + // Build query + var query = (typeof fileIdObject == 'string' || Object.prototype.toString.call(fileIdObject) == '[object RegExp]' ) + ? {'filename':fileIdObject} + : {'_id':fileIdObject}; // Attempt to locate file + + collection.find(query, {readPreference:readPreference}, function(err, cursor) { + if(err) return callback(err); + + cursor.nextObject(function(err, item) { + if(err) return callback(err); + callback(null, item == null ? false : true); + }); + }); + }); +}; + +/** + * Gets the list of files stored in the GridFS. + * + * @param {Db} db the database to query. + * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * @param {Function} callback this will be called after this method executes. Passes null to the first and passes an array of strings containing the names of the files. + * @return {null} + * @api public + */ +GridStore.list = function(db, rootCollection, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + rootCollection = args.length ? args.shift() : null; + options = args.length ? args.shift() : {}; + + // Ensure we have correct values + if(rootCollection != null && typeof rootCollection == 'object') { + options = rootCollection; + rootCollection = null; + } + + // Establish read preference + var readPreference = options.readPreference || 'primary'; + // Check if we are returning by id not filename + var byId = options['id'] != null ? options['id'] : false; + // Fetch item + var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION; + var items = []; + db.collection((rootCollectionFinal + ".files"), function(err, collection) { + if(err) return callback(err); + + collection.find({}, {readPreference:readPreference}, function(err, cursor) { + if(err) return callback(err); + + cursor.each(function(err, item) { + if(item != null) { + items.push(byId ? item._id : item.filename); + } else { + callback(err, items); + } + }); + }); + }); +}; + +/** + * Reads the contents of a file. + * + * This method has the following signatures + * + * (db, name, callback) + * (db, name, length, callback) + * (db, name, length, offset, callback) + * (db, name, length, offset, options, callback) + * + * @param {Db} db the database to query. + * @param {String} name the name of the file. + * @param {Number} [length] the size of data to read. + * @param {Number} [offset] the offset from the head of the file of which to start reading from. + * @param {Object} [options] the options for the file. + * @param {Function} callback this will be called after this method executes. A string with an error message will be passed to the first parameter when the length and offset combination exceeds the length of the file while an Error object will be passed if other forms of error occured, otherwise, a string is passed. The second parameter will contain the data read if successful or null if an error occured. + * @return {null} + * @api public + */ +GridStore.read = function(db, name, length, offset, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + length = args.length ? args.shift() : null; + offset = args.length ? args.shift() : null; + options = args.length ? args.shift() : null; + + new GridStore(db, name, "r", options).open(function(err, gridStore) { + if(err) return callback(err); + // Make sure we are not reading out of bounds + if(offset && offset >= gridStore.length) return callback("offset larger than size of file", null); + if(length && length > gridStore.length) return callback("length is larger than the size of the file", null); + if(offset && length && (offset + length) > gridStore.length) return callback("offset and length is larger than the size of the file", null); + + if(offset != null) { + gridStore.seek(offset, function(err, gridStore) { + if(err) return callback(err); + gridStore.read(length, callback); + }); + } else { + gridStore.read(length, callback); + } + }); +}; + +/** + * Reads the data of this file. + * + * @param {Db} db the database to query. + * @param {String} name the name of the file. + * @param {String} [separator] the character to be recognized as the newline separator. + * @param {Object} [options] file options. + * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character. + * @return {null} + * @api public + */ +GridStore.readlines = function(db, name, separator, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + separator = args.length ? args.shift() : null; + options = args.length ? args.shift() : null; + + var finalSeperator = separator == null ? "\n" : separator; + new GridStore(db, name, "r", options).open(function(err, gridStore) { + if(err) return callback(err); + gridStore.readlines(finalSeperator, callback); + }); +}; + +/** + * Deletes the chunks and metadata information of a file from GridFS. + * + * @param {Db} db the database to interact with. + * @param {String|Array} names the name/names of the files to delete. + * @param {Object} [options] the options for the files. + * @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.unlink = function(db, names, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() : null; + + if(names.constructor == Array) { + var tc = 0; + for(var i = 0; i < names.length; i++) { + ++tc; + self.unlink(db, names[i], function(result) { + if(--tc == 0) { + callback(null, self); + } + }); + } + } else { + new GridStore(db, names, "w", options).open(function(err, gridStore) { + if(err) return callback(err); + deleteChunks(gridStore, function(err, result) { + if(err) return callback(err); + gridStore.collection(function(err, collection) { + if(err) return callback(err); + collection.remove({'_id':gridStore.fileId}, {safe:true}, function(err, collection) { + callback(err, self); + }); + }); + }); + }); + } +}; + +/** + * Returns the current chunksize of the file. + * + * @field chunkSize + * @type {Number} + * @getter + * @setter + * @property return number of bytes in the current chunkSize. + */ +Object.defineProperty(GridStore.prototype, "chunkSize", { enumerable: true + , get: function () { + return this.internalChunkSize; + } + , set: function(value) { + if(!(this.mode[0] == "w" && this.position == 0 && this.uploadDate == null)) { + this.internalChunkSize = this.internalChunkSize; + } else { + this.internalChunkSize = value; + } + } +}); + +/** + * The md5 checksum for this file. + * + * @field md5 + * @type {Number} + * @getter + * @setter + * @property return this files md5 checksum. + */ +Object.defineProperty(GridStore.prototype, "md5", { enumerable: true + , get: function () { + return this.internalMd5; + } +}); + +/** + * GridStore Streaming methods + * Handles the correct return of the writeable stream status + * @ignore + */ +Object.defineProperty(GridStore.prototype, "writable", { enumerable: true + , get: function () { + if(this._writeable == null) { + this._writeable = this.mode != null && this.mode.indexOf("w") != -1; + } + // Return the _writeable + return this._writeable; + } + , set: function(value) { + this._writeable = value; + } +}); + +/** + * Handles the correct return of the readable stream status + * @ignore + */ +Object.defineProperty(GridStore.prototype, "readable", { enumerable: true + , get: function () { + if(this._readable == null) { + this._readable = this.mode != null && this.mode.indexOf("r") != -1; + } + return this._readable; + } + , set: function(value) { + this._readable = value; + } +}); + +GridStore.prototype.paused; + +/** + * Handles the correct setting of encoding for the stream + * @ignore + */ +GridStore.prototype.setEncoding = fs.ReadStream.prototype.setEncoding; + +/** + * Handles the end events + * @ignore + */ +GridStore.prototype.end = function end(data) { + var self = this; + // allow queued data to write before closing + if(!this.writable) return; + this.writable = false; + + if(data) { + this._q.push(data); + } + + this.on('drain', function () { + self.close(function (err) { + if (err) return _error(self, err); + self.emit('close'); + }); + }); + + _flush(self); +} + +/** + * Handles the normal writes to gridstore + * @ignore + */ +var _writeNormal = function(self, data, close, callback) { + // If we have a buffer write it using the writeBuffer method + if(Buffer.isBuffer(data)) { + return writeBuffer(self, data, close, callback); + } else { + // Wrap the string in a buffer and write + return writeBuffer(self, new Buffer(data, 'binary'), close, callback); + } +} + +/** + * Writes some data. This method will work properly only if initialized with mode "w" or "w+". + * + * @param {String|Buffer} data the data to write. + * @param {Boolean} [close] closes this file after writing if set to true. + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.write = function write(data, close, callback) { + // If it's a normal write delegate the call + if(typeof close == 'function' || typeof callback == 'function') { + return _writeNormal(this, data, close, callback); + } + + // Otherwise it's a stream write + var self = this; + if (!this.writable) { + throw new Error('GridWriteStream is not writable'); + } + + // queue data until we open. + if (!this._opened) { + // Set up a queue to save data until gridstore object is ready + this._q = []; + _openStream(self); + this._q.push(data); + return false; + } + + // Push data to queue + this._q.push(data); + _flush(this); + // Return write successful + return true; +} + +/** + * Handles the destroy part of a stream + * @ignore + */ +GridStore.prototype.destroy = function destroy() { + // close and do not emit any more events. queued data is not sent. + if(!this.writable) return; + this.readable = false; + if(this.writable) { + this.writable = false; + this._q.length = 0; + this.emit('close'); + } +} + +/** + * Handles the destroySoon part of a stream + * @ignore + */ +GridStore.prototype.destroySoon = function destroySoon() { + // as soon as write queue is drained, destroy. + // may call destroy immediately if no data is queued. + if(!this._q.length) { + return this.destroy(); + } + this._destroying = true; +} + +/** + * Handles the pipe part of the stream + * @ignore + */ +GridStore.prototype.pipe = function(destination, options) { + var self = this; + // Open the gridstore + this.open(function(err, result) { + if(err) _errorRead(self, err); + if(!self.readable) return; + // Set up the pipe + self._pipe(destination, options); + // Emit the stream is open + self.emit('open'); + // Read from the stream + _read(self); + }) +} + +/** + * Internal module methods + * @ignore + */ +var _read = function _read(self) { + if (!self.readable || self.paused || self.reading) { + return; + } + + self.reading = true; + var stream = self._stream = self.stream(); + stream.paused = self.paused; + + stream.on('data', function (data) { + if (self._decoder) { + var str = self._decoder.write(data); + if (str.length) self.emit('data', str); + } else { + self.emit('data', data); + } + }); + + stream.on('end', function (data) { + self.emit('end', data); + }); + + stream.on('error', function (data) { + _errorRead(self, data); + }); + + stream.on('close', function (data) { + self.emit('close', data); + }); + + self.pause = function () { + // native doesn't always pause. + // bypass its pause() method to hack it + self.paused = stream.paused = true; + } + + self.resume = function () { + if(!self.paused) return; + + self.paused = false; + stream.resume(); + self.readable = stream.readable; + } + + self.destroy = function () { + self.readable = false; + stream.destroy(); + } +} + +/** + * pause + * @ignore + */ +GridStore.prototype.pause = function pause () { + // Overridden when the GridStore opens. + this.paused = true; +} + +/** + * resume + * @ignore + */ +GridStore.prototype.resume = function resume () { + // Overridden when the GridStore opens. + this.paused = false; +} + +/** + * Internal module methods + * @ignore + */ +var _flush = function _flush(self, _force) { + if (!self._opened) return; + if (!_force && self._flushing) return; + self._flushing = true; + + // write the entire q to gridfs + if (!self._q.length) { + self._flushing = false; + self.emit('drain'); + + if(self._destroying) { + self.destroy(); + } + return; + } + + self.write(self._q.shift(), function (err, store) { + if (err) return _error(self, err); + self.emit('progress', store.position); + _flush(self, true); + }); +} + +var _openStream = function _openStream (self) { + if(self._opening == true) return; + self._opening = true; + + // Open the store + self.open(function (err, gridstore) { + if (err) return _error(self, err); + self._opened = true; + self.emit('open'); + _flush(self); + }); +} + +var _error = function _error(self, err) { + self.destroy(); + self.emit('error', err); +} + +var _errorRead = function _errorRead (self, err) { + self.readable = false; + self.emit('error', err); +} + +/** + * @ignore + */ +var _hasWriteConcern = function(errorOptions) { + return errorOptions == true + || errorOptions.w > 0 + || errorOptions.w == 'majority' + || errorOptions.j == true + || errorOptions.journal == true + || errorOptions.fsync == true +} + +/** + * @ignore + */ +var _setWriteConcernHash = function(options) { + var finalOptions = {}; + if(options.w != null) finalOptions.w = options.w; + if(options.journal == true) finalOptions.j = options.journal; + if(options.j == true) finalOptions.j = options.j; + if(options.fsync == true) finalOptions.fsync = options.fsync; + if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; + return finalOptions; +} + +/** + * @ignore + */ +var _getWriteConcern = function(self, options, callback) { + // Final options + var finalOptions = {w:1}; + options = options || {}; + // Local options verification + if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(options); + } else if(typeof options.safe == "boolean") { + finalOptions = {w: (options.safe ? 1 : 0)}; + } else if(options.safe != null && typeof options.safe == 'object') { + finalOptions = _setWriteConcernHash(options.safe); + } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.db.safe); + } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.db.options); + } else if(typeof self.db.safe == "boolean") { + finalOptions = {w: (self.db.safe ? 1 : 0)}; + } + + // Ensure we don't have an invalid combination of write concerns + if(finalOptions.w < 1 + && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true"); + + // Return the options + return finalOptions; +} + +/** + * @ignore + * @api private + */ +exports.GridStore = GridStore; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js new file mode 100644 index 0000000..8ff9973 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js @@ -0,0 +1,193 @@ +var Stream = require('stream').Stream, + timers = require('timers'), + util = require('util'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; +processor = process.nextTick + +/** + * ReadStream + * + * Returns a stream interface for the **file**. + * + * Events + * - **data** {function(item) {}} the data event triggers when a document is ready. + * - **end** {function() {}} the end event triggers when there is no more documents available. + * - **close** {function() {}} the close event triggers when the stream is closed. + * - **error** {function(err) {}} the error event triggers if an error happens. + * + * @class Represents a GridFS File Stream. + * @param {Boolean} autoclose automatically close file when the stream reaches the end. + * @param {GridStore} cursor a cursor object that the stream wraps. + * @return {ReadStream} + */ +function ReadStream(autoclose, gstore) { + if (!(this instanceof ReadStream)) return new ReadStream(autoclose, gstore); + Stream.call(this); + + this.autoclose = !!autoclose; + this.gstore = gstore; + + this.finalLength = gstore.length - gstore.position; + this.completedLength = 0; + this.currentChunkNumber = gstore.currentChunk.chunkNumber; + + this.paused = false; + this.readable = true; + this.pendingChunk = null; + this.executing = false; + + // Calculate the number of chunks + this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize); + + // This seek start position inside the current chunk + this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize); + + var self = this; + processor(function() { + self._execute(); + }); +}; + +/** + * Inherit from Stream + * @ignore + * @api private + */ +ReadStream.prototype.__proto__ = Stream.prototype; + +/** + * Flag stating whether or not this stream is readable. + */ +ReadStream.prototype.readable; + +/** + * Flag stating whether or not this stream is paused. + */ +ReadStream.prototype.paused; + +/** + * @ignore + * @api private + */ +ReadStream.prototype._execute = function() { + if(this.paused === true || this.readable === false) { + return; + } + + var gstore = this.gstore; + var self = this; + // Set that we are executing + this.executing = true; + + var last = false; + var toRead = 0; + + if(gstore.currentChunk.chunkNumber >= (this.numberOfChunks - 1)) { + self.executing = false; + last = true; + } + + // Data setup + var data = null; + + // Read a slice (with seek set if none) + if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) { + data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition); + this.seekStartPosition = 0; + } else { + data = gstore.currentChunk.readSlice(gstore.currentChunk.length()); + } + + // Return the data + if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) { + self.currentChunkNumber = self.currentChunkNumber + 1; + self.completedLength += data.length; + self.pendingChunk = null; + self.emit("data", data); + } + + if(last === true) { + self.readable = false; + self.emit("end"); + + if(self.autoclose === true) { + if(gstore.mode[0] == "w") { + gstore.close(function(err, doc) { + if (err) { + self.emit("error", err); + return; + } + self.readable = false; + self.emit("close", doc); + }); + } else { + self.readable = false; + self.emit("close"); + } + } + } else { + gstore._nthChunk(gstore.currentChunk.chunkNumber + 1, function(err, chunk) { + if(err) { + self.readable = false; + self.emit("error", err); + self.executing = false; + return; + } + + self.pendingChunk = chunk; + if(self.paused === true) { + self.executing = false; + return; + } + + gstore.currentChunk = self.pendingChunk; + self._execute(); + }); + } +}; + +/** + * Pauses this stream, then no farther events will be fired. + * + * @ignore + * @api public + */ +ReadStream.prototype.pause = function() { + if(!this.executing) { + this.paused = true; + } +}; + +/** + * Destroys the stream, then no farther events will be fired. + * + * @ignore + * @api public + */ +ReadStream.prototype.destroy = function() { + this.readable = false; + // Emit close event + this.emit("close"); +}; + +/** + * Resumes this stream. + * + * @ignore + * @api public + */ +ReadStream.prototype.resume = function() { + if(this.paused === false || !this.readable) { + return; + } + + this.paused = false; + var self = this; + processor(function() { + self._execute(); + }); +}; + +exports.ReadStream = ReadStream; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js new file mode 100644 index 0000000..91d28df --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js @@ -0,0 +1,69 @@ +try { + exports.BSONPure = require('bson').BSONPure; + exports.BSONNative = require('bson').BSONNative; +} catch(err) { + // do nothing +} + +// export the driver version +exports.version = require('../../package').version; + +[ 'commands/base_command' + , 'admin' + , 'collection' + , 'connection/read_preference' + , 'connection/connection' + , 'connection/server' + , 'connection/mongos' + , 'connection/repl_set/repl_set' + , 'mongo_client' + , 'cursor' + , 'db' + , 'mongo_client' + , 'gridfs/grid' + , 'gridfs/chunk' + , 'gridfs/gridstore'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + exports[i] = module[i]; + } +}); + +// backwards compat +exports.ReplSetServers = exports.ReplSet; +// Add BSON Classes +exports.Binary = require('bson').Binary; +exports.Code = require('bson').Code; +exports.DBRef = require('bson').DBRef; +exports.Double = require('bson').Double; +exports.Long = require('bson').Long; +exports.MinKey = require('bson').MinKey; +exports.MaxKey = require('bson').MaxKey; +exports.ObjectID = require('bson').ObjectID; +exports.Symbol = require('bson').Symbol; +exports.Timestamp = require('bson').Timestamp; +// Add BSON Parser +exports.BSON = require('bson').BSONPure.BSON; + +// Get the Db object +var Db = require('./db').Db; +// Set up the connect function +var connect = Db.connect; +var obj = connect; +// Map all values to the exports value +for(var name in exports) { + obj[name] = exports[name]; +} + +// Add the pure and native backward compatible functions +exports.pure = exports.native = function() { + return obj; +} + +// Map all values to the exports value +for(var name in exports) { + connect[name] = exports[name]; +} + +// Set our exports to be the connect function +module.exports = connect; diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js new file mode 100644 index 0000000..d37d269 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js @@ -0,0 +1,371 @@ +var Db = require('./db').Db + , Server = require('./connection/server').Server + , Mongos = require('./connection/mongos').Mongos + , ReplSet = require('./connection/repl_set/repl_set').ReplSet + , ReadPreference = require('./connection/read_preference').ReadPreference + , inherits = require('util').inherits + , EventEmitter = require('events').EventEmitter + , parse = require('./connection/url_parser').parse; + +/** + * Create a new MongoClient instance. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning + * - **journal**, (Boolean, default:false) write waits for journal sync before returning + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **native_parser** {Boolean, default:false}, use c++ bson parser. + * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **serializeFunctions** {Boolean, default:false}, serialize functions. + * - **raw** {Boolean, default:false}, peform operations using raw bson buffers. + * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution. + * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries. + * - **numberOfRetries** {Number, default:5}, number of retries off connection. + * + * Deprecated Options + * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB. + * + * @class Represents a MongoClient + * @param {Object} serverConfig server config object. + * @param {Object} [options] additional options for the collection. + */ +function MongoClient(serverConfig, options) { + if(serverConfig != null) { + options = options == null ? {} : options; + // If no write concern is set set the default to w:1 + if(options != null && !options.journal && !options.w && !options.fsync) { + options.w = 1; + } + + // The internal db instance we are wrapping + this._db = new Db('test', serverConfig, options); + } +} + +/** + * @ignore + */ +inherits(MongoClient, EventEmitter); + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Options + * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication + * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** + * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** + * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** + * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** + * + * @param {String} url connection url for MongoDB. + * @param {Object} [options] optional options for insert command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.prototype.connect = function(url, options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + MongoClient.connect(url, options, function(err, db) { + if(err) return callback(err, db); + // Store internal db instance reference + self._db = db; + // Emit open and perform callback + self.emit("open", err, db); + callback(err, db); + }); +} + +/** + * Initialize the database connection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the connected mongoclient or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.prototype.open = function(callback) { + // Self reference + var self = this; + // Open the db + this._db.open(function(err, db) { + if(err) return callback(err, null); + // Emit open event + self.emit("open", err, db); + // Callback + callback(null, self); + }) +} + +/** + * Close the current db connection, including all the child db instances. Emits close event if no callback is provided. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the close method or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.prototype.close = function(callback) { + this._db.close(callback); +} + +/** + * Create a new Db instance sharing the current socket connections. + * + * @param {String} dbName the name of the database we want to use. + * @return {Db} a db instance using the new database. + * @api public + */ +MongoClient.prototype.db = function(dbName) { + return this._db.db(dbName); +} + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Options + * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication + * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** + * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** + * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** + * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** + * + * @param {String} url connection url for MongoDB. + * @param {Object} [options] optional options for insert command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.connect = function(url, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = typeof args[args.length - 1] == 'function' ? args.pop() : null; + options = args.length ? args.shift() : null; + options = options || {}; + + // Set default empty server options + var serverOptions = options.server || {}; + var mongosOptions = options.mongos || {}; + var replSetServersOptions = options.replSet || options.replSetServers || {}; + var dbOptions = options.db || {}; + + // If callback is null throw an exception + if(callback == null) throw new Error("no callback function provided"); + + // Parse the string + var object = parse(url, options); + // Merge in any options for db in options object + if(dbOptions) { + for(var name in dbOptions) object.db_options[name] = dbOptions[name]; + } + + // Added the url to the options + object.db_options.url = url; + + // Merge in any options for server in options object + if(serverOptions) { + for(var name in serverOptions) object.server_options[name] = serverOptions[name]; + } + + // Merge in any replicaset server options + if(replSetServersOptions) { + for(var name in replSetServersOptions) object.rs_options[name] = replSetServersOptions[name]; + } + + // Merge in any replicaset server options + if(mongosOptions) { + for(var name in mongosOptions) object.mongos_options[name] = mongosOptions[name]; + } + + // We need to ensure that the list of servers are only either direct members or mongos + // they cannot be a mix of monogs and mongod's + var totalNumberOfServers = object.servers.length; + var totalNumberOfMongosServers = 0; + var totalNumberOfMongodServers = 0; + var serverConfig = null; + var errorServers = {}; + + // Failure modes + if(object.servers.length == 0) throw new Error("connection string must contain at least one seed host"); + + // If we have no db setting for the native parser try to set the c++ one first + object.db_options.native_parser = _setNativeParser(object.db_options); + // If no auto_reconnect is set, set it to true as default for single servers + if(typeof object.server_options.auto_reconnect != 'boolean') { + object.server_options.auto_reconnect = true; + } + + // If we have more than a server, it could be replicaset or mongos list + // need to verify that it's one or the other and fail if it's a mix + // Connect to all servers and run ismaster + for(var i = 0; i < object.servers.length; i++) { + // Set up socket options + var _server_options = {poolSize:1, socketOptions:{connectTimeoutMS:1000}, auto_reconnect:false}; + + // Ensure we have ssl setup for the servers + if(object.rs_options.ssl) { + _server_options.ssl = object.rs_options.ssl; + _server_options.sslValidate = object.rs_options.sslValidate; + _server_options.sslCA = object.rs_options.sslCA; + _server_options.sslCert = object.rs_options.sslCert; + _server_options.sslKey = object.rs_options.sslKey; + _server_options.sslPass = object.rs_options.sslPass; + } else if(object.server_options.ssl) { + _server_options.ssl = object.server_options.ssl; + _server_options.sslValidate = object.server_options.sslValidate; + _server_options.sslCA = object.server_options.sslCA; + _server_options.sslCert = object.server_options.sslCert; + _server_options.sslKey = object.server_options.sslKey; + _server_options.sslPass = object.server_options.sslPass; + } + + // Set up the Server object + var _server = object.servers[i].domain_socket + ? new Server(object.servers[i].domain_socket, _server_options) + : new Server(object.servers[i].host, object.servers[i].port, _server_options); + + var connectFunction = function(__server) { + // Attempt connect + new Db(object.dbName, __server, {safe:false, native_parser:false}).open(function(err, db) { + // Update number of servers + totalNumberOfServers = totalNumberOfServers - 1; + // If no error do the correct checks + if(!err) { + // Close the connection + db.close(true); + var isMasterDoc = db.serverConfig.isMasterDoc; + // Check what type of server we have + if(isMasterDoc.setName) totalNumberOfMongodServers++; + if(isMasterDoc.msg && isMasterDoc.msg == "isdbgrid") totalNumberOfMongosServers++; + } else { + errorServers[__server.host + ":" + __server.port] = __server; + } + + if(totalNumberOfServers == 0) { + // If we have a mix of mongod and mongos, throw an error + if(totalNumberOfMongosServers > 0 && totalNumberOfMongodServers > 0) + return callback(new Error("cannot combine a list of replicaset seeds and mongos seeds")); + + if(totalNumberOfMongodServers == 0 && object.servers.length == 1) { + var obj = object.servers[0]; + serverConfig = obj.domain_socket ? + new Server(obj.domain_socket, object.server_options) + : new Server(obj.host, obj.port, object.server_options); + } else if(totalNumberOfMongodServers > 0 || totalNumberOfMongosServers > 0) { + var finalServers = object.servers + .filter(function(serverObj) { + return errorServers[serverObj.host + ":" + serverObj.port] == null; + }) + .map(function(serverObj) { + return new Server(serverObj.host, serverObj.port, object.server_options); + }); + // Clean out any error servers + errorServers = {}; + // Set up the final configuration + if(totalNumberOfMongodServers > 0) { + serverConfig = new ReplSet(finalServers, object.rs_options); + } else { + serverConfig = new Mongos(finalServers, object.mongos_options); + } + } + + if(serverConfig == null) return callback(new Error("Could not locate any valid servers in initial seed list")); + // Ensure no firing off open event before we are ready + serverConfig.emitOpen = false; + // Set up all options etc and connect to the database + _finishConnecting(serverConfig, object, options, callback) + } + }); + } + + // Wrap the context of the call + connectFunction(_server); + } +} + +var _setNativeParser = function(db_options) { + if(typeof db_options.native_parser == 'boolean') return db_options.native_parser; + + try { + require('bson').BSONNative.BSON; + return true; + } catch(err) { + return false; + } +} + +var _finishConnecting = function(serverConfig, object, options, callback) { + // Safe settings + var safe = {}; + // Build the safe parameter if needed + if(object.db_options.journal) safe.j = object.db_options.journal; + if(object.db_options.w) safe.w = object.db_options.w; + if(object.db_options.fsync) safe.fsync = object.db_options.fsync; + if(object.db_options.wtimeoutMS) safe.wtimeout = object.db_options.wtimeoutMS; + + // If we have a read Preference set + if(object.db_options.read_preference) { + var readPreference = new ReadPreference(object.db_options.read_preference); + // If we have the tags set up + if(object.db_options.read_preference_tags) + readPreference = new ReadPreference(object.db_options.read_preference, object.db_options.read_preference_tags); + // Add the read preference + object.db_options.readPreference = readPreference; + } + + // No safe mode if no keys + if(Object.keys(safe).length == 0) safe = false; + + // Add the safe object + object.db_options.safe = safe; + + // Set up the db options + var db = new Db(object.dbName, serverConfig, object.db_options); + // Open the db + db.open(function(err, db){ + if(err) return callback(err, null); + + if(db.options !== null && !db.options.safe && !db.options.journal + && !db.options.w && !db.options.fsync && typeof db.options.w != 'number' + && (db.options.safe == false && object.db_options.url.indexOf("safe=") == -1)) { + db.options.w = 1; + } + + if(err == null && object.auth){ + // What db to authenticate against + var authentication_db = db; + if(object.db_options && object.db_options.authSource) { + authentication_db = db.db(object.db_options.authSource); + } + + // Build options object + var options = {}; + if(object.db_options.authMechanism) options.authMechanism = object.db_options.authMechanism; + if(object.db_options.gssapiServiceName) options.gssapiServiceName = object.db_options.gssapiServiceName; + + // Authenticate + authentication_db.authenticate(object.auth.user, object.auth.password, options, function(err, success){ + if(success){ + callback(null, db); + } else { + if(db) db.close(); + callback(err ? err : new Error('Could not authenticate user ' + auth[0]), null); + } + }); + } else { + callback(err, db); + } + }); +} + + +exports.MongoClient = MongoClient; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js new file mode 100644 index 0000000..b27b812 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js @@ -0,0 +1,144 @@ +var Long = require('bson').Long + , timers = require('timers'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = timers.setImmediate ? timers.setImmediate : process.nextTick; + +/** + Reply message from mongo db +**/ +var MongoReply = exports.MongoReply = function() { + this.documents = []; + this.index = 0; +}; + +MongoReply.prototype.parseHeader = function(binary_reply, bson) { + // Unpack the standard header first + this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Fetch the request id for this reply + this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Fetch the id of the request that triggered the response + this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + // Skip op-code field + this.index = this.index + 4 + 4; + // Unpack the reply message + this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Unpack the cursor id (a 64 bit long integer) + var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + this.cursorId = new Long(low_bits, high_bits); + // Unpack the starting from + this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Unpack the number of objects returned + this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; +} + +MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) { + raw = raw == null ? false : raw; + // Just set a doc limit for deserializing + var docLimitSize = 1024*20; + + // If our message length is very long, let's switch to process.nextTick for messages + if(this.messageLength > docLimitSize) { + var batchSize = this.numberReturned; + this.documents = new Array(this.numberReturned); + + // Just walk down until we get a positive number >= 1 + for(var i = 50; i > 0; i--) { + if((this.numberReturned/i) >= 1) { + batchSize = i; + break; + } + } + + // Actual main creator of the processFunction setting internal state to control the flow + var parseFunction = function(_self, _binary_reply, _batchSize, _numberReturned) { + var object_index = 0; + // Internal loop process that will use nextTick to ensure we yield some time + var processFunction = function() { + // Adjust batchSize if we have less results left than batchsize + if((_numberReturned - object_index) < _batchSize) { + _batchSize = _numberReturned - object_index; + } + + // If raw just process the entries + if(raw) { + // Iterate over the batch + for(var i = 0; i < _batchSize; i++) { + // Are we done ? + if(object_index <= _numberReturned) { + // Read the size of the bson object + var bsonObjectSize = _binary_reply[_self.index] | _binary_reply[_self.index + 1] << 8 | _binary_reply[_self.index + 2] << 16 | _binary_reply[_self.index + 3] << 24; + // If we are storing the raw responses to pipe straight through + _self.documents[object_index] = binary_reply.slice(_self.index, _self.index + bsonObjectSize); + // Adjust binary index to point to next block of binary bson data + _self.index = _self.index + bsonObjectSize; + // Update number of docs parsed + object_index = object_index + 1; + } + } + } else { + try { + // Parse documents + _self.index = bson.deserializeStream(binary_reply, _self.index, _batchSize, _self.documents, object_index); + // Adjust index + object_index = object_index + _batchSize; + } catch (err) { + return callback(err); + } + } + + // If we have more documents process NextTick + if(object_index < _numberReturned) { + processor(processFunction); + } else { + callback(null); + } + } + + // Return the process function + return processFunction; + }(this, binary_reply, batchSize, this.numberReturned)(); + } else { + try { + // Let's unpack all the bson documents, deserialize them and store them + for(var object_index = 0; object_index < this.numberReturned; object_index++) { + // Read the size of the bson object + var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + // If we are storing the raw responses to pipe straight through + if(raw) { + // Deserialize the object and add to the documents array + this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize)); + } else { + // Deserialize the object and add to the documents array + this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize))); + } + // Adjust binary index to point to next block of binary bson data + this.index = this.index + bsonObjectSize; + } + } catch(err) { + return callback(err); + } + + // No error return + callback(null); + } +} + +MongoReply.prototype.is_error = function(){ + if(this.documents.length == 1) { + return this.documents[0].ok == 1 ? false : true; + } + return false; +}; + +MongoReply.prototype.error_message = function() { + return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg; +}; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js new file mode 100644 index 0000000..087789d --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js @@ -0,0 +1,137 @@ +/** + * Sort functions, Normalize and prepare sort parameters + */ +var formatSortValue = exports.formatSortValue = function(sortDirection) { + var value = ("" + sortDirection).toLowerCase(); + + switch (value) { + case 'ascending': + case 'asc': + case '1': + return 1; + case 'descending': + case 'desc': + case '-1': + return -1; + default: + throw new Error("Illegal sort clause, must be of the form " + + "[['field1', '(ascending|descending)'], " + + "['field2', '(ascending|descending)']]"); + } +}; + +var formattedOrderClause = exports.formattedOrderClause = function(sortValue) { + var orderBy = {}; + + if (Array.isArray(sortValue)) { + for(var i = 0; i < sortValue.length; i++) { + if(sortValue[i].constructor == String) { + orderBy[sortValue[i]] = 1; + } else { + orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]); + } + } + } else if(Object.prototype.toString.call(sortValue) === '[object Object]') { + orderBy = sortValue; + } else if (sortValue.constructor == String) { + orderBy[sortValue] = 1; + } else { + throw new Error("Illegal sort clause, must be of the form " + + "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"); + } + + return orderBy; +}; + +exports.encodeInt = function(value) { + var buffer = new Buffer(4); + buffer[3] = (value >> 24) & 0xff; + buffer[2] = (value >> 16) & 0xff; + buffer[1] = (value >> 8) & 0xff; + buffer[0] = value & 0xff; + return buffer; +} + +exports.encodeIntInPlace = function(value, buffer, index) { + buffer[index + 3] = (value >> 24) & 0xff; + buffer[index + 2] = (value >> 16) & 0xff; + buffer[index + 1] = (value >> 8) & 0xff; + buffer[index] = value & 0xff; +} + +exports.encodeCString = function(string) { + var buf = new Buffer(string, 'utf8'); + return [buf, new Buffer([0])]; +} + +exports.decodeUInt32 = function(array, index) { + return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24; +} + +// Decode the int +exports.decodeUInt8 = function(array, index) { + return array[index]; +} + +/** + * Context insensitive type checks + */ + +var toString = Object.prototype.toString; + +exports.isObject = function (arg) { + return '[object Object]' == toString.call(arg) +} + +exports.isArray = function (arg) { + return Array.isArray(arg) || + 'object' == typeof arg && '[object Array]' == toString.call(arg) +} + +exports.isDate = function (arg) { + return 'object' == typeof arg && '[object Date]' == toString.call(arg) +} + +exports.isRegExp = function (arg) { + return 'object' == typeof arg && '[object RegExp]' == toString.call(arg) +} + +/** + * Wrap a Mongo error document in an Error instance + * @ignore + * @api private + */ +exports.toError = function(error) { + if (error instanceof Error) return error; + + var msg = error.err || error.errmsg || error; + var e = new Error(msg); + e.name = 'MongoError'; + + // Get all object keys + var keys = typeof error == 'object' + ? Object.keys(error) + : []; + + for(var i = 0; i < keys.length; i++) { + e[keys[i]] = error[keys[i]]; + } + + return e; +} + +/** + * Convert a single level object to an array + * @ignore + * @api private + */ +exports.objectToArray = function(object) { + var list = []; + + for(var name in object) { + list.push(object[name]) + } + + return list; +} + diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml new file mode 100644 index 0000000..94740d0 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 # development version of 0.8, may be unstable \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile new file mode 100644 index 0000000..77ce4e0 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile @@ -0,0 +1,19 @@ +NODE = node +NPM = npm +NODEUNIT = node_modules/nodeunit/bin/nodeunit + +all: clean node_gyp + +test: clean node_gyp + npm test + +node_gyp: clean + node-gyp configure build + +clean: + node-gyp clean + +browserify: + node_modules/.bin/onejs build browser_build/package.json browser_build/bson.js + +.PHONY: all diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md new file mode 100644 index 0000000..1a6fc2b --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md @@ -0,0 +1,45 @@ +Javascript + C++ BSON parser +============================ + +This BSON parser is primarily meant for usage with the `mongodb` node.js driver. However thanks to such wonderful tools at `onejs` we are able to package up a BSON parser that will work in the browser aswell. The current build is located in the `browser_build/bson.js` file. + +A simple example on how to use it + + + + + + + + + It's got two simple methods to use in your application. + + * BSON.serialize(object, checkKeys, asBuffer, serializeFunctions) + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)** + * @return {TypedArray/Array} returns a TypedArray or Array depending on what your browser supports + + * BSON.deserialize(buffer, options, isArray) + * Options + * **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * @param {TypedArray/Array} a TypedArray/Array containing the BSON data + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp new file mode 100644 index 0000000..42445d3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp @@ -0,0 +1,17 @@ +{ + 'targets': [ + { + 'target_name': 'bson', + 'sources': [ 'ext/bson.cc' ], + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions' ], + 'conditions': [ + ['OS=="mac"', { + 'xcode_settings': { + 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES' + } + }] + ] + } + ] +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/bson.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/bson.js new file mode 100644 index 0000000..7132496 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/bson.js @@ -0,0 +1,4815 @@ +var bson = (function(){ + + var pkgmap = {}, + global = {}, + nativeRequire = typeof require != 'undefined' && require, + lib, ties, main, async; + + function exports(){ return main(); }; + + exports.main = exports; + exports.module = module; + exports.packages = pkgmap; + exports.pkg = pkg; + exports.require = function require(uri){ return pkgmap.main.index.require(uri); }; + + + ties = {}; + + aliases = {}; + + + return exports; + +function join() { + return normalize(Array.prototype.join.call(arguments, "/")); +}; + +function normalize(path) { + var ret = [], parts = path.split('/'), cur, prev; + + var i = 0, l = parts.length-1; + for (; i <= l; i++) { + cur = parts[i]; + + if (cur === "." && prev !== undefined) continue; + + if (cur === ".." && ret.length && prev !== ".." && prev !== "." && prev !== undefined) { + ret.pop(); + prev = ret.slice(-1)[0]; + } else { + if (prev === ".") ret.pop(); + ret.push(cur); + prev = cur; + } + } + + return ret.join("/"); +}; + +function dirname(path) { + return path && path.substr(0, path.lastIndexOf("/")) || "."; +}; + +function findModule(workingModule, uri){ + var moduleId = join(dirname(workingModule.id), uri).replace(/\.js$/, ''), + moduleIndexId = join(moduleId, 'index'), + pkg = workingModule.pkg, + module; + + var i = pkg.modules.length, + id; + + while(i-->0){ + id = pkg.modules[i].id; + if(id==moduleId || id == moduleIndexId){ + module = pkg.modules[i]; + break; + } + } + + return module; +} + +function newRequire(callingModule){ + function require(uri){ + var module, pkg; + + if(/^\./.test(uri)){ + module = findModule(callingModule, uri); + } else if ( ties && ties.hasOwnProperty( uri ) ) { + return ties[uri]; + } else if ( aliases && aliases.hasOwnProperty( uri ) ) { + return require(aliases[uri]); + } else { + pkg = pkgmap[uri]; + + if(!pkg && nativeRequire){ + try { + pkg = nativeRequire(uri); + } catch (nativeRequireError) {} + + if(pkg) return pkg; + } + + if(!pkg){ + throw new Error('Cannot find module "'+uri+'" @[module: '+callingModule.id+' package: '+callingModule.pkg.name+']'); + } + + module = pkg.index; + } + + if(!module){ + throw new Error('Cannot find module "'+uri+'" @[module: '+callingModule.id+' package: '+callingModule.pkg.name+']'); + } + + module.parent = callingModule; + return module.call(); + }; + + + return require; +} + + +function module(parent, id, wrapper){ + var mod = { pkg: parent, id: id, wrapper: wrapper }, + cached = false; + + mod.exports = {}; + mod.require = newRequire(mod); + + mod.call = function(){ + if(cached) { + return mod.exports; + } + + cached = true; + + global.require = mod.require; + + mod.wrapper(mod, mod.exports, global, global.require); + return mod.exports; + }; + + if(parent.mainModuleId == mod.id){ + parent.index = mod; + parent.parents.length === 0 && ( main = mod.call ); + } + + parent.modules.push(mod); +} + +function pkg(/* [ parentId ...], wrapper */){ + var wrapper = arguments[ arguments.length - 1 ], + parents = Array.prototype.slice.call(arguments, 0, arguments.length - 1), + ctx = wrapper(parents); + + + pkgmap[ctx.name] = ctx; + + arguments.length == 1 && ( pkgmap.main = ctx ); + + return function(modules){ + var id; + for(id in modules){ + module(ctx, id, modules[id]); + } + }; +} + + +}(this)); + +bson.pkg(function(parents){ + + return { + 'name' : 'bson', + 'mainModuleId' : 'bson', + 'modules' : [], + 'parents' : parents + }; + +})({ 'binary': function(module, exports, global, require, undefined){ + /** + * Module dependencies. + */ +if(typeof window === 'undefined') { + var Buffer = require('buffer').Buffer; // TODO just use global Buffer +} + +// Binary default subtype +var BSON_BINARY_SUBTYPE_DEFAULT = 0; + +/** + * @ignore + * @api private + */ +var writeStringToArray = function(data) { + // Create a buffer + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length); + // Write the content to the buffer + for(var i = 0; i < data.length; i++) { + buffer[i] = data.charCodeAt(i); + } + // Write the string to the buffer + return buffer; +} + +/** + * Convert Array ot Uint8Array to Binary String + * + * @ignore + * @api private + */ +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + return result; +}; + +/** + * A class representation of the BSON Binary type. + * + * Sub types + * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type. + * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type. + * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type. + * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type. + * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type. + * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type. + * + * @class Represents the Binary BSON type. + * @param {Buffer} buffer a buffer object containing the binary data. + * @param {Number} [subType] the option binary type. + * @return {Grid} + */ +function Binary(buffer, subType) { + if(!(this instanceof Binary)) return new Binary(buffer, subType); + + this._bsontype = 'Binary'; + + if(buffer instanceof Number) { + this.sub_type = buffer; + this.position = 0; + } else { + this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType; + this.position = 0; + } + + if(buffer != null && !(buffer instanceof Number)) { + // Only accept Buffer, Uint8Array or Arrays + if(typeof buffer == 'string') { + // Different ways of writing the length of the string for the different types + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(buffer); + } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) { + this.buffer = writeStringToArray(buffer); + } else { + throw new Error("only String, Buffer, Uint8Array or Array accepted"); + } + } else { + this.buffer = buffer; + } + this.position = buffer.length; + } else { + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(Binary.BUFFER_SIZE); + } else if(typeof Uint8Array != 'undefined'){ + this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE)); + } else { + this.buffer = new Array(Binary.BUFFER_SIZE); + } + // Set position to start of buffer + this.position = 0; + } +}; + +/** + * Updates this binary with byte_value. + * + * @param {Character} byte_value a single byte we wish to write. + * @api public + */ +Binary.prototype.put = function put(byte_value) { + // If it's a string and a has more than one character throw an error + if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array"); + if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); + + // Decode the byte value once + var decoded_byte = null; + if(typeof byte_value == 'string') { + decoded_byte = byte_value.charCodeAt(0); + } else if(byte_value['length'] != null) { + decoded_byte = byte_value[0]; + } else { + decoded_byte = byte_value; + } + + if(this.buffer.length > this.position) { + this.buffer[this.position++] = decoded_byte; + } else { + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + // Create additional overflow buffer + var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); + // Combine the two buffers together + this.buffer.copy(buffer, 0, 0, this.buffer.length); + this.buffer = buffer; + this.buffer[this.position++] = decoded_byte; + } else { + var buffer = null; + // Create a new buffer (typed or normal array) + if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); + } else { + buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); + } + + // We need to copy all the content to the new array + for(var i = 0; i < this.buffer.length; i++) { + buffer[i] = this.buffer[i]; + } + + // Reassign the buffer + this.buffer = buffer; + // Write the byte + this.buffer[this.position++] = decoded_byte; + } + } +}; + +/** + * Writes a buffer or string to the binary. + * + * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. + * @param {Number} offset specify the binary of where to write the content. + * @api public + */ +Binary.prototype.write = function write(string, offset) { + offset = typeof offset == 'number' ? offset : this.position; + + // If the buffer is to small let's extend the buffer + if(this.buffer.length < offset + string.length) { + var buffer = null; + // If we are in node.js + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + buffer = new Buffer(this.buffer.length + string.length); + this.buffer.copy(buffer, 0, 0, this.buffer.length); + } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + // Create a new buffer + buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) + // Copy the content + for(var i = 0; i < this.position; i++) { + buffer[i] = this.buffer[i]; + } + } + + // Assign the new buffer + this.buffer = buffer; + } + + if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { + string.copy(this.buffer, offset, 0, string.length); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length + } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { + this.buffer.write(string, 'binary', offset); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length; + } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' + || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string[i]; + } + + this.position = offset > this.position ? offset : this.position; + } else if(typeof string == 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string.charCodeAt(i); + } + + this.position = offset > this.position ? offset : this.position; + } +}; + +/** + * Reads **length** bytes starting at **position**. + * + * @param {Number} position read from the given position in the Binary. + * @param {Number} length the number of bytes to read. + * @return {Buffer} + * @api public + */ +Binary.prototype.read = function read(position, length) { + length = length && length > 0 + ? length + : this.position; + + // Let's return the data based on the type we have + if(this.buffer['slice']) { + return this.buffer.slice(position, position + length); + } else { + // Create a buffer to keep the result + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); + for(var i = 0; i < length; i++) { + buffer[i] = this.buffer[position++]; + } + } + // Return the buffer + return buffer; +}; + +/** + * Returns the value of this binary as a string. + * + * @return {String} + * @api public + */ +Binary.prototype.value = function value(asRaw) { + asRaw = asRaw == null ? false : asRaw; + + // If it's a node.js buffer object + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); + } else { + if(asRaw) { + // we support the slice command use it + if(this.buffer['slice'] != null) { + return this.buffer.slice(0, this.position); + } else { + // Create a new buffer to copy content to + var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); + // Copy content + for(var i = 0; i < this.position; i++) { + newBuffer[i] = this.buffer[i]; + } + // Return the buffer + return newBuffer; + } + } else { + return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); + } + } +}; + +/** + * Length. + * + * @return {Number} the length of the binary. + * @api public + */ +Binary.prototype.length = function length() { + return this.position; +}; + +/** + * @ignore + * @api private + */ +Binary.prototype.toJSON = function() { + return this.buffer != null ? this.buffer.toString('base64') : ''; +} + +/** + * @ignore + * @api private + */ +Binary.prototype.toString = function(format) { + return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; +} + +Binary.BUFFER_SIZE = 256; + +/** + * Default BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_DEFAULT = 0; +/** + * Function BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_FUNCTION = 1; +/** + * Byte Array BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_BYTE_ARRAY = 2; +/** + * OLD UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID_OLD = 3; +/** + * UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID = 4; +/** + * MD5 BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_MD5 = 5; +/** + * User BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_USER_DEFINED = 128; + +/** + * Expose. + */ +exports.Binary = Binary; + + +}, + + + +'binary_parser': function(module, exports, global, require, undefined){ + /** + * Binary Parser. + * Jonas Raoni Soares Silva + * http://jsfromhell.com/classes/binary-parser [v1.0] + */ +var chr = String.fromCharCode; + +var maxBits = []; +for (var i = 0; i < 64; i++) { + maxBits[i] = Math.pow(2, i); +} + +function BinaryParser (bigEndian, allowExceptions) { + if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions); + + this.bigEndian = bigEndian; + this.allowExceptions = allowExceptions; +}; + +BinaryParser.warn = function warn (msg) { + if (this.allowExceptions) { + throw new Error(msg); + } + + return 1; +}; + +BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { + var b = new this.Buffer(this.bigEndian, data); + + b.checkBuffer(precisionBits + exponentBits + 1); + + var bias = maxBits[exponentBits - 1] - 1 + , signal = b.readBits(precisionBits + exponentBits, 1) + , exponent = b.readBits(precisionBits, exponentBits) + , significand = 0 + , divisor = 2 + , curByte = b.buffer.length + (-precisionBits >> 3) - 1; + + do { + for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); + } while (precisionBits -= startBit); + + return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); +}; + +BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { + var b = new this.Buffer(this.bigEndian || forceBigEndian, data) + , x = b.readBits(0, bits) + , max = maxBits[bits]; //max = Math.pow( 2, bits ); + + return signed && x >= max / 2 + ? x - max + : x; +}; + +BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { + var bias = maxBits[exponentBits - 1] - 1 + , minExp = -bias + 1 + , maxExp = bias + , minUnnormExp = minExp - precisionBits + , n = parseFloat(data) + , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 + , exp = 0 + , len = 2 * bias + 1 + precisionBits + 3 + , bin = new Array(len) + , signal = (n = status !== 0 ? 0 : n) < 0 + , intPart = Math.floor(n = Math.abs(n)) + , floatPart = n - intPart + , lastBit + , rounded + , result + , i + , j; + + for (i = len; i; bin[--i] = 0); + + for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); + + for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); + + for (i = -1; ++i < len && !bin[i];); + + if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); + } + + for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); + } + + for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); + + if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { + ++i; + } else if (exp < minExp) { + exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); + i = bias + 1 - (exp = minExp - 1); + } + + if (intPart || status !== 0) { + this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); + exp = maxExp + 1; + i = bias + 2; + + if (status == -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[i] = 1; + } + } + + for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); + + for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { + n += (1 << j) * result.charAt(--i); + if (j == 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + } + + r[r.length] = n + ? String.fromCharCode(n) + : ""; + + return (this.bigEndian ? r.reverse() : r).join(""); +}; + +BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { + var max = maxBits[bits]; + + if (data >= max || data < -(max / 2)) { + this.warn("encodeInt::overflow"); + data = 0; + } + + if (data < 0) { + data += max; + } + + for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); + + for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); + + return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); +}; + +BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; +BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; +BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; +BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; +BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; +BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; +BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; +BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; +BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; +BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; +BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; +BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; +BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; +BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; +BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; +BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; + +// Factor out the encode so it can be shared by add_header and push_int32 +BinaryParser.encode_int32 = function encode_int32 (number, asArray) { + var a, b, c, d, unsigned; + unsigned = (number < 0) ? (number + 0x100000000) : number; + a = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + b = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + c = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + d = Math.floor(unsigned); + return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); +}; + +BinaryParser.encode_int64 = function encode_int64 (number) { + var a, b, c, d, e, f, g, h, unsigned; + unsigned = (number < 0) ? (number + 0x10000000000000000) : number; + a = Math.floor(unsigned / 0xffffffffffffff); + unsigned &= 0xffffffffffffff; + b = Math.floor(unsigned / 0xffffffffffff); + unsigned &= 0xffffffffffff; + c = Math.floor(unsigned / 0xffffffffff); + unsigned &= 0xffffffffff; + d = Math.floor(unsigned / 0xffffffff); + unsigned &= 0xffffffff; + e = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + f = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + g = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + h = Math.floor(unsigned); + return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); +}; + +/** + * UTF8 methods + */ + +// Take a raw binary string and return a utf8 string +BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { + var len = binaryStr.length + , decoded = '' + , i = 0 + , c = 0 + , c1 = 0 + , c2 = 0 + , c3; + + while (i < len) { + c = binaryStr.charCodeAt(i); + if (c < 128) { + decoded += String.fromCharCode(c); + i++; + } else if ((c > 191) && (c < 224)) { + c2 = binaryStr.charCodeAt(i+1); + decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = binaryStr.charCodeAt(i+1); + c3 = binaryStr.charCodeAt(i+2); + decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return decoded; +}; + +// Encode a cstring +BinaryParser.encode_cstring = function encode_cstring (s) { + return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); +}; + +// Take a utf8 string and return a binary string +BinaryParser.encode_utf8 = function encode_utf8 (s) { + var a = "" + , c; + + for (var n = 0, len = s.length; n < len; n++) { + c = s.charCodeAt(n); + + if (c < 128) { + a += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + a += String.fromCharCode((c>>6) | 192) ; + a += String.fromCharCode((c&63) | 128); + } else { + a += String.fromCharCode((c>>12) | 224); + a += String.fromCharCode(((c>>6) & 63) | 128); + a += String.fromCharCode((c&63) | 128); + } + } + + return a; +}; + +BinaryParser.hprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } + } + + process.stdout.write("\n\n"); +}; + +BinaryParser.ilprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +BinaryParser.hlprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +/** + * BinaryParser buffer constructor. + */ +function BinaryParserBuffer (bigEndian, buffer) { + this.bigEndian = bigEndian || 0; + this.buffer = []; + this.setBuffer(buffer); +}; + +BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { + var l, i, b; + + if (data) { + i = l = data.length; + b = this.buffer = new Array(l); + for (; i; b[l - i] = data.charCodeAt(--i)); + this.bigEndian && b.reverse(); + } +}; + +BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { + return this.buffer.length >= -(-neededBits >> 3); +}; + +BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { + if (!this.hasNeededBits(neededBits)) { + throw new Error("checkBuffer::missing bytes"); + } +}; + +BinaryParserBuffer.prototype.readBits = function readBits (start, length) { + //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) + + function shl (a, b) { + for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); + return a; + } + + if (start < 0 || length <= 0) { + return 0; + } + + this.checkBuffer(start + length); + + var offsetLeft + , offsetRight = start % 8 + , curByte = this.buffer.length - ( start >> 3 ) - 1 + , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) + , diff = curByte - lastByte + , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); + + for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); + + return sum; +}; + +/** + * Expose. + */ +BinaryParser.Buffer = BinaryParserBuffer; + +exports.BinaryParser = BinaryParser; + +}, + + + +'bson': function(module, exports, global, require, undefined){ + var Long = require('./long').Long + , Double = require('./double').Double + , Timestamp = require('./timestamp').Timestamp + , ObjectID = require('./objectid').ObjectID + , Symbol = require('./symbol').Symbol + , Code = require('./code').Code + , MinKey = require('./min_key').MinKey + , MaxKey = require('./max_key').MaxKey + , DBRef = require('./db_ref').DBRef + , Binary = require('./binary').Binary + , BinaryParser = require('./binary_parser').BinaryParser + , writeIEEE754 = require('./float_parser').writeIEEE754 + , readIEEE754 = require('./float_parser').readIEEE754 + +// To ensure that 0.4 of node works correctly +var isDate = function isDate(d) { + return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; +} + +/** + * Create a new BSON instance + * + * @class Represents the BSON Parser + * @return {BSON} instance of BSON Parser. + */ +function BSON () {}; + +/** + * @ignore + * @api private + */ +// BSON MAX VALUES +BSON.BSON_INT32_MAX = 0x7FFFFFFF; +BSON.BSON_INT32_MIN = -0x80000000; + +BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; +BSON.BSON_INT64_MIN = -Math.pow(2, 63); + +// JS MAX PRECISE VALUES +BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. +BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. + +// Internal long versions +var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. +var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. + +/** + * Number BSON Type + * + * @classconstant BSON_DATA_NUMBER + **/ +BSON.BSON_DATA_NUMBER = 1; +/** + * String BSON Type + * + * @classconstant BSON_DATA_STRING + **/ +BSON.BSON_DATA_STRING = 2; +/** + * Object BSON Type + * + * @classconstant BSON_DATA_OBJECT + **/ +BSON.BSON_DATA_OBJECT = 3; +/** + * Array BSON Type + * + * @classconstant BSON_DATA_ARRAY + **/ +BSON.BSON_DATA_ARRAY = 4; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_BINARY + **/ +BSON.BSON_DATA_BINARY = 5; +/** + * ObjectID BSON Type + * + * @classconstant BSON_DATA_OID + **/ +BSON.BSON_DATA_OID = 7; +/** + * Boolean BSON Type + * + * @classconstant BSON_DATA_BOOLEAN + **/ +BSON.BSON_DATA_BOOLEAN = 8; +/** + * Date BSON Type + * + * @classconstant BSON_DATA_DATE + **/ +BSON.BSON_DATA_DATE = 9; +/** + * null BSON Type + * + * @classconstant BSON_DATA_NULL + **/ +BSON.BSON_DATA_NULL = 10; +/** + * RegExp BSON Type + * + * @classconstant BSON_DATA_REGEXP + **/ +BSON.BSON_DATA_REGEXP = 11; +/** + * Code BSON Type + * + * @classconstant BSON_DATA_CODE + **/ +BSON.BSON_DATA_CODE = 13; +/** + * Symbol BSON Type + * + * @classconstant BSON_DATA_SYMBOL + **/ +BSON.BSON_DATA_SYMBOL = 14; +/** + * Code with Scope BSON Type + * + * @classconstant BSON_DATA_CODE_W_SCOPE + **/ +BSON.BSON_DATA_CODE_W_SCOPE = 15; +/** + * 32 bit Integer BSON Type + * + * @classconstant BSON_DATA_INT + **/ +BSON.BSON_DATA_INT = 16; +/** + * Timestamp BSON Type + * + * @classconstant BSON_DATA_TIMESTAMP + **/ +BSON.BSON_DATA_TIMESTAMP = 17; +/** + * Long BSON Type + * + * @classconstant BSON_DATA_LONG + **/ +BSON.BSON_DATA_LONG = 18; +/** + * MinKey BSON Type + * + * @classconstant BSON_DATA_MIN_KEY + **/ +BSON.BSON_DATA_MIN_KEY = 0xff; +/** + * MaxKey BSON Type + * + * @classconstant BSON_DATA_MAX_KEY + **/ +BSON.BSON_DATA_MAX_KEY = 0x7f; + +/** + * Binary Default Type + * + * @classconstant BSON_BINARY_SUBTYPE_DEFAULT + **/ +BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +/** + * Binary Function Type + * + * @classconstant BSON_BINARY_SUBTYPE_FUNCTION + **/ +BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +/** + * Binary Byte Array Type + * + * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY + **/ +BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +/** + * Binary UUID Type + * + * @classconstant BSON_BINARY_SUBTYPE_UUID + **/ +BSON.BSON_BINARY_SUBTYPE_UUID = 3; +/** + * Binary MD5 Type + * + * @classconstant BSON_BINARY_SUBTYPE_MD5 + **/ +BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +/** + * Binary User Defined Type + * + * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED + **/ +BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { + var totalLength = (4 + 1); + + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + totalLength += calculateElement(i.toString(), object[i], serializeFunctions) + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Calculate size + for(var key in object) { + totalLength += calculateElement(key, object[key], serializeFunctions) + } + } + + return totalLength; +} + +/** + * @ignore + * @api private + */ +function calculateElement(name, value, serializeFunctions) { + var isBuffer = typeof Buffer !== 'undefined'; + + switch(typeof value) { + case 'string': + return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1; + case 'number': + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + } else { // 64 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + case 'undefined': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + case 'boolean': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1); + case 'object': + if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1); + } else if(value instanceof Date || isDate(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length; + } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp + || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + // Calculate size depending on the availability of a scope + if(value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Check what kind of subtype we have + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1); + } + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1); + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else if(serializeFunctions) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1; + } + } + } + + return 0; +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { + // Default setting false + serializeFunctions = serializeFunctions == null ? false : serializeFunctions; + // Write end information (length of the object) + var size = buffer.length; + // Write the size of the object + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; +} + +/** + * @ignore + * @api private + */ +var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { + // Process the object + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Serialize the object + for(var key in object) { + // Check the key and throw error if it's illegal + if(checkKeys == true && (key != '$db' && key != '$ref' && key != '$id')) { + BSON.checkKey(key); + } + + // Pack the element + index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); + } + } + + // Write zero + buffer[index++] = 0; + return index; +} + +var stringToBytes = function(str) { + var ch, st, re = []; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re.concat( st.reverse() ); + } + // return an array of bytes + return re; +} + +var numberOfBytes = function(str) { + var ch, st, re = 0; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re + st.length; + } + // return an array of bytes + return re; +} + +/** + * @ignore + * @api private + */ +var writeToTypedArray = function(buffer, string, index) { + var bytes = stringToBytes(string); + for(var i = 0; i < bytes.length; i++) { + buffer[index + i] = bytes[i]; + } + return bytes.length; +} + +/** + * @ignore + * @api private + */ +var supportsBuffer = typeof Buffer != 'undefined'; + +/** + * @ignore + * @api private + */ +var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { + var startIndex = index; + + switch(typeof value) { + case 'string': + // Encode String type + buffer[index++] = BSON.BSON_DATA_STRING; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1; + // Write the size of the string to buffer + buffer[index + 3] = (size >> 24) & 0xff; + buffer[index + 2] = (size >> 16) & 0xff; + buffer[index + 1] = (size >> 8) & 0xff; + buffer[index] = size & 0xff; + // Ajust the index + index = index + 4; + // Write the string + supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + // Return index + return index; + case 'number': + // We have an integer value + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // If the value fits in 32 bits encode as int, if it fits in a double + // encode it as a double, otherwise long + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { + // Set int type 32 bits or less + buffer[index++] = BSON.BSON_DATA_INT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the int value + buffer[index++] = value & 0xff; + buffer[index++] = (value >> 8) & 0xff; + buffer[index++] = (value >> 16) & 0xff; + buffer[index++] = (value >> 24) & 0xff; + } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } else { + // Set long type + buffer[index++] = BSON.BSON_DATA_LONG; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var longVal = Long.fromNumber(value); + var lowBits = longVal.getLowBits(); + var highBits = longVal.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + } + } else { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } + + return index; + case 'undefined': + // Set long type + buffer[index++] = BSON.BSON_DATA_NULL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + case 'boolean': + // Write the type + buffer[index++] = BSON.BSON_DATA_BOOLEAN; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Encode the boolean value + buffer[index++] = value ? 1 : 0; + return index; + case 'object': + if(value === null || value instanceof MinKey || value instanceof MaxKey + || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + // Write the type of either min or max key + if(value === null) { + buffer[index++] = BSON.BSON_DATA_NULL; + } else if(value instanceof MinKey) { + buffer[index++] = BSON.BSON_DATA_MIN_KEY; + } else { + buffer[index++] = BSON.BSON_DATA_MAX_KEY; + } + + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OID; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write objectid + supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index); + // Ajust index + index = index + 12; + return index; + } else if(value instanceof Date || isDate(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_DATE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the date + var dateInMilis = Long.fromNumber(value.getTime()); + var lowBits = dateInMilis.getLowBits(); + var highBits = dateInMilis.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Get size of the buffer (current write point) + var size = value.length; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the default subtype + buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; + // Copy the content form the binary field to the buffer + value.copy(buffer, index, 0, size); + // Adjust the index + index = index + size; + return index; + } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { + // Write the type + buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the date + var lowBits = value.getLowBits(); + var highBits = value.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(value instanceof Double || value['_bsontype'] == 'Double') { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + return index; + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + if(value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.code.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize + 4; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize)); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index); + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.code.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Extract the buffer + var data = value.value(true); + // Calculate size + var size = value.position; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the subtype to the buffer + buffer[index++] = value.sub_type; + + // If we have binary type 2 the 4 first bytes are the size + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + } + + // Write the data to the object + supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index); + // Ajust index + index = index + value.position; + return index; + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + // Write the type + buffer[index++] = BSON.BSON_DATA_SYMBOL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(value.value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0x00; + return index; + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + // Message size + var size = BSON.calculateObjectSize(ordered_values, serializeFunctions); + // Serialize the object + var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write zero for object + buffer[endIndex++] = 0x00; + // Return the end index + return endIndex; + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + // Write the type + buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Adjust the index + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); + // Write size + var size = endIndex - index; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return endIndex; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = new Buffer(scopeSize); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize - 4; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + scopeObjectBuffer.copy(buffer, index, 0, scopeSize); + + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else if(serializeFunctions) { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } + } + + // If no value to serialize + return index; +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + var buffer = null; + // Calculate the size of the object + var size = BSON.calculateObjectSize(object, serializeFunctions); + // Fetch the best available type for storing the binary data + if(buffer = typeof Buffer != 'undefined') { + buffer = new Buffer(size); + asBuffer = true; + } else if(typeof Uint8Array != 'undefined') { + buffer = new Uint8Array(new ArrayBuffer(size)); + } else { + buffer = new Array(size); + } + + // If asBuffer is false use typed arrays + BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); + return buffer; +} + +/** + * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 + * + * @ignore + * @api private + */ +var functionCache = BSON.functionCache = {}; + +/** + * Crc state variables shared by function + * + * @ignore + * @api private + */ +var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; + +/** + * CRC32 hash method, Fast and enough versitility for our usage + * + * @ignore + * @api private + */ +var crc32 = function(string, start, end) { + var crc = 0 + var x = 0; + var y = 0; + crc = crc ^ (-1); + + for(var i = start, iTop = end; i < iTop;i++) { + y = (crc ^ string[i]) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); + options = options != null ? options : {}; + var index = startIndex; + // Loop over all documents + for(var i = 0; i < numberOfDocuments; i++) { + // Find size of the document + var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; + // Update options with index + options['index'] = index; + // Parse the document at this point + documents[docStartIndex + i] = BSON.deserialize(data, options); + // Adjust index by the document size + index = index + size; + } + + // Return object containing end index of parsing and list of documents + return index; +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEvalWithHash = function(functionCache, hash, functionString, object) { + // Contains the value we are going to set + var value = null; + + // Check for cache hit, eval if missing and return cached function + if(functionCache[hash] == null) { + eval("value = " + functionString); + functionCache[hash] = value; + } + // Set the object + return functionCache[hash].bind(object); +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEval = function(functionString) { + // Contains the value we are going to set + var value = null; + // Eval the function + eval("value = " + functionString); + return value; +} + +/** + * Convert Uint8Array to String + * + * @ignore + * @api private + */ +var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) { + return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex)); +} + +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + + return result; +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.deserialize = function(buffer, options, isArray) { + // Options + options = options == null ? {} : options; + var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; + var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; + var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; + + // Validate that we have at least 4 bytes of buffer + if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); + + // Set up index + var index = typeof options['index'] == 'number' ? options['index'] : 0; + // Reads in a C style string + var readCStyleString = function() { + // Get the start search index + var i = index; + // Locate the end of the c string + while(buffer[i] !== 0x00) { i++ } + // Grab utf8 encoded string + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i); + // Update index position + index = i + 1; + // Return string + return string; + } + + // Create holding object + var object = isArray ? [] : {}; + + // Read the document size + var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + + // Ensure buffer is valid size + if(size < 5 || size > buffer.length) throw new Error("corrupt bson message"); + + // While we have more left data left keep parsing + while(true) { + // Read the type + var elementType = buffer[index++]; + // If we get a zero it's the last byte, exit + if(elementType == 0) break; + // Read the name of the field + var name = readCStyleString(); + // Switch on the type + switch(elementType) { + case BSON.BSON_DATA_OID: + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12); + // Decode the oid + object[name] = new ObjectID(string); + // Update index + index = index + 12; + break; + case BSON.BSON_DATA_STRING: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_INT: + // Decode the 32bit value + object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + break; + case BSON.BSON_DATA_NUMBER: + // Decode the double value + object[name] = readIEEE754(buffer, index, 'little', 52, 8); + // Update the index + index = index + 8; + break; + case BSON.BSON_DATA_DATE: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set date object + object[name] = new Date(new Long(lowBits, highBits).toNumber()); + break; + case BSON.BSON_DATA_BOOLEAN: + // Parse the boolean value + object[name] = buffer[index++] == 1; + break; + case BSON.BSON_DATA_NULL: + // Parse the boolean value + object[name] = null; + break; + case BSON.BSON_DATA_BINARY: + // Decode the size of the binary blob + var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Decode the subtype + var subType = buffer[index++]; + // Decode as raw Buffer object if options specifies it + if(buffer['slice'] != null) { + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Slice the data + object[name] = new Binary(buffer.slice(index, index + binarySize), subType); + } else { + var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize); + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Copy the data + for(var i = 0; i < binarySize; i++) { + _buffer[i] = buffer[index + i]; + } + // Create the binary object + object[name] = new Binary(_buffer, subType); + } + // Update the index + index = index + binarySize; + break; + case BSON.BSON_DATA_ARRAY: + options['index'] = index; + // Decode the size of the array document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, true); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_OBJECT: + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_REGEXP: + // Create the regexp + var source = readCStyleString(); + var regExpOptions = readCStyleString(); + // For each option add the corresponding one for javascript + var optionsArray = new Array(regExpOptions.length); + + // Parse options + for(var i = 0; i < regExpOptions.length; i++) { + switch(regExpOptions[i]) { + case 'm': + optionsArray[i] = 'm'; + break; + case 's': + optionsArray[i] = 'g'; + break; + case 'i': + optionsArray[i] = 'i'; + break; + } + } + + object[name] = new RegExp(source, optionsArray.join('')); + break; + case BSON.BSON_DATA_LONG: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Create long object + var long = new Long(lowBits, highBits); + // Set the object + object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; + break; + case BSON.BSON_DATA_SYMBOL: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_TIMESTAMP: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set the object + object[name] = new Timestamp(lowBits, highBits); + break; + case BSON.BSON_DATA_MIN_KEY: + // Parse the object + object[name] = new MinKey(); + break; + case BSON.BSON_DATA_MAX_KEY: + // Parse the object + object[name] = new MaxKey(); + break; + case BSON.BSON_DATA_CODE: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Function string + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + } else { + object[name] = new Code(functionString, {}); + } + + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_CODE_W_SCOPE: + // Read the content of the field + var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Javascript function + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + // Parse the element + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Decode the scope object + var scopeObject = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + + // Set the scope on the object + object[name].scope = scopeObject; + } else { + object[name] = new Code(functionString, scopeObject); + } + + // Add string to object + break; + } + } + + // Check if we have a db ref object + if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + + // Return the final objects + return object; +} + +/** + * Check if key name is valid. + * + * @ignore + * @api private + */ +BSON.checkKey = function checkKey (key) { + if (!key.length) return; + // Check if we have a legal key for the object + if('$' == key[0]) { + throw Error("key " + key + " must not start with '$'"); + } else if (!!~key.indexOf('.')) { + throw Error("key " + key + " must not contain '.'"); + } +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.prototype.deserialize = function(data, options) { + return BSON.deserialize(data, options); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); +} + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { + return BSON.calculateObjectSize(object, serializeFunctions); +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { + return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); +} + +/** + * @ignore + * @api private + */ +exports.Code = Code; +exports.Symbol = Symbol; +exports.BSON = BSON; +exports.DBRef = DBRef; +exports.Binary = Binary; +exports.ObjectID = ObjectID; +exports.Long = Long; +exports.Timestamp = Timestamp; +exports.Double = Double; +exports.MinKey = MinKey; +exports.MaxKey = MaxKey; + +}, + + + +'code': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON Code type. + * + * @class Represents the BSON Code type. + * @param {String|Function} code a string or function. + * @param {Object} [scope] an optional scope for the function. + * @return {Code} + */ +function Code(code, scope) { + if(!(this instanceof Code)) return new Code(code, scope); + + this._bsontype = 'Code'; + this.code = code; + this.scope = scope == null ? {} : scope; +}; + +/** + * @ignore + * @api private + */ +Code.prototype.toJSON = function() { + return {scope:this.scope, code:this.code}; +} + +exports.Code = Code; +}, + + + +'db_ref': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON DBRef type. + * + * @class Represents the BSON DBRef type. + * @param {String} namespace the collection name. + * @param {ObjectID} oid the reference ObjectID. + * @param {String} [db] optional db name, if omitted the reference is local to the current db. + * @return {DBRef} + */ +function DBRef(namespace, oid, db) { + if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db); + + this._bsontype = 'DBRef'; + this.namespace = namespace; + this.oid = oid; + this.db = db; +}; + +/** + * @ignore + * @api private + */ +DBRef.prototype.toJSON = function() { + return { + '$ref':this.namespace, + '$id':this.oid, + '$db':this.db == null ? '' : this.db + }; +} + +exports.DBRef = DBRef; +}, + + + +'double': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON Double type. + * + * @class Represents the BSON Double type. + * @param {Number} value the number we want to represent as a double. + * @return {Double} + */ +function Double(value) { + if(!(this instanceof Double)) return new Double(value); + + this._bsontype = 'Double'; + this.value = value; +} + +/** + * Access the number value. + * + * @return {Number} returns the wrapped double number. + * @api public + */ +Double.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Double.prototype.toJSON = function() { + return this.value; +} + +exports.Double = Double; +}, + + + +'float_parser': function(module, exports, global, require, undefined){ + // Copyright (c) 2008, Fair Oaks Labs, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// +// Modifications to writeIEEE754 to support negative zeroes made by Brian White + +var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { + var e, m, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = bBE ? 0 : (nBytes - 1), + d = bBE ? 1 : -1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { + var e, m, c, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = bBE ? (nBytes-1) : 0, + d = bBE ? -1 : 1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e+eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +exports.readIEEE754 = readIEEE754; +exports.writeIEEE754 = writeIEEE754; +}, + + + +'index': function(module, exports, global, require, undefined){ + try { + exports.BSONPure = require('./bson'); + exports.BSONNative = require('../../ext'); +} catch(err) { + // do nothing +} + +[ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + exports[i] = module[i]; + } +}); + +// Exports all the classes for the NATIVE JS BSON Parser +exports.native = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '../../ext' +].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} + +// Exports all the classes for the PURE JS BSON Parser +exports.pure = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '././bson'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} + +}, + + + +'long': function(module, exports, global, require, undefined){ + // Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Long". This + * implementation is derived from LongLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a Long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Long type. + * @param {Number} low the low (signed) 32 bits of the Long. + * @param {Number} high the high (signed) 32 bits of the Long. + */ +function Long(low, high) { + if(!(this instanceof Long)) return new Long(low, high); + + this._bsontype = 'Long'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Long.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Long.prototype.toNumber = function() { + return this.high_ * Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Long.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Long.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Long.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Long. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. + * @api public + */ +Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Long equals the other + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long equals the other + * @api public + */ +Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Long does not equal the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long does not equal the other. + * @api public + */ +Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Long is less than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than the other. + * @api public + */ +Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Long is less than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than or equal to the other. + * @api public + */ +Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Long is greater than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than the other. + * @api public + */ +Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Long is greater than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than or equal to the other. + * @api public + */ +Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Long with the given one. + * + * @param {Long} other Long to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Long} the negation of this value. + * @api public + */ +Long.prototype.negate = function() { + if (this.equals(Long.MIN_VALUE)) { + return Long.MIN_VALUE; + } else { + return this.not().add(Long.ONE); + } +}; + +/** + * Returns the sum of this and the given Long. + * + * @param {Long} other Long to add to this one. + * @return {Long} the sum of this and the given Long. + * @api public + */ +Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Long. + * + * @param {Long} other Long to subtract from this. + * @return {Long} the difference of this and the given Long. + * @api public + */ +Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Long. + * + * @param {Long} other Long to multiply with this. + * @return {Long} the product of this and the other. + * @api public + */ +Long.prototype.multiply = function(other) { + if (this.isZero()) { + return Long.ZERO; + } else if (other.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } else if (other.equals(Long.MIN_VALUE)) { + return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Longs are small, use float multiplication + if (this.lessThan(Long.TWO_PWR_24_) && + other.lessThan(Long.TWO_PWR_24_)) { + return Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Long divided by the given one. + * + * @param {Long} other Long by which to divide. + * @return {Long} this Long divided by the given one. + * @api public + */ +Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + if (other.equals(Long.ONE) || + other.equals(Long.NEG_ONE)) { + return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Long.ZERO)) { + return other.isNegative() ? Long.ONE : Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Long modulo the given one. + * + * @param {Long} other Long by which to mod. + * @return {Long} this Long modulo the given one. + * @api public + */ +Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Long} the bitwise-NOT of this value. + * @api public + */ +Long.prototype.not = function() { + return Long.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Long and the given one. + * + * @param {Long} other the Long with which to AND. + * @return {Long} the bitwise-AND of this and the other. + * @api public + */ +Long.prototype.and = function(other) { + return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Long and the given one. + * + * @param {Long} other the Long with which to OR. + * @return {Long} the bitwise-OR of this and the other. + * @api public + */ +Long.prototype.or = function(other) { + return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Long and the given one. + * + * @param {Long} other the Long with which to XOR. + * @return {Long} the bitwise-XOR of this and the other. + * @api public + */ +Long.prototype.xor = function(other) { + return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Long with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the left by the given amount. + * @api public + */ +Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Long.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount. + * @api public + */ +Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Long.fromBits(high, 0); + } else { + return Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Long representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Long.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Long.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Long.ZERO; + } else if (value <= -Long.TWO_PWR_63_DBL_) { + return Long.MIN_VALUE; + } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { + return Long.MAX_VALUE; + } else if (value < 0) { + return Long.fromNumber(-value).negate(); + } else { + return new Long( + (value % Long.TWO_PWR_32_DBL_) | 0, + (value / Long.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromBits = function(lowBits, highBits) { + return new Long(lowBits, highBits); +}; + +/** + * Returns a Long representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Long. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 8)); + + var result = Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Long.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Long representations of small integer values. + * @type {Object} + * @api private + */ +Long.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Long.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; + +/** @type {Long} */ +Long.ZERO = Long.fromInt(0); + +/** @type {Long} */ +Long.ONE = Long.fromInt(1); + +/** @type {Long} */ +Long.NEG_ONE = Long.fromInt(-1); + +/** @type {Long} */ +Long.MAX_VALUE = + Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Long} */ +Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); + +/** + * @type {Long} + * @api private + */ +Long.TWO_PWR_24_ = Long.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Long = Long; +}, + + + +'max_key': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON MaxKey type. + * + * @class Represents the BSON MaxKey type. + * @return {MaxKey} + */ +function MaxKey() { + if(!(this instanceof MaxKey)) return new MaxKey(); + + this._bsontype = 'MaxKey'; +} + +exports.MaxKey = MaxKey; +}, + + + +'min_key': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON MinKey type. + * + * @class Represents the BSON MinKey type. + * @return {MinKey} + */ +function MinKey() { + if(!(this instanceof MinKey)) return new MinKey(); + + this._bsontype = 'MinKey'; +} + +exports.MinKey = MinKey; +}, + + + +'objectid': function(module, exports, global, require, undefined){ + /** + * Module dependencies. + */ +var BinaryParser = require('./binary_parser').BinaryParser; + +/** + * Machine id. + * + * Create a random 3-byte value (i.e. unique for this + * process). Other drivers use a md5 of the machine id here, but + * that would mean an asyc call to gethostname, so we don't bother. + */ +var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); + +// Regular expression that checks for hex value +var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); + +/** +* Create a new ObjectID instance +* +* @class Represents the BSON ObjectID type +* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. +* @return {Object} instance of ObjectID. +*/ +var ObjectID = function ObjectID(id, _hex) { + if(!(this instanceof ObjectID)) return new ObjectID(id, _hex); + + this._bsontype = 'ObjectID'; + var __id = null; + + // Throw an error if it's not a valid setup + if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + // Generate id based on the input + if(id == null || typeof id == 'number') { + // convert to 12 byte binary string + this.id = this.generate(id); + } else if(id != null && id.length === 12) { + // assume 12 byte string + this.id = id; + } else if(checkForHexRegExp.test(id)) { + return ObjectID.createFromHexString(id); + } else if(!checkForHexRegExp.test(id)) { + throw new Error("Value passed in is not a valid 24 character hex string"); + } + + if(ObjectID.cacheHexString) this.__id = this.toHexString(); +}; + +// Allow usage of ObjectId aswell as ObjectID +var ObjectId = ObjectID; + +/** +* Return the ObjectID id as a 24 byte hex string representation +* +* @return {String} return the 24 byte hex string representation. +* @api public +*/ +ObjectID.prototype.toHexString = function() { + if(ObjectID.cacheHexString && this.__id) return this.__id; + + var hexString = '' + , number + , value; + + for (var index = 0, len = this.id.length; index < len; index++) { + value = BinaryParser.toByte(this.id[index]); + number = value <= 15 + ? '0' + value.toString(16) + : value.toString(16); + hexString = hexString + number; + } + + if(ObjectID.cacheHexString) this.__id = hexString; + return hexString; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.get_inc = function() { + return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.getInc = function() { + return this.get_inc(); +}; + +/** +* Generate a 12 byte id string used in ObjectID's +* +* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. +* @return {String} return the 12 byte id binary string. +* @api private +*/ +ObjectID.prototype.generate = function(time) { + if ('number' == typeof time) { + var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); + /* for time-based ObjectID the bytes following the time will be zeroed */ + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } else { + var unixTime = parseInt(Date.now()/1000,10); + var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true); + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } + + return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; +}; + +/** +* Converts the id into a 24 byte hex string for printing +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toString = function() { + return this.toHexString(); +}; + +/** +* Converts to a string representation of this Id. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.inspect = ObjectID.prototype.toString; + +/** +* Converts to its JSON representation. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toJSON = function() { + return this.toHexString(); +}; + +/** +* Compares the equality of this ObjectID with `otherID`. +* +* @param {Object} otherID ObjectID instance to compare against. +* @return {Bool} the result of comparing two ObjectID's +* @api public +*/ +ObjectID.prototype.equals = function equals (otherID) { + var id = (otherID instanceof ObjectID || otherID.toHexString) + ? otherID.id + : ObjectID.createFromHexString(otherID).id; + + return this.id === id; +} + +/** +* Returns the generation time in seconds that this ID was generated. +* +* @return {Number} return number of seconds in the timestamp part of the 12 byte id. +* @api public +*/ +ObjectID.prototype.getTimestamp = function() { + var timestamp = new Date(); + timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); + return timestamp; +} + +/** +* @ignore +* @api private +*/ +ObjectID.index = 0; + +ObjectID.createPk = function createPk () { + return new ObjectID(); +}; + +/** +* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. +* +* @param {Number} time an integer number representing a number of seconds. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromTime = function createFromTime (time) { + var id = BinaryParser.encodeInt(time, 32, true, true) + + BinaryParser.encodeInt(0, 64, true, true); + return new ObjectID(id); +}; + +/** +* Creates an ObjectID from a hex string representation of an ObjectID. +* +* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromHexString = function createFromHexString (hexString) { + // Throw an error if it's not a valid setup + if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + var len = hexString.length; + + if(len > 12*2) { + throw new Error('Id cannot be longer than 12 bytes'); + } + + var result = '' + , string + , number; + + for (var index = 0; index < len; index += 2) { + string = hexString.substr(index, 2); + number = parseInt(string, 16); + result += BinaryParser.fromByte(number); + } + + return new ObjectID(result, hexString); +}; + +/** +* @ignore +*/ +Object.defineProperty(ObjectID.prototype, "generationTime", { + enumerable: true + , get: function () { + return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); + } + , set: function (value) { + var value = BinaryParser.encodeInt(value, 32, true, true); + this.id = value + this.id.substr(4); + // delete this.__id; + this.toHexString(); + } +}); + +/** + * Expose. + */ +exports.ObjectID = ObjectID; +exports.ObjectId = ObjectID; +}, + + + +'symbol': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON Symbol type. + * + * @class Represents the BSON Symbol type. + * @param {String} value the string representing the symbol. + * @return {Symbol} + */ +function Symbol(value) { + if(!(this instanceof Symbol)) return new Symbol(value); + this._bsontype = 'Symbol'; + this.value = value; +} + +/** + * Access the wrapped string value. + * + * @return {String} returns the wrapped string. + * @api public + */ +Symbol.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Symbol.prototype.toString = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.inspect = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.toJSON = function() { + return this.value; +} + +exports.Symbol = Symbol; +}, + + + +'timestamp': function(module, exports, global, require, undefined){ + // Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Timestamp class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Timestamp". This + * implementation is derived from TimestampLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Timestamps. + * + * The internal representation of a Timestamp is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Timestamp type. + * @param {Number} low the low (signed) 32 bits of the Timestamp. + * @param {Number} high the high (signed) 32 bits of the Timestamp. + */ +function Timestamp(low, high) { + if(!(this instanceof Timestamp)) return new Timestamp(low, high); + this._bsontype = 'Timestamp'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Timestamp.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Timestamp.prototype.toNumber = function() { + return this.high_ * Timestamp.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Timestamp.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Timestamp.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + // We need to change the Timestamp value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixTimestamp = Timestamp.fromNumber(radix); + var div = this.div(radixTimestamp); + var rem = div.multiply(radixTimestamp).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Timestamp.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Timestamp. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. + * @api public + */ +Timestamp.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Timestamp.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Timestamp.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Timestamp.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Timestamp equals the other + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp equals the other + * @api public + */ +Timestamp.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Timestamp does not equal the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp does not equal the other. + * @api public + */ +Timestamp.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Timestamp is less than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than the other. + * @api public + */ +Timestamp.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Timestamp is less than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than or equal to the other. + * @api public + */ +Timestamp.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Timestamp is greater than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than the other. + * @api public + */ +Timestamp.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Timestamp is greater than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than or equal to the other. + * @api public + */ +Timestamp.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Timestamp with the given one. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Timestamp.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Timestamp} the negation of this value. + * @api public + */ +Timestamp.prototype.negate = function() { + if (this.equals(Timestamp.MIN_VALUE)) { + return Timestamp.MIN_VALUE; + } else { + return this.not().add(Timestamp.ONE); + } +}; + +/** + * Returns the sum of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to add to this one. + * @return {Timestamp} the sum of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to subtract from this. + * @return {Timestamp} the difference of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to multiply with this. + * @return {Timestamp} the product of this and the other. + * @api public + */ +Timestamp.prototype.multiply = function(other) { + if (this.isZero()) { + return Timestamp.ZERO; + } else if (other.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } else if (other.equals(Timestamp.MIN_VALUE)) { + return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Timestamps are small, use float multiplication + if (this.lessThan(Timestamp.TWO_PWR_24_) && + other.lessThan(Timestamp.TWO_PWR_24_)) { + return Timestamp.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Timestamp divided by the given one. + * + * @param {Timestamp} other Timestamp by which to divide. + * @return {Timestamp} this Timestamp divided by the given one. + * @api public + */ +Timestamp.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + if (other.equals(Timestamp.ONE) || + other.equals(Timestamp.NEG_ONE)) { + return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Timestamp.ZERO)) { + return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Timestamp.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Timestamp.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Timestamp.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Timestamp.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Timestamp modulo the given one. + * + * @param {Timestamp} other Timestamp by which to mod. + * @return {Timestamp} this Timestamp modulo the given one. + * @api public + */ +Timestamp.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Timestamp} the bitwise-NOT of this value. + * @api public + */ +Timestamp.prototype.not = function() { + return Timestamp.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to AND. + * @return {Timestamp} the bitwise-AND of this and the other. + * @api public + */ +Timestamp.prototype.and = function(other) { + return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to OR. + * @return {Timestamp} the bitwise-OR of this and the other. + * @api public + */ +Timestamp.prototype.or = function(other) { + return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to XOR. + * @return {Timestamp} the bitwise-XOR of this and the other. + * @api public + */ +Timestamp.prototype.xor = function(other) { + return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Timestamp with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the left by the given amount. + * @api public + */ +Timestamp.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Timestamp.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Timestamp.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount. + * @api public + */ +Timestamp.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Timestamp.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Timestamp.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Timestamp.fromBits(high, 0); + } else { + return Timestamp.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Timestamp representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Timestamp.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Timestamp.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Timestamp.ZERO; + } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MIN_VALUE; + } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MAX_VALUE; + } else if (value < 0) { + return Timestamp.fromNumber(-value).negate(); + } else { + return new Timestamp( + (value % Timestamp.TWO_PWR_32_DBL_) | 0, + (value / Timestamp.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromBits = function(lowBits, highBits) { + return new Timestamp(lowBits, highBits); +}; + +/** + * Returns a Timestamp representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Timestamp. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Timestamp.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); + + var result = Timestamp.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Timestamp.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Timestamp.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Timestamp.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Timestamp representations of small integer values. + * @type {Object} + * @api private + */ +Timestamp.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; + +/** @type {Timestamp} */ +Timestamp.ZERO = Timestamp.fromInt(0); + +/** @type {Timestamp} */ +Timestamp.ONE = Timestamp.fromInt(1); + +/** @type {Timestamp} */ +Timestamp.NEG_ONE = Timestamp.fromInt(-1); + +/** @type {Timestamp} */ +Timestamp.MAX_VALUE = + Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Timestamp} */ +Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); + +/** + * @type {Timestamp} + * @api private + */ +Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Timestamp = Timestamp; +}, + + }); + + +if(typeof module != 'undefined' && module.exports ){ + module.exports = bson; + + if( !module.parent ){ + bson(); + } +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/package.json b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/package.json new file mode 100644 index 0000000..3ebb587 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/browser_build/package.json @@ -0,0 +1,8 @@ +{ "name" : "bson" +, "description" : "A bson parser for node.js and the browser" +, "main": "../lib/bson/bson" +, "directories" : { "lib" : "../lib/bson" } +, "engines" : { "node" : ">=0.6.0" } +, "licenses" : [ { "type" : "Apache License, Version 2.0" + , "url" : "http://www.apache.org/licenses/LICENSE-2.0" } ] +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile new file mode 100644 index 0000000..c3c4e92 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile @@ -0,0 +1,333 @@ +# We borrow heavily from the kernel build setup, though we are simpler since +# we don't have Kconfig tweaking settings on us. + +# The implicit make rules have it looking for RCS files, among other things. +# We instead explicitly write all the rules we care about. +# It's even quicker (saves ~200ms) to pass -r on the command line. +MAKEFLAGS=-r + +# The source directory tree. +srcdir := .. +abs_srcdir := $(abspath $(srcdir)) + +# The name of the builddir. +builddir_name ?= . + +# The V=1 flag on command line makes us verbosely print command lines. +ifdef V + quiet= +else + quiet=quiet_ +endif + +# Specify BUILDTYPE=Release on the command line for a release build. +BUILDTYPE ?= Release + +# Directory all our build output goes into. +# Note that this must be two directories beneath src/ for unit tests to pass, +# as they reach into the src/ directory for data with relative paths. +builddir ?= $(builddir_name)/$(BUILDTYPE) +abs_builddir := $(abspath $(builddir)) +depsdir := $(builddir)/.deps + +# Object output directory. +obj := $(builddir)/obj +abs_obj := $(abspath $(obj)) + +# We build up a list of every single one of the targets so we can slurp in the +# generated dependency rule Makefiles in one pass. +all_deps := + + + +# C++ apps need to be linked with g++. +# +# Note: flock is used to seralize linking. Linking is a memory-intensive +# process so running parallel links can often lead to thrashing. To disable +# the serialization, override LINK via an envrionment variable as follows: +# +# export LINK=g++ +# +# This will allow make to invoke N linker processes as specified in -jN. +LINK ?= flock $(builddir)/linker.lock $(CXX) + +CC.target ?= $(CC) +CFLAGS.target ?= $(CFLAGS) +CXX.target ?= $(CXX) +CXXFLAGS.target ?= $(CXXFLAGS) +LINK.target ?= $(LINK) +LDFLAGS.target ?= $(LDFLAGS) +AR.target ?= $(AR) + +# TODO(evan): move all cross-compilation logic to gyp-time so we don't need +# to replicate this environment fallback in make as well. +CC.host ?= gcc +CFLAGS.host ?= +CXX.host ?= g++ +CXXFLAGS.host ?= +LINK.host ?= g++ +LDFLAGS.host ?= +AR.host ?= ar + +# Define a dir function that can handle spaces. +# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions +# "leading spaces cannot appear in the text of the first argument as written. +# These characters can be put into the argument value by variable substitution." +empty := +space := $(empty) $(empty) + +# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces +replace_spaces = $(subst $(space),?,$1) +unreplace_spaces = $(subst ?,$(space),$1) +dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) + +# Flags to make gcc output dependency info. Note that you need to be +# careful here to use the flags that ccache and distcc can understand. +# We write to a dep file on the side first and then rename at the end +# so we can't end up with a broken dep file. +depfile = $(depsdir)/$(call replace_spaces,$@).d +DEPFLAGS = -MMD -MF $(depfile).raw + +# We have to fixup the deps output in a few ways. +# (1) the file output should mention the proper .o file. +# ccache or distcc lose the path to the target, so we convert a rule of +# the form: +# foobar.o: DEP1 DEP2 +# into +# path/to/foobar.o: DEP1 DEP2 +# (2) we want missing files not to cause us to fail to build. +# We want to rewrite +# foobar.o: DEP1 DEP2 \ +# DEP3 +# to +# DEP1: +# DEP2: +# DEP3: +# so if the files are missing, they're just considered phony rules. +# We have to do some pretty insane escaping to get those backslashes +# and dollar signs past make, the shell, and sed at the same time. +# Doesn't work with spaces, but that's fine: .d files have spaces in +# their names replaced with other characters. +define fixup_dep +# The depfile may not exist if the input file didn't have any #includes. +touch $(depfile).raw +# Fixup path as in (1). +sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds, and deletes the output file when done +# if any of the postbuilds failed. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + F=$$?;\ + if [ $$F -ne 0 ]; then\ + E=$$F;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 1,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,bson.target.mk)))),) + include bson.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = /srv/biomedjs/node/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/srv/biomedjs/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/config.gypi -I/srv/biomedjs/node/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/home/akira/.node-gyp/0.10.4/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/akira/.node-gyp/0.10.4" "-Dmodule_root_dir=/srv/biomedjs/node_modules/mongoose/node_modules/mongodb/node_modules/bson" binding.gyp +Makefile: $(srcdir)/../../../../../../node/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/../../../../../../../../home/akira/.node-gyp/0.10.4/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d new file mode 100644 index 0000000..866c155 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d @@ -0,0 +1 @@ +cmd_Release/bson.node := rm -rf "Release/bson.node" && cp -af "Release/obj.target/bson.node" "Release/bson.node" diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson.node.d b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson.node.d new file mode 100644 index 0000000..20f4900 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson.node.d @@ -0,0 +1 @@ +cmd_Release/obj.target/bson.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -m64 -Wl,-soname=bson.node -o Release/obj.target/bson.node -Wl,--start-group Release/obj.target/bson/ext/bson.o -Wl,--end-group diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d new file mode 100644 index 0000000..cb495a6 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d @@ -0,0 +1,28 @@ +cmd_Release/obj.target/bson/ext/bson.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/home/akira/.node-gyp/0.10.4/src -I/home/akira/.node-gyp/0.10.4/deps/uv/include -I/home/akira/.node-gyp/0.10.4/deps/v8/include -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-tree-sink -fno-rtti -MMD -MF ./Release/.deps/Release/obj.target/bson/ext/bson.o.d.raw -c -o Release/obj.target/bson/ext/bson.o ../ext/bson.cc +Release/obj.target/bson/ext/bson.o: ../ext/bson.cc \ + /home/akira/.node-gyp/0.10.4/deps/v8/include/v8.h \ + /home/akira/.node-gyp/0.10.4/deps/v8/include/v8stdint.h \ + /home/akira/.node-gyp/0.10.4/src/node.h \ + /home/akira/.node-gyp/0.10.4/deps/uv/include/uv.h \ + /home/akira/.node-gyp/0.10.4/deps/uv/include/uv-private/uv-unix.h \ + /home/akira/.node-gyp/0.10.4/deps/uv/include/uv-private/ngx-queue.h \ + /home/akira/.node-gyp/0.10.4/deps/uv/include/uv-private/uv-linux.h \ + /home/akira/.node-gyp/0.10.4/src/node_object_wrap.h \ + /home/akira/.node-gyp/0.10.4/src/node.h \ + /home/akira/.node-gyp/0.10.4/src/node_version.h \ + /home/akira/.node-gyp/0.10.4/src/node_buffer.h ../ext/bson.h \ + /home/akira/.node-gyp/0.10.4/src/node_object_wrap.h +../ext/bson.cc: +/home/akira/.node-gyp/0.10.4/deps/v8/include/v8.h: +/home/akira/.node-gyp/0.10.4/deps/v8/include/v8stdint.h: +/home/akira/.node-gyp/0.10.4/src/node.h: +/home/akira/.node-gyp/0.10.4/deps/uv/include/uv.h: +/home/akira/.node-gyp/0.10.4/deps/uv/include/uv-private/uv-unix.h: +/home/akira/.node-gyp/0.10.4/deps/uv/include/uv-private/ngx-queue.h: +/home/akira/.node-gyp/0.10.4/deps/uv/include/uv-private/uv-linux.h: +/home/akira/.node-gyp/0.10.4/src/node_object_wrap.h: +/home/akira/.node-gyp/0.10.4/src/node.h: +/home/akira/.node-gyp/0.10.4/src/node_version.h: +/home/akira/.node-gyp/0.10.4/src/node_buffer.h: +../ext/bson.h: +/home/akira/.node-gyp/0.10.4/src/node_object_wrap.h: diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/bson.node b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/bson.node new file mode 100755 index 0000000000000000000000000000000000000000..a1b409a2b4ea071cc42b8c6c97f66da14c2ff0d4 GIT binary patch literal 57312 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

    ss}@Lxs2R{@`Zr(DAK-_`(U`$+vKNj>T7Lp83o zwe@u_e6^#|W0W^~nmqWLczU_va^;pRTI?z;C@yiiK;;dg=H+Tx74@#QHT7%CYFvDS z(^b~oiZ4giHq_u-juq*dSu-;Y%5YUzv=Vi;A?~17G}qQ{RP{I(=5aOoi*pt@T#BM< z)On~DzMIOmsIMuxRutN8OC5aw758|H=0pD#D;7?tuc+8Uw@CA#WKT8mLTnxz@I}x*G6E zLwy~-6Y1ILYOxtEDPd85ezBv(RgyEO(BU#vi4`RUMKr7{n(AHR8P&1@y%&8Ifs5BfZd*D+ii3% zzQ$;uwyd$*;}+@{R5%vTAKI@rtzVIcA&=n#Q0nS%kg^;)q>E2m=-%K!OsS=e`Q#&l z)oxqjsmzl8&uUPnh#zMcG_i`JRa|JXd#$6jAq%a_uPIwQyuHY9tdoYa&&ZeG$yfHb z+o_-ggSN6yFR5y*-w=#^j)ldpkOzli8N`+>9Ug;1O|{$e@M8%T?m6_68)43C3(0}_ zEO#9k@p~00tj!%17w5IO(8%g0bWv^%eZ{|tnls!vax)x@i(PC^-OfK55g@Iirl=)5 zdv0ODoZRKhUDML1Qw=i@k1;gF*+Rf>A@^9(-pOZ zkC17h4iB1_?IRdx=BVEZaTv8&LDZKIv$Qr!X7XsHk>V&SuP&@-Y190S|H&Gi6WB47z!ygML{ctXGB(;LuRaDrgczFEkd#7@bkj zMBWg!XJ$~(ps2fb5&r;*9I~Q+78D>}RTIzK&$?$=dFIhLfF3?tq{O=m$3ggZ|?{Z_&P zx2LMUqJY;6;p^z(xWs2nq=28kon8vWcym+|%hfPy703(Mb z`%En?sh`pUb2OvV5K`-&X~U;qU0va;!k!KqX^|&mv7{ZosLFtJUaHU%G<={ASrCRC z!JZ-gKnoVyFr~#J+aZKyWYVC)0v^*^K^=t}TEga6yK5>C1caZ`;F9Z2yWLsV6bv>| zCl(%)y}p>CjL=xFZsqF*x)RCG#sV&9PJzpwJ}t7>V452;NeCV6VOJV* zRWp2LBBv;!j0l7C%XuVf$`&+i?@pnN{46cpOa;oyRNbLXV?N391Id@x|nBiX2K^!PRsN4f5di+sD|Mr}luf z->ct7BrXU*s4}ZsD>oCAwN3}s9$Ah)cSk#;ZMRD}gwRQCBmG7J9$9<-eDzFWqh*9* z?a*#(aB4RTWWrU=c5%d44>2zUjD;Of%`c6vj3QMk!OIAR%1tXSErrR65KuOtcKXk5 zb{$EJxgGz0b6~Opt|}<$ZZmvd?s0Fb7Lt2u{t}sp2DXy9BhPT+C8XjBRiRs0R1$(C zee;%dQJdhM!%=Lx4ls1-nU{vBtaMgmDA9EW7qlQC*|7fmUVKizF^60dh$&mLwyP=Ov;wX z=Mdtbl#%3HA$<+92rsh9)wo7=KibJwj zdY5U6K(UGA``)gYgz=>cVDx^396jANbu<6@^;E~Oi$*BnK#|N>KWm=P0Qf~my8%{U ec?9p3`*viNqDWHW_=T8zh94Ak2n+DvzU&_qBOBxZ literal 0 HcmV?d00001 diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/linker.lock b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/linker.lock new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson.node b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson.node new file mode 100755 index 0000000000000000000000000000000000000000..a1b409a2b4ea071cc42b8c6c97f66da14c2ff0d4 GIT binary patch literal 57312 zcmd4434ByV);@f*LDix;c{j^cl{+8hxP7A7PyW^QJR00__{?3n z#OQwf(q*GBwViy&zQ)?r`<}jK=Z$x)C1I!IQ;rXn8->r-rx<1D6jyl%pga|%J zCRI?4&pLe8<5P=IJw6xV(}d3kd^X~9F+P{!qmDM5T!D{Q0>75&R-}G>uEK{Z+J?{7 z_*{z*ne_&I)Uh2WH{x>(J}vjA-gVOH-}mKL?Y?Qzlo9tI{Y-rJC#nB+!3UQ6J{frZ zU{Y(}Jze8QY}<5lY4t&u_q~GHq+<@$uRQqP2_N-7KeJ=|rPhIOH+N6W+V;e0$E;nn z>Dz*9E6%+B>L-t`?>u&V;$2^UklL1T%z=GxKeo^wGy1C@bItEMPyTcL^j99A`217d zANgu_-&DHk=mVF&^z_z}*ojxXyL|Av@9%o#`i#!D8=QZ7{)=n=^7SikU$p$B$Nzrq zrT@yvTJzM6VBIEDI zMaGYZ^F)%f5`#Jt{^Z!m_}D1*J~1vb|L?~~#&1Q7BGvoXF_Cc^cGh85FpM*!;7ehL z2@&`=Lr^5VD~f&cqu`rIN7ggxn8@66Wk01a>vQHh_6bau4;gRsCqu^ts z^zUZ~N|EH87o}Z?5eOskzY+ys0Q*PcpBP2{ol*4P6h+Su5GW(buT6@K$4BYMGcA$% z3t_iN{diH7{=G7a{%=OH{})mGZABFPB>2N=5&XO{iau{fY1dmYS|qzY9c8>{MA2tN z6u&(+%D8Te60drq$hV+fk@UO{I6}>^V;PW0{J)E0|97L<%@@V5&X3|(15x7P$5`h? z(&yeN<03c8IC>z8oqrXjy|+iP=fzRlyF5yNJrkwBUWhV|(xcdIS`_`$qV(@qQTpq~ zDEeOvBS*6H%TeqzF^Zp;M;Y(eM(N+SDDC3FX zfK?Ko4Zl4Ncvq7EE|mBga1!EAE*HQoj6*uEll5(4*>A@fMR@|6CUY8OyLub~ptU$1|HSwr`K7X58HfvX z%!A)jyLv7W^m`&PY*K%lY%j$@I&Q+eN&L1BL1)PJu7DlJ8z&fB@3wLV%*Y4DRI0Z~ zwri%ut>`b3)88V1y;7g;=y$@qn+0x@{PQutk2j7tvZeeqiBE?=oN63nbaz`BQT$V7 zd%L84lpTJM_UX+h3?AF#O=zB$C zEQ8$$w@O^~;{&i8)q7}(V0=~T^D5*Mf41zG>!h4@vb_z`pU;r^?Q*=d$@VJ!kCy#t zll@pF`QxRX!~3O);}!b-e8K3D{gNyFyieL^hm`Xy+Ldg4G1w~oLBhtX65k$%KZW^= z+dEHiUMUMqKt0sne%Y>*C4Q>ZGgRRtv@&X}71O{-x5-)wuf~S#P*MjFLEC zyhBvKtanlrKe^NLN!^C(x(aCD)Le^(xYo9|x*FV# zP4(0?&qh~^jjEbnS6|__+ZL@^=PvgwYbN;2twayT=pouQBBy3+< zR$UWOi)oA9l|hq2_{`iI2qn#;%8byKybP96vUGSem7S$d8JWdyPf^*_-jb4gv}&{o+ql*xXgW$-r`A!|X|diRfT7PS=Rx4_`` zq5T!=uHsCWYBzOQ=7O@u^#yem?glsh)OmiaF>{I+EtKXQZp=Iz+qt4fSZX>m3vA(h z=sq*2aV?y%&eK%g>IjaAC8!hw&0QfnnmuvGoaV|(cjNTDGEW)%UTBPHZbvRda)lpe z6*Ni5Qr;*#b=ui;-5zRRtGlA85yQ06Q|)eYv2Up$n|hBz4{r2?z**bUvmDa z3Q(S?clxxSRgV!Rv!|A4FI2O+zTB*&YMva5=F!(S60fxs5 z)nsV$W1%8sHM@-~6mevjP8pf3lTf(`Zd(l-$~uLLnT7S`Wi=6$p(><$cH0t9WtQG< zEpsNHnH->VYHDByPtZ6j%GW~Wi;Y@@(fV?urKtgPf~Qi>E)1fK%dNQ4 zsFH%Ba+&X;$RFO$tlTPh`TF_pjk1N2?cd~SEU#+hvNL!Tx)Eoqc`j?r&2SX)&@6&6 z$%>IU78kpsWZLbE-DMTIx^;$2u+JbS%$V-hMLgRziNPI#^K9azNW0eE_!B~H#QGCF z8N?Ix0`9z!Bg)y>BYbRFyX`abLUs}(B5MvN%94!@m^nqP$;xl8E2sI}ZpYMKP>01s zUAbGd4i!yb*j!T+wXHKX`FZu_918{W5YN-YSOkmdT5|LX)_%6MBe#Ve}NA#hRaki$6>hEFt$jYl@46q(Kw~il@1dV?SF?VHU<-yau;$hxK?t|o1-~}E!>B{9S+W+FZOE;`O7^FgeV8|>){>>% z0y)NM{g@@zz_?DrYTexkqyD5U9(`f~5$15LJGVuxzNpf=4IF&9X8j^dMj~46tRs!6 zbTHh}vTtEot&A0#Q8H)_Dfc)oYDOs0hYEs`xbotP&@i{BSk0RA+&hadQ5x$#^&U)13*4Tn`icVb(y-;e z-DRJl>MwEEHq;=j;zH5kXen`FQBssoRfNL7=GkI>sr8ErFvA6MKawa-Qb=bK=ufij+Sg!Vnb=0uP66!wgD<0;y@_MWg8k@^K^^Go%>IK={2rZhS z!mCn0=sEW3!aGz(h8+zX5&}hNRa067;Tb5wn-@GNhW1&=CPC%xGvTA<&Ez+t>SB!W z$Pr2yXBss*I9`5)Gvn+a*RpC)mAKZ+slzG|*JzQ;k$(?!XS*E(RQb4^R9Kau_{IXe zo$Vsyt9^PfOT^3Y;hYijUNVIJXNwaNwx}gs;IyFvLs1Bqt76S06c1(0ENGfjUypr` zy6_wVs6N% zL*ezOEEVc+HhQK zEb@Zx>#vN8>Q2Yunx_c;|dySA&8ip^Hc!QK51GXy!EB|fP zaJPoHX}G%AMcKVk@U0rYS(Ecz6ud{nuhsZ>Xt=!f%DKI_TR9~kqUR>n@tlU^mQ3*I z({S863Lg73{DvTk`#Kt4t>LDIpQ_=9G`vm24{Lb3h9}B?B>m;BEzV8WaCI+=GOA=h z#^7AXQ#5`bOAvpo8h(?8r)hYthTAm!w;GCoFPCy~yA9qS zI!ZPC>JV&HX?UE5H)yzuCzRc);g@OrZ5l3by>aeV4IiQLcWF53s*dd%uErkab!#{R zLGZXo!$${E!|2g)1e)NnL&I^4H+b}F__iQw7|&@q9^D8YeHu>p7}c>)!*NS8c=T)d zgdl1driSAdd+<1<;pIWpFb-=tZsCWHJFR?9wrmQaMxutx(8;;U8m>YlWu$2Mahe>f zhNozFnuZ^*;WiCFLBq2&e4~bEYxs#8?$q#;G`vW|f1%;aHQcM=r5fI;;Z+*0?zK~P zgNC1?@waNYRm0mf{4@>Us^P!X@GcEc)$r{ae!7NtYxqPBzemF-X?Tx@U$5aiG(1hi zdo}#OH2gUYpRD118m^wbpzM7bex}CXui;ZP+|=;38h%K_+co^KhM%S3#_z05k^c{g z{~BJQ@h5BeR1HtjaP{mCWm`4euJNa7xOygovTYi!p2;9QOT+bbWwwTA5~Dnv8eXM9 zq(vG&L&KMA_}Lm>s^R)0`BfU;q476pc$bE^YWOS-Z`1H|G<>Uut7l3myGz4oYy8_a z{5%cs)^K_zR2}zdc(wwO_Gq|zwuZ8IX!sV5zgNR^H2gUYzeU6QG<=SR@6+&H4e!_R zJPkKByg|bcY51iYeptgj8gATWWs3aYq2Y-dp0DA_8a`LUQ#9PE;Z_YV(C{=3zg)v@ z8eXH}SsFf1!?QJflZHDre7=SkY4`>WU#{Wm892%=)$l@%ze>XwXn2E$FVyf>4PT_; zZ5m#r;afHQd=2l?@WmRwUBfFiyj#PIHT)h8FVXNG4PT<+J2ZT$hWBdtG7W!D!?$aA zpN22j@O>J7frj^MxO$e6vP}(NrSTuq@YNcASi^s<;l|xorbgm#orWiB_=Osttl=&V zPtovF4Yz7|nTDrn_!#9f1#jq9w&;OQRx zwVaZTGom@-2l@wboW71|x-1FwF};T9SfYEGUO{vm(LGErCOV$zZl>oEoj`OK({qR( zL3A6_vxp}11sa&nAR3Aqfl{W=Aexrmfg+|)Bbt`nfo!HvAbJeZHl`;KO-t;6mFdw$ zk0Uyn=~$wZh&Gu1t{OBgu>*&W066_iqLYd4XZlm3X-OUEWBNm)X(=7(W%?bWX$c+Z zVfr1T+hrEj2(>77I$M|1QMME`>5WTvkmnwFdagXxQjrln@!(7&nujYM0C?q_-( z(WesK$MhPaX{j0LWqJkCw8RYbFuj=QRHD0?o=5cQM0YVghv1+tkwf#@@dwlO_{XjD!5>B~T!n=^KfrrBA@d^tD9O zk|$tg`bwf_6P?WT6-3h#CtxsrG10WN2^{*K`=97+qWhU%M>H)>0)0%cA)1yRfnKIp z5KT*tKo8T4iOwUso9TH()6yW&#q=Da^NDU_dKS@hiEdyzgJ>twrA(hebOF&tOrJ(H zP2quTrcWSxKG8O&ClF0jZNSR(XrgI~4J0!iOEgWb0fXu9)`F%fHE`%V?th|bDh>2A z{VCBjg$DYV{*Y*zIs?5-ze6-lje#DfUn82P#6UOGFAz;rVW5lYXNaaLFwn;IPNHe* z3p6nOAkj3n1xlH|muQ;O0!2*UPBcwrfo!I4Bzh&$Hm0v7nx?dXmFX*qrl~BD%=8sR z)07l2n7){3nu-F4zUBTWx|HaCrq>ZoQ%|6e=`}>tloRM>dIiztME5YgnCJ?kyP2Lx zw43NIrsoh{Npu_2vxr_xbOX~FL{|}A%JdmTR})>t^l3z|BRZSu6Np|# z^lL^sR{%|6bb?L&pUoM3tWV*+KM{j*=7q%(6pa?QJ_CV#?P1nospLo7DB zy1J+!ayC&;N3SP#u#cA^$Pveqw%N&$U^smr=advTuW@>3w}IF2jDrR{^ zzwzTe33uT%W@XN*)w?P!r?eY%puTK~G?qXC&k10Ew-oHqG-)*yn24;wep)B3-X-)c zcKW_Yo2*XXCuSew$&+xQL8ouO`4y?@+iRXfMnhWsFG@dg`gWNn;x1Z^GW%BU0zhTo zAPmLs!<)B6m}0$Ih0&7V^3D|b;lmJ~ZTf3^>$+k2h9l2n`1SD2br=*vsZ zF2tGBbGBu2UTTqLa$#zzWpYVsgJtr~scm4lOujR3Og(NP(L|+tIa~6`%r=J>q1}cVeSt9dFD0$MA7nn&W?AR$2HN7V1G}hp%|FF>o{O6Iusq8n$2z@xFyuBQx4+i>g>&*A^qBYa81wJs|8&I> zR^GoX+1_h;MEEBR(DrSu=Zwp3?azD8_3iP#65IA|HF7O^d)R>mL-YRNc=bLPKkzjA zlXzp=zHI{Iz@I>WMME0xgMa+H*#53ib6K+Gkyxki)%M=zNdpdHUtgc)$qAh&-Q?_a zLhA+K$d2h;wW81Id!fD8WA&Q0b4Rtj4Rd@@5VVrHg&N~ul04As^gbQq+eZbdaVrrP z!rI62Zf>&QhG7`*`x2&b#ylf>dawBkxjq>sLGYVp|2v9hC`b7$Y@LZ@4=?DxuyNFIK$X{WDwcS7dZX!uh!+}EogY)Fd*f>-XjT?_PbHU za!MOu!?Nv0{Pi9gX=(pf$a{wAL`(arkmo%z%F_NFYFFibU&6FEW4R|C&^!|jLjRes z!{Y+mP*&*aJu=SHK1lU!J0HcpN0KbV<1V?Z@vzZpq>6z z2wwi0)RaPh1tOStcN)i0j4t$9QM^A35jNRh6_4)5fX+=e*TH1IgHB(3s_7!PLCnJ# zjdS`wd=eExU~7^24OAbvlgHgKIh{q2Q=GgR6T>Nnwk9}zmn3If9{Gp&-!M-WswngwFtZO04i?6g zCqsLGHk3dMZi!q&nmL_n*pCZJ=?A8ldm}zoHWebNsaA6gF+KuDY1hY5N#L#^P5Qxx z7%ObNvru1PD~oN11T@zVe(K`5uPB|88lk;5^R6#Y?0gjK@*at?bo>`=M}oh!B-4Tb zO_`f)o<NP_oM9S?9_2Yq|Y(@AT(UMAC94NFG{&N~JxyDaVX zI198WIWXp^Jbx)0H1H^+ZLD`3NqAB!;`Ae22tB@ZTF!XJ>_DY_y-aFa9-&-Bqq&Ho zo(1L(G&SHwQ5qM1RxjMH+2%vkoD0Du>?#Iqsrea|oy%o~9w(9>GeUfDQKuhsYjHAZ z(rb<(O^yxb=Pb!7!5YE$y&ZuHTS%XgN&Lkr1wO2$P;_QrQ#Sc+p5>7=p)@Q9udm?l z+3$Nc$MVQO&AUL+6aChBcCL+6qooWA#Ip*4mT`^5Yu z*%5;o(Y6N59`Eif9>>AMjD@tWPd+35*FFTrX6N~ z>ROXJxgQfZ&0koDiO#N~Qne_R=U<)d=y=z%jdmrS{!NMIap=qTUd+dyZ0~n5mz{%^ z`b*d$F7Y`b{Oy_SxJEIRu*x+r*h;1~DAc+g2jgZ6ik-O(KH^e-Pt-ZV*8 zd^XsL-plQ`wBN)Pd}6Ns6oK3KNdZFGeKL#Y8e$zwdX+zi7R6h(TunWX^{y35Qyv}% z%_;002h9>VEN^hCc>X$huy1eRYL01!xr;s8fYCJ@b-agMOcsM!MUC+uzT9&4ivZ9k zmTk{aPUq}Z*vT^YQVc2wP}yZ(BIVu>lIGXW*?%IIJBfuhIA#5LsK`Oqf04aacFr^2 z579Xg-~JIdW%lV*wu;Ke3wic$$l^1|*?hYKPf?w`PRjEyfV}4|+x#qVQ{t2HI5Gbc z0HgPCJi5)Yt${D)_L@$ZGtcixhCLnBZ`--ZlElZT2qsFZ;d<~$Q+^P#=KCBK4w@s7 zf{QL~Rt`Y9b;0;*UV^N^RMaHr!}VNbZ=ePc#ru_#zL#S-oGWD9ZNCN<7(r!&*Nf(v z%>PWl1=#8RG{$p2ITL!mk$ZN(IgdP`bKF-s)c2X6VP_IHKPC$o`LoFa114v`A+lc< z*+=~f*|eugH_$j*Bv=tR2OsEVixc89!xa96ICRk ziocS?7toA>`tbP~<=_+g z7T_vx+n-bhnwM<82#4Uzm>l1;mTm1?W}Y|7HGBHt|CUDD?fyT<|ds#DDRk(d?3$ z#WM2{2EVXvVfi7;Ho9I4nYS33dA{!oeP56-*qoDJb;j|Y#rudA=0DLEN5?-rY4&&J z`iq#%B*2~1&y))v+b4*HyJGTY4m9^u`?8&9UYeSf7c*$)BPg(o;WFC%Ez}BZ<>8(! z>|p=K^biLk*d#TMav_@H@t;MUGp9+qm>CT7my&Lk`A125zNF(MeKKg($~1EmT8Ycv z(d-U^e?kekQ{oJ`(@`|)zNB&ZJeol@Uy0l<^Knpt`vv0zh!*Cj7;1s%X&znM-kJMFghBRHk#>IU;+y z$iA3Fa$uTp#g^t=+M6==&ZTWFB2#2)m1!EM-ri*7(UuqSAiN;OKF!{_ z*?hWpE-rgHt4OBHWm+oJDw#IOv{j_PZle^3bMLRWiZeRx3Y~5bopy&#?+Kmugid#a zPJ2VA&xKC=LZ|yer~RQ*Gjw_=bb2^+N^4X)pd>A8RQB$_6spHlLw@elXuQ;K&I2@-GO4 zzFggWeSCFwsF+M68 zU4n6Ns?hd2t!syH}`UluWFTX2{zA}tHKa5TZ zqxa($kS_18FuFF3o(>x839-f-OJ0eEKlc3gnu|b$?PsX#1-@9o-YqT)#9BYDUl#PX zCdYVe@c946LnP){avHUAIfXn0J4ZvW2gE+SzctZ3~8(bJOM&zK6ntr<|!xsnA=ILShv)^hjpd>BZqx(;4~q(;~&@uCmFctT*QpIDLLN1 z#^iW+$B?)ep?A*A-4^e~5S2$4r~fh^eMbs>*1TEBHdEgRVA^AMQgwZ@x_&Z=FV~9dVh64^pZ*(Gj=nvCvvq%lfL0QaCj?koz+a_++k}8L z2#62Nr(#`B|3huar6S`+k+Zl6ZMIMoYeW$niX;Y7P$V?|VnI=PiY!$ARp^7Yt0+&u zKS|}Mi1Jw|pB$i(7AkL-hbW$r9;1XF zQ&^9DsYiv-!wEgI`9ZEwJN^c(P`q0fe*rFoU8xQZn*N6L zD-a`yS8-|4jgG{X$J?ot%#NLeON+Uv#oYH6RO%eJS!C}N*=rCDcH+?p!+eagRY({M zv(UxNN1XBnhmZ3I2HvN6f$vAsPP!9!s0V3W`u|MRyBzQ1U>Ld+|4wrf0t*b-hg*tb zzgM#DH+}o43K;lV^A!ky%dfCMPj|+#zkSerT;=XEdqns-iS)UiL%=h-&^9Pf?fo`Q zZb6$5Fw=f>tzaH_mF{0>eu$Pnl?`6=YTyIcQ3MU{H>vid(H7HRshody&#$b8{WbLb zBGQFo+c#7b0`RS99;xpC#S`Fh`pz+5f{st3{hWRI{~)___ED(tNp#DgnM79fpF>y0 zUy&^TF{`K?kj~5s3djE@+xm}L8bsR&{Y0P*L9~$2R|UEzh%P4dae zPNC7}DN-Z4R@{h2(BA$#P>U=cARe@SJo!1c&(UKc`@r3j&=T?wuzW5Jya%k9(((+0 zt}o#ZR?6+7!GOLx%v_(Cy_E8k8nU?RpI@VR@P04f>gAihykAcDdlA(?G3P)UHZ8q} zu{*jH7WN*-t-Vcr5@)&k2{O5#_NU(~fTLO3|A-vgAYPARG_IcjJ!H#;BL{7#eqw&Y z3ht89x9wwDn=pQ{-L(>y!(O}tcbR*E?}Qj^Cpq!(hZSeWp1jmFV{1w3WZL7mS+?B= z%<0E=E*@CPrkNL(z{4lzZd8FS603P8*9Aj=VzxoGfeFHHaFgdJqN6Tlk7DCq!{*~H z{^hjAUqoB{Vs}5(AJ{()?XFweXHwq;ci1f*lbK#VlAj&sb=+%#^MD1{ALfg1B5E%b z5c-cd`{%+pF?-_1)9m+7hf<%Qe*%@n(*;8Wu0YsP>pyY7g84mTD3ih&_8YyMuxof4 z<+2ss@F_@q9}*uViN7I!2=NNPyKZN1&`Nw=uXU~xb3$2 zGn!JwBI$i7!(NbJxq30XR=lOX01?-F7>@;{&;^(7W9jk2$40_O$j5#U&Y?c$h7jRn zUTB7$HP|KAvh7xOMz&3|`88 z`C-epRUwHf=Eyg&X7cSpOC0upcn@QEtR_94=T@A-N@A-o&-Yc{)|%Apt%a#MbZ5%x zjClv1EuNYxNzJlsJC214XD-4(Aw7yrAEc9emy*qFgq50qrZ&L8vuF#@=8XBiaOU@x zE&s)aoo%Hazk{589OCcnQ!(L~*RylW9kaX9652BL-gmsLm&wxp8+aj&1FSXaR+FWp9YCSKbY$QX;h#C3 zm!3Ch-bxjt6}acK$NU0q;O#Q<8}lJ{s=a~Lg5SJD(sVUL_c5*mjg%j%Cx1Uo_vw_o zx4g#v*s%=;6ul6*OqApC@(C=6Y3@WCFSlbAK=N{h`~mr#4~-w(QR5DfW9U>C+WdlW zp({gK$>sr(^#HkpWt*0jV$O$LjJ)e%_>^D5@F&6#c?4rXJ(UJKc4qE4iIUkLoU8`a zqkkox+F)Le2N=OtvzV)Z#+G(ksyv43jljcDUdAuFZ)xFnSvubOfjtuqcq=3#(JX~G z(@JiK$i_H$J(QhniuPGLev9lU;o}&)2hCNemS);^uHMpdDP>~VaptdN=13{ng-kSr zp5`~FVN3>Y4C-fpJ}?qQ7uof)S;3Cl#3j)x&&fG|;U>Ka8Pp#S@zC2Fpa&yBV;}_{ zN0xb$zz24l*GP_33S;ep=;ALum@P6Zjk2mGaSvzO6xv>Dut+`w&Q4&+yX z7HubETU-EU>*m96(X8t7y1Ux6JBO3LJRwA zSaV!9o9wZT-uD&sqFoiHwkNQvmft)hu6H{hPHjWIq==Q~CH|9! z6@-nnu#*;eUR5xe7xu{>fW2QpDctR|@VaFu4S_=65t{41eTfv@Yo5w|&u*}XbsiW< zrg;0b6~iHwg0`3=XR<$XwC#ozr~hUdSno`wh)MyMMtGtB;Z(ZVEA-1JU^nk3$B^-f zV+X-_8Uc!JAliwCpiRc`#V+aU8l)C@%1yYN3omxE@Aap?C!A=917h2*r40{5E0Q_J^Ps<+X5L8z{s4icPRL;0lf3_mC|* zh}Z8bSU(T@(WE;A^$pxCd{p&K6?*VGCr0QYXnfWEhnc1@t z&dswBA?2e3?PM0id>35smOuhTpk3yRl6FY?aY^Ti_L+Z>G+ks8|4ov%N!l;zQqYKQ zHK&npXS$E2WcIccHKkNM&)Ew^cD~5I3Qi+}pM$c6d)|n_L~h*(WAnW)EIam^@kEKI z*aGY`2hH=@kNF{lHvyTOQ7~{K)V9Anfb}(226<@jdY}V$4-CkD9r#c^nJ=Hur{`&% zzOQhV!IymRQFA)}K~c&xAJ=-Gh4gIO%q529`d+wTHlBIv=xyFWSM(@$(0mVy1D_kV zB?2FQjk-l#K9T<*I9=a6@B~a$ZDkY9IfhO2&@W(v7V4Rt=THFigUJ4+$bN*fTPgcA zk$tAf#;g9wz<$c!K-qDWEiAa49b&&}BTLeyx$m&ke|e&_W6(3so1Gj(7tMi(UgX-& z72^JUG>cnB;+B)RhxcOe;lM4z-`cG5vJUtE=(%hmD%0#om1ui9?|hV#JZypRg>pW1 z5p9v6$^>&c*>rDiBIFt?cbSu+R*0SNAI0r?3oDzQ)zqGk_HcHs$lfEe@1pD~%6?X4 zFBI8#i|mDzy_T}?LbgyD_V7)OVvjzk5VS|JGy&UV2Dx|89!^p^WRK&~T|s+5{^V%# z8-)B!l4O1*MY8-isq=&KO{!YT$Cz0ec3;8RZ z+jp5Cq8DHf-yz|G{9TkI)DT3Q1C-)xC%#yxH#aeUrBnv;Xv#LjpGQx@<`=%KVIJHi zis4~b{vHO3``0J#L}Wyhp2Y*5>l5ia8hD1%e1lrCov!GUoiUjI)?)+hBs^SPgZ+B% z?v!AKRNo=-d?;_MpehVM-~X7`Q76PuF+6cX*x&8KmsZF}o<)E8u;KKHy%*ax*ywj-{}`IVa=!QJftKxf zu%sYnH)lNe420neHC8l*9y-I;i|K)>>A{l+oL+}P5zVHaU<#U!^&@-Wk{{1q(#Djy z^jFVc`ezmR-Z0m(b5OrD`nK%-?hCEFE;CBdFdE+A}e?aTbA=jtlsTWk;JV)fCEVzZMv3ryKp$fWu@7 zG@uXl$u1F{MmPA)cVsU4FSuyi{?R8zfm6_*9leMqmi8P{2JR2S+)8>2_j?(fv;2>EE$cD!T^~$e*5JMcHDbg-Y~XggKW~LV!r70I{C} zM6y}@6iLvHOAkDlCrMV0CCq9y(-bTB5gEcTzSXx{5>JrO&I4}*2!@lYq-gED3S{Y={;H?bV) z{yXRr%zOn|0WWZlW%MU_f0x&-v}omsdwH_?rRWz5xs(1v+VhRjtI$gneew9O4-&C7 z&gXc9Z+pR~=ufc$jv=tSic=OXLY~$_%J(kZ8oH>L-9x<{O@O#Pj}gmzk#=e23Khnmt;CO!DC&GmoXcmYmQAGs0$tdmIL@8_d4~ zpk>KcR87Gc-;4F%%)6wtbxI?ic1<}hfbIsZc1dy3Ew2AKr%#Ba*l9a4t_Y<4_09D#eMOF?(X0l){)= zKvoCIcp_^RxhEDj7A*^$I!N~$Og{t#LiCZ@H$SYogl^qQej$_z3?xrL<+}o z693>1*w9?YRa)BVtCLPzxEu>piJ2fpP0rI$lw8KkJh=iFlXHs9x<${zm6B&m)ofjPDIZ%%J{VgzsvUs&&m03sg_NOY-$^5hWggQLwMlPLKAZ6&AYM z!kBb+I=Iipc*VA_RjvxGV!i@m144n>W`0j%(F@MWrq5vn{_q`}g<^>EvP0B>k6;c` z@&`(X#FvdIp)FNTggn@%eT&d3j&#C=^vPIUpeB&b&^w(D?rifmQMamy*D{w-1)cbA z6lSC%sdo|EkA1o`^LCOHFC>wBV;;y&G)snx;W7;=4C<`^BY*bZ4~?v2*d zo2<3XO&)7qy~oP$HMMTQ8#b(yQgKIbL3L9TUUp=~ujE_nE3Fms1!UG*y#CSMXq~jm z1|}T2Rn;{Wp=^3Pox7sR+E9j9`*GpzJ?p&TZ+A(XY(39vQ}veDH#Rmmc&zmD1uNc&(Nwn9Z9P{R z%vw`lM;pVq^Qhjs8EQnDs5p&Yp)h%hRlHUtt(xAyVy&*T4uwNKr(6bIQ*W&Zy(gXUbTrl@m7ztdVVutSp?s)Doe%QBqai_~Yz9-9pw6FH6B#8eVUmXc_#~ZEeC! za`e#^ZYl^Wu5OJeCW`v7OJzjKwf6xN+muTm+-3d28@0uc_iCOjGmfo7dF1rKUGTjv7JrDyk735U(2DcpVf9sCE%A z9nr?uO40n)g3B;UHq-|@rzzy?XIUlV6hy9idasTwL2_XY&rcLvO-zwQ`OxJeB%XSz>aQtmRWdH#i}$0Q644A1!C?xa|Nh^tCsM};wFsUB{ZHuwrKr{9 z8RQ`P_8g zlZ{g)BVb2ugJ&b45TY}pFy<)v&gG#6>E+ZwxDuYR!j~op;GQzXiAm{`jDk8yLI@xp zicTCbj3srVR=LEWSFp~qo?fBU)3n12fFO-t(F$L5;dcwy;-?kGOi*8EG&Qerai(xl z(PSePsu`)(6-H{s8l#S0C)H3^?l$Uy(Cd+mCVHE@3{(b%NkfH6Lxf3#!laQm2Vv3> zVbTy`(g=o0#9<1Ph6t0!!g>(_Ls3!%LM(SE{FPZ%L^R5Wzj)1PQZFJL{>n5%n~L>w z@zOKn^kySHeX6_FGnFirUS7`cNK#SLFj}e`J$MtMwFS+GCKc{kvqWp@J@B(;@$1Ub zn^6x{et6N#LUMjY045brb$PVv$(M5RvP60feOgP_tXZL#(4R}>Qu6Zirf~5yB5JAh zi_$)H;g2YXR!1pE)?tO5yk28vM0?L0s)lS|$r%xiOAG#JVyr89^3 zQhs?=S)-~#teIxb!W-er!i5WiX)4O{v~qFLl><3|5+GjM9bH7siE-y_$2LL+REqy2 zE`+hKl8Uq)X&%y>kyapmX%y!D`v(W<5%)Kc{(#5qrav$^coKFAzD9a3(uaEn2WyB% z+K$xor@_Jd2uHdb>Cq1k4!(!M~UVa1Vop|UYbtLM=b3B(KeHc%8-G}sRr0t22 zheyY1(2kOQD2KG-Z-av$p*{4yt0`z_JJJfIA0eg3>#pAqeUW~R^arFR{m>Wfego;b zNaH_%zDVCH&5NBRWie~9u(rz2ejJ?=#M2GYF04-Os;eU3IE2kF;H??d`< zU~uqjq}P9edY~U34dEl^;-bREMoeq+$eT`|U^PxWaqP%MdJZxbx%BC|Z*Z^#Y5a*O zoRgI7jh&lh^NdbP&Pz(n8DkhzkXMLL>$`)4{lqs?@NJ3BOG@#^%}vUVT{=1`1toKm z67$9wxUa!S%*9-5jH-|Hp-=LA(3?2&l9EeCCnY*i2OU(7@Sb}I2dzjAXHqgHREG3R zLAhlF0Qbhm7N97p$K^aow}+J@c~{}n9fnhz@5Cn!^6o_{+PoIxoMV=2`cSG=Yv9PlZe$pBxe+u%ukbef{OM5uS6ePjI-0ni;cOyTO^0{w{ zlz7gsL4Ggt@uZ2&UxNHxwkXwqmCT<+`H=68UBj}8r2PAk--q&51T5GR=Z!B&vR)M% zdp@`*|0U#G;m>^0xnN7IH!d&9dZ7?O`JYjF*mo6`XZ_|S*s~>{m2ydXWEUFh6(Pi1}B=dlTk&#;q6)Pt6+>>!vh!4E5(K@MptcrxCwA zs6RcxtAJlb80)bScE}%-gTKo(|Dt%*3qFchWRF@jh2+wBHG!`nTplF%CEzy1FC|y{ ze14KOwp_V9mH!%iTfwL7Ojag*EXHp)aQsFR)o1enC%LJ>p94NG9)z^J?W)+g)iJ^D zHKrr05PXLa|E|QjF()axGj>i=%2jbWN!Bg#IZ0{WgaVlRqNFtR3JeQ|IZ26R_jZ(X zB0h4zEKJI#o{L=|`i;i&oygyc{PF0&h;rv96~%Ur9xB)|CU%uV99$I&3qSfA@|GhG zN2-t7dllNb9r+nZj<=Z{GR|IwJ|3_MLl{uqCz;OBUcE+8E!pq`7o-H`hn>b(x< z)b?%E2c6UhSCQXsp+4}A$V)1Xy@V|fhYVVt>Y@2I4fDlb*w0vSRh&10`+7@!>|FFU zSp~xZpDEz$qj{2ms5Z_MeO(&co0J8khxIho_Zj3=;jy{-7>Ds|@n?ZIeoI_IQUk`6 zg~rtUF_BF&E8xyHQ6s3duo96#M^xtUoPyB5Vy1+Yf%ZQbz`|8+jah>s3CB*HZ=E8lL zKOPfF57srY#J@kp-xuOPJ{J6Q!B6q(3CQodV{mXbRX9H>`63ZAjKRT}Zgffv9n@e^>mBYqCx>k|mR zCm{jnFC@&z`Ew)a{Ie0)#DKUpk%%3M#MH;Zs?-`Ns z?WnjXM!ZcK-HDXZlXyDLe@`{NFe<^sl9IZ`*f-LOv;T`nj;IT_cKA>=htmoVPqVwN z;n4r5G)5sG^iEqk6n#|~P4Cdv^Y09!=^eUsB#Fd$Q_^E4y(3GUjFa>|Tg1unk~XAW z@DMZ~G(o^&J@$`u9v0IQ)d$ zqx3i=>AEzLkNdZrui7cl|Ns2`-}-N#?C0rui~mD$`1tw#amgOmC3s zT{3+{rh8=irc4jW^c$IuI7ikm(}^;jA=7-BE|qDeOj~5SMW#2%^e&k`BGWxGeN(0f zWcrOvN6^9x$FVY0L5?M5cRW`ld_|$n+bTjyO-YU#1gfIzy)UGF>Xu zN}0CEbc;-Hkm+4AeMF{vWcsE|56JWznU26OuF`R=Oee~8hD`Hix>Tl>GHsFR7Mb24 z)4OE)h)nm$^i7!_km)xv9g)q|8^_9YqD*JVG+(AmWm+lI7MX65=?yY9Sb|JAG|kbNZTQJcMu-_T!nVDr>4T(knLB zp`=JXjUos4pqi?&&(CaYlO%-JDZ+!4foY2Du-(W6O z<<k%- z(s1I8=6Y3L&F?BbH%x!Ur_v=TPiqH7tM!9Q+hk3oKk2FTm#|TR6V*1t)OtmwYP}L} zKh^%au<~mCqf)hAqVlxnQuV9yt-z>>YJH~Ge=1dcVBv#w)epKkub1!361l-tEyQFY zRh~C#fn63>zB^kmsx&cQ(CV)$r|5Q^==H1hs!G*5SMjU*6@8^Fullc7u6I@Xj#?PY z0#;Q}rt}pPs$Z4AnKwTSBbZXAc7)g8jXb@4)^7x}N()toNf}|Jac@}p_FDv_N|Tjh zvV3^`PXH$yDgRRId!t(v2(K@kehzG;zbc>DZRLWA-JBTV{S{uG9-7t5r^xatKePOs zVdc|g`7~KRyuNVy-LUd%-JC7UcOhRttU7^n6CWBos{Lx++}8~d2ez#FP|rR z1pZosXW}FQm6I%0O{*;5D$9rSt9q4~(I`*)+Y}&ERepIGPP}xebUe;g-JBu+^vU{< zQj8K0BUw(^5Mj=HdPIS(M~n1iB(&sG`m4A|*O8Ixw>>M$^_(D5^*6kJg-1%`pq-kB z_53(Q8#TWU#p4V$Zw|%d4K*JQ#S;uQ&ke;#7;63+ijNG=Pebv<;C1&<9Q#$_4g`ic z%tUH_7|K7!=+4#=aUN%kHB>y;bK{J0hKkce@uXn<9g15F6<3Gi$%cxTLveUlw^fJu zJkFS4s5qx*#u-N$Dt-;ck2X|X8j2rdsCY9JKh{ujWGH@|q2j|(JjGDsekgvtkuAsL zQ2Yc#jnknxtpBhDkg$`Xd5Obf_=z6Vz7%GZXXA5 zs<$+(-j&QB(x3FBV;w#*#tBB7Y_A%pt-wi6f0&$T`nR*32}W|a6=$L28l1)$7Nbqh zuPWy@#)s?w2jEn1!xqIU(x;I`vfJ~LKY5PeD-ntD9?}^2c|R$DV}VEvdZi5E*|Y$` zak@y1YT#6_8b?-%`y_w2l#?cL`n@aS@68r~RpRt^36gJ>>zT79o*66cnJoaT#A|^Q zf2rh`+auTrm$cc{(B zLoDZbqan;6{>u0lgW==lW656?#{U)L5ymMdbn<6ww^i0Cl5vcGF&I96j|Hyge7!(E z@Cj&FGC4es43QY?qwse{!RekE$)R^d(y>Y;2Hn4iRIfb>zAy@283k{Pg444!k?MUS z3O)e*RO1+MN#l_;AEe!Ji&dDEYt@4G~oU6dYa~WI{w7` z;#~jxtmL=Rg%1vXwgl;GQTYD>Jdzy-qu@u4jLc8Z@=S;@53XT+jB$uAL~+nPYdY#B zZp#<+B#{``0q6Eg1Dq@I`EA8mOs1&T_^rgV<@l1*r(s5sb22X0 zPm^W!WESIN3~Qr6Ra`0tPX4bJ4r*R#V_cUY&VK_uQhNhY@X40Q{Bxt=E2H3Bqu@^g zC;hY62>o_Rl@9|adxpp11SlU#|CA{BB;ez*e%N}ql_evL@IkK(iX^8LAl2I-`|%9P z-@$dh#=Ez?*?55=p1MH2re zikxGQ5ps$)2}V4i!$&3XNc~99DR95baiQctB=K$;xA|E|NcuR69OKx?@}~ojWY0q8 z|6*{v9PdI)!#F>RoXeu%H$=gA0;hKMR|?7W%oQD9GA_>bze&dl{$x3!(KC5;oG0

    ss}@Lxs2R{@`Zr(DAK-_`(U`$+vKNj>T7Lp83o zwe@u_e6^#|W0W^~nmqWLczU_va^;pRTI?z;C@yiiK;;dg=H+Tx74@#QHT7%CYFvDS z(^b~oiZ4giHq_u-juq*dSu-;Y%5YUzv=Vi;A?~17G}qQ{RP{I(=5aOoi*pt@T#BM< z)On~DzMIOmsIMuxRutN8OC5aw758|H=0pD#D;7?tuc+8Uw@CA#WKT8mLTnxz@I}x*G6E zLwy~-6Y1ILYOxtEDPd85ezBv(RgyEO(BU#vi4`RUMKr7{n(AHR8P&1@y%&8Ifs5BfZd*D+ii3% zzQ$;uwyd$*;}+@{R5%vTAKI@rtzVIcA&=n#Q0nS%kg^;)q>E2m=-%K!OsS=e`Q#&l z)oxqjsmzl8&uUPnh#zMcG_i`JRa|JXd#$6jAq%a_uPIwQyuHY9tdoYa&&ZeG$yfHb z+o_-ggSN6yFR5y*-w=#^j)ldpkOzli8N`+>9Ug;1O|{$e@M8%T?m6_68)43C3(0}_ zEO#9k@p~00tj!%17w5IO(8%g0bWv^%eZ{|tnls!vax)x@i(PC^-OfK55g@Iirl=)5 zdv0ODoZRKhUDML1Qw=i@k1;gF*+Rf>A@^9(-pOZ zkC17h4iB1_?IRdx=BVEZaTv8&LDZKIv$Qr!X7XsHk>V&SuP&@-Y190S|H&Gi6WB47z!ygML{ctXGB(;LuRaDrgczFEkd#7@bkj zMBWg!XJ$~(ps2fb5&r;*9I~Q+78D>}RTIzK&$?$=dFIhLfF3?tq{O=m$3ggZ|?{Z_&P zx2LMUqJY;6;p^z(xWs2nq=28kon8vWcym+|%hfPy703(Mb z`%En?sh`pUb2OvV5K`-&X~U;qU0va;!k!KqX^|&mv7{ZosLFtJUaHU%G<={ASrCRC z!JZ-gKnoVyFr~#J+aZKyWYVC)0v^*^K^=t}TEga6yK5>C1caZ`;F9Z2yWLsV6bv>| zCl(%)y}p>CjL=xFZsqF*x)RCG#sV&9PJzpwJ}t7>V452;NeCV6VOJV* zRWp2LBBv;!j0l7C%XuVf$`&+i?@pnN{46cpOa;oyRNbLXV?N391Id@x|nBiX2K^!PRsN4f5di+sD|Mr}luf z->ct7BrXU*s4}ZsD>oCAwN3}s9$Ah)cSk#;ZMRD}gwRQCBmG7J9$9<-eDzFWqh*9* z?a*#(aB4RTWWrU=c5%d44>2zUjD;Of%`c6vj3QMk!OIAR%1tXSErrR65KuOtcKXk5 zb{$EJxgGz0b6~Opt|}<$ZZmvd?s0Fb7Lt2u{t}sp2DXy9BhPT+C8XjBRiRs0R1$(C zee;%dQJdhM!%=Lx4ls1-nU{vBtaMgmDA9EW7qlQC*|7fmUVKizF^60dh$&mLwyP=Ov;wX z=Mdtbl#%3HA$<+92rsh9)wo7=KibJwj zdY5U6K(UGA``)gYgz=>cVDx^396jANbu<6@^;E~Oi$*BnK#|N>KWm=P0Qf~my8%{U ec?9p3`*viNqDWHW_=T8zh94Ak2n+DvzU&_qBOBxZ literal 0 HcmV?d00001 diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o new file mode 100644 index 0000000000000000000000000000000000000000..e371bca9dbd7c308307f917b7d94acc2b9bd781b GIT binary patch literal 67288 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 +#include +#include +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif + +#include + +// this and the above block must be around the v8.h header otherwise +// v8 is not happy +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __sun + #include +#endif + +#include "bson.h" + +using namespace v8; +using namespace node; + +//=========================================================================== + +void DataStream::WriteObjectId(const Handle& object, const Handle& key) +{ + uint16_t buffer[12]; + object->Get(key)->ToString()->Write(buffer, 0, 12); + for(uint32_t i = 0; i < 12; ++i) + { + *p++ = (char) buffer[i]; + } +} + +void ThrowAllocatedStringException(size_t allocationSize, const char* format, ...) +{ + va_list args; + va_start(args, format); + char* string = (char*) malloc(allocationSize); + vsprintf(string, format, args); + va_end(args); + + throw string; +} + +void DataStream::CheckKey(const Local& keyName) +{ + size_t keyLength = keyName->Utf8Length(); + if(keyLength == 0) return; + + char* keyStringBuffer = (char*) alloca(keyLength+1); + keyName->WriteUtf8(keyStringBuffer); + + if(keyStringBuffer[0] == '$') + { + ThrowAllocatedStringException(64+keyLength, "key %s must not start with '$'", keyStringBuffer); + } + + if(strchr(keyStringBuffer, '.') != NULL) + { + ThrowAllocatedStringException(64+keyLength, "key %s must not contain '.'", keyStringBuffer); + } +} + +template void BSONSerializer::SerializeDocument(const Handle& value) +{ + void* documentSize = this->BeginWriteSize(); + Local object = bson->GetSerializeObject(value); + + // Get the object property names + #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 6 + Local propertyNames = object->GetPropertyNames(); + #else + Local propertyNames = object->GetOwnPropertyNames(); + #endif + + // Length of the property + int propertyLength = propertyNames->Length(); + for(int i = 0; i < propertyLength; ++i) + { + const Local& propertyName = propertyNames->Get(i)->ToString(); + if(checkKeys) this->CheckKey(propertyName); + + const Local& propertyValue = object->Get(propertyName); + + if(serializeFunctions || !propertyValue->IsFunction()) + { + void* typeLocation = this->BeginWriteType(); + this->WriteString(propertyName); + SerializeValue(typeLocation, propertyValue); + } + } + + this->WriteByte(0); + this->CommitSize(documentSize); +} + +template void BSONSerializer::SerializeArray(const Handle& value) +{ + void* documentSize = this->BeginWriteSize(); + + Local array = Local::Cast(value->ToObject()); + uint32_t arrayLength = array->Length(); + + for(uint32_t i = 0; i < arrayLength; ++i) + { + void* typeLocation = this->BeginWriteType(); + this->WriteUInt32String(i); + SerializeValue(typeLocation, array->Get(i)); + } + + this->WriteByte(0); + this->CommitSize(documentSize); +} + +// This is templated so that we can use this function to both count the number of bytes, and to serialize those bytes. +// The template approach eliminates almost all of the inspection of values unless they're required (eg. string lengths) +// and ensures that there is always consistency between bytes counted and bytes written by design. +template void BSONSerializer::SerializeValue(void* typeLocation, const Handle& value) +{ + if(value->IsNumber()) + { + double doubleValue = value->NumberValue(); + int intValue = (int) doubleValue; + if(intValue == doubleValue) + { + this->CommitType(typeLocation, BSON_TYPE_INT); + this->WriteInt32(intValue); + } + else + { + this->CommitType(typeLocation, BSON_TYPE_NUMBER); + this->WriteDouble(doubleValue); + } + } + else if(value->IsString()) + { + this->CommitType(typeLocation, BSON_TYPE_STRING); + this->WriteLengthPrefixedString(value->ToString()); + } + else if(value->IsBoolean()) + { + this->CommitType(typeLocation, BSON_TYPE_BOOLEAN); + this->WriteBool(value); + } + else if(value->IsArray()) + { + this->CommitType(typeLocation, BSON_TYPE_ARRAY); + SerializeArray(value); + } + else if(value->IsDate()) + { + this->CommitType(typeLocation, BSON_TYPE_DATE); + this->WriteInt64(value); + } + else if(value->IsRegExp()) + { + this->CommitType(typeLocation, BSON_TYPE_REGEXP); + const Handle& regExp = Handle::Cast(value); + + this->WriteString(regExp->GetSource()); + + int flags = regExp->GetFlags(); + if(flags & RegExp::kGlobal) this->WriteByte('s'); + if(flags & RegExp::kIgnoreCase) this->WriteByte('i'); + if(flags & RegExp::kMultiline) this->WriteByte('m'); + this->WriteByte(0); + } + else if(value->IsFunction()) + { + this->CommitType(typeLocation, BSON_TYPE_CODE); + this->WriteLengthPrefixedString(value->ToString()); + } + else if(value->IsObject()) + { + const Local& object = value->ToObject(); + if(object->Has(bson->_bsontypeString)) + { + const Local& constructorString = object->GetConstructorName(); + if(bson->longString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_LONG); + this->WriteInt32(object, bson->_longLowString); + this->WriteInt32(object, bson->_longHighString); + } + else if(bson->timestampString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_TIMESTAMP); + this->WriteInt32(object, bson->_longLowString); + this->WriteInt32(object, bson->_longHighString); + } + else if(bson->objectIDString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_OID); + this->WriteObjectId(object, bson->_objectIDidString); + } + else if(bson->binaryString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_BINARY); + + uint32_t length = object->Get(bson->_binaryPositionString)->Uint32Value(); + Local bufferObj = object->Get(bson->_binaryBufferString)->ToObject(); + + this->WriteInt32(length); + this->WriteByte(object, bson->_binarySubTypeString); // write subtype + // If type 0x02 write the array length aswell + if(object->Get(bson->_binarySubTypeString)->Int32Value() == 0x02) { + this->WriteInt32(length); + } + // Write the actual data + this->WriteData(Buffer::Data(bufferObj), length); + } + else if(bson->doubleString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_NUMBER); + this->WriteDouble(object, bson->_doubleValueString); + } + else if(bson->symbolString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_SYMBOL); + this->WriteLengthPrefixedString(object->Get(bson->_symbolValueString)->ToString()); + } + else if(bson->codeString->StrictEquals(constructorString)) + { + const Local& function = object->Get(bson->_codeCodeString)->ToString(); + const Local& scope = object->Get(bson->_codeScopeString)->ToObject(); + + // For Node < 0.6.X use the GetPropertyNames + #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 6 + uint32_t propertyNameLength = scope->GetPropertyNames()->Length(); + #else + uint32_t propertyNameLength = scope->GetOwnPropertyNames()->Length(); + #endif + + if(propertyNameLength > 0) + { + this->CommitType(typeLocation, BSON_TYPE_CODE_W_SCOPE); + void* codeWidthScopeSize = this->BeginWriteSize(); + this->WriteLengthPrefixedString(function->ToString()); + SerializeDocument(scope); + this->CommitSize(codeWidthScopeSize); + } + else + { + this->CommitType(typeLocation, BSON_TYPE_CODE); + this->WriteLengthPrefixedString(function->ToString()); + } + } + else if(bson->dbrefString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_OBJECT); + + void* dbRefSize = this->BeginWriteSize(); + + void* refType = this->BeginWriteType(); + this->WriteData("$ref", 5); + SerializeValue(refType, object->Get(bson->_dbRefNamespaceString)); + + void* idType = this->BeginWriteType(); + this->WriteData("$id", 4); + SerializeValue(idType, object->Get(bson->_dbRefOidString)); + + const Local& refDbValue = object->Get(bson->_dbRefDbString); + if(!refDbValue->IsUndefined()) + { + void* dbType = this->BeginWriteType(); + this->WriteData("$db", 4); + SerializeValue(dbType, refDbValue); + } + + this->WriteByte(0); + this->CommitSize(dbRefSize); + } + else if(bson->minKeyString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_MIN_KEY); + } + else if(bson->maxKeyString->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_MAX_KEY); + } + } + else if(Buffer::HasInstance(value)) + { + this->CommitType(typeLocation, BSON_TYPE_BINARY); + + #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 + Buffer *buffer = ObjectWrap::Unwrap(value->ToObject()); + uint32_t length = object->length(); + #else + uint32_t length = Buffer::Length(value->ToObject()); + #endif + + this->WriteInt32(length); + this->WriteByte(0); + this->WriteData(Buffer::Data(value->ToObject()), length); + } + else + { + this->CommitType(typeLocation, BSON_TYPE_OBJECT); + SerializeDocument(value); + } + } + else if(value->IsNull() || value->IsUndefined()) + { + this->CommitType(typeLocation, BSON_TYPE_NULL); + } +} + +// Data points to start of element list, length is length of entire document including '\0' but excluding initial size +BSONDeserializer::BSONDeserializer(BSON* aBson, char* data, size_t length) +: bson(aBson), + pStart(data), + p(data), + pEnd(data + length - 1) +{ + if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'"); +} + +BSONDeserializer::BSONDeserializer(BSONDeserializer& parentSerializer, size_t length) +: bson(parentSerializer.bson), + pStart(parentSerializer.p), + p(parentSerializer.p), + pEnd(parentSerializer.p + length - 1) +{ + parentSerializer.p += length; + if(pEnd > parentSerializer.pEnd) ThrowAllocatedStringException(64, "Child document exceeds parent's bounds"); + if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'"); +} + +Local BSONDeserializer::ReadCString() +{ + char* start = p; + while(*p++) { } + return String::New(start, (int32_t) (p-start-1) ); +} + +int32_t BSONDeserializer::ReadRegexOptions() +{ + int32_t options = 0; + for(;;) + { + switch(*p++) + { + case '\0': return options; + case 's': options |= RegExp::kGlobal; break; + case 'i': options |= RegExp::kIgnoreCase; break; + case 'm': options |= RegExp::kMultiline; break; + } + } +} + +uint32_t BSONDeserializer::ReadIntegerString() +{ + uint32_t value = 0; + while(*p) + { + if(*p < '0' || *p > '9') ThrowAllocatedStringException(64, "Invalid key for array"); + value = value * 10 + *p++ - '0'; + } + ++p; + return value; +} + +Local BSONDeserializer::ReadString() +{ + uint32_t length = ReadUInt32(); + char* start = p; + p += length; + return String::New(start, length-1); +} + +Local BSONDeserializer::ReadObjectId() +{ + uint16_t objectId[12]; + for(size_t i = 0; i < 12; ++i) + { + objectId[i] = *reinterpret_cast(p++); + } + return String::New(objectId, 12); +} + +Handle BSONDeserializer::DeserializeDocument() +{ + uint32_t length = ReadUInt32(); + if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Document is less than 5 bytes"); + + BSONDeserializer documentDeserializer(*this, length-4); + return documentDeserializer.DeserializeDocumentInternal(); +} + +Handle BSONDeserializer::DeserializeDocumentInternal() +{ + Local returnObject = Object::New(); + + while(HasMoreData()) + { + BsonType type = (BsonType) ReadByte(); + const Local& name = ReadCString(); + const Handle& value = DeserializeValue(type); + returnObject->ForceSet(name, value); + } + if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Document: Serialize consumed unexpected number of bytes"); + + // From JavaScript: + // if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + if(returnObject->Has(bson->_dbRefIdRefString)) + { + Local argv[] = { returnObject->Get(bson->_dbRefRefString), returnObject->Get(bson->_dbRefIdRefString), returnObject->Get(bson->_dbRefDbRefString) }; + return bson->dbrefConstructor->NewInstance(3, argv); + } + else + { + return returnObject; + } +} + +Handle BSONDeserializer::DeserializeArray() +{ + uint32_t length = ReadUInt32(); + if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Array Document is less than 5 bytes"); + + BSONDeserializer documentDeserializer(*this, length-4); + return documentDeserializer.DeserializeArrayInternal(); +} + +Handle BSONDeserializer::DeserializeArrayInternal() +{ + Local returnArray = Array::New(); + + while(HasMoreData()) + { + BsonType type = (BsonType) ReadByte(); + uint32_t index = ReadIntegerString(); + const Handle& value = DeserializeValue(type); + returnArray->Set(index, value); + } + if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Array: Serialize consumed unexpected number of bytes"); + + return returnArray; +} + +Handle BSONDeserializer::DeserializeValue(BsonType type) +{ + switch(type) + { + case BSON_TYPE_STRING: + return ReadString(); + + case BSON_TYPE_INT: + return Integer::New(ReadInt32()); + + case BSON_TYPE_NUMBER: + return Number::New(ReadDouble()); + + case BSON_TYPE_NULL: + return Null(); + + case BSON_TYPE_UNDEFINED: + return Undefined(); + + case BSON_TYPE_TIMESTAMP: + { + int32_t lowBits = ReadInt32(); + int32_t highBits = ReadInt32(); + Local argv[] = { Int32::New(lowBits), Int32::New(highBits) }; + return bson->timestampConstructor->NewInstance(2, argv); + } + + case BSON_TYPE_BOOLEAN: + return (ReadByte() != 0) ? True() : False(); + + case BSON_TYPE_REGEXP: + { + const Local& regex = ReadCString(); + int32_t options = ReadRegexOptions(); + return RegExp::New(regex, (RegExp::Flags) options); + } + + case BSON_TYPE_CODE: + { + const Local& code = ReadString(); + const Local& scope = Object::New(); + Local argv[] = { code, scope }; + return bson->codeConstructor->NewInstance(2, argv); + } + + case BSON_TYPE_CODE_W_SCOPE: + { + ReadUInt32(); + const Local& code = ReadString(); + const Handle& scope = DeserializeDocument(); + Local argv[] = { code, scope->ToObject() }; + return bson->codeConstructor->NewInstance(2, argv); + } + + case BSON_TYPE_OID: + { + Local argv[] = { ReadObjectId() }; + return bson->objectIDConstructor->NewInstance(1, argv); + } + + case BSON_TYPE_BINARY: + { + uint32_t length = ReadUInt32(); + uint32_t subType = ReadByte(); + if(subType == 0x02) { + length = ReadInt32(); + } + + Buffer* buffer = Buffer::New(p, length); + p += length; + + Handle argv[] = { buffer->handle_, Uint32::New(subType) }; + return bson->binaryConstructor->NewInstance(2, argv); + } + + case BSON_TYPE_LONG: + { + // Read 32 bit integers + int32_t lowBits = (int32_t) ReadInt32(); + int32_t highBits = (int32_t) ReadInt32(); + + // If value is < 2^53 and >-2^53 + if((highBits < 0x200000 || (highBits == 0x200000 && lowBits == 0)) && highBits >= -0x200000) { + // Adjust the pointer and read as 64 bit value + p -= 8; + // Read the 64 bit value + int64_t finalValue = (int64_t) ReadInt64(); + return Number::New(finalValue); + } + + Local argv[] = { Int32::New(lowBits), Int32::New(highBits) }; + return bson->longConstructor->NewInstance(2, argv); + } + + case BSON_TYPE_DATE: + return Date::New((double) ReadInt64()); + + case BSON_TYPE_ARRAY: + return DeserializeArray(); + + case BSON_TYPE_OBJECT: + return DeserializeDocument(); + + case BSON_TYPE_SYMBOL: + { + const Local& string = ReadString(); + Local argv[] = { string }; + return bson->symbolConstructor->NewInstance(1, argv); + } + + case BSON_TYPE_MIN_KEY: + return bson->minKeyConstructor->NewInstance(); + + case BSON_TYPE_MAX_KEY: + return bson->maxKeyConstructor->NewInstance(); + + default: + ThrowAllocatedStringException(64, "Unhandled BSON Type: %d", type); + } + + return v8::Null(); +} + + +static Handle VException(const char *msg) +{ + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +} + +Persistent BSON::constructor_template; + +BSON::BSON() : ObjectWrap() +{ + // Setup pre-allocated comparision objects + _bsontypeString = Persistent::New(String::New("_bsontype")); + _longLowString = Persistent::New(String::New("low_")); + _longHighString = Persistent::New(String::New("high_")); + _objectIDidString = Persistent::New(String::New("id")); + _binaryPositionString = Persistent::New(String::New("position")); + _binarySubTypeString = Persistent::New(String::New("sub_type")); + _binaryBufferString = Persistent::New(String::New("buffer")); + _doubleValueString = Persistent::New(String::New("value")); + _symbolValueString = Persistent::New(String::New("value")); + _dbRefRefString = Persistent::New(String::New("$ref")); + _dbRefIdRefString = Persistent::New(String::New("$id")); + _dbRefDbRefString = Persistent::New(String::New("$db")); + _dbRefNamespaceString = Persistent::New(String::New("namespace")); + _dbRefDbString = Persistent::New(String::New("db")); + _dbRefOidString = Persistent::New(String::New("oid")); + _codeCodeString = Persistent::New(String::New("code")); + _codeScopeString = Persistent::New(String::New("scope")); + _toBSONString = Persistent::New(String::New("toBSON")); + + longString = Persistent::New(String::New("Long")); + objectIDString = Persistent::New(String::New("ObjectID")); + binaryString = Persistent::New(String::New("Binary")); + codeString = Persistent::New(String::New("Code")); + dbrefString = Persistent::New(String::New("DBRef")); + symbolString = Persistent::New(String::New("Symbol")); + doubleString = Persistent::New(String::New("Double")); + timestampString = Persistent::New(String::New("Timestamp")); + minKeyString = Persistent::New(String::New("MinKey")); + maxKeyString = Persistent::New(String::New("MaxKey")); +} + +void BSON::Initialize(v8::Handle target) +{ + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("BSON")); + + // Instance methods + NODE_SET_PROTOTYPE_METHOD(constructor_template, "calculateObjectSize", CalculateObjectSize); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", BSONSerialize); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "serializeWithBufferAndIndex", SerializeWithBufferAndIndex); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "deserialize", BSONDeserialize); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "deserializeStream", BSONDeserializeStream); + + target->ForceSet(String::NewSymbol("BSON"), constructor_template->GetFunction()); +} + +// Create a new instance of BSON and passing it the existing context +Handle BSON::New(const Arguments &args) +{ + HandleScope scope; + + // Check that we have an array + if(args.Length() == 1 && args[0]->IsArray()) + { + // Cast the array to a local reference + Local array = Local::Cast(args[0]); + + if(array->Length() > 0) + { + // Create a bson object instance and return it + BSON *bson = new BSON(); + + uint32_t foundClassesMask = 0; + + // Iterate over all entries to save the instantiate funtions + for(uint32_t i = 0; i < array->Length(); i++) { + // Let's get a reference to the function + Local func = Local::Cast(array->Get(i)); + Local functionName = func->GetName()->ToString(); + + // Save the functions making them persistant handles (they don't get collected) + if(functionName->StrictEquals(bson->longString)) { + bson->longConstructor = Persistent::New(func); + foundClassesMask |= 1; + } else if(functionName->StrictEquals(bson->objectIDString)) { + bson->objectIDConstructor = Persistent::New(func); + foundClassesMask |= 2; + } else if(functionName->StrictEquals(bson->binaryString)) { + bson->binaryConstructor = Persistent::New(func); + foundClassesMask |= 4; + } else if(functionName->StrictEquals(bson->codeString)) { + bson->codeConstructor = Persistent::New(func); + foundClassesMask |= 8; + } else if(functionName->StrictEquals(bson->dbrefString)) { + bson->dbrefConstructor = Persistent::New(func); + foundClassesMask |= 0x10; + } else if(functionName->StrictEquals(bson->symbolString)) { + bson->symbolConstructor = Persistent::New(func); + foundClassesMask |= 0x20; + } else if(functionName->StrictEquals(bson->doubleString)) { + bson->doubleConstructor = Persistent::New(func); + foundClassesMask |= 0x40; + } else if(functionName->StrictEquals(bson->timestampString)) { + bson->timestampConstructor = Persistent::New(func); + foundClassesMask |= 0x80; + } else if(functionName->StrictEquals(bson->minKeyString)) { + bson->minKeyConstructor = Persistent::New(func); + foundClassesMask |= 0x100; + } else if(functionName->StrictEquals(bson->maxKeyString)) { + bson->maxKeyConstructor = Persistent::New(func); + foundClassesMask |= 0x200; + } + } + + // Check if we have the right number of constructors otherwise throw an error + if(foundClassesMask != 0x3ff) { + delete bson; + return VException("Missing function constructor for either [Long/ObjectID/Binary/Code/DbRef/Symbol/Double/Timestamp/MinKey/MaxKey]"); + } else { + bson->Wrap(args.This()); + return args.This(); + } + } + else + { + return VException("No types passed in"); + } + } + else + { + return VException("Argument passed in must be an array of types"); + } +} + +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ + +Handle BSON::BSONDeserialize(const Arguments &args) +{ + HandleScope scope; + + // Ensure that we have an parameter + if(Buffer::HasInstance(args[0]) && args.Length() > 1) return VException("One argument required - buffer1."); + if(args[0]->IsString() && args.Length() > 1) return VException("One argument required - string1."); + // Throw an exception if the argument is not of type Buffer + if(!Buffer::HasInstance(args[0]) && !args[0]->IsString()) return VException("Argument must be a Buffer or String."); + + // Define pointer to data + Local obj = args[0]->ToObject(); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + + // If we passed in a buffer, let's unpack it, otherwise let's unpack the string + if(Buffer::HasInstance(obj)) + { +#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 + Buffer *buffer = ObjectWrap::Unwrap(obj); + char* data = buffer->data(); + size_t length = buffer->length(); +#else + char* data = Buffer::Data(obj); + size_t length = Buffer::Length(obj); +#endif + + // Validate that we have at least 5 bytes + if(length < 5) return VException("corrupt bson message < 5 bytes long"); + + try + { + BSONDeserializer deserializer(bson, data, length); + return deserializer.DeserializeDocument(); + } + catch(char* exception) + { + Handle error = VException(exception); + free(exception); + return error; + } + + } + else + { + // The length of the data for this encoding + ssize_t len = DecodeBytes(args[0], BINARY); + + // Validate that we have at least 5 bytes + if(len < 5) return VException("corrupt bson message < 5 bytes long"); + + // Let's define the buffer size + char* data = (char *)malloc(len); + DecodeWrite(data, len, args[0], BINARY); + + try + { + BSONDeserializer deserializer(bson, data, len); + Handle result = deserializer.DeserializeDocument(); + free(data); + return result; + + } + catch(char* exception) + { + Handle error = VException(exception); + free(exception); + free(data); + return error; + } + } +} + +Local BSON::GetSerializeObject(const Handle& argValue) +{ + Local object = argValue->ToObject(); + if(object->Has(_toBSONString)) + { + const Local& toBSON = object->Get(_toBSONString); + if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function"); + + Local result = Local::Cast(toBSON)->Call(object, 0, NULL); + if(!result->IsObject()) ThrowAllocatedStringException(64, "toBSON function did not return an object"); + return result->ToObject(); + } + else + { + return object; + } +} + +Handle BSON::BSONSerialize(const Arguments &args) +{ + HandleScope scope; + + if(args.Length() == 1 && !args[0]->IsObject()) return VException("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); + if(args.Length() == 2 && !args[0]->IsObject() && !args[1]->IsBoolean()) return VException("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); + if(args.Length() == 3 && !args[0]->IsObject() && !args[1]->IsBoolean() && !args[2]->IsBoolean()) return VException("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); + if(args.Length() == 4 && !args[0]->IsObject() && !args[1]->IsBoolean() && !args[2]->IsBoolean() && !args[3]->IsBoolean()) return VException("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]"); + if(args.Length() > 4) return VException("One, two, tree or four arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]"); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + + // Calculate the total size of the document in binary form to ensure we only allocate memory once + // With serialize function + bool serializeFunctions = (args.Length() >= 4) && args[3]->BooleanValue(); + + char *serialized_object = NULL; + size_t object_size; + try + { + Local object = bson->GetSerializeObject(args[0]); + + BSONSerializer counter(bson, false, serializeFunctions); + counter.SerializeDocument(object); + object_size = counter.GetSerializeSize(); + + // Allocate the memory needed for the serialization + serialized_object = (char *)malloc(object_size); + + // Check if we have a boolean value + bool checkKeys = args.Length() >= 3 && args[1]->IsBoolean() && args[1]->BooleanValue(); + BSONSerializer data(bson, checkKeys, serializeFunctions, serialized_object); + data.SerializeDocument(object); + } + catch(char *err_msg) + { + free(serialized_object); + Handle error = VException(err_msg); + free(err_msg); + return error; + } + + // If we have 3 arguments + if(args.Length() == 3 || args.Length() == 4) + { + Buffer *buffer = Buffer::New(serialized_object, object_size); + free(serialized_object); + return scope.Close(buffer->handle_); + } + else + { + Local bin_value = Encode(serialized_object, object_size, BINARY)->ToString(); + free(serialized_object); + return bin_value; + } +} + +Handle BSON::CalculateObjectSize(const Arguments &args) +{ + HandleScope scope; + // Ensure we have a valid object + if(args.Length() == 1 && !args[0]->IsObject()) return VException("One argument required - [object]"); + if(args.Length() == 2 && !args[0]->IsObject() && !args[1]->IsBoolean()) return VException("Two arguments required - [object, boolean]"); + if(args.Length() > 3) return VException("One or two arguments required - [object] or [object, boolean]"); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + bool serializeFunctions = (args.Length() >= 2) && args[1]->BooleanValue(); + BSONSerializer countSerializer(bson, false, serializeFunctions); + countSerializer.SerializeDocument(args[0]); + + // Return the object size + return scope.Close(Uint32::New((uint32_t) countSerializer.GetSerializeSize())); +} + +Handle BSON::SerializeWithBufferAndIndex(const Arguments &args) +{ + HandleScope scope; + + //BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, ->, buffer, index) { + // Ensure we have the correct values + if(args.Length() > 5) return VException("Four or five parameters required [object, boolean, Buffer, int] or [object, boolean, Buffer, int, boolean]"); + if(args.Length() == 4 && !args[0]->IsObject() && !args[1]->IsBoolean() && !Buffer::HasInstance(args[2]) && !args[3]->IsUint32()) return VException("Four parameters required [object, boolean, Buffer, int]"); + if(args.Length() == 5 && !args[0]->IsObject() && !args[1]->IsBoolean() && !Buffer::HasInstance(args[2]) && !args[3]->IsUint32() && !args[4]->IsBoolean()) return VException("Four parameters required [object, boolean, Buffer, int, boolean]"); + + uint32_t index; + size_t object_size; + + try + { + BSON *bson = ObjectWrap::Unwrap(args.This()); + + Local obj = args[2]->ToObject(); + char* data = Buffer::Data(obj); + size_t length = Buffer::Length(obj); + + index = args[3]->Uint32Value(); + bool checkKeys = args.Length() >= 4 && args[1]->IsBoolean() && args[1]->BooleanValue(); + bool serializeFunctions = (args.Length() == 5) && args[4]->BooleanValue(); + + BSONSerializer dataSerializer(bson, checkKeys, serializeFunctions, data+index); + dataSerializer.SerializeDocument(bson->GetSerializeObject(args[0])); + object_size = dataSerializer.GetSerializeSize(); + + if(object_size + index > length) return VException("Serious error - overflowed buffer!!"); + } + catch(char *exception) + { + Handle error = VException(exception); + free(exception); + return error; + } + + return scope.Close(Uint32::New((uint32_t) (index + object_size - 1))); +} + +Handle BSON::BSONDeserializeStream(const Arguments &args) +{ + HandleScope scope; + + // At least 3 arguments required + if(args.Length() < 5) return VException("Arguments required (Buffer(data), Number(index in data), Number(number of documents to deserialize), Array(results), Number(index in the array), Object(optional))"); + + // If the number of argumets equals 3 + if(args.Length() >= 5) + { + if(!Buffer::HasInstance(args[0])) return VException("First argument must be Buffer instance"); + if(!args[1]->IsUint32()) return VException("Second argument must be a positive index number"); + if(!args[2]->IsUint32()) return VException("Third argument must be a positive number of documents to deserialize"); + if(!args[3]->IsArray()) return VException("Fourth argument must be an array the size of documents to deserialize"); + if(!args[4]->IsUint32()) return VException("Sixth argument must be a positive index number"); + } + + // If we have 4 arguments + if(args.Length() == 6 && !args[5]->IsObject()) return VException("Fifth argument must be an object with options"); + + // Define pointer to data + Local obj = args[0]->ToObject(); + uint32_t numberOfDocuments = args[2]->Uint32Value(); + uint32_t index = args[1]->Uint32Value(); + uint32_t resultIndex = args[4]->Uint32Value(); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + + // Unpack the buffer variable +#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 + Buffer *buffer = ObjectWrap::Unwrap(obj); + char* data = buffer->data(); + size_t length = buffer->length(); +#else + char* data = Buffer::Data(obj); + size_t length = Buffer::Length(obj); +#endif + + // Fetch the documents + Local documents = args[3]->ToObject(); + + BSONDeserializer deserializer(bson, data+index, length-index); + for(uint32_t i = 0; i < numberOfDocuments; i++) + { + try + { + documents->Set(i + resultIndex, deserializer.DeserializeDocument()); + } + catch (char* exception) + { + Handle error = VException(exception); + free(exception); + return error; + } + } + + // Return new index of parsing + return scope.Close(Uint32::New((uint32_t) (index + deserializer.GetSerializeSize()))); +} + +// Exporting function +extern "C" void init(Handle target) +{ + HandleScope scope; + BSON::Initialize(target); +} + +NODE_MODULE(bson, BSON::Initialize); diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.h b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.h new file mode 100644 index 0000000..b0fac94 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.h @@ -0,0 +1,277 @@ +//=========================================================================== + +#ifndef BSON_H_ +#define BSON_H_ + +//=========================================================================== + +#ifdef __arm__ +#define USE_MISALIGNED_MEMORY_ACCESS 0 +#else +#define USE_MISALIGNED_MEMORY_ACCESS 1 +#endif + +#include +#include +#include + +using namespace v8; +using namespace node; + +//=========================================================================== + +enum BsonType +{ + BSON_TYPE_NUMBER = 1, + BSON_TYPE_STRING = 2, + BSON_TYPE_OBJECT = 3, + BSON_TYPE_ARRAY = 4, + BSON_TYPE_BINARY = 5, + BSON_TYPE_UNDEFINED = 6, + BSON_TYPE_OID = 7, + BSON_TYPE_BOOLEAN = 8, + BSON_TYPE_DATE = 9, + BSON_TYPE_NULL = 10, + BSON_TYPE_REGEXP = 11, + BSON_TYPE_CODE = 13, + BSON_TYPE_SYMBOL = 14, + BSON_TYPE_CODE_W_SCOPE = 15, + BSON_TYPE_INT = 16, + BSON_TYPE_TIMESTAMP = 17, + BSON_TYPE_LONG = 18, + BSON_TYPE_MAX_KEY = 0x7f, + BSON_TYPE_MIN_KEY = 0xff +}; + +//=========================================================================== + +template class BSONSerializer; + +class BSON : public ObjectWrap { +public: + BSON(); + ~BSON() {} + + static void Initialize(Handle target); + static Handle BSONDeserializeStream(const Arguments &args); + + // JS based objects + static Handle BSONSerialize(const Arguments &args); + static Handle BSONDeserialize(const Arguments &args); + + // Calculate size of function + static Handle CalculateObjectSize(const Arguments &args); + static Handle SerializeWithBufferAndIndex(const Arguments &args); + + // Constructor used for creating new BSON objects from C++ + static Persistent constructor_template; + +private: + static Handle New(const Arguments &args); + static Handle deserialize(BSON *bson, char *data, uint32_t dataLength, uint32_t startIndex, bool is_array_item); + + // BSON type instantiate functions + Persistent longConstructor; + Persistent objectIDConstructor; + Persistent binaryConstructor; + Persistent codeConstructor; + Persistent dbrefConstructor; + Persistent symbolConstructor; + Persistent doubleConstructor; + Persistent timestampConstructor; + Persistent minKeyConstructor; + Persistent maxKeyConstructor; + + // Equality Objects + Persistent longString; + Persistent objectIDString; + Persistent binaryString; + Persistent codeString; + Persistent dbrefString; + Persistent symbolString; + Persistent doubleString; + Persistent timestampString; + Persistent minKeyString; + Persistent maxKeyString; + + // Equality speed up comparison objects + Persistent _bsontypeString; + Persistent _longLowString; + Persistent _longHighString; + Persistent _objectIDidString; + Persistent _binaryPositionString; + Persistent _binarySubTypeString; + Persistent _binaryBufferString; + Persistent _doubleValueString; + Persistent _symbolValueString; + + Persistent _dbRefRefString; + Persistent _dbRefIdRefString; + Persistent _dbRefDbRefString; + Persistent _dbRefNamespaceString; + Persistent _dbRefDbString; + Persistent _dbRefOidString; + + Persistent _codeCodeString; + Persistent _codeScopeString; + Persistent _toBSONString; + + Local GetSerializeObject(const Handle& object); + + template friend class BSONSerializer; + friend class BSONDeserializer; +}; + +//=========================================================================== + +class CountStream +{ +public: + CountStream() : count(0) { } + + void WriteByte(int value) { ++count; } + void WriteByte(const Handle&, const Handle&) { ++count; } + void WriteBool(const Handle& value) { ++count; } + void WriteInt32(int32_t value) { count += 4; } + void WriteInt32(const Handle& value) { count += 4; } + void WriteInt32(const Handle& object, const Handle& key) { count += 4; } + void WriteInt64(int64_t value) { count += 8; } + void WriteInt64(const Handle& value) { count += 8; } + void WriteDouble(double value) { count += 8; } + void WriteDouble(const Handle& value) { count += 8; } + void WriteDouble(const Handle&, const Handle&) { count += 8; } + void WriteUInt32String(uint32_t name) { char buffer[32]; count += sprintf(buffer, "%u", name) + 1; } + void WriteLengthPrefixedString(const Local& value) { count += value->Utf8Length()+5; } + void WriteObjectId(const Handle& object, const Handle& key) { count += 12; } + void WriteString(const Local& value) { count += value->Utf8Length() + 1; } // This returns the number of bytes exclusive of the NULL terminator + void WriteData(const char* data, size_t length) { count += length; } + + void* BeginWriteType() { ++count; return NULL; } + void CommitType(void*, BsonType) { } + void* BeginWriteSize() { count += 4; return NULL; } + void CommitSize(void*) { } + + size_t GetSerializeSize() const { return count; } + + // Do nothing. CheckKey is implemented for DataStream + void CheckKey(const Local&) { } + +private: + size_t count; +}; + +class DataStream +{ +public: + DataStream(char* aDestinationBuffer) : destinationBuffer(aDestinationBuffer), p(aDestinationBuffer) { } + + void WriteByte(int value) { *p++ = value; } + void WriteByte(const Handle& object, const Handle& key) { *p++ = object->Get(key)->Int32Value(); } +#if USE_MISALIGNED_MEMORY_ACCESS + void WriteInt32(int32_t value) { *reinterpret_cast(p) = value; p += 4; } + void WriteInt64(int64_t value) { *reinterpret_cast(p) = value; p += 8; } + void WriteDouble(double value) { *reinterpret_cast(p) = value; p += 8; } +#else + void WriteInt32(int32_t value) { memcpy(p, &value, 4); p += 4; } + void WriteInt64(int64_t value) { memcpy(p, &value, 8); p += 8; } + void WriteDouble(double value) { memcpy(p, &value, 8); p += 8; } +#endif + void WriteBool(const Handle& value) { WriteByte(value->BooleanValue() ? 1 : 0); } + void WriteInt32(const Handle& value) { WriteInt32(value->Int32Value()); } + void WriteInt32(const Handle& object, const Handle& key) { WriteInt32(object->Get(key)); } + void WriteInt64(const Handle& value) { WriteInt64(value->IntegerValue()); } + void WriteDouble(const Handle& value) { WriteDouble(value->NumberValue()); } + void WriteDouble(const Handle& object, const Handle& key) { WriteDouble(object->Get(key)); } + void WriteUInt32String(uint32_t name) { p += sprintf(p, "%u", name) + 1; } + void WriteLengthPrefixedString(const Local& value) { WriteInt32(value->Utf8Length()+1); WriteString(value); } + void WriteObjectId(const Handle& object, const Handle& key); + void WriteString(const Local& value) { p += value->WriteUtf8(p); } // This returns the number of bytes inclusive of the NULL terminator. + void WriteData(const char* data, size_t length) { memcpy(p, data, length); p += length; } + + void* BeginWriteType() { void* returnValue = p; p++; return returnValue; } + void CommitType(void* beginPoint, BsonType value) { *reinterpret_cast(beginPoint) = value; } + void* BeginWriteSize() { void* returnValue = p; p += 4; return returnValue; } + +#if USE_MISALIGNED_MEMORY_ACCESS + void CommitSize(void* beginPoint) { *reinterpret_cast(beginPoint) = (int32_t) (p - (char*) beginPoint); } +#else + void CommitSize(void* beginPoint) { int32_t value = (int32_t) (p - (char*) beginPoint); memcpy(beginPoint, &value, 4); } +#endif + + size_t GetSerializeSize() const { return p - destinationBuffer; } + + void CheckKey(const Local& keyName); + +protected: + char *const destinationBuffer; // base, never changes + char* p; // cursor into buffer +}; + +template class BSONSerializer : public T +{ +private: + typedef T Inherited; + +public: + BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions) : Inherited(), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { } + BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions, char* parentParam) : Inherited(parentParam), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { } + + void SerializeDocument(const Handle& value); + void SerializeArray(const Handle& value); + void SerializeValue(void* typeLocation, const Handle& value); + +private: + bool checkKeys; + bool serializeFunctions; + BSON* bson; +}; + +//=========================================================================== + +class BSONDeserializer +{ +public: + BSONDeserializer(BSON* aBson, char* data, size_t length); + BSONDeserializer(BSONDeserializer& parentSerializer, size_t length); + + Handle DeserializeDocument(); + + bool HasMoreData() const { return p < pEnd; } + Local ReadCString(); + uint32_t ReadIntegerString(); + int32_t ReadRegexOptions(); + Local ReadString(); + Local ReadObjectId(); + + unsigned char ReadByte() { return *reinterpret_cast(p++); } +#if USE_MISALIGNED_MEMORY_ACCESS + int32_t ReadInt32() { int32_t returnValue = *reinterpret_cast(p); p += 4; return returnValue; } + uint32_t ReadUInt32() { uint32_t returnValue = *reinterpret_cast(p); p += 4; return returnValue; } + int64_t ReadInt64() { int64_t returnValue = *reinterpret_cast(p); p += 8; return returnValue; } + double ReadDouble() { double returnValue = *reinterpret_cast(p); p += 8; return returnValue; } +#else + int32_t ReadInt32() { int32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; } + uint32_t ReadUInt32() { uint32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; } + int64_t ReadInt64() { int64_t returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; } + double ReadDouble() { double returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; } +#endif + + size_t GetSerializeSize() const { return p - pStart; } + +private: + Handle DeserializeArray(); + Handle DeserializeValue(BsonType type); + Handle DeserializeDocumentInternal(); + Handle DeserializeArrayInternal(); + + BSON* bson; + char* const pStart; + char* p; + char* const pEnd; +}; + +//=========================================================================== + +#endif // BSON_H_ + +//=========================================================================== diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/index.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/index.js new file mode 100644 index 0000000..85e243c --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/index.js @@ -0,0 +1,30 @@ +var bson = null; + +// Load the precompiled win32 binary +if(process.platform == "win32" && process.arch == "x64") { + bson = require('./win32/x64/bson'); +} else if(process.platform == "win32" && process.arch == "ia32") { + bson = require('./win32/ia32/bson'); +} else { + bson = require('../build/Release/bson'); +} + +exports.BSON = bson.BSON; +exports.Long = require('../lib/bson/long').Long; +exports.ObjectID = require('../lib/bson/objectid').ObjectID; +exports.DBRef = require('../lib/bson/db_ref').DBRef; +exports.Code = require('../lib/bson/code').Code; +exports.Timestamp = require('../lib/bson/timestamp').Timestamp; +exports.Binary = require('../lib/bson/binary').Binary; +exports.Double = require('../lib/bson/double').Double; +exports.MaxKey = require('../lib/bson/max_key').MaxKey; +exports.MinKey = require('../lib/bson/min_key').MinKey; +exports.Symbol = require('../lib/bson/symbol').Symbol; + +// Just add constants tot he Native BSON parser +exports.BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +exports.BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +exports.BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +exports.BSON.BSON_BINARY_SUBTYPE_UUID = 3; +exports.BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +exports.BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node new file mode 100644 index 0000000000000000000000000000000000000000..b27819bb1a8a4fb1bda843df4d87dd0753137603 GIT binary patch literal 113152 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 literal 0 HcmV?d00001 diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/win32/x64/bson.node b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/win32/x64/bson.node new file mode 100644 index 0000000000000000000000000000000000000000..a544c8ed6385a61b494425288425714221fc77f4 GIT binary patch literal 118272 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Ò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 A$p8QV literal 0 HcmV?d00001 diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/wscript b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/wscript new file mode 100644 index 0000000..40f5317 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/wscript @@ -0,0 +1,39 @@ +import Options +from os import unlink, symlink, popen +from os.path import exists + +srcdir = "." +blddir = "build" +VERSION = "0.1.0" + +def set_options(opt): + opt.tool_options("compiler_cxx") + opt.add_option( '--debug' + , action='store_true' + , default=False + , help='Build debug variant [Default: False]' + , dest='debug' + ) + +def configure(conf): + conf.check_tool("compiler_cxx") + conf.check_tool("node_addon") + conf.env.append_value('CXXFLAGS', ['-O3', '-funroll-loops']) + + # conf.env.append_value('CXXFLAGS', ['-DDEBUG', '-g', '-O0', '-Wall', '-Wextra']) + # conf.check(lib='node', libpath=['/usr/lib', '/usr/local/lib'], uselib_store='NODE') + +def build(bld): + obj = bld.new_task_gen("cxx", "shlib", "node_addon") + obj.target = "bson" + obj.source = ["bson.cc"] + # obj.uselib = "NODE" + +def shutdown(): + # HACK to get compress.node out of build directory. + # better way to do this? + if Options.commands['clean']: + if exists('bson.node'): unlink('bson.node') + else: + if exists('build/default/bson.node') and not exists('bson.node'): + symlink('build/default/bson.node', 'bson.node') diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary.js new file mode 100644 index 0000000..82d4d04 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary.js @@ -0,0 +1,339 @@ +/** + * Module dependencies. + */ +if(typeof window === 'undefined') { + var Buffer = require('buffer').Buffer; // TODO just use global Buffer +} + +// Binary default subtype +var BSON_BINARY_SUBTYPE_DEFAULT = 0; + +/** + * @ignore + * @api private + */ +var writeStringToArray = function(data) { + // Create a buffer + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length); + // Write the content to the buffer + for(var i = 0; i < data.length; i++) { + buffer[i] = data.charCodeAt(i); + } + // Write the string to the buffer + return buffer; +} + +/** + * Convert Array ot Uint8Array to Binary String + * + * @ignore + * @api private + */ +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + return result; +}; + +/** + * A class representation of the BSON Binary type. + * + * Sub types + * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type. + * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type. + * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type. + * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type. + * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type. + * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type. + * + * @class Represents the Binary BSON type. + * @param {Buffer} buffer a buffer object containing the binary data. + * @param {Number} [subType] the option binary type. + * @return {Grid} + */ +function Binary(buffer, subType) { + if(!(this instanceof Binary)) return new Binary(buffer, subType); + + this._bsontype = 'Binary'; + + if(buffer instanceof Number) { + this.sub_type = buffer; + this.position = 0; + } else { + this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType; + this.position = 0; + } + + if(buffer != null && !(buffer instanceof Number)) { + // Only accept Buffer, Uint8Array or Arrays + if(typeof buffer == 'string') { + // Different ways of writing the length of the string for the different types + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(buffer); + } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) { + this.buffer = writeStringToArray(buffer); + } else { + throw new Error("only String, Buffer, Uint8Array or Array accepted"); + } + } else { + this.buffer = buffer; + } + this.position = buffer.length; + } else { + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(Binary.BUFFER_SIZE); + } else if(typeof Uint8Array != 'undefined'){ + this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE)); + } else { + this.buffer = new Array(Binary.BUFFER_SIZE); + } + // Set position to start of buffer + this.position = 0; + } +}; + +/** + * Updates this binary with byte_value. + * + * @param {Character} byte_value a single byte we wish to write. + * @api public + */ +Binary.prototype.put = function put(byte_value) { + // If it's a string and a has more than one character throw an error + if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array"); + if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); + + // Decode the byte value once + var decoded_byte = null; + if(typeof byte_value == 'string') { + decoded_byte = byte_value.charCodeAt(0); + } else if(byte_value['length'] != null) { + decoded_byte = byte_value[0]; + } else { + decoded_byte = byte_value; + } + + if(this.buffer.length > this.position) { + this.buffer[this.position++] = decoded_byte; + } else { + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + // Create additional overflow buffer + var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); + // Combine the two buffers together + this.buffer.copy(buffer, 0, 0, this.buffer.length); + this.buffer = buffer; + this.buffer[this.position++] = decoded_byte; + } else { + var buffer = null; + // Create a new buffer (typed or normal array) + if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); + } else { + buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); + } + + // We need to copy all the content to the new array + for(var i = 0; i < this.buffer.length; i++) { + buffer[i] = this.buffer[i]; + } + + // Reassign the buffer + this.buffer = buffer; + // Write the byte + this.buffer[this.position++] = decoded_byte; + } + } +}; + +/** + * Writes a buffer or string to the binary. + * + * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. + * @param {Number} offset specify the binary of where to write the content. + * @api public + */ +Binary.prototype.write = function write(string, offset) { + offset = typeof offset == 'number' ? offset : this.position; + + // If the buffer is to small let's extend the buffer + if(this.buffer.length < offset + string.length) { + var buffer = null; + // If we are in node.js + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + buffer = new Buffer(this.buffer.length + string.length); + this.buffer.copy(buffer, 0, 0, this.buffer.length); + } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + // Create a new buffer + buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) + // Copy the content + for(var i = 0; i < this.position; i++) { + buffer[i] = this.buffer[i]; + } + } + + // Assign the new buffer + this.buffer = buffer; + } + + if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { + string.copy(this.buffer, offset, 0, string.length); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length + } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { + this.buffer.write(string, 'binary', offset); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length; + } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' + || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string[i]; + } + + this.position = offset > this.position ? offset : this.position; + } else if(typeof string == 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string.charCodeAt(i); + } + + this.position = offset > this.position ? offset : this.position; + } +}; + +/** + * Reads **length** bytes starting at **position**. + * + * @param {Number} position read from the given position in the Binary. + * @param {Number} length the number of bytes to read. + * @return {Buffer} + * @api public + */ +Binary.prototype.read = function read(position, length) { + length = length && length > 0 + ? length + : this.position; + + // Let's return the data based on the type we have + if(this.buffer['slice']) { + return this.buffer.slice(position, position + length); + } else { + // Create a buffer to keep the result + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); + for(var i = 0; i < length; i++) { + buffer[i] = this.buffer[position++]; + } + } + // Return the buffer + return buffer; +}; + +/** + * Returns the value of this binary as a string. + * + * @return {String} + * @api public + */ +Binary.prototype.value = function value(asRaw) { + asRaw = asRaw == null ? false : asRaw; + + // If it's a node.js buffer object + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); + } else { + if(asRaw) { + // we support the slice command use it + if(this.buffer['slice'] != null) { + return this.buffer.slice(0, this.position); + } else { + // Create a new buffer to copy content to + var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); + // Copy content + for(var i = 0; i < this.position; i++) { + newBuffer[i] = this.buffer[i]; + } + // Return the buffer + return newBuffer; + } + } else { + return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); + } + } +}; + +/** + * Length. + * + * @return {Number} the length of the binary. + * @api public + */ +Binary.prototype.length = function length() { + return this.position; +}; + +/** + * @ignore + * @api private + */ +Binary.prototype.toJSON = function() { + return this.buffer != null ? this.buffer.toString('base64') : ''; +} + +/** + * @ignore + * @api private + */ +Binary.prototype.toString = function(format) { + return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; +} + +Binary.BUFFER_SIZE = 256; + +/** + * Default BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_DEFAULT = 0; +/** + * Function BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_FUNCTION = 1; +/** + * Byte Array BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_BYTE_ARRAY = 2; +/** + * OLD UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID_OLD = 3; +/** + * UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID = 4; +/** + * MD5 BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_MD5 = 5; +/** + * User BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_USER_DEFINED = 128; + +/** + * Expose. + */ +exports.Binary = Binary; + diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js new file mode 100644 index 0000000..d2fc811 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js @@ -0,0 +1,385 @@ +/** + * Binary Parser. + * Jonas Raoni Soares Silva + * http://jsfromhell.com/classes/binary-parser [v1.0] + */ +var chr = String.fromCharCode; + +var maxBits = []; +for (var i = 0; i < 64; i++) { + maxBits[i] = Math.pow(2, i); +} + +function BinaryParser (bigEndian, allowExceptions) { + if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions); + + this.bigEndian = bigEndian; + this.allowExceptions = allowExceptions; +}; + +BinaryParser.warn = function warn (msg) { + if (this.allowExceptions) { + throw new Error(msg); + } + + return 1; +}; + +BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { + var b = new this.Buffer(this.bigEndian, data); + + b.checkBuffer(precisionBits + exponentBits + 1); + + var bias = maxBits[exponentBits - 1] - 1 + , signal = b.readBits(precisionBits + exponentBits, 1) + , exponent = b.readBits(precisionBits, exponentBits) + , significand = 0 + , divisor = 2 + , curByte = b.buffer.length + (-precisionBits >> 3) - 1; + + do { + for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); + } while (precisionBits -= startBit); + + return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); +}; + +BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { + var b = new this.Buffer(this.bigEndian || forceBigEndian, data) + , x = b.readBits(0, bits) + , max = maxBits[bits]; //max = Math.pow( 2, bits ); + + return signed && x >= max / 2 + ? x - max + : x; +}; + +BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { + var bias = maxBits[exponentBits - 1] - 1 + , minExp = -bias + 1 + , maxExp = bias + , minUnnormExp = minExp - precisionBits + , n = parseFloat(data) + , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 + , exp = 0 + , len = 2 * bias + 1 + precisionBits + 3 + , bin = new Array(len) + , signal = (n = status !== 0 ? 0 : n) < 0 + , intPart = Math.floor(n = Math.abs(n)) + , floatPart = n - intPart + , lastBit + , rounded + , result + , i + , j; + + for (i = len; i; bin[--i] = 0); + + for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); + + for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); + + for (i = -1; ++i < len && !bin[i];); + + if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); + } + + for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); + } + + for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); + + if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { + ++i; + } else if (exp < minExp) { + exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); + i = bias + 1 - (exp = minExp - 1); + } + + if (intPart || status !== 0) { + this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); + exp = maxExp + 1; + i = bias + 2; + + if (status == -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[i] = 1; + } + } + + for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); + + for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { + n += (1 << j) * result.charAt(--i); + if (j == 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + } + + r[r.length] = n + ? String.fromCharCode(n) + : ""; + + return (this.bigEndian ? r.reverse() : r).join(""); +}; + +BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { + var max = maxBits[bits]; + + if (data >= max || data < -(max / 2)) { + this.warn("encodeInt::overflow"); + data = 0; + } + + if (data < 0) { + data += max; + } + + for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); + + for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); + + return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); +}; + +BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; +BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; +BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; +BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; +BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; +BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; +BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; +BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; +BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; +BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; +BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; +BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; +BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; +BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; +BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; +BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; + +// Factor out the encode so it can be shared by add_header and push_int32 +BinaryParser.encode_int32 = function encode_int32 (number, asArray) { + var a, b, c, d, unsigned; + unsigned = (number < 0) ? (number + 0x100000000) : number; + a = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + b = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + c = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + d = Math.floor(unsigned); + return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); +}; + +BinaryParser.encode_int64 = function encode_int64 (number) { + var a, b, c, d, e, f, g, h, unsigned; + unsigned = (number < 0) ? (number + 0x10000000000000000) : number; + a = Math.floor(unsigned / 0xffffffffffffff); + unsigned &= 0xffffffffffffff; + b = Math.floor(unsigned / 0xffffffffffff); + unsigned &= 0xffffffffffff; + c = Math.floor(unsigned / 0xffffffffff); + unsigned &= 0xffffffffff; + d = Math.floor(unsigned / 0xffffffff); + unsigned &= 0xffffffff; + e = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + f = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + g = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + h = Math.floor(unsigned); + return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); +}; + +/** + * UTF8 methods + */ + +// Take a raw binary string and return a utf8 string +BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { + var len = binaryStr.length + , decoded = '' + , i = 0 + , c = 0 + , c1 = 0 + , c2 = 0 + , c3; + + while (i < len) { + c = binaryStr.charCodeAt(i); + if (c < 128) { + decoded += String.fromCharCode(c); + i++; + } else if ((c > 191) && (c < 224)) { + c2 = binaryStr.charCodeAt(i+1); + decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = binaryStr.charCodeAt(i+1); + c3 = binaryStr.charCodeAt(i+2); + decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return decoded; +}; + +// Encode a cstring +BinaryParser.encode_cstring = function encode_cstring (s) { + return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); +}; + +// Take a utf8 string and return a binary string +BinaryParser.encode_utf8 = function encode_utf8 (s) { + var a = "" + , c; + + for (var n = 0, len = s.length; n < len; n++) { + c = s.charCodeAt(n); + + if (c < 128) { + a += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + a += String.fromCharCode((c>>6) | 192) ; + a += String.fromCharCode((c&63) | 128); + } else { + a += String.fromCharCode((c>>12) | 224); + a += String.fromCharCode(((c>>6) & 63) | 128); + a += String.fromCharCode((c&63) | 128); + } + } + + return a; +}; + +BinaryParser.hprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } + } + + process.stdout.write("\n\n"); +}; + +BinaryParser.ilprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +BinaryParser.hlprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +/** + * BinaryParser buffer constructor. + */ +function BinaryParserBuffer (bigEndian, buffer) { + this.bigEndian = bigEndian || 0; + this.buffer = []; + this.setBuffer(buffer); +}; + +BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { + var l, i, b; + + if (data) { + i = l = data.length; + b = this.buffer = new Array(l); + for (; i; b[l - i] = data.charCodeAt(--i)); + this.bigEndian && b.reverse(); + } +}; + +BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { + return this.buffer.length >= -(-neededBits >> 3); +}; + +BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { + if (!this.hasNeededBits(neededBits)) { + throw new Error("checkBuffer::missing bytes"); + } +}; + +BinaryParserBuffer.prototype.readBits = function readBits (start, length) { + //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) + + function shl (a, b) { + for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); + return a; + } + + if (start < 0 || length <= 0) { + return 0; + } + + this.checkBuffer(start + length); + + var offsetLeft + , offsetRight = start % 8 + , curByte = this.buffer.length - ( start >> 3 ) - 1 + , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) + , diff = curByte - lastByte + , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); + + for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); + + return sum; +}; + +/** + * Expose. + */ +BinaryParser.Buffer = BinaryParserBuffer; + +exports.BinaryParser = BinaryParser; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/bson.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/bson.js new file mode 100644 index 0000000..7da8249 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/bson.js @@ -0,0 +1,1519 @@ +var Long = require('./long').Long + , Double = require('./double').Double + , Timestamp = require('./timestamp').Timestamp + , ObjectID = require('./objectid').ObjectID + , Symbol = require('./symbol').Symbol + , Code = require('./code').Code + , MinKey = require('./min_key').MinKey + , MaxKey = require('./max_key').MaxKey + , DBRef = require('./db_ref').DBRef + , Binary = require('./binary').Binary + , BinaryParser = require('./binary_parser').BinaryParser + , writeIEEE754 = require('./float_parser').writeIEEE754 + , readIEEE754 = require('./float_parser').readIEEE754 + +// To ensure that 0.4 of node works correctly +var isDate = function isDate(d) { + return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; +} + +/** + * Create a new BSON instance + * + * @class Represents the BSON Parser + * @return {BSON} instance of BSON Parser. + */ +function BSON () {}; + +/** + * @ignore + * @api private + */ +// BSON MAX VALUES +BSON.BSON_INT32_MAX = 0x7FFFFFFF; +BSON.BSON_INT32_MIN = -0x80000000; + +BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; +BSON.BSON_INT64_MIN = -Math.pow(2, 63); + +// JS MAX PRECISE VALUES +BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. +BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. + +// Internal long versions +var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. +var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. + +/** + * Number BSON Type + * + * @classconstant BSON_DATA_NUMBER + **/ +BSON.BSON_DATA_NUMBER = 1; +/** + * String BSON Type + * + * @classconstant BSON_DATA_STRING + **/ +BSON.BSON_DATA_STRING = 2; +/** + * Object BSON Type + * + * @classconstant BSON_DATA_OBJECT + **/ +BSON.BSON_DATA_OBJECT = 3; +/** + * Array BSON Type + * + * @classconstant BSON_DATA_ARRAY + **/ +BSON.BSON_DATA_ARRAY = 4; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_BINARY + **/ +BSON.BSON_DATA_BINARY = 5; +/** + * ObjectID BSON Type + * + * @classconstant BSON_DATA_OID + **/ +BSON.BSON_DATA_OID = 7; +/** + * Boolean BSON Type + * + * @classconstant BSON_DATA_BOOLEAN + **/ +BSON.BSON_DATA_BOOLEAN = 8; +/** + * Date BSON Type + * + * @classconstant BSON_DATA_DATE + **/ +BSON.BSON_DATA_DATE = 9; +/** + * null BSON Type + * + * @classconstant BSON_DATA_NULL + **/ +BSON.BSON_DATA_NULL = 10; +/** + * RegExp BSON Type + * + * @classconstant BSON_DATA_REGEXP + **/ +BSON.BSON_DATA_REGEXP = 11; +/** + * Code BSON Type + * + * @classconstant BSON_DATA_CODE + **/ +BSON.BSON_DATA_CODE = 13; +/** + * Symbol BSON Type + * + * @classconstant BSON_DATA_SYMBOL + **/ +BSON.BSON_DATA_SYMBOL = 14; +/** + * Code with Scope BSON Type + * + * @classconstant BSON_DATA_CODE_W_SCOPE + **/ +BSON.BSON_DATA_CODE_W_SCOPE = 15; +/** + * 32 bit Integer BSON Type + * + * @classconstant BSON_DATA_INT + **/ +BSON.BSON_DATA_INT = 16; +/** + * Timestamp BSON Type + * + * @classconstant BSON_DATA_TIMESTAMP + **/ +BSON.BSON_DATA_TIMESTAMP = 17; +/** + * Long BSON Type + * + * @classconstant BSON_DATA_LONG + **/ +BSON.BSON_DATA_LONG = 18; +/** + * MinKey BSON Type + * + * @classconstant BSON_DATA_MIN_KEY + **/ +BSON.BSON_DATA_MIN_KEY = 0xff; +/** + * MaxKey BSON Type + * + * @classconstant BSON_DATA_MAX_KEY + **/ +BSON.BSON_DATA_MAX_KEY = 0x7f; + +/** + * Binary Default Type + * + * @classconstant BSON_BINARY_SUBTYPE_DEFAULT + **/ +BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +/** + * Binary Function Type + * + * @classconstant BSON_BINARY_SUBTYPE_FUNCTION + **/ +BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +/** + * Binary Byte Array Type + * + * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY + **/ +BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +/** + * Binary UUID Type + * + * @classconstant BSON_BINARY_SUBTYPE_UUID + **/ +BSON.BSON_BINARY_SUBTYPE_UUID = 3; +/** + * Binary MD5 Type + * + * @classconstant BSON_BINARY_SUBTYPE_MD5 + **/ +BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +/** + * Binary User Defined Type + * + * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED + **/ +BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { + var totalLength = (4 + 1); + + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + totalLength += calculateElement(i.toString(), object[i], serializeFunctions) + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Calculate size + for(var key in object) { + totalLength += calculateElement(key, object[key], serializeFunctions) + } + } + + return totalLength; +} + +/** + * @ignore + * @api private + */ +function calculateElement(name, value, serializeFunctions) { + var isBuffer = typeof Buffer !== 'undefined'; + + switch(typeof value) { + case 'string': + return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1; + case 'number': + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + } else { // 64 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + case 'undefined': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + case 'boolean': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1); + case 'object': + if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1); + } else if(value instanceof Date || isDate(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length; + } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp + || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + // Calculate size depending on the availability of a scope + if(value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Check what kind of subtype we have + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1); + } + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1); + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else if(serializeFunctions) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1; + } + } + } + + return 0; +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { + // Default setting false + serializeFunctions = serializeFunctions == null ? false : serializeFunctions; + // Write end information (length of the object) + var size = buffer.length; + // Write the size of the object + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; +} + +/** + * @ignore + * @api private + */ +var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { + // Process the object + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Serialize the object + for(var key in object) { + // Check the key and throw error if it's illegal + if(checkKeys == true && (key != '$db' && key != '$ref' && key != '$id')) { + BSON.checkKey(key); + } + + // Pack the element + index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); + } + } + + // Write zero + buffer[index++] = 0; + return index; +} + +var stringToBytes = function(str) { + var ch, st, re = []; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re.concat( st.reverse() ); + } + // return an array of bytes + return re; +} + +var numberOfBytes = function(str) { + var ch, st, re = 0; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re + st.length; + } + // return an array of bytes + return re; +} + +/** + * @ignore + * @api private + */ +var writeToTypedArray = function(buffer, string, index) { + var bytes = stringToBytes(string); + for(var i = 0; i < bytes.length; i++) { + buffer[index + i] = bytes[i]; + } + return bytes.length; +} + +/** + * @ignore + * @api private + */ +var supportsBuffer = typeof Buffer != 'undefined'; + +/** + * @ignore + * @api private + */ +var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { + var startIndex = index; + + switch(typeof value) { + case 'string': + // Encode String type + buffer[index++] = BSON.BSON_DATA_STRING; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1; + // Write the size of the string to buffer + buffer[index + 3] = (size >> 24) & 0xff; + buffer[index + 2] = (size >> 16) & 0xff; + buffer[index + 1] = (size >> 8) & 0xff; + buffer[index] = size & 0xff; + // Ajust the index + index = index + 4; + // Write the string + supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + // Return index + return index; + case 'number': + // We have an integer value + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // If the value fits in 32 bits encode as int, if it fits in a double + // encode it as a double, otherwise long + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { + // Set int type 32 bits or less + buffer[index++] = BSON.BSON_DATA_INT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the int value + buffer[index++] = value & 0xff; + buffer[index++] = (value >> 8) & 0xff; + buffer[index++] = (value >> 16) & 0xff; + buffer[index++] = (value >> 24) & 0xff; + } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } else { + // Set long type + buffer[index++] = BSON.BSON_DATA_LONG; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var longVal = Long.fromNumber(value); + var lowBits = longVal.getLowBits(); + var highBits = longVal.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + } + } else { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } + + return index; + case 'undefined': + // Set long type + buffer[index++] = BSON.BSON_DATA_NULL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + case 'boolean': + // Write the type + buffer[index++] = BSON.BSON_DATA_BOOLEAN; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Encode the boolean value + buffer[index++] = value ? 1 : 0; + return index; + case 'object': + if(value === null || value instanceof MinKey || value instanceof MaxKey + || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + // Write the type of either min or max key + if(value === null) { + buffer[index++] = BSON.BSON_DATA_NULL; + } else if(value instanceof MinKey) { + buffer[index++] = BSON.BSON_DATA_MIN_KEY; + } else { + buffer[index++] = BSON.BSON_DATA_MAX_KEY; + } + + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OID; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write objectid + supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index); + // Ajust index + index = index + 12; + return index; + } else if(value instanceof Date || isDate(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_DATE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the date + var dateInMilis = Long.fromNumber(value.getTime()); + var lowBits = dateInMilis.getLowBits(); + var highBits = dateInMilis.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Get size of the buffer (current write point) + var size = value.length; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the default subtype + buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; + // Copy the content form the binary field to the buffer + value.copy(buffer, index, 0, size); + // Adjust the index + index = index + size; + return index; + } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { + // Write the type + buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the date + var lowBits = value.getLowBits(); + var highBits = value.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(value instanceof Double || value['_bsontype'] == 'Double') { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + return index; + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + if(value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.code.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize + 4; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize)); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index); + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.code.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Extract the buffer + var data = value.value(true); + // Calculate size + var size = value.position; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the subtype to the buffer + buffer[index++] = value.sub_type; + + // If we have binary type 2 the 4 first bytes are the size + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + } + + // Write the data to the object + supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index); + // Ajust index + index = index + value.position; + return index; + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + // Write the type + buffer[index++] = BSON.BSON_DATA_SYMBOL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(value.value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0x00; + return index; + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + // Message size + var size = BSON.calculateObjectSize(ordered_values, serializeFunctions); + // Serialize the object + var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write zero for object + buffer[endIndex++] = 0x00; + // Return the end index + return endIndex; + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + // Write the type + buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Adjust the index + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); + // Write size + var size = endIndex - index; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return endIndex; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = new Buffer(scopeSize); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize - 4; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + scopeObjectBuffer.copy(buffer, index, 0, scopeSize); + + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else if(serializeFunctions) { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } + } + + // If no value to serialize + return index; +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + var buffer = null; + // Calculate the size of the object + var size = BSON.calculateObjectSize(object, serializeFunctions); + // Fetch the best available type for storing the binary data + if(buffer = typeof Buffer != 'undefined') { + buffer = new Buffer(size); + asBuffer = true; + } else if(typeof Uint8Array != 'undefined') { + buffer = new Uint8Array(new ArrayBuffer(size)); + } else { + buffer = new Array(size); + } + + // If asBuffer is false use typed arrays + BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); + return buffer; +} + +/** + * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 + * + * @ignore + * @api private + */ +var functionCache = BSON.functionCache = {}; + +/** + * Crc state variables shared by function + * + * @ignore + * @api private + */ +var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; + +/** + * CRC32 hash method, Fast and enough versitility for our usage + * + * @ignore + * @api private + */ +var crc32 = function(string, start, end) { + var crc = 0 + var x = 0; + var y = 0; + crc = crc ^ (-1); + + for(var i = start, iTop = end; i < iTop;i++) { + y = (crc ^ string[i]) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); + options = options != null ? options : {}; + var index = startIndex; + // Loop over all documents + for(var i = 0; i < numberOfDocuments; i++) { + // Find size of the document + var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; + // Update options with index + options['index'] = index; + // Parse the document at this point + documents[docStartIndex + i] = BSON.deserialize(data, options); + // Adjust index by the document size + index = index + size; + } + + // Return object containing end index of parsing and list of documents + return index; +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEvalWithHash = function(functionCache, hash, functionString, object) { + // Contains the value we are going to set + var value = null; + + // Check for cache hit, eval if missing and return cached function + if(functionCache[hash] == null) { + eval("value = " + functionString); + functionCache[hash] = value; + } + // Set the object + return functionCache[hash].bind(object); +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEval = function(functionString) { + // Contains the value we are going to set + var value = null; + // Eval the function + eval("value = " + functionString); + return value; +} + +/** + * Convert Uint8Array to String + * + * @ignore + * @api private + */ +var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) { + return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex)); +} + +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + + return result; +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.deserialize = function(buffer, options, isArray) { + // Options + options = options == null ? {} : options; + var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; + var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; + var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; + + // Validate that we have at least 4 bytes of buffer + if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); + + // Set up index + var index = typeof options['index'] == 'number' ? options['index'] : 0; + // Reads in a C style string + var readCStyleString = function() { + // Get the start search index + var i = index; + // Locate the end of the c string + while(buffer[i] !== 0x00) { i++ } + // Grab utf8 encoded string + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i); + // Update index position + index = i + 1; + // Return string + return string; + } + + // Create holding object + var object = isArray ? [] : {}; + + // Read the document size + var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + + // Ensure buffer is valid size + if(size < 5 || size > buffer.length) throw new Error("corrupt bson message"); + + // While we have more left data left keep parsing + while(true) { + // Read the type + var elementType = buffer[index++]; + // If we get a zero it's the last byte, exit + if(elementType == 0) break; + // Read the name of the field + var name = readCStyleString(); + // Switch on the type + switch(elementType) { + case BSON.BSON_DATA_OID: + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12); + // Decode the oid + object[name] = new ObjectID(string); + // Update index + index = index + 12; + break; + case BSON.BSON_DATA_STRING: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_INT: + // Decode the 32bit value + object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + break; + case BSON.BSON_DATA_NUMBER: + // Decode the double value + object[name] = readIEEE754(buffer, index, 'little', 52, 8); + // Update the index + index = index + 8; + break; + case BSON.BSON_DATA_DATE: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set date object + object[name] = new Date(new Long(lowBits, highBits).toNumber()); + break; + case BSON.BSON_DATA_BOOLEAN: + // Parse the boolean value + object[name] = buffer[index++] == 1; + break; + case BSON.BSON_DATA_NULL: + // Parse the boolean value + object[name] = null; + break; + case BSON.BSON_DATA_BINARY: + // Decode the size of the binary blob + var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Decode the subtype + var subType = buffer[index++]; + // Decode as raw Buffer object if options specifies it + if(buffer['slice'] != null) { + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Slice the data + object[name] = new Binary(buffer.slice(index, index + binarySize), subType); + } else { + var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize); + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Copy the data + for(var i = 0; i < binarySize; i++) { + _buffer[i] = buffer[index + i]; + } + // Create the binary object + object[name] = new Binary(_buffer, subType); + } + // Update the index + index = index + binarySize; + break; + case BSON.BSON_DATA_ARRAY: + options['index'] = index; + // Decode the size of the array document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, true); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_OBJECT: + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_REGEXP: + // Create the regexp + var source = readCStyleString(); + var regExpOptions = readCStyleString(); + // For each option add the corresponding one for javascript + var optionsArray = new Array(regExpOptions.length); + + // Parse options + for(var i = 0; i < regExpOptions.length; i++) { + switch(regExpOptions[i]) { + case 'm': + optionsArray[i] = 'm'; + break; + case 's': + optionsArray[i] = 'g'; + break; + case 'i': + optionsArray[i] = 'i'; + break; + } + } + + object[name] = new RegExp(source, optionsArray.join('')); + break; + case BSON.BSON_DATA_LONG: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Create long object + var long = new Long(lowBits, highBits); + // Set the object + object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; + break; + case BSON.BSON_DATA_SYMBOL: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_TIMESTAMP: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set the object + object[name] = new Timestamp(lowBits, highBits); + break; + case BSON.BSON_DATA_MIN_KEY: + // Parse the object + object[name] = new MinKey(); + break; + case BSON.BSON_DATA_MAX_KEY: + // Parse the object + object[name] = new MaxKey(); + break; + case BSON.BSON_DATA_CODE: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Function string + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + } else { + object[name] = new Code(functionString, {}); + } + + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_CODE_W_SCOPE: + // Read the content of the field + var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Javascript function + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + // Parse the element + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Decode the scope object + var scopeObject = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + + // Set the scope on the object + object[name].scope = scopeObject; + } else { + object[name] = new Code(functionString, scopeObject); + } + + // Add string to object + break; + } + } + + // Check if we have a db ref object + if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + + // Return the final objects + return object; +} + +/** + * Check if key name is valid. + * + * @ignore + * @api private + */ +BSON.checkKey = function checkKey (key) { + if (!key.length) return; + // Check if we have a legal key for the object + if('$' == key[0]) { + throw Error("key " + key + " must not start with '$'"); + } else if (!!~key.indexOf('.')) { + throw Error("key " + key + " must not contain '.'"); + } +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.prototype.deserialize = function(data, options) { + return BSON.deserialize(data, options); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); +} + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { + return BSON.calculateObjectSize(object, serializeFunctions); +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { + return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); +} + +/** + * @ignore + * @api private + */ +exports.Code = Code; +exports.Symbol = Symbol; +exports.BSON = BSON; +exports.DBRef = DBRef; +exports.Binary = Binary; +exports.ObjectID = ObjectID; +exports.Long = Long; +exports.Timestamp = Timestamp; +exports.Double = Double; +exports.MinKey = MinKey; +exports.MaxKey = MaxKey; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/code.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/code.js new file mode 100644 index 0000000..69b56a3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/code.js @@ -0,0 +1,25 @@ +/** + * A class representation of the BSON Code type. + * + * @class Represents the BSON Code type. + * @param {String|Function} code a string or function. + * @param {Object} [scope] an optional scope for the function. + * @return {Code} + */ +function Code(code, scope) { + if(!(this instanceof Code)) return new Code(code, scope); + + this._bsontype = 'Code'; + this.code = code; + this.scope = scope == null ? {} : scope; +}; + +/** + * @ignore + * @api private + */ +Code.prototype.toJSON = function() { + return {scope:this.scope, code:this.code}; +} + +exports.Code = Code; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js new file mode 100644 index 0000000..56b6510 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js @@ -0,0 +1,31 @@ +/** + * A class representation of the BSON DBRef type. + * + * @class Represents the BSON DBRef type. + * @param {String} namespace the collection name. + * @param {ObjectID} oid the reference ObjectID. + * @param {String} [db] optional db name, if omitted the reference is local to the current db. + * @return {DBRef} + */ +function DBRef(namespace, oid, db) { + if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db); + + this._bsontype = 'DBRef'; + this.namespace = namespace; + this.oid = oid; + this.db = db; +}; + +/** + * @ignore + * @api private + */ +DBRef.prototype.toJSON = function() { + return { + '$ref':this.namespace, + '$id':this.oid, + '$db':this.db == null ? '' : this.db + }; +} + +exports.DBRef = DBRef; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/double.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/double.js new file mode 100644 index 0000000..ae51463 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/double.js @@ -0,0 +1,33 @@ +/** + * A class representation of the BSON Double type. + * + * @class Represents the BSON Double type. + * @param {Number} value the number we want to represent as a double. + * @return {Double} + */ +function Double(value) { + if(!(this instanceof Double)) return new Double(value); + + this._bsontype = 'Double'; + this.value = value; +} + +/** + * Access the number value. + * + * @return {Number} returns the wrapped double number. + * @api public + */ +Double.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Double.prototype.toJSON = function() { + return this.value; +} + +exports.Double = Double; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js new file mode 100644 index 0000000..6fca392 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js @@ -0,0 +1,121 @@ +// Copyright (c) 2008, Fair Oaks Labs, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// +// Modifications to writeIEEE754 to support negative zeroes made by Brian White + +var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { + var e, m, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = bBE ? 0 : (nBytes - 1), + d = bBE ? 1 : -1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { + var e, m, c, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = bBE ? (nBytes-1) : 0, + d = bBE ? -1 : 1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e+eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +exports.readIEEE754 = readIEEE754; +exports.writeIEEE754 = writeIEEE754; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/index.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/index.js new file mode 100644 index 0000000..950fcad --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/index.js @@ -0,0 +1,74 @@ +try { + exports.BSONPure = require('./bson'); + exports.BSONNative = require('../../ext'); +} catch(err) { + // do nothing +} + +[ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + exports[i] = module[i]; + } +}); + +// Exports all the classes for the NATIVE JS BSON Parser +exports.native = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '../../ext' +].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} + +// Exports all the classes for the PURE JS BSON Parser +exports.pure = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '././bson'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/long.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/long.js new file mode 100644 index 0000000..f8f37a6 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/long.js @@ -0,0 +1,854 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Long". This + * implementation is derived from LongLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a Long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Long type. + * @param {Number} low the low (signed) 32 bits of the Long. + * @param {Number} high the high (signed) 32 bits of the Long. + */ +function Long(low, high) { + if(!(this instanceof Long)) return new Long(low, high); + + this._bsontype = 'Long'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Long.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Long.prototype.toNumber = function() { + return this.high_ * Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Long.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Long.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Long.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Long. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. + * @api public + */ +Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Long equals the other + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long equals the other + * @api public + */ +Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Long does not equal the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long does not equal the other. + * @api public + */ +Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Long is less than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than the other. + * @api public + */ +Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Long is less than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than or equal to the other. + * @api public + */ +Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Long is greater than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than the other. + * @api public + */ +Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Long is greater than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than or equal to the other. + * @api public + */ +Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Long with the given one. + * + * @param {Long} other Long to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Long} the negation of this value. + * @api public + */ +Long.prototype.negate = function() { + if (this.equals(Long.MIN_VALUE)) { + return Long.MIN_VALUE; + } else { + return this.not().add(Long.ONE); + } +}; + +/** + * Returns the sum of this and the given Long. + * + * @param {Long} other Long to add to this one. + * @return {Long} the sum of this and the given Long. + * @api public + */ +Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Long. + * + * @param {Long} other Long to subtract from this. + * @return {Long} the difference of this and the given Long. + * @api public + */ +Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Long. + * + * @param {Long} other Long to multiply with this. + * @return {Long} the product of this and the other. + * @api public + */ +Long.prototype.multiply = function(other) { + if (this.isZero()) { + return Long.ZERO; + } else if (other.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } else if (other.equals(Long.MIN_VALUE)) { + return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Longs are small, use float multiplication + if (this.lessThan(Long.TWO_PWR_24_) && + other.lessThan(Long.TWO_PWR_24_)) { + return Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Long divided by the given one. + * + * @param {Long} other Long by which to divide. + * @return {Long} this Long divided by the given one. + * @api public + */ +Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + if (other.equals(Long.ONE) || + other.equals(Long.NEG_ONE)) { + return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Long.ZERO)) { + return other.isNegative() ? Long.ONE : Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Long modulo the given one. + * + * @param {Long} other Long by which to mod. + * @return {Long} this Long modulo the given one. + * @api public + */ +Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Long} the bitwise-NOT of this value. + * @api public + */ +Long.prototype.not = function() { + return Long.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Long and the given one. + * + * @param {Long} other the Long with which to AND. + * @return {Long} the bitwise-AND of this and the other. + * @api public + */ +Long.prototype.and = function(other) { + return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Long and the given one. + * + * @param {Long} other the Long with which to OR. + * @return {Long} the bitwise-OR of this and the other. + * @api public + */ +Long.prototype.or = function(other) { + return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Long and the given one. + * + * @param {Long} other the Long with which to XOR. + * @return {Long} the bitwise-XOR of this and the other. + * @api public + */ +Long.prototype.xor = function(other) { + return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Long with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the left by the given amount. + * @api public + */ +Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Long.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount. + * @api public + */ +Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Long.fromBits(high, 0); + } else { + return Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Long representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Long.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Long.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Long.ZERO; + } else if (value <= -Long.TWO_PWR_63_DBL_) { + return Long.MIN_VALUE; + } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { + return Long.MAX_VALUE; + } else if (value < 0) { + return Long.fromNumber(-value).negate(); + } else { + return new Long( + (value % Long.TWO_PWR_32_DBL_) | 0, + (value / Long.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromBits = function(lowBits, highBits) { + return new Long(lowBits, highBits); +}; + +/** + * Returns a Long representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Long. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 8)); + + var result = Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Long.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Long representations of small integer values. + * @type {Object} + * @api private + */ +Long.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Long.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; + +/** @type {Long} */ +Long.ZERO = Long.fromInt(0); + +/** @type {Long} */ +Long.ONE = Long.fromInt(1); + +/** @type {Long} */ +Long.NEG_ONE = Long.fromInt(-1); + +/** @type {Long} */ +Long.MAX_VALUE = + Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Long} */ +Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); + +/** + * @type {Long} + * @api private + */ +Long.TWO_PWR_24_ = Long.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Long = Long; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js new file mode 100644 index 0000000..0825408 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js @@ -0,0 +1,13 @@ +/** + * A class representation of the BSON MaxKey type. + * + * @class Represents the BSON MaxKey type. + * @return {MaxKey} + */ +function MaxKey() { + if(!(this instanceof MaxKey)) return new MaxKey(); + + this._bsontype = 'MaxKey'; +} + +exports.MaxKey = MaxKey; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js new file mode 100644 index 0000000..230c2e6 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js @@ -0,0 +1,13 @@ +/** + * A class representation of the BSON MinKey type. + * + * @class Represents the BSON MinKey type. + * @return {MinKey} + */ +function MinKey() { + if(!(this instanceof MinKey)) return new MinKey(); + + this._bsontype = 'MinKey'; +} + +exports.MinKey = MinKey; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js new file mode 100644 index 0000000..183bbc3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js @@ -0,0 +1,253 @@ +/** + * Module dependencies. + */ +var BinaryParser = require('./binary_parser').BinaryParser; + +/** + * Machine id. + * + * Create a random 3-byte value (i.e. unique for this + * process). Other drivers use a md5 of the machine id here, but + * that would mean an asyc call to gethostname, so we don't bother. + */ +var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); + +// Regular expression that checks for hex value +var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); + +/** +* Create a new ObjectID instance +* +* @class Represents the BSON ObjectID type +* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. +* @return {Object} instance of ObjectID. +*/ +var ObjectID = function ObjectID(id, _hex) { + if(!(this instanceof ObjectID)) return new ObjectID(id, _hex); + + this._bsontype = 'ObjectID'; + var __id = null; + + // Throw an error if it's not a valid setup + if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + // Generate id based on the input + if(id == null || typeof id == 'number') { + // convert to 12 byte binary string + this.id = this.generate(id); + } else if(id != null && id.length === 12) { + // assume 12 byte string + this.id = id; + } else if(checkForHexRegExp.test(id)) { + return ObjectID.createFromHexString(id); + } else { + throw new Error("Value passed in is not a valid 24 character hex string"); + } + + if(ObjectID.cacheHexString) this.__id = this.toHexString(); +}; + +// Allow usage of ObjectId aswell as ObjectID +var ObjectId = ObjectID; + +/** +* Return the ObjectID id as a 24 byte hex string representation +* +* @return {String} return the 24 byte hex string representation. +* @api public +*/ +ObjectID.prototype.toHexString = function() { + if(ObjectID.cacheHexString && this.__id) return this.__id; + + var hexString = '' + , number + , value; + + for (var index = 0, len = this.id.length; index < len; index++) { + value = BinaryParser.toByte(this.id[index]); + number = value <= 15 + ? '0' + value.toString(16) + : value.toString(16); + hexString = hexString + number; + } + + if(ObjectID.cacheHexString) this.__id = hexString; + return hexString; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.get_inc = function() { + return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.getInc = function() { + return this.get_inc(); +}; + +/** +* Generate a 12 byte id string used in ObjectID's +* +* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. +* @return {String} return the 12 byte id binary string. +* @api private +*/ +ObjectID.prototype.generate = function(time) { + if ('number' == typeof time) { + var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); + /* for time-based ObjectID the bytes following the time will be zeroed */ + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } else { + var unixTime = parseInt(Date.now()/1000,10); + var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true); + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } + + return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; +}; + +/** +* Converts the id into a 24 byte hex string for printing +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toString = function() { + return this.toHexString(); +}; + +/** +* Converts to a string representation of this Id. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.inspect = ObjectID.prototype.toString; + +/** +* Converts to its JSON representation. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toJSON = function() { + return this.toHexString(); +}; + +/** +* Compares the equality of this ObjectID with `otherID`. +* +* @param {Object} otherID ObjectID instance to compare against. +* @return {Bool} the result of comparing two ObjectID's +* @api public +*/ +ObjectID.prototype.equals = function equals (otherID) { + var id = (otherID instanceof ObjectID || otherID.toHexString) + ? otherID.id + : ObjectID.createFromHexString(otherID).id; + + return this.id === id; +} + +/** +* Returns the generation date (accurate up to the second) that this ID was generated. +* +* @return {Date} the generation date +* @api public +*/ +ObjectID.prototype.getTimestamp = function() { + var timestamp = new Date(); + timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); + return timestamp; +} + +/** +* @ignore +* @api private +*/ +ObjectID.index = 0; + +ObjectID.createPk = function createPk () { + return new ObjectID(); +}; + +/** +* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. +* +* @param {Number} time an integer number representing a number of seconds. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromTime = function createFromTime (time) { + var id = BinaryParser.encodeInt(time, 32, true, true) + + BinaryParser.encodeInt(0, 64, true, true); + return new ObjectID(id); +}; + +/** +* Creates an ObjectID from a hex string representation of an ObjectID. +* +* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromHexString = function createFromHexString (hexString) { + // Throw an error if it's not a valid setup + if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + var len = hexString.length; + + if(len > 12*2) { + throw new Error('Id cannot be longer than 12 bytes'); + } + + var result = '' + , string + , number; + + for (var index = 0; index < len; index += 2) { + string = hexString.substr(index, 2); + number = parseInt(string, 16); + result += BinaryParser.fromByte(number); + } + + return new ObjectID(result, hexString); +}; + +/** +* @ignore +*/ +Object.defineProperty(ObjectID.prototype, "generationTime", { + enumerable: true + , get: function () { + return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); + } + , set: function (value) { + var value = BinaryParser.encodeInt(value, 32, true, true); + this.id = value + this.id.substr(4); + // delete this.__id; + this.toHexString(); + } +}); + +/** + * Expose. + */ +exports.ObjectID = ObjectID; +exports.ObjectId = ObjectID; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js new file mode 100644 index 0000000..8e2838d --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js @@ -0,0 +1,48 @@ +/** + * A class representation of the BSON Symbol type. + * + * @class Represents the BSON Symbol type. + * @param {String} value the string representing the symbol. + * @return {Symbol} + */ +function Symbol(value) { + if(!(this instanceof Symbol)) return new Symbol(value); + this._bsontype = 'Symbol'; + this.value = value; +} + +/** + * Access the wrapped string value. + * + * @return {String} returns the wrapped string. + * @api public + */ +Symbol.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Symbol.prototype.toString = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.inspect = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.toJSON = function() { + return this.value; +} + +exports.Symbol = Symbol; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js new file mode 100644 index 0000000..c650d15 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js @@ -0,0 +1,853 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Timestamp class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Timestamp". This + * implementation is derived from TimestampLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Timestamps. + * + * The internal representation of a Timestamp is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Timestamp type. + * @param {Number} low the low (signed) 32 bits of the Timestamp. + * @param {Number} high the high (signed) 32 bits of the Timestamp. + */ +function Timestamp(low, high) { + if(!(this instanceof Timestamp)) return new Timestamp(low, high); + this._bsontype = 'Timestamp'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Timestamp.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Timestamp.prototype.toNumber = function() { + return this.high_ * Timestamp.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Timestamp.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Timestamp.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + // We need to change the Timestamp value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixTimestamp = Timestamp.fromNumber(radix); + var div = this.div(radixTimestamp); + var rem = div.multiply(radixTimestamp).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Timestamp.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Timestamp. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. + * @api public + */ +Timestamp.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Timestamp.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Timestamp.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Timestamp.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Timestamp equals the other + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp equals the other + * @api public + */ +Timestamp.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Timestamp does not equal the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp does not equal the other. + * @api public + */ +Timestamp.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Timestamp is less than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than the other. + * @api public + */ +Timestamp.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Timestamp is less than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than or equal to the other. + * @api public + */ +Timestamp.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Timestamp is greater than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than the other. + * @api public + */ +Timestamp.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Timestamp is greater than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than or equal to the other. + * @api public + */ +Timestamp.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Timestamp with the given one. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Timestamp.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Timestamp} the negation of this value. + * @api public + */ +Timestamp.prototype.negate = function() { + if (this.equals(Timestamp.MIN_VALUE)) { + return Timestamp.MIN_VALUE; + } else { + return this.not().add(Timestamp.ONE); + } +}; + +/** + * Returns the sum of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to add to this one. + * @return {Timestamp} the sum of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to subtract from this. + * @return {Timestamp} the difference of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to multiply with this. + * @return {Timestamp} the product of this and the other. + * @api public + */ +Timestamp.prototype.multiply = function(other) { + if (this.isZero()) { + return Timestamp.ZERO; + } else if (other.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } else if (other.equals(Timestamp.MIN_VALUE)) { + return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Timestamps are small, use float multiplication + if (this.lessThan(Timestamp.TWO_PWR_24_) && + other.lessThan(Timestamp.TWO_PWR_24_)) { + return Timestamp.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Timestamp divided by the given one. + * + * @param {Timestamp} other Timestamp by which to divide. + * @return {Timestamp} this Timestamp divided by the given one. + * @api public + */ +Timestamp.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + if (other.equals(Timestamp.ONE) || + other.equals(Timestamp.NEG_ONE)) { + return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Timestamp.ZERO)) { + return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Timestamp.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Timestamp.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Timestamp.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Timestamp.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Timestamp modulo the given one. + * + * @param {Timestamp} other Timestamp by which to mod. + * @return {Timestamp} this Timestamp modulo the given one. + * @api public + */ +Timestamp.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Timestamp} the bitwise-NOT of this value. + * @api public + */ +Timestamp.prototype.not = function() { + return Timestamp.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to AND. + * @return {Timestamp} the bitwise-AND of this and the other. + * @api public + */ +Timestamp.prototype.and = function(other) { + return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to OR. + * @return {Timestamp} the bitwise-OR of this and the other. + * @api public + */ +Timestamp.prototype.or = function(other) { + return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to XOR. + * @return {Timestamp} the bitwise-XOR of this and the other. + * @api public + */ +Timestamp.prototype.xor = function(other) { + return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Timestamp with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the left by the given amount. + * @api public + */ +Timestamp.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Timestamp.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Timestamp.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount. + * @api public + */ +Timestamp.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Timestamp.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Timestamp.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Timestamp.fromBits(high, 0); + } else { + return Timestamp.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Timestamp representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Timestamp.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Timestamp.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Timestamp.ZERO; + } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MIN_VALUE; + } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MAX_VALUE; + } else if (value < 0) { + return Timestamp.fromNumber(-value).negate(); + } else { + return new Timestamp( + (value % Timestamp.TWO_PWR_32_DBL_) | 0, + (value / Timestamp.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromBits = function(lowBits, highBits) { + return new Timestamp(lowBits, highBits); +}; + +/** + * Returns a Timestamp representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Timestamp. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Timestamp.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); + + var result = Timestamp.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Timestamp.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Timestamp.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Timestamp.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Timestamp representations of small integer values. + * @type {Object} + * @api private + */ +Timestamp.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; + +/** @type {Timestamp} */ +Timestamp.ZERO = Timestamp.fromInt(0); + +/** @type {Timestamp} */ +Timestamp.ONE = Timestamp.fromInt(1); + +/** @type {Timestamp} */ +Timestamp.NEG_ONE = Timestamp.fromInt(-1); + +/** @type {Timestamp} */ +Timestamp.MAX_VALUE = + Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Timestamp} */ +Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); + +/** + * @type {Timestamp} + * @api private + */ +Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Timestamp = Timestamp; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/package.json b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/package.json new file mode 100644 index 0000000..807571a --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/package.json @@ -0,0 +1,56 @@ +{ + "name": "bson", + "description": "A bson parser for node.js and the browser", + "keywords": [ + "mongodb", + "bson", + "parser" + ], + "version": "0.1.9", + "author": { + "name": "Christian Amor Kvalheim", + "email": "christkv@gmail.com" + }, + "contributors": [], + "repository": { + "type": "git", + "url": "git://github.com/mongodb/js-bson.git" + }, + "bugs": { + "mail": "node-mongodb-native@googlegroups.com", + "url": "https://github.com/mongodb/js-bson/issues" + }, + "devDependencies": { + "nodeunit": "0.7.3", + "gleak": "0.2.3", + "one": "latest" + }, + "config": { + "native": false + }, + "main": "./lib/bson/index", + "directories": { + "lib": "./lib/bson" + }, + "engines": { + "node": ">=0.6.19" + }, + "scripts": { + "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", + "test": "nodeunit ./test/node && TEST_NATIVE=TRUE nodeunit ./test/node" + }, + "licenses": [ + { + "type": "Apache License, Version 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], + "readme": "Javascript + C++ BSON parser\n============================\n\nThis BSON parser is primarily meant for usage with the `mongodb` node.js driver. However thanks to such wonderful tools at `onejs` we are able to package up a BSON parser that will work in the browser aswell. The current build is located in the `browser_build/bson.js` file.\n\nA simple example on how to use it\n\n \n \n \n \n \n \n\n It's got two simple methods to use in your application.\n\n * BSON.serialize(object, checkKeys, asBuffer, serializeFunctions)\n * @param {Object} object the Javascript object to serialize.\n * @param {Boolean} checkKeys the serializer will check if keys are valid.\n * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**.\n * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**\n * @return {TypedArray/Array} returns a TypedArray or Array depending on what your browser supports\n \n * BSON.deserialize(buffer, options, isArray)\n * Options\n * **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.\n * **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.\n * **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.\n * @param {TypedArray/Array} a TypedArray/Array containing the BSON data\n * @param {Object} [options] additional options used for the deserialization.\n * @param {Boolean} [isArray] ignore used for recursive parsing.\n * @return {Object} returns the deserialized Javascript Object.\n", + "readmeFilename": "README.md", + "_id": "bson@0.1.9", + "dist": { + "shasum": "2ed652fa3857de6f0745d7820537f139c067630f" + }, + "_from": "bson@0.1.9", + "_resolved": "https://registry.npmjs.org/bson/-/bson-0.1.9.tgz" +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/gleak.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/gleak.js new file mode 100644 index 0000000..c707cfc --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/gleak.js @@ -0,0 +1,21 @@ + +var gleak = require('gleak')(); +gleak.ignore('AssertionError'); +gleak.ignore('testFullSpec_param_found'); +gleak.ignore('events'); +gleak.ignore('Uint8Array'); +gleak.ignore('Uint8ClampedArray'); +gleak.ignore('TAP_Global_Harness'); +gleak.ignore('setImmediate'); +gleak.ignore('clearImmediate'); + +gleak.ignore('DTRACE_NET_SERVER_CONNECTION'); +gleak.ignore('DTRACE_NET_STREAM_END'); +gleak.ignore('DTRACE_NET_SOCKET_READ'); +gleak.ignore('DTRACE_NET_SOCKET_WRITE'); +gleak.ignore('DTRACE_HTTP_SERVER_REQUEST'); +gleak.ignore('DTRACE_HTTP_SERVER_RESPONSE'); +gleak.ignore('DTRACE_HTTP_CLIENT_REQUEST'); +gleak.ignore('DTRACE_HTTP_CLIENT_RESPONSE'); + +module.exports = gleak; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE new file mode 100644 index 0000000..7c435ba --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008-2011 Pivotal Labs + +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/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js new file mode 100644 index 0000000..7383401 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js @@ -0,0 +1,190 @@ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css new file mode 100644 index 0000000..6583fe7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css @@ -0,0 +1,166 @@ +body { + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; +} + + +.jasmine_reporter a:visited, .jasmine_reporter a { + color: #303; +} + +.jasmine_reporter a:hover, .jasmine_reporter a:active { + color: blue; +} + +.run_spec { + float:right; + padding-right: 5px; + font-size: .8em; + text-decoration: none; +} + +.jasmine_reporter { + margin: 0 5px; +} + +.banner { + color: #303; + background-color: #fef; + padding: 5px; +} + +.logo { + float: left; + font-size: 1.1em; + padding-left: 5px; +} + +.logo .version { + font-size: .6em; + padding-left: 1em; +} + +.runner.running { + background-color: yellow; +} + + +.options { + text-align: right; + font-size: .8em; +} + + + + +.suite { + border: 1px outset gray; + margin: 5px 0; + padding-left: 1em; +} + +.suite .suite { + margin: 5px; +} + +.suite.passed { + background-color: #dfd; +} + +.suite.failed { + background-color: #fdd; +} + +.spec { + margin: 5px; + padding-left: 1em; + clear: both; +} + +.spec.failed, .spec.passed, .spec.skipped { + padding-bottom: 5px; + border: 1px solid gray; +} + +.spec.failed { + background-color: #fbb; + border-color: red; +} + +.spec.passed { + background-color: #bfb; + border-color: green; +} + +.spec.skipped { + background-color: #bbb; +} + +.messages { + border-left: 1px dashed gray; + padding-left: 1em; + padding-right: 1em; +} + +.passed { + background-color: #cfc; + display: none; +} + +.failed { + background-color: #fbb; +} + +.skipped { + color: #777; + background-color: #eee; + display: none; +} + + +/*.resultMessage {*/ + /*white-space: pre;*/ +/*}*/ + +.resultMessage span.result { + display: block; + line-height: 2em; + color: black; +} + +.resultMessage .mismatch { + color: black; +} + +.stackTrace { + white-space: pre; + font-size: .8em; + margin-left: 10px; + max-height: 5em; + overflow: auto; + border: 1px inset red; + padding: 1em; + background: #eef; +} + +.finished-at { + padding-left: 1em; + font-size: .6em; +} + +.show-passed .passed, +.show-skipped .skipped { + display: block; +} + + +#jasmine_content { + position:fixed; + right: 100%; +} + +.runner { + border: 1px solid gray; + display: block; + margin: 5px 0; + padding: 2px 0 2px 10px; +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js new file mode 100644 index 0000000..c3d2dc7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js @@ -0,0 +1,2476 @@ +var isCommonJS = typeof window == "undefined"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @returns a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a instanceof jasmine.Matchers.Any) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.Any) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toNotEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + if (this.actual.callCount === 0) { + // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." + ]; + } else { + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) + ]; + } + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toNotContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + var multiplier = Math.pow(10, precision); + var actual = Math.round(this.actual * multiplier); + expected = Math.round(expected * multiplier); + return expected == actual; +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} expected + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.matches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.toString = function() { + return ''; +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + if (this.ppNestLevel_ > 40) { + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value instanceof jasmine.Matchers.Any) { + this.emitScalar(value.toString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block) { + this.blocks.unshift(block); +}; + +jasmine.Queue.prototype.add = function(block) { + this.blocks.push(block); +}; + +jasmine.Queue.prototype.insertNext = function(block) { + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !this.abort) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this)); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 1, + "build": 0, + "revision": 1315677058 +}; diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png b/node_modules/mongoose/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..218f3b43713598fa5a3e78b57aceb909c33f46df GIT binary patch literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds, and deletes the output file when done +# if any of the postbuilds failed. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + F=$$?;\ + if [ $$F -ne 0 ]; then\ + E=$$F;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 1,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,kerberos.target.mk)))),) + include kerberos.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = /srv/biomedjs/node/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/srv/biomedjs/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/config.gypi -I/srv/biomedjs/node/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/home/akira/.node-gyp/0.10.4/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/akira/.node-gyp/0.10.4" "-Dmodule_root_dir=/srv/biomedjs/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos" binding.gyp +Makefile: $(srcdir)/../../../../../../node/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/../../../../../../../../home/akira/.node-gyp/0.10.4/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/kerberos.node.d b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/kerberos.node.d new file mode 100644 index 0000000..0bc3206 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/kerberos.node.d @@ -0,0 +1 @@ +cmd_Release/kerberos.node := rm -rf "Release/kerberos.node" && cp -af "Release/obj.target/kerberos.node" "Release/kerberos.node" diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos.node.d b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos.node.d new file mode 100644 index 0000000..eec5672 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos.node.d @@ -0,0 +1 @@ +cmd_Release/obj.target/kerberos.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -m64 -Wl,-soname=kerberos.node -o Release/obj.target/kerberos.node -Wl,--start-group -Wl,--end-group diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/kerberos.node b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/build/Release/kerberos.node new file mode 100755 index 0000000000000000000000000000000000000000..a06202d9ef0ef4d29baf0b512ab6be8a04a30780 GIT binary patch literal 5445 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 +#include + +// base64 tables +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static signed char index_64[128] = +{ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +// base64_encode : base64 encode +// +// value : data to encode +// vlen : length of data +// (result) : new char[] - c-str of result +char *base64_encode(const unsigned char *value, int vlen) +{ + char *result = (char *)malloc((vlen * 4) / 3 + 5); + char *out = result; + while (vlen >= 3) + { + *out++ = basis_64[value[0] >> 2]; + *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; + *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; + *out++ = basis_64[value[2] & 0x3F]; + value += 3; + vlen -= 3; + } + if (vlen > 0) + { + *out++ = basis_64[value[0] >> 2]; + unsigned char oval = (value[0] << 4) & 0x30; + if (vlen > 1) oval |= value[1] >> 4; + *out++ = basis_64[oval]; + *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; + *out++ = '='; + } + *out = '\0'; + + return result; +} + +// base64_decode : base64 decode +// +// value : c-str to decode +// rlen : length of decoded result +// (result) : new unsigned char[] - decoded result +unsigned char *base64_decode(const char *value, int *rlen) +{ + *rlen = 0; + int c1, c2, c3, c4; + + int vlen = strlen(value); + unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1); + unsigned char *out = result; + + while (1) + { + if (value[0]==0) + return result; + c1 = value[0]; + if (CHAR64(c1) == -1) + goto base64_decode_error;; + c2 = value[1]; + if (CHAR64(c2) == -1) + goto base64_decode_error;; + c3 = value[2]; + if ((c3 != '=') && (CHAR64(c3) == -1)) + goto base64_decode_error;; + c4 = value[3]; + if ((c4 != '=') && (CHAR64(c4) == -1)) + goto base64_decode_error;; + + value += 4; + *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + *rlen += 1; + if (c3 != '=') + { + *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + *rlen += 1; + if (c4 != '=') + { + *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + *rlen += 1; + } + } + } + +base64_decode_error: + *result = 0; + *rlen = 0; + return result; +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/base64.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/base64.h new file mode 100644 index 0000000..f0e1f06 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/base64.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +char *base64_encode(const unsigned char *value, int vlen); +unsigned char *base64_decode(const char *value, int *rlen); diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc new file mode 100644 index 0000000..08eda82 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc @@ -0,0 +1,563 @@ +#include "kerberos.h" +#include +#include "worker.h" +#include "kerberos_context.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#endif + +Persistent Kerberos::constructor_template; + +// Call structs +typedef struct AuthGSSClientCall { + uint32_t flags; + char *uri; +} AuthGSSClientCall; + +typedef struct AuthGSSClientStepCall { + KerberosContext *context; + char *challenge; +} AuthGSSClientStepCall; + +typedef struct AuthGSSClientUnwrapCall { + KerberosContext *context; + char *challenge; +} AuthGSSClientUnwrapCall; + +typedef struct AuthGSSClientWrapCall { + KerberosContext *context; + char *challenge; + char *user_name; +} AuthGSSClientWrapCall; + +typedef struct AuthGSSClientCleanCall { + KerberosContext *context; +} AuthGSSClientCleanCall; + +// VException object (causes throw in calling code) +static Handle VException(const char *msg) { + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +} + +Kerberos::Kerberos() : ObjectWrap() { +} + +void Kerberos::Initialize(v8::Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(Kerberos::New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("Kerberos")); + + // Set up method for the Kerberos instance + NODE_SET_PROTOTYPE_METHOD(constructor_template, "authGSSClientInit", AuthGSSClientInit); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "authGSSClientStep", AuthGSSClientStep); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "authGSSClientUnwrap", AuthGSSClientUnwrap); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "authGSSClientWrap", AuthGSSClientWrap); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "authGSSClientClean", AuthGSSClientClean); + + // Set the symbol + target->ForceSet(String::NewSymbol("Kerberos"), constructor_template->GetFunction()); +} + +Handle Kerberos::New(const Arguments &args) { + // Create a Kerberos instance + Kerberos *kerberos = new Kerberos(); + // Return the kerberos object + kerberos->Wrap(args.This()); + return args.This(); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientInit +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientInit(Worker *worker) { + gss_client_state *state; + gss_client_response *response; + + // Allocate state + state = (gss_client_state *)malloc(sizeof(gss_client_state)); + + // Unpack the parameter data struct + AuthGSSClientCall *call = (AuthGSSClientCall *)worker->parameters; + // Start the kerberos client + response = authenticate_gss_client_init(call->uri, call->flags, state); + + // Release the parameter struct memory + free(call->uri); + free(call); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_value = state; + } + + // Free structure + free(response); +} + +static Handle _map_authGSSClientInit(Worker *worker) { + HandleScope scope; + + KerberosContext *context = KerberosContext::New(); + context->state = (gss_client_state *)worker->return_value; + // Persistent _context = Persistent::New(context->handle_); + return scope.Close(context->handle_); +} + +// Initialize method +Handle Kerberos::AuthGSSClientInit(const Arguments &args) { + HandleScope scope; + + // Ensure valid call + if(args.Length() != 3) return VException("Requires a service string uri, integer flags and a callback function"); + if(args.Length() == 3 && !args[0]->IsString() && !args[1]->IsInt32() && !args[2]->IsFunction()) + return VException("Requires a service string uri, integer flags and a callback function"); + + Local service = args[0]->ToString(); + // Convert uri string to c-string + char *service_str = (char *)calloc(service->Utf8Length() + 1, sizeof(char)); + // Write v8 string to c-string + service->WriteUtf8(service_str); + + // Allocate a structure + AuthGSSClientCall *call = (AuthGSSClientCall *)calloc(1, sizeof(AuthGSSClientCall)); + call->flags =args[1]->ToInt32()->Uint32Value(); + call->uri = service_str; + + // Unpack the callback + Local callback = Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _authGSSClientInit; + worker->mapper = _map_authGSSClientInit; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + // Return no value as it's callback based + return scope.Close(Undefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientStep +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientStep(Worker *worker) { + gss_client_state *state; + gss_client_response *response; + char *challenge; + + // Unpack the parameter data struct + AuthGSSClientStepCall *call = (AuthGSSClientStepCall *)worker->parameters; + // Get the state + state = call->context->state; + challenge = call->challenge; + + // Check what kind of challenge we have + if(call->challenge == NULL) { + challenge = (char *)""; + } + + // Perform authentication step + response = authenticate_gss_client_step(state, challenge); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + if(call->challenge != NULL) free(call->challenge); + free(call); + free(response); +} + +static Handle _map_authGSSClientStep(Worker *worker) { + HandleScope scope; + // Return the return code + return scope.Close(Int32::New(worker->return_code)); +} + +// Initialize method +Handle Kerberos::AuthGSSClientStep(const Arguments &args) { + HandleScope scope; + + // Ensure valid call + if(args.Length() != 2 && args.Length() != 3) return VException("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 2 && !KerberosContext::HasInstance(args[0])) return VException("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString()) return VException("Requires a GSS context, optional challenge string and callback function"); + + // Challenge string + char *challenge_str = NULL; + // Let's unpack the parameters + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // If we have a challenge string + if(args.Length() == 3) { + // Unpack the challenge string + Local challenge = args[1]->ToString(); + // Convert uri string to c-string + challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); + // Write v8 string to c-string + challenge->WriteUtf8(challenge_str); + } + + // Allocate a structure + AuthGSSClientStepCall *call = (AuthGSSClientStepCall *)calloc(1, sizeof(AuthGSSClientCall)); + call->context = kerberos_context; + call->challenge = challenge_str; + + // Unpack the callback + Local callback = Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _authGSSClientStep; + worker->mapper = _map_authGSSClientStep; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + return scope.Close(Undefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientUnwrap +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientUnwrap(Worker *worker) { + gss_client_response *response; + char *challenge; + + // Unpack the parameter data struct + AuthGSSClientUnwrapCall *call = (AuthGSSClientUnwrapCall *)worker->parameters; + challenge = call->challenge; + + // Check what kind of challenge we have + if(call->challenge == NULL) { + challenge = (char *)""; + } + + // Perform authentication step + response = authenticate_gss_client_unwrap(call->context->state, challenge); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + if(call->challenge != NULL) free(call->challenge); + free(call); + free(response); +} + +static Handle _map_authGSSClientUnwrap(Worker *worker) { + HandleScope scope; + // Return the return code + return scope.Close(Int32::New(worker->return_code)); +} + +// Initialize method +Handle Kerberos::AuthGSSClientUnwrap(const Arguments &args) { + HandleScope scope; + + // Ensure valid call + if(args.Length() != 2 && args.Length() != 3) return VException("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 2 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsFunction()) return VException("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsFunction()) return VException("Requires a GSS context, optional challenge string and callback function"); + + // Challenge string + char *challenge_str = NULL; + // Let's unpack the parameters + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // If we have a challenge string + if(args.Length() == 3) { + // Unpack the challenge string + Local challenge = args[1]->ToString(); + // Convert uri string to c-string + challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); + // Write v8 string to c-string + challenge->WriteUtf8(challenge_str); + } + + // Allocate a structure + AuthGSSClientUnwrapCall *call = (AuthGSSClientUnwrapCall *)calloc(1, sizeof(AuthGSSClientUnwrapCall)); + call->context = kerberos_context; + call->challenge = challenge_str; + + // Unpack the callback + Local callback = args.Length() == 3 ? Local::Cast(args[2]) : Local::Cast(args[1]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _authGSSClientUnwrap; + worker->mapper = _map_authGSSClientUnwrap; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + return scope.Close(Undefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientWrap +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientWrap(Worker *worker) { + gss_client_response *response; + char *user_name = NULL; + + // Unpack the parameter data struct + AuthGSSClientWrapCall *call = (AuthGSSClientWrapCall *)worker->parameters; + user_name = call->user_name; + + // Check what kind of challenge we have + if(call->user_name == NULL) { + user_name = (char *)""; + } + + // Perform authentication step + response = authenticate_gss_client_wrap(call->context->state, call->challenge, user_name); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + if(call->challenge != NULL) free(call->challenge); + if(call->user_name != NULL) free(call->user_name); + free(call); + free(response); +} + +static Handle _map_authGSSClientWrap(Worker *worker) { + HandleScope scope; + // Return the return code + return scope.Close(Int32::New(worker->return_code)); +} + +// Initialize method +Handle Kerberos::AuthGSSClientWrap(const Arguments &args) { + HandleScope scope; + + // Ensure valid call + if(args.Length() != 3 && args.Length() != 4) return VException("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); + if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsFunction()) return VException("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); + if(args.Length() == 4 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsString() && !args[2]->IsFunction()) return VException("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); + + // Challenge string + char *challenge_str = NULL; + char *user_name_str = NULL; + + // Let's unpack the kerberos context + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // Unpack the challenge string + Local challenge = args[1]->ToString(); + // Convert uri string to c-string + challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); + // Write v8 string to c-string + challenge->WriteUtf8(challenge_str); + + // If we have a user string + if(args.Length() == 4) { + // Unpack user name + Local user_name = args[2]->ToString(); + // Convert uri string to c-string + user_name_str = (char *)calloc(user_name->Utf8Length() + 1, sizeof(char)); + // Write v8 string to c-string + user_name->WriteUtf8(user_name_str); + } + + // Allocate a structure + AuthGSSClientWrapCall *call = (AuthGSSClientWrapCall *)calloc(1, sizeof(AuthGSSClientWrapCall)); + call->context = kerberos_context; + call->challenge = challenge_str; + call->user_name = user_name_str; + + // Unpack the callback + Local callback = args.Length() == 4 ? Local::Cast(args[3]) : Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _authGSSClientWrap; + worker->mapper = _map_authGSSClientWrap; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + return scope.Close(Undefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientWrap +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientClean(Worker *worker) { + gss_client_response *response; + + // Unpack the parameter data struct + AuthGSSClientCleanCall *call = (AuthGSSClientCleanCall *)worker->parameters; + + // Perform authentication step + response = authenticate_gss_client_clean(call->context->state); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + free(call); + free(response); +} + +static Handle _map_authGSSClientClean(Worker *worker) { + HandleScope scope; + // Return the return code + return scope.Close(Int32::New(worker->return_code)); +} + +// Initialize method +Handle Kerberos::AuthGSSClientClean(const Arguments &args) { + HandleScope scope; + + // // Ensure valid call + if(args.Length() != 2) return VException("Requires a GSS context and callback function"); + if(!KerberosContext::HasInstance(args[0]) && !args[1]->IsFunction()) return VException("Requires a GSS context and callback function"); + + // Let's unpack the kerberos context + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // Allocate a structure + AuthGSSClientCleanCall *call = (AuthGSSClientCleanCall *)calloc(1, sizeof(AuthGSSClientCleanCall)); + call->context = kerberos_context; + + // Unpack the callback + Local callback = Local::Cast(args[1]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _authGSSClientClean; + worker->mapper = _map_authGSSClientClean; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + return scope.Close(Undefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// UV Lib callbacks +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +void Kerberos::Process(uv_work_t* work_req) { + // Grab the worker + Worker *worker = static_cast(work_req->data); + // Execute the worker code + worker->execute(worker); +} + +void Kerberos::After(uv_work_t* work_req) { + // Grab the scope of the call from Node + v8::HandleScope scope; + + // Get the worker reference + Worker *worker = static_cast(work_req->data); + + // If we have an error + if(worker->error) { + v8::Local err = v8::Exception::Error(v8::String::New(worker->error_message)); + Local obj = err->ToObject(); + obj->Set(NODE_PSYMBOL("code"), Int32::New(worker->error_code)); + v8::Local args[2] = { err, v8::Local::New(v8::Null()) }; + // Execute the error + v8::TryCatch try_catch; + // Call the callback + worker->callback->Call(v8::Context::GetCurrent()->Global(), ARRAY_SIZE(args), args); + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } else { + // // Map the data + v8::Handle result = worker->mapper(worker); + // Set up the callback with a null first + v8::Handle args[2] = { v8::Local::New(v8::Null()), result}; + // Wrap the callback function call in a TryCatch so that we can call + // node's FatalException afterwards. This makes it possible to catch + // the exception from JavaScript land using the + // process.on('uncaughtException') event. + v8::TryCatch try_catch; + // Call the callback + worker->callback->Call(v8::Context::GetCurrent()->Global(), ARRAY_SIZE(args), args); + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + // Clean up the memory + worker->callback.Dispose(); + delete worker; +} + +// Exporting function +extern "C" void init(Handle target) { + HandleScope scope; + Kerberos::Initialize(target); + KerberosContext::Initialize(target); +} + +NODE_MODULE(kerberos, init); diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h new file mode 100644 index 0000000..f0fbcdc --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h @@ -0,0 +1,47 @@ +#ifndef KERBEROS_H +#define KERBEROS_H + +#include +#include +#include + +#include +#include +#include + +extern "C" { + #include "kerberosgss.h" +} + +using namespace v8; +using namespace node; + +class Kerberos : public ObjectWrap { + +public: + Kerberos(); + ~Kerberos() {}; + + // Constructor used for creating new Kerberos objects from C++ + static Persistent constructor_template; + + // Initialize function for the object + static void Initialize(Handle target); + + // Method available + static Handle AuthGSSClientInit(const Arguments &args); + static Handle AuthGSSClientStep(const Arguments &args); + static Handle AuthGSSClientUnwrap(const Arguments &args); + static Handle AuthGSSClientWrap(const Arguments &args); + static Handle AuthGSSClientClean(const Arguments &args); + +private: + static Handle New(const Arguments &args); + + // Handles the uv calls + static void Process(uv_work_t* work_req); + // Called after work is done + static void After(uv_work_t* work_req); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js new file mode 100644 index 0000000..b1a701b --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js @@ -0,0 +1,91 @@ +var kerberos = require('../build/Release/kerberos') + , KerberosNative = kerberos.Kerberos; + +var Kerberos = function() { + this._native_kerberos = new KerberosNative(); +} + +Kerberos.prototype.authGSSClientInit = function(uri, flags, callback) { + return this._native_kerberos.authGSSClientInit(uri, flags, callback); +} + +Kerberos.prototype.authGSSClientStep = function(context, challenge, callback) { + if(typeof challenge == 'function') { + callback = challenge; + challenge = ''; + } + + return this._native_kerberos.authGSSClientStep(context, challenge, callback); +} + +Kerberos.prototype.authGSSClientUnwrap = function(context, challenge, callback) { + if(typeof challenge == 'function') { + callback = challenge; + challenge = ''; + } + + return this._native_kerberos.authGSSClientUnwrap(context, challenge, callback); +} + +Kerberos.prototype.authGSSClientWrap = function(context, challenge, user_name, callback) { + if(typeof user_name == 'function') { + callback = user_name; + user_name = ''; + } + + return this._native_kerberos.authGSSClientWrap(context, challenge, user_name, callback); +} + +Kerberos.prototype.authGSSClientClean = function(context, callback) { + return this._native_kerberos.authGSSClientClean(context, callback); +} + +Kerberos.prototype.acquireAlternateCredentials = function(user_name, password, domain) { + return this._native_kerberos.acquireAlternateCredentials(user_name, password, domain); +} + +Kerberos.prototype.prepareOutboundPackage = function(principal, inputdata) { + return this._native_kerberos.prepareOutboundPackage(principal, inputdata); +} + +Kerberos.prototype.decryptMessage = function(challenge) { + return this._native_kerberos.decryptMessage(challenge); +} + +Kerberos.prototype.encryptMessage = function(challenge) { + return this._native_kerberos.encryptMessage(challenge); +} + +Kerberos.prototype.queryContextAttribute = function(attribute) { + if(typeof attribute != 'number' && attribute != 0x00) throw new Error("Attribute not supported"); + return this._native_kerberos.queryContextAttribute(attribute); +} + +// Some useful result codes +Kerberos.AUTH_GSS_CONTINUE = 0; +Kerberos.AUTH_GSS_COMPLETE = 1; + +// Some useful gss flags +Kerberos.GSS_C_DELEG_FLAG = 1; +Kerberos.GSS_C_MUTUAL_FLAG = 2; +Kerberos.GSS_C_REPLAY_FLAG = 4; +Kerberos.GSS_C_SEQUENCE_FLAG = 8; +Kerberos.GSS_C_CONF_FLAG = 16; +Kerberos.GSS_C_INTEG_FLAG = 32; +Kerberos.GSS_C_ANON_FLAG = 64; +Kerberos.GSS_C_PROT_READY_FLAG = 128; +Kerberos.GSS_C_TRANS_FLAG = 256; + +// Export Kerberos class +exports.Kerberos = Kerberos; + +// If we have SSPI (windows) +if(kerberos.SecurityCredentials) { + // Put all SSPI classes in it's own namespace + exports.SSIP = { + SecurityCredentials: require('./win32/wrappers/security_credentials').SecurityCredentials + , SecurityContext: require('./win32/wrappers/security_context').SecurityContext + , SecurityBuffer: require('./win32/wrappers/security_buffer').SecurityBuffer + , SecurityBufferDescriptor: require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor + } +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc new file mode 100644 index 0000000..7a5f4eb --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc @@ -0,0 +1,74 @@ +#include "kerberos_context.h" + +Persistent KerberosContext::constructor_template; + +KerberosContext::KerberosContext() : ObjectWrap() { +} + +KerberosContext::~KerberosContext() { +} + +KerberosContext* KerberosContext::New() { + HandleScope scope; + + Local obj = constructor_template->GetFunction()->NewInstance(); + KerberosContext *kerberos_context = ObjectWrap::Unwrap(obj); + + return kerberos_context; +} + +Handle KerberosContext::New(const Arguments &args) { + HandleScope scope; + // Create code object + KerberosContext *kerberos_context = new KerberosContext(); + // Wrap it + kerberos_context->Wrap(args.This()); + // Return the object + return args.This(); +} + +static Persistent response_symbol; + +void KerberosContext::Initialize(Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("KerberosContext")); + + // Property symbols + response_symbol = NODE_PSYMBOL("response"); + + // Getter for the response + constructor_template->InstanceTemplate()->SetAccessor(response_symbol, ResponseGetter); + + // Set up the Symbol for the Class on the Module + target->Set(String::NewSymbol("KerberosContext"), constructor_template->GetFunction()); +} + +// +// Response Setter / Getter +Handle KerberosContext::ResponseGetter(Local property, const AccessorInfo& info) { + HandleScope scope; + gss_client_state *state; + + // Unpack the object + KerberosContext *context = ObjectWrap::Unwrap(info.Holder()); + // Let's grab the response + state = context->state; + // No state no response + if(state == NULL || state->response == NULL) return scope.Close(Null()); + // Return the response + return scope.Close(String::New(state->response)); +} + + + + + + + + + diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h new file mode 100644 index 0000000..1b62cba --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h @@ -0,0 +1,48 @@ +#ifndef KERBEROS_CONTEXT_H +#define KERBEROS_CONTEXT_H + +#include +#include +#include + +#include +#include +#include + +extern "C" { + #include "kerberosgss.h" +} + +using namespace v8; +using namespace node; + +class KerberosContext : public ObjectWrap { + +public: + KerberosContext(); + ~KerberosContext(); + + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return constructor_template->HasInstance(obj); + }; + + // Constructor used for creating new Kerberos objects from C++ + static Persistent constructor_template; + + // Initialize function for the object + static void Initialize(Handle target); + + // Public constructor + static KerberosContext* New(); + + // Handle to the kerberos context + gss_client_state *state; + +private: + static Handle New(const Arguments &args); + + static Handle ResponseGetter(Local property, const AccessorInfo& info); +}; +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c new file mode 100644 index 0000000..ddf8c4a --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c @@ -0,0 +1,668 @@ +/** + * Copyright (c) 2006-2010 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "kerberosgss.h" + +#include "base64.h" + +#include +#include +#include +#include + +static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min); + +/*extern PyObject *GssException_class; +extern PyObject *KrbException_class; + +char* server_principal_details(const char* service, const char* hostname) +{ + char match[1024]; + int match_len = 0; + char* result = NULL; + + int code; + krb5_context kcontext; + krb5_keytab kt = NULL; + krb5_kt_cursor cursor = NULL; + krb5_keytab_entry entry; + char* pname = NULL; + + // Generate the principal prefix we want to match + snprintf(match, 1024, "%s/%s@", service, hostname); + match_len = strlen(match); + + code = krb5_init_context(&kcontext); + if (code) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot initialize Kerberos5 context", code)); + return NULL; + } + + if ((code = krb5_kt_default(kcontext, &kt))) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot get default keytab", code)); + goto end; + } + + if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot get sequence cursor from keytab", code)); + goto end; + } + + while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) + { + if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot parse principal name from keytab", code)); + goto end; + } + + if (strncmp(pname, match, match_len) == 0) + { + result = malloc(strlen(pname) + 1); + strcpy(result, pname); + krb5_free_unparsed_name(kcontext, pname); + krb5_free_keytab_entry_contents(kcontext, &entry); + break; + } + + krb5_free_unparsed_name(kcontext, pname); + krb5_free_keytab_entry_contents(kcontext, &entry); + } + + if (result == NULL) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Principal not found in keytab", -1)); + } + +end: + if (cursor) + krb5_kt_end_seq_get(kcontext, kt, &cursor); + if (kt) + krb5_kt_close(kcontext, kt); + krb5_free_context(kcontext); + + return result; +} +*/ +gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; + gss_client_response *response = NULL; + int ret = AUTH_GSS_COMPLETE; + + state->server_name = GSS_C_NO_NAME; + state->context = GSS_C_NO_CONTEXT; + state->gss_flags = gss_flags; + state->username = NULL; + state->response = NULL; + + // Import server name first + name_token.length = strlen(service); + name_token.value = (char *)service; + + maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name); + + if (GSS_ERROR(maj_stat)) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } + +end: + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + response->return_code = ret; + } + + return response; +} + +gss_client_response *authenticate_gss_client_clean(gss_client_state *state) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + int ret = AUTH_GSS_COMPLETE; + gss_client_response *response = NULL; + + if(state->context != GSS_C_NO_CONTEXT) + maj_stat = gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); + + if(state->server_name != GSS_C_NO_NAME) + maj_stat = gss_release_name(&min_stat, &state->server_name); + + if(state->username != NULL) { + free(state->username); + state->username = NULL; + } + + if (state->response != NULL) { + free(state->response); + state->response = NULL; + } + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + response->return_code = ret; + } + + return response; +} + +gss_client_response *authenticate_gss_client_step(gss_client_state* state, const char* challenge) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_CONTINUE; + gss_client_response *response = NULL; + + // Always clear out the old response + if (state->response != NULL) { + free(state->response); + state->response = NULL; + } + + // If there is a challenge (data from the server) we need to give it to GSS + if (challenge && *challenge) { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + + // Do GSSAPI step + maj_stat = gss_init_sec_context(&min_stat, + GSS_C_NO_CREDENTIAL, + &state->context, + state->server_name, + GSS_C_NO_OID, + (OM_uint32)state->gss_flags, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + NULL, + &output_token, + NULL, + NULL); + + if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } + + ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE; + // Grab the client response to send back to the server + if(output_token.length) { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); + maj_stat = gss_release_buffer(&min_stat, &output_token); + } + + // Try to get the user name if we have completed all GSS operations + if (ret == AUTH_GSS_COMPLETE) { + gss_name_t gssuser = GSS_C_NO_NAME; + maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL); + + if(GSS_ERROR(maj_stat)) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } + + gss_buffer_desc name_token; + name_token.length = 0; + maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL); + + if(GSS_ERROR(maj_stat)) { + if(name_token.value) + gss_release_buffer(&min_stat, &name_token); + gss_release_name(&min_stat, &gssuser); + + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } else { + state->username = (char *)malloc(name_token.length + 1); + strncpy(state->username, (char*) name_token.value, name_token.length); + state->username[name_token.length] = 0; + gss_release_buffer(&min_stat, &name_token); + gss_release_name(&min_stat, &gssuser); + } + } + +end: + if(output_token.value) + gss_release_buffer(&min_stat, &output_token); + if(input_token.value) + free(input_token.value); + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + response->return_code = ret; + } + + // Return the response + return response; +} + +gss_client_response *authenticate_gss_client_unwrap(gss_client_state *state, const char *challenge) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_client_response *response = NULL; + int ret = AUTH_GSS_CONTINUE; + + // Always clear out the old response + if(state->response != NULL) { + free(state->response); + state->response = NULL; + } + + // If there is a challenge (data from the server) we need to give it to GSS + if(challenge && *challenge) { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + + // Do GSSAPI step + maj_stat = gss_unwrap(&min_stat, + state->context, + &input_token, + &output_token, + NULL, + NULL); + + if(maj_stat != GSS_S_COMPLETE) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } else { + ret = AUTH_GSS_COMPLETE; + } + + // Grab the client response + if(output_token.length) { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); + maj_stat = gss_release_buffer(&min_stat, &output_token); + } +end: + if(output_token.value) + gss_release_buffer(&min_stat, &output_token); + if(input_token.value) + free(input_token.value); + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + response->return_code = ret; + } + + // Return the response + return response; +} + +gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_CONTINUE; + gss_client_response *response = NULL; + char buf[4096], server_conf_flags; + unsigned long buf_size; + + // Always clear out the old response + if(state->response != NULL) { + free(state->response); + state->response = NULL; + } + + if(challenge && *challenge) { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + + if(user) { + // get bufsize + server_conf_flags = ((char*) input_token.value)[0]; + ((char*) input_token.value)[0] = 0; + buf_size = ntohl(*((long *) input_token.value)); + free(input_token.value); +#ifdef PRINTFS + printf("User: %s, %c%c%c\n", user, + server_conf_flags & GSS_AUTH_P_NONE ? 'N' : '-', + server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-', + server_conf_flags & GSS_AUTH_P_PRIVACY ? 'P' : '-'); + printf("Maximum GSS token size is %ld\n", buf_size); +#endif + + // agree to terms (hack!) + buf_size = htonl(buf_size); // not relevant without integrity/privacy + memcpy(buf, &buf_size, 4); + buf[0] = GSS_AUTH_P_NONE; + // server decides if principal can log in as user + strncpy(buf + 4, user, sizeof(buf) - 4); + input_token.value = buf; + input_token.length = 4 + strlen(user); + } + + // Do GSSAPI wrap + maj_stat = gss_wrap(&min_stat, + state->context, + 0, + GSS_C_QOP_DEFAULT, + &input_token, + NULL, + &output_token); + + if (maj_stat != GSS_S_COMPLETE) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } else + ret = AUTH_GSS_COMPLETE; + // Grab the client response to send back to the server + if (output_token.length) { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; + maj_stat = gss_release_buffer(&min_stat, &output_token); + } +end: + if (output_token.value) + gss_release_buffer(&min_stat, &output_token); + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + response->return_code = ret; + } + + // Return the response + return response; +} + +int authenticate_gss_server_init(const char *service, gss_server_state *state) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_COMPLETE; + + state->context = GSS_C_NO_CONTEXT; + state->server_name = GSS_C_NO_NAME; + state->client_name = GSS_C_NO_NAME; + state->server_creds = GSS_C_NO_CREDENTIAL; + state->client_creds = GSS_C_NO_CREDENTIAL; + state->username = NULL; + state->targetname = NULL; + state->response = NULL; + + // Server name may be empty which means we aren't going to create our own creds + size_t service_len = strlen(service); + if (service_len != 0) + { + // Import server name first + name_token.length = strlen(service); + name_token.value = (char *)service; + + maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name); + + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + + // Get credentials + maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_ACCEPT, &state->server_creds, NULL, NULL); + + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + } + +end: + return ret; +} + +int authenticate_gss_server_clean(gss_server_state *state) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + int ret = AUTH_GSS_COMPLETE; + + if (state->context != GSS_C_NO_CONTEXT) + maj_stat = gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); + if (state->server_name != GSS_C_NO_NAME) + maj_stat = gss_release_name(&min_stat, &state->server_name); + if (state->client_name != GSS_C_NO_NAME) + maj_stat = gss_release_name(&min_stat, &state->client_name); + if (state->server_creds != GSS_C_NO_CREDENTIAL) + maj_stat = gss_release_cred(&min_stat, &state->server_creds); + if (state->client_creds != GSS_C_NO_CREDENTIAL) + maj_stat = gss_release_cred(&min_stat, &state->client_creds); + if (state->username != NULL) + { + free(state->username); + state->username = NULL; + } + if (state->targetname != NULL) + { + free(state->targetname); + state->targetname = NULL; + } + if (state->response != NULL) + { + free(state->response); + state->response = NULL; + } + + return ret; +} + +/*int authenticate_gss_server_step(gss_server_state *state, const char *challenge) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_CONTINUE; + + // Always clear out the old response + if (state->response != NULL) + { + free(state->response); + state->response = NULL; + } + + // If there is a challenge (data from the server) we need to give it to GSS + if (challenge && *challenge) + { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + else + { + PyErr_SetString(KrbException_class, "No challenge parameter in request from client"); + ret = AUTH_GSS_ERROR; + goto end; + } + + maj_stat = gss_accept_sec_context(&min_stat, + &state->context, + state->server_creds, + &input_token, + GSS_C_NO_CHANNEL_BINDINGS, + &state->client_name, + NULL, + &output_token, + NULL, + NULL, + &state->client_creds); + + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + + // Grab the server response to send back to the client + if (output_token.length) + { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; + maj_stat = gss_release_buffer(&min_stat, &output_token); + } + + // Get the user name + maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL); + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + state->username = (char *)malloc(output_token.length + 1); + strncpy(state->username, (char*) output_token.value, output_token.length); + state->username[output_token.length] = 0; + + // Get the target name if no server creds were supplied + if (state->server_creds == GSS_C_NO_CREDENTIAL) + { + gss_name_t target_name = GSS_C_NO_NAME; + maj_stat = gss_inquire_context(&min_stat, state->context, NULL, &target_name, NULL, NULL, NULL, NULL, NULL); + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + maj_stat = gss_display_name(&min_stat, target_name, &output_token, NULL); + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + state->targetname = (char *)malloc(output_token.length + 1); + strncpy(state->targetname, (char*) output_token.value, output_token.length); + state->targetname[output_token.length] = 0; + } + + ret = AUTH_GSS_COMPLETE; + +end: + if (output_token.length) + gss_release_buffer(&min_stat, &output_token); + if (input_token.value) + free(input_token.value); + return ret; +} +*/ + +static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf_maj[512]; + char buf_min[512]; + + do { + maj_stat = gss_display_status (&min_stat, + err_maj, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(GSS_ERROR(maj_stat)) + break; + + strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj)); + gss_release_buffer(&min_stat, &status_string); + + maj_stat = gss_display_status (&min_stat, + err_min, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + if (!GSS_ERROR(maj_stat)) { + + strncpy(buf_min, (char*) status_string.value , sizeof(buf_min)); + gss_release_buffer(&min_stat, &status_string); + } + } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); +} + +gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char *buf_maj = calloc(512, sizeof(char)); + char *buf_min = calloc(512, sizeof(char)); + char *message = NULL; + gss_client_response *response = calloc(1, sizeof(gss_client_response)); + + do { + maj_stat = gss_display_status (&min_stat, + err_maj, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(GSS_ERROR(maj_stat)) + break; + + strncpy(buf_maj, (char*) status_string.value, 512); + gss_release_buffer(&min_stat, &status_string); + + maj_stat = gss_display_status (&min_stat, + err_min, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + if(!GSS_ERROR(maj_stat)) { + strncpy(buf_min, (char*) status_string.value , 512); + gss_release_buffer(&min_stat, &status_string); + } + } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); + + // Join the strings + message = calloc(1024, sizeof(1)); + // Join the two messages + sprintf(message, "%s, %s", buf_maj, buf_min); + // Free data + free(buf_min); + free(buf_maj); + // Set the message + response->message = message; + // Return the message + return response; +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h new file mode 100644 index 0000000..58ac0b7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2006-2009 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#ifndef KERBEROS_GSS_H +#define KERBEROS_GSS_H + +#include +#include +#include + +#define krb5_get_err_text(context,code) error_message(code) + +#define AUTH_GSS_ERROR -1 +#define AUTH_GSS_COMPLETE 1 +#define AUTH_GSS_CONTINUE 0 + +#define GSS_AUTH_P_NONE 1 +#define GSS_AUTH_P_INTEGRITY 2 +#define GSS_AUTH_P_PRIVACY 4 + +typedef struct { + int return_code; + char *message; +} gss_client_response; + +typedef struct { + gss_ctx_id_t context; + gss_name_t server_name; + long int gss_flags; + char* username; + char* response; +} gss_client_state; + +typedef struct { + gss_ctx_id_t context; + gss_name_t server_name; + gss_name_t client_name; + gss_cred_id_t server_creds; + gss_cred_id_t client_creds; + char* username; + char* targetname; + char* response; +} gss_server_state; + +// char* server_principal_details(const char* service, const char* hostname); + +gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state); +gss_client_response *authenticate_gss_client_clean(gss_client_state *state); +gss_client_response *authenticate_gss_client_step(gss_client_state *state, const char *challenge); +gss_client_response *authenticate_gss_client_unwrap(gss_client_state* state, const char* challenge); +gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user); + +int authenticate_gss_server_init(const char* service, gss_server_state* state); +int authenticate_gss_server_clean(gss_server_state *state); +// int authenticate_gss_server_step(gss_server_state *state, const char *challenge); + +gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min); +#endif diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/sspi.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/sspi.js new file mode 100644 index 0000000..d9120fb --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/sspi.js @@ -0,0 +1,15 @@ +// Load the native SSPI classes +var kerberos = require('../build/Release/kerberos') + , Kerberos = kerberos.Kerberos + , SecurityBuffer = require('./win32/wrappers/security_buffer').SecurityBuffer + , SecurityBufferDescriptor = require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor + , SecurityCredentials = require('./win32/wrappers/security_credentials').SecurityCredentials + , SecurityContext = require('./win32/wrappers/security_context').SecurityContext; +var SSPI = function() { +} + +exports.SSPI = SSPI; +exports.SecurityBuffer = SecurityBuffer; +exports.SecurityBufferDescriptor = SecurityBufferDescriptor; +exports.SecurityCredentials = SecurityCredentials; +exports.SecurityContext = SecurityContext; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c new file mode 100644 index 0000000..502a021 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "base64.h" + +#include +#include + +// base64 tables +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static signed char index_64[128] = +{ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +// base64_encode : base64 encode +// +// value : data to encode +// vlen : length of data +// (result) : new char[] - c-str of result +char *base64_encode(const unsigned char *value, int vlen) +{ + char *result = (char *)malloc((vlen * 4) / 3 + 5); + char *out = result; + unsigned char oval; + + while (vlen >= 3) + { + *out++ = basis_64[value[0] >> 2]; + *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; + *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; + *out++ = basis_64[value[2] & 0x3F]; + value += 3; + vlen -= 3; + } + if (vlen > 0) + { + *out++ = basis_64[value[0] >> 2]; + oval = (value[0] << 4) & 0x30; + if (vlen > 1) oval |= value[1] >> 4; + *out++ = basis_64[oval]; + *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; + *out++ = '='; + } + *out = '\0'; + + return result; +} + +// base64_decode : base64 decode +// +// value : c-str to decode +// rlen : length of decoded result +// (result) : new unsigned char[] - decoded result +unsigned char *base64_decode(const char *value, int *rlen) +{ + int c1, c2, c3, c4; + int vlen = (int)strlen(value); + unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1); + unsigned char *out = result; + *rlen = 0; + + while (1) + { + if (value[0]==0) + return result; + c1 = value[0]; + if (CHAR64(c1) == -1) + goto base64_decode_error;; + c2 = value[1]; + if (CHAR64(c2) == -1) + goto base64_decode_error;; + c3 = value[2]; + if ((c3 != '=') && (CHAR64(c3) == -1)) + goto base64_decode_error;; + c4 = value[3]; + if ((c4 != '=') && (CHAR64(c4) == -1)) + goto base64_decode_error;; + + value += 4; + *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + *rlen += 1; + if (c3 != '=') + { + *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + *rlen += 1; + if (c4 != '=') + { + *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + *rlen += 1; + } + } + } + +base64_decode_error: + *result = 0; + *rlen = 0; + return result; +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h new file mode 100644 index 0000000..f0e1f06 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +char *base64_encode(const unsigned char *value, int vlen); +unsigned char *base64_decode(const char *value, int *rlen); diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc new file mode 100644 index 0000000..7fd521b --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc @@ -0,0 +1,53 @@ +#include "kerberos.h" +#include +#include +#include "base64.h" +#include "wrappers/security_buffer.h" +#include "wrappers/security_buffer_descriptor.h" +#include "wrappers/security_context.h" +#include "wrappers/security_credentials.h" + +Persistent Kerberos::constructor_template; + +// VException object (causes throw in calling code) +static Handle VException(const char *msg) { + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +} + +Kerberos::Kerberos() : ObjectWrap() { +} + +void Kerberos::Initialize(v8::Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(Kerberos::New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("Kerberos")); + // Set the symbol + target->ForceSet(String::NewSymbol("Kerberos"), constructor_template->GetFunction()); +} + +Handle Kerberos::New(const Arguments &args) { + // Load the security.dll library + load_library(); + // Create a Kerberos instance + Kerberos *kerberos = new Kerberos(); + // Return the kerberos object + kerberos->Wrap(args.This()); + return args.This(); +} + +// Exporting function +extern "C" void init(Handle target) { + HandleScope scope; + Kerberos::Initialize(target); + SecurityContext::Initialize(target); + SecurityBuffer::Initialize(target); + SecurityBufferDescriptor::Initialize(target); + SecurityCredentials::Initialize(target); +} + +NODE_MODULE(kerberos, init); diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h new file mode 100644 index 0000000..8443e78 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h @@ -0,0 +1,59 @@ +#ifndef KERBEROS_H +#define KERBEROS_H + +#include +#include +#include + +extern "C" { + #include "kerberos_sspi.h" + #include "base64.h" +} + +using namespace v8; +using namespace node; + +class Kerberos : public ObjectWrap { + +public: + Kerberos(); + ~Kerberos() {}; + + // Constructor used for creating new Kerberos objects from C++ + static Persistent constructor_template; + + // Initialize function for the object + static void Initialize(Handle target); + + // Method available + static Handle AcquireAlternateCredentials(const Arguments &args); + static Handle PrepareOutboundPackage(const Arguments &args); + static Handle DecryptMessage(const Arguments &args); + static Handle EncryptMessage(const Arguments &args); + static Handle QueryContextAttributes(const Arguments &args); + +private: + static Handle New(const Arguments &args); + + // Pointer to context object + SEC_WINNT_AUTH_IDENTITY m_Identity; + // credentials + CredHandle m_Credentials; + // Expiry time for ticket + TimeStamp Expiration; + // package info + SecPkgInfo m_PkgInfo; + // context + CtxtHandle m_Context; + // Do we have a context + bool m_HaveContext; + // Attributes + DWORD CtxtAttr; + + // Handles the uv calls + static void Process(uv_work_t* work_req); + // Called after work is done + static void After(uv_work_t* work_req); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c new file mode 100644 index 0000000..d75c9ab --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c @@ -0,0 +1,244 @@ +#include "kerberos_sspi.h" +#include +#include + +static HINSTANCE _sspi_security_dll = NULL; +static HINSTANCE _sspi_secur32_dll = NULL; + +/** + * Encrypt A Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo) { + // Create function pointer instance + encryptMessage_fn pfn_encryptMessage = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + // Map function to library method + pfn_encryptMessage = (encryptMessage_fn)GetProcAddress(_sspi_security_dll, "EncryptMessage"); + // Check if the we managed to map function pointer + if(!pfn_encryptMessage) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_encryptMessage)(phContext, fQOP, pMessage, MessageSeqNo); +} + +/** + * Acquire Credentials + */ +SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle( + LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, + void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument, + PCredHandle phCredential, PTimeStamp ptsExpiry +) { + SECURITY_STATUS status; + // Create function pointer instance + acquireCredentialsHandle_fn pfn_acquireCredentialsHandle = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + // Map function + #ifdef _UNICODE + pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleW"); + #else + pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleA"); + #endif + + // Check if the we managed to map function pointer + if(!pfn_acquireCredentialsHandle) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Status + status = (*pfn_acquireCredentialsHandle)(pszPrincipal, pszPackage, fCredentialUse, + pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry + ); + + // Call the function + return status; +} + +/** + * Delete Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext(PCtxtHandle phContext) { + // Create function pointer instance + deleteSecurityContext_fn pfn_deleteSecurityContext = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + // Map function + pfn_deleteSecurityContext = (deleteSecurityContext_fn)GetProcAddress(_sspi_security_dll, "DeleteSecurityContext"); + + // Check if the we managed to map function pointer + if(!pfn_deleteSecurityContext) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_deleteSecurityContext)(phContext); +} + +/** + * Decrypt Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP) { + // Create function pointer instance + decryptMessage_fn pfn_decryptMessage = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + // Map function + pfn_decryptMessage = (decryptMessage_fn)GetProcAddress(_sspi_security_dll, "DecryptMessage"); + + // Check if the we managed to map function pointer + if(!pfn_decryptMessage) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_decryptMessage)(phContext, pMessage, MessageSeqNo, pfQOP); +} + +/** + * Initialize Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext( + PCredHandle phCredential, PCtxtHandle phContext, + LPSTR pszTargetName, unsigned long fContextReq, + unsigned long Reserved1, unsigned long TargetDataRep, + PSecBufferDesc pInput, unsigned long Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, + unsigned long * pfContextAttr, PTimeStamp ptsExpiry +) { + SECURITY_STATUS status; + // Create function pointer instance + initializeSecurityContext_fn pfn_initializeSecurityContext = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + // Map function + #ifdef _UNICODE + pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextW"); + #else + pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextA"); + #endif + + // Check if the we managed to map function pointer + if(!pfn_initializeSecurityContext) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Execute intialize context + status = (*pfn_initializeSecurityContext)( + phCredential, phContext, pszTargetName, fContextReq, + Reserved1, TargetDataRep, pInput, Reserved2, + phNewContext, pOutput, pfContextAttr, ptsExpiry + ); + + // Call the function + return status; +} +/** + * Query Context Attributes + */ +SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes( + PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer +) { + // Create function pointer instance + queryContextAttributes_fn pfn_queryContextAttributes = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + #ifdef _UNICODE + pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesW"); + #else + pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesA"); + #endif + + // Check if the we managed to map function pointer + if(!pfn_queryContextAttributes) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_queryContextAttributes)( + phContext, ulAttribute, pBuffer + ); +} + +/** + * InitSecurityInterface + */ +PSecurityFunctionTable _ssip_InitSecurityInterface() { + INIT_SECURITY_INTERFACE InitSecurityInterface; + PSecurityFunctionTable pSecurityInterface = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return NULL; + + #ifdef _UNICODE + // Get the address of the InitSecurityInterface function. + InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress ( + _sspi_secur32_dll, + TEXT("InitSecurityInterfaceW")); + #else + // Get the address of the InitSecurityInterface function. + InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress ( + _sspi_secur32_dll, + TEXT("InitSecurityInterfaceA")); + #endif + + if(!InitSecurityInterface) { + printf (TEXT("Failed in getting the function address, Error: %x"), GetLastError ()); + return NULL; + } + + // Use InitSecurityInterface to get the function table. + pSecurityInterface = (*InitSecurityInterface)(); + + if(!pSecurityInterface) { + printf (TEXT("Failed in getting the function table, Error: %x"), GetLastError ()); + return NULL; + } + + return pSecurityInterface; +} + +/** + * Load security.dll dynamically + */ +int load_library() { + DWORD err; + // Load the library + _sspi_security_dll = LoadLibrary("security.dll"); + + // Check if the library loaded + if(_sspi_security_dll == NULL) { + err = GetLastError(); + return err; + } + + // Load the library + _sspi_secur32_dll = LoadLibrary("secur32.dll"); + + // Check if the library loaded + if(_sspi_secur32_dll == NULL) { + err = GetLastError(); + return err; + } + + return 0; +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h new file mode 100644 index 0000000..a3008dc --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h @@ -0,0 +1,106 @@ +#ifndef SSPI_C_H +#define SSPI_C_H + +#define SECURITY_WIN32 1 + +#include +#include + +/** + * Encrypt A Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo); + +typedef DWORD (WINAPI *encryptMessage_fn)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); + +/** + * Acquire Credentials + */ +SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle( + LPSTR pszPrincipal, // Name of principal + LPSTR pszPackage, // Name of package + unsigned long fCredentialUse, // Flags indicating use + void * pvLogonId, // Pointer to logon ID + void * pAuthData, // Package specific data + SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func + void * pvGetKeyArgument, // Value to pass to GetKey() + PCredHandle phCredential, // (out) Cred Handle + PTimeStamp ptsExpiry // (out) Lifetime (optional) +); + +typedef DWORD (WINAPI *acquireCredentialsHandle_fn)( + LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, + void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument, + PCredHandle phCredential, PTimeStamp ptsExpiry + ); + +/** + * Delete Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext( + PCtxtHandle phContext // Context to delete +); + +typedef DWORD (WINAPI *deleteSecurityContext_fn)(PCtxtHandle phContext); + +/** + * Decrypt Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage( + PCtxtHandle phContext, + PSecBufferDesc pMessage, + unsigned long MessageSeqNo, + unsigned long pfQOP +); + +typedef DWORD (WINAPI *decryptMessage_fn)( + PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP); + +/** + * Initialize Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext( + PCredHandle phCredential, // Cred to base context + PCtxtHandle phContext, // Existing context (OPT) + LPSTR pszTargetName, // Name of target + unsigned long fContextReq, // Context Requirements + unsigned long Reserved1, // Reserved, MBZ + unsigned long TargetDataRep, // Data rep of target + PSecBufferDesc pInput, // Input Buffers + unsigned long Reserved2, // Reserved, MBZ + PCtxtHandle phNewContext, // (out) New Context handle + PSecBufferDesc pOutput, // (inout) Output Buffers + unsigned long * pfContextAttr, // (out) Context attrs + PTimeStamp ptsExpiry // (out) Life span (OPT) +); + +typedef DWORD (WINAPI *initializeSecurityContext_fn)( + PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, unsigned long fContextReq, + unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long * pfContextAttr, PTimeStamp ptsExpiry); + +/** + * Query Context Attributes + */ +SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes( + PCtxtHandle phContext, // Context to query + unsigned long ulAttribute, // Attribute to query + void * pBuffer // Buffer for attributes +); + +typedef DWORD (WINAPI *queryContextAttributes_fn)( + PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer); + +/** + * InitSecurityInterface + */ +PSecurityFunctionTable _ssip_InitSecurityInterface(); + +typedef DWORD (WINAPI *initSecurityInterface_fn) (); + +/** + * Load security.dll dynamically + */ +int load_library(); + +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc new file mode 100644 index 0000000..e7a472f --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc @@ -0,0 +1,7 @@ +#include "worker.h" + +Worker::Worker() { +} + +Worker::~Worker() { +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h new file mode 100644 index 0000000..f73a4a7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h @@ -0,0 +1,37 @@ +#ifndef WORKER_H_ +#define WORKER_H_ + +#include +#include +#include + +using namespace node; +using namespace v8; + +class Worker { + public: + Worker(); + virtual ~Worker(); + + // libuv's request struct. + uv_work_t request; + // Callback + v8::Persistent callback; + // Parameters + void *parameters; + // Results + void *return_value; + // Did we raise an error + bool error; + // The error message + char *error_message; + // Error code if not message + int error_code; + // Any return code + int return_code; + // Method we are going to fire + void (*execute)(Worker *worker); + Handle (*mapper)(Worker *worker); +}; + +#endif // WORKER_H_ diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc new file mode 100644 index 0000000..e583336 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "security_buffer.h" + +using namespace node; + +static Handle VException(const char *msg) { + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +}; + +Persistent SecurityBuffer::constructor_template; + +SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size) : ObjectWrap() { + this->size = size; + this->data = calloc(size, sizeof(char)); + this->security_type = security_type; + // Set up the data in the sec_buffer + this->sec_buffer.BufferType = security_type; + this->sec_buffer.cbBuffer = (unsigned long)size; + this->sec_buffer.pvBuffer = this->data; +} + +SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size, void *data) : ObjectWrap() { + this->size = size; + this->data = data; + this->security_type = security_type; + // Set up the data in the sec_buffer + this->sec_buffer.BufferType = security_type; + this->sec_buffer.cbBuffer = (unsigned long)size; + this->sec_buffer.pvBuffer = this->data; +} + +SecurityBuffer::~SecurityBuffer() { + free(this->data); +} + +Handle SecurityBuffer::New(const Arguments &args) { + HandleScope scope; + SecurityBuffer *security_obj; + + if(args.Length() != 2) + return VException("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); + + if(!args[0]->IsInt32()) + return VException("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); + + if(!args[1]->IsInt32() && !Buffer::HasInstance(args[1])) + return VException("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); + + // Unpack buffer type + uint32_t buffer_type = args[0]->ToUint32()->Value(); + + // If we have an integer + if(args[1]->IsInt32()) { + security_obj = new SecurityBuffer(buffer_type, args[1]->ToUint32()->Value()); + } else { + // Get the length of the Buffer + size_t length = Buffer::Length(args[1]->ToObject()); + // Allocate space for the internal void data pointer + void *data = calloc(length, sizeof(char)); + // Write the data to out of V8 heap space + memcpy(data, Buffer::Data(args[1]->ToObject()), length); + // Create new SecurityBuffer + security_obj = new SecurityBuffer(buffer_type, length, data); + } + + // Wrap it + security_obj->Wrap(args.This()); + // Return the object + return args.This(); +} + +Handle SecurityBuffer::ToBuffer(const Arguments &args) { + HandleScope scope; + + // Unpack the Security Buffer object + SecurityBuffer *security_obj = ObjectWrap::Unwrap(args.This()); + // Create a Buffer + Buffer *buffer = Buffer::New((char *)security_obj->data, (size_t)security_obj->size); + + // Return the buffer + return scope.Close(buffer->handle_); +} + +void SecurityBuffer::Initialize(Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("SecurityBuffer")); + + // Set up method for the Kerberos instance + NODE_SET_PROTOTYPE_METHOD(constructor_template, "toBuffer", ToBuffer); + + // Set up class + target->Set(String::NewSymbol("SecurityBuffer"), constructor_template->GetFunction()); +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h new file mode 100644 index 0000000..d6a5675 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h @@ -0,0 +1,46 @@ +#ifndef SECURITY_BUFFER_H +#define SECURITY_BUFFER_H + +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include +#include + +using namespace v8; +using namespace node; + +class SecurityBuffer : public ObjectWrap { + public: + SecurityBuffer(uint32_t security_type, size_t size); + SecurityBuffer(uint32_t security_type, size_t size, void *data); + ~SecurityBuffer(); + + // Internal values + void *data; + size_t size; + uint32_t security_type; + SecBuffer sec_buffer; + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return constructor_template->HasInstance(obj); + }; + + // Functions available from V8 + static void Initialize(Handle target); + static Handle ToBuffer(const Arguments &args); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + static Handle New(const Arguments &args); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js new file mode 100644 index 0000000..4996163 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js @@ -0,0 +1,12 @@ +var SecurityBufferNative = require('../../../build/Release/kerberos').SecurityBuffer; + +// Add some attributes +SecurityBufferNative.VERSION = 0; +SecurityBufferNative.EMPTY = 0; +SecurityBufferNative.DATA = 1; +SecurityBufferNative.TOKEN = 2; +SecurityBufferNative.PADDING = 9; +SecurityBufferNative.STREAM = 10; + +// Export the modified class +exports.SecurityBuffer = SecurityBufferNative; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc new file mode 100644 index 0000000..3bda0b7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include "security_buffer_descriptor.h" +#include "security_buffer.h" + +static Handle VException(const char *msg) { + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +}; + +Persistent SecurityBufferDescriptor::constructor_template; + +SecurityBufferDescriptor::SecurityBufferDescriptor() : ObjectWrap() { +} + +SecurityBufferDescriptor::SecurityBufferDescriptor(Persistent arrayObject) : ObjectWrap() { + SecurityBuffer *security_obj = NULL; + // Safe reference to array + this->arrayObject = arrayObject; + + // Unpack the array and ensure we have a valid descriptor + this->secBufferDesc.cBuffers = arrayObject->Length(); + this->secBufferDesc.ulVersion = SECBUFFER_VERSION; + + if(arrayObject->Length() == 1) { + // Unwrap the buffer + security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); + // Assign the buffer + this->secBufferDesc.pBuffers = &security_obj->sec_buffer; + } else { + this->secBufferDesc.pBuffers = new SecBuffer[arrayObject->Length()]; + this->secBufferDesc.cBuffers = arrayObject->Length(); + + // Assign the buffers + for(uint32_t i = 0; i < arrayObject->Length(); i++) { + security_obj = ObjectWrap::Unwrap(arrayObject->Get(i)->ToObject()); + this->secBufferDesc.pBuffers[i].BufferType = security_obj->sec_buffer.BufferType; + this->secBufferDesc.pBuffers[i].pvBuffer = security_obj->sec_buffer.pvBuffer; + this->secBufferDesc.pBuffers[i].cbBuffer = security_obj->sec_buffer.cbBuffer; + } + } +} + +SecurityBufferDescriptor::~SecurityBufferDescriptor() { +} + +size_t SecurityBufferDescriptor::bufferSize() { + SecurityBuffer *security_obj = NULL; + + if(this->secBufferDesc.cBuffers == 1) { + security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); + return security_obj->size; + } else { + int bytesToAllocate = 0; + + for(unsigned int i = 0; i < this->secBufferDesc.cBuffers; i++) { + bytesToAllocate += this->secBufferDesc.pBuffers[i].cbBuffer; + } + + // Return total size + return bytesToAllocate; + } +} + +char *SecurityBufferDescriptor::toBuffer() { + SecurityBuffer *security_obj = NULL; + char *data = NULL; + + if(this->secBufferDesc.cBuffers == 1) { + security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); + data = (char *)malloc(security_obj->size * sizeof(char)); + memcpy(data, security_obj->data, security_obj->size); + } else { + size_t bytesToAllocate = this->bufferSize(); + char *data = (char *)calloc(bytesToAllocate, sizeof(char)); + int offset = 0; + + for(unsigned int i = 0; i < this->secBufferDesc.cBuffers; i++) { + memcpy((data + offset), this->secBufferDesc.pBuffers[i].pvBuffer, this->secBufferDesc.pBuffers[i].cbBuffer); + offset +=this->secBufferDesc.pBuffers[i].cbBuffer; + } + + // Return the data + return data; + } + + return data; +} + +Handle SecurityBufferDescriptor::New(const Arguments &args) { + HandleScope scope; + SecurityBufferDescriptor *security_obj; + Persistent arrayObject; + + if(args.Length() != 1) + return VException("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); + + if(!args[0]->IsInt32() && !args[0]->IsArray()) + return VException("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); + + if(args[0]->IsArray()) { + Handle array = Handle::Cast(args[0]); + // Iterate over all items and ensure we the right type + for(uint32_t i = 0; i < array->Length(); i++) { + if(!SecurityBuffer::HasInstance(array->Get(i))) { + return VException("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); + } + } + } + + // We have a single integer + if(args[0]->IsInt32()) { + // Create new SecurityBuffer instance + Local argv[] = {Int32::New(0x02), args[0]}; + Handle security_buffer = SecurityBuffer::constructor_template->GetFunction()->NewInstance(2, argv); + // Create a new array + Local array = Array::New(1); + // Set the first value + array->Set(0, security_buffer); + // Create persistent handle + arrayObject = Persistent::New(array); + // Create descriptor + security_obj = new SecurityBufferDescriptor(arrayObject); + } else { + arrayObject = Persistent::New(Handle::Cast(args[0])); + security_obj = new SecurityBufferDescriptor(arrayObject); + } + + // Wrap it + security_obj->Wrap(args.This()); + // Return the object + return args.This(); +} + +Handle SecurityBufferDescriptor::ToBuffer(const Arguments &args) { + HandleScope scope; + + // Unpack the Security Buffer object + SecurityBufferDescriptor *security_obj = ObjectWrap::Unwrap(args.This()); + + // Get the buffer + char *buffer_data = security_obj->toBuffer(); + size_t buffer_size = security_obj->bufferSize(); + + // Create a Buffer + Buffer *buffer = Buffer::New(buffer_data, buffer_size); + + // Return the buffer + return scope.Close(buffer->handle_); +} + +void SecurityBufferDescriptor::Initialize(Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("SecurityBufferDescriptor")); + + // Set up method for the Kerberos instance + NODE_SET_PROTOTYPE_METHOD(constructor_template, "toBuffer", ToBuffer); + + target->Set(String::NewSymbol("SecurityBufferDescriptor"), constructor_template->GetFunction()); +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h new file mode 100644 index 0000000..8588632 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h @@ -0,0 +1,44 @@ +#ifndef SECURITY_BUFFER_DESCRIPTOR_H +#define SECURITY_BUFFER_DESCRIPTOR_H + +#include +#include +#include + +#include +#include + +using namespace v8; +using namespace node; + +class SecurityBufferDescriptor : public ObjectWrap { + public: + Persistent arrayObject; + SecBufferDesc secBufferDesc; + + SecurityBufferDescriptor(); + SecurityBufferDescriptor(Persistent arrayObject); + ~SecurityBufferDescriptor(); + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return constructor_template->HasInstance(obj); + }; + + char *toBuffer(); + size_t bufferSize(); + + // Functions available from V8 + static void Initialize(Handle target); + static Handle ToBuffer(const Arguments &args); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + static Handle New(const Arguments &args); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js new file mode 100644 index 0000000..9421392 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js @@ -0,0 +1,3 @@ +var SecurityBufferDescriptorNative = require('../../../build/Release/kerberos').SecurityBufferDescriptor; +// Export the modified class +exports.SecurityBufferDescriptor = SecurityBufferDescriptorNative; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc new file mode 100644 index 0000000..8c3691a --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc @@ -0,0 +1,1211 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "security_context.h" +#include "security_buffer_descriptor.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#endif + +static LPSTR DisplaySECError(DWORD ErrCode); + +static Handle VException(const char *msg) { + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +}; + +static Handle VExceptionErrNo(const char *msg, const int errorNumber) { + HandleScope scope; + + Local err = Exception::Error(String::New(msg)); + Local obj = err->ToObject(); + obj->Set(NODE_PSYMBOL("code"), Int32::New(errorNumber)); + return ThrowException(err); +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// UV Lib callbacks +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void Process(uv_work_t* work_req) { + // Grab the worker + Worker *worker = static_cast(work_req->data); + // Execute the worker code + worker->execute(worker); +} + +static void After(uv_work_t* work_req) { + // Grab the scope of the call from Node + v8::HandleScope scope; + + // Get the worker reference + Worker *worker = static_cast(work_req->data); + + // If we have an error + if(worker->error) { + v8::Local err = v8::Exception::Error(v8::String::New(worker->error_message)); + Local obj = err->ToObject(); + obj->Set(NODE_PSYMBOL("code"), Int32::New(worker->error_code)); + v8::Local args[2] = { err, v8::Local::New(v8::Null()) }; + // Execute the error + v8::TryCatch try_catch; + // Call the callback + worker->callback->Call(v8::Context::GetCurrent()->Global(), ARRAY_SIZE(args), args); + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } else { + // // Map the data + v8::Handle result = worker->mapper(worker); + // Set up the callback with a null first + v8::Handle args[2] = { v8::Local::New(v8::Null()), result}; + // Wrap the callback function call in a TryCatch so that we can call + // node's FatalException afterwards. This makes it possible to catch + // the exception from JavaScript land using the + // process.on('uncaughtException') event. + v8::TryCatch try_catch; + // Call the callback + worker->callback->Call(v8::Context::GetCurrent()->Global(), ARRAY_SIZE(args), args); + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + // Clean up the memory + worker->callback.Dispose(); + free(worker->parameters); + delete worker; +} + +Persistent SecurityContext::constructor_template; + +SecurityContext::SecurityContext() : ObjectWrap() { +} + +SecurityContext::~SecurityContext() { + if(this->hasContext) { + _sspi_DeleteSecurityContext(&this->m_Context); + } +} + +Handle SecurityContext::New(const Arguments &args) { + HandleScope scope; + + PSecurityFunctionTable pSecurityInterface = NULL; + DWORD dwNumOfPkgs; + SECURITY_STATUS status; + + // Create code object + SecurityContext *security_obj = new SecurityContext(); + // Get security table interface + pSecurityInterface = _ssip_InitSecurityInterface(); + // Call the security interface + status = (*pSecurityInterface->EnumerateSecurityPackages)( + &dwNumOfPkgs, + &security_obj->m_PkgInfo); + if(status != SEC_E_OK) { + printf(TEXT("Failed in retrieving security packages, Error: %x"), GetLastError()); + return VException("Failed in retrieving security packages"); + } + + // Wrap it + security_obj->Wrap(args.This()); + // Return the object + return args.This(); +} + +Handle SecurityContext::InitializeContextSync(const Arguments &args) { + HandleScope scope; + char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; + BYTE *out_bound_data_str = NULL; + int decoded_input_str_length = NULL; + // Store reference to security credentials + SecurityCredentials *security_credentials = NULL; + // Status of operation + SECURITY_STATUS status; + + // We need 3 parameters + if(args.Length() != 3) + return VException("Initialize must be called with either [credential:SecurityCredential, servicePrincipalName:string, input:string]"); + + // First parameter must be an instance of SecurityCredentials + if(!SecurityCredentials::HasInstance(args[0])) + return VException("First parameter for Initialize must be an instance of SecurityCredentials"); + + // Second parameter must be a string + if(!args[1]->IsString()) + return VException("Second parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[2]->IsString()) + return VException("Second parameter for Initialize must be a string"); + + // Let's unpack the values + Local service_principal_name = args[1]->ToString(); + service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); + service_principal_name->WriteUtf8(service_principal_name_str); + + // Unpack the user name + Local input = args[2]->ToString(); + + if(input->Utf8Length() > 0) { + input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); + input->WriteUtf8(input_str); + + // Now let's get the base64 decoded string + decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); + } + + // Unpack the Security credentials + security_credentials = ObjectWrap::Unwrap(args[0]->ToObject()); + + // Create Security context instance + Local security_context_value = constructor_template->GetFunction()->NewInstance(); + // Unwrap the security context + SecurityContext *security_context = ObjectWrap::Unwrap(security_context_value); + // Add a reference to the security_credentials + security_context->security_credentials = security_credentials; + + // Structures used for c calls + SecBufferDesc ibd, obd; + SecBuffer ib, ob; + + // + // Prepare data structure for returned data from SSPI + ob.BufferType = SECBUFFER_TOKEN; + ob.cbBuffer = security_context->m_PkgInfo->cbMaxToken; + // Allocate space for return data + out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; + ob.pvBuffer = out_bound_data_str; + // prepare buffer description + obd.cBuffers = 1; + obd.ulVersion = SECBUFFER_VERSION; + obd.pBuffers = &ob; + + // + // Prepare the data we are passing to the SSPI method + if(input->Utf8Length() > 0) { + ib.BufferType = SECBUFFER_TOKEN; + ib.cbBuffer = decoded_input_str_length; + ib.pvBuffer = decoded_input_str; + // prepare buffer description + ibd.cBuffers = 1; + ibd.ulVersion = SECBUFFER_VERSION; + ibd.pBuffers = &ib; + } + + // Perform initialization step + status = _sspi_initializeSecurityContext( + &security_credentials->m_Credentials + , NULL + , const_cast(service_principal_name_str) + , 0x02 // MUTUAL + , 0 + , 0 // Network + , input->Utf8Length() > 0 ? &ibd : NULL + , 0 + , &security_context->m_Context + , &obd + , &security_context->CtxtAttr + , &security_context->Expiration + ); + + // If we have a ok or continue let's prepare the result + if(status == SEC_E_OK + || status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_CONTINUE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE + ) { + security_context->hasContext = true; + security_context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); + } else { + LPSTR err_message = DisplaySECError(status); + + if(err_message != NULL) { + return VExceptionErrNo(err_message, status); + } else { + return VExceptionErrNo("Unknown error", status); + } + } + + // Return security context + return scope.Close(security_context_value); +} + +// +// Async InitializeContext +// +typedef struct SecurityContextStaticInitializeCall { + char *service_principal_name_str; + char *decoded_input_str; + int decoded_input_str_length; + SecurityContext *context; +} SecurityContextStaticInitializeCall; + +static void _initializeContext(Worker *worker) { + // Status of operation + SECURITY_STATUS status; + BYTE *out_bound_data_str = NULL; + SecurityContextStaticInitializeCall *call = (SecurityContextStaticInitializeCall *)worker->parameters; + + // Structures used for c calls + SecBufferDesc ibd, obd; + SecBuffer ib, ob; + + // + // Prepare data structure for returned data from SSPI + ob.BufferType = SECBUFFER_TOKEN; + ob.cbBuffer = call->context->m_PkgInfo->cbMaxToken; + // Allocate space for return data + out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; + ob.pvBuffer = out_bound_data_str; + // prepare buffer description + obd.cBuffers = 1; + obd.ulVersion = SECBUFFER_VERSION; + obd.pBuffers = &ob; + + // + // Prepare the data we are passing to the SSPI method + if(call->decoded_input_str_length > 0) { + ib.BufferType = SECBUFFER_TOKEN; + ib.cbBuffer = call->decoded_input_str_length; + ib.pvBuffer = call->decoded_input_str; + // prepare buffer description + ibd.cBuffers = 1; + ibd.ulVersion = SECBUFFER_VERSION; + ibd.pBuffers = &ib; + } + + // Perform initialization step + status = _sspi_initializeSecurityContext( + &call->context->security_credentials->m_Credentials + , NULL + , const_cast(call->service_principal_name_str) + , 0x02 // MUTUAL + , 0 + , 0 // Network + , call->decoded_input_str_length > 0 ? &ibd : NULL + , 0 + , &call->context->m_Context + , &obd + , &call->context->CtxtAttr + , &call->context->Expiration + ); + + // If we have a ok or continue let's prepare the result + if(status == SEC_E_OK + || status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_CONTINUE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE + ) { + call->context->hasContext = true; + call->context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); + + // Set the context + worker->return_code = status; + worker->return_value = call->context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } + + // Clean up data + if(call->decoded_input_str != NULL) free(call->decoded_input_str); + if(call->service_principal_name_str != NULL) free(call->service_principal_name_str); +} + +static Handle _map_initializeContext(Worker *worker) { + HandleScope scope; + + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return scope.Close(context->handle_); +} + +Handle SecurityContext::InitializeContext(const Arguments &args) { + HandleScope scope; + char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; + int decoded_input_str_length = NULL; + // Store reference to security credentials + SecurityCredentials *security_credentials = NULL; + + // We need 3 parameters + if(args.Length() != 4) + return VException("Initialize must be called with [credential:SecurityCredential, servicePrincipalName:string, input:string, callback:function]"); + + // First parameter must be an instance of SecurityCredentials + if(!SecurityCredentials::HasInstance(args[0])) + return VException("First parameter for Initialize must be an instance of SecurityCredentials"); + + // Second parameter must be a string + if(!args[1]->IsString()) + return VException("Second parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[2]->IsString()) + return VException("Second parameter for Initialize must be a string"); + + // Third parameter must be a callback + if(!args[3]->IsFunction()) + return VException("Third parameter for Initialize must be a callback function"); + + // Let's unpack the values + Local service_principal_name = args[1]->ToString(); + service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); + service_principal_name->WriteUtf8(service_principal_name_str); + + // Unpack the user name + Local input = args[2]->ToString(); + + if(input->Utf8Length() > 0) { + input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); + input->WriteUtf8(input_str); + + // Now let's get the base64 decoded string + decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); + // Free original allocation + free(input_str); + } + + // Unpack the Security credentials + security_credentials = ObjectWrap::Unwrap(args[0]->ToObject()); + // Create Security context instance + Local security_context_value = constructor_template->GetFunction()->NewInstance(); + // Unwrap the security context + SecurityContext *security_context = ObjectWrap::Unwrap(security_context_value); + // Add a reference to the security_credentials + security_context->security_credentials = security_credentials; + + // Build the call function + SecurityContextStaticInitializeCall *call = (SecurityContextStaticInitializeCall *)calloc(1, sizeof(SecurityContextStaticInitializeCall)); + call->context = security_context; + call->decoded_input_str = decoded_input_str; + call->decoded_input_str_length = decoded_input_str_length; + call->service_principal_name_str = service_principal_name_str; + + // Callback + Local callback = Local::Cast(args[3]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _initializeContext; + worker->mapper = _map_initializeContext; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return no value + return scope.Close(Undefined()); +} + +Handle SecurityContext::PayloadGetter(Local property, const AccessorInfo& info) { + HandleScope scope; + // Unpack the context object + SecurityContext *context = ObjectWrap::Unwrap(info.Holder()); + // Return the low bits + return scope.Close(String::New(context->payload)); +} + +Handle SecurityContext::HasContextGetter(Local property, const AccessorInfo& info) { + HandleScope scope; + // Unpack the context object + SecurityContext *context = ObjectWrap::Unwrap(info.Holder()); + // Return the low bits + return scope.Close(Boolean::New(context->hasContext)); +} + +// +// Async InitializeContextStep +// +typedef struct SecurityContextStepStaticInitializeCall { + char *service_principal_name_str; + char *decoded_input_str; + int decoded_input_str_length; + SecurityContext *context; +} SecurityContextStepStaticInitializeCall; + +static void _initializeContextStep(Worker *worker) { + // Outbound data array + BYTE *out_bound_data_str = NULL; + // Status of operation + SECURITY_STATUS status; + // Unpack data + SecurityContextStepStaticInitializeCall *call = (SecurityContextStepStaticInitializeCall *)worker->parameters; + SecurityContext *context = call->context; + // Structures used for c calls + SecBufferDesc ibd, obd; + SecBuffer ib, ob; + + // + // Prepare data structure for returned data from SSPI + ob.BufferType = SECBUFFER_TOKEN; + ob.cbBuffer = context->m_PkgInfo->cbMaxToken; + // Allocate space for return data + out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; + ob.pvBuffer = out_bound_data_str; + // prepare buffer description + obd.cBuffers = 1; + obd.ulVersion = SECBUFFER_VERSION; + obd.pBuffers = &ob; + + // + // Prepare the data we are passing to the SSPI method + if(call->decoded_input_str_length > 0) { + ib.BufferType = SECBUFFER_TOKEN; + ib.cbBuffer = call->decoded_input_str_length; + ib.pvBuffer = call->decoded_input_str; + // prepare buffer description + ibd.cBuffers = 1; + ibd.ulVersion = SECBUFFER_VERSION; + ibd.pBuffers = &ib; + } + + // Perform initialization step + status = _sspi_initializeSecurityContext( + &context->security_credentials->m_Credentials + , context->hasContext == true ? &context->m_Context : NULL + , const_cast(call->service_principal_name_str) + , 0x02 // MUTUAL + , 0 + , 0 // Network + , call->decoded_input_str_length ? &ibd : NULL + , 0 + , &context->m_Context + , &obd + , &context->CtxtAttr + , &context->Expiration + ); + + // If we have a ok or continue let's prepare the result + if(status == SEC_E_OK + || status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_CONTINUE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE + ) { + // Set the new payload + if(context->payload != NULL) free(context->payload); + context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); + worker->return_code = status; + worker->return_value = context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } + + // Clean up data + if(call->decoded_input_str != NULL) free(call->decoded_input_str); + if(call->service_principal_name_str != NULL) free(call->service_principal_name_str); +} + +static Handle _map_initializeContextStep(Worker *worker) { + HandleScope scope; + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return scope.Close(context->handle_); +} + +Handle SecurityContext::InitalizeStep(const Arguments &args) { + HandleScope scope; + + char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; + int decoded_input_str_length = NULL; + + // We need 3 parameters + if(args.Length() != 3) + return VException("Initialize must be called with [servicePrincipalName:string, input:string, callback:function]"); + + // Second parameter must be a string + if(!args[0]->IsString()) + return VException("First parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[1]->IsString()) + return VException("Second parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[2]->IsFunction()) + return VException("Third parameter for Initialize must be a callback function"); + + // Let's unpack the values + Local service_principal_name = args[0]->ToString(); + service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); + service_principal_name->WriteUtf8(service_principal_name_str); + + // Unpack the user name + Local input = args[1]->ToString(); + + if(input->Utf8Length() > 0) { + input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); + input->WriteUtf8(input_str); + // Now let's get the base64 decoded string + decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); + // Free input string + free(input_str); + } + + // Unwrap the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Create call structure + SecurityContextStepStaticInitializeCall *call = (SecurityContextStepStaticInitializeCall *)calloc(1, sizeof(SecurityContextStepStaticInitializeCall)); + call->context = security_context; + call->decoded_input_str = decoded_input_str; + call->decoded_input_str_length = decoded_input_str_length; + call->service_principal_name_str = service_principal_name_str; + + // Callback + Local callback = Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _initializeContextStep; + worker->mapper = _map_initializeContextStep; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return undefined + return scope.Close(Undefined()); +} + +Handle SecurityContext::InitalizeStepSync(const Arguments &args) { + HandleScope scope; + + char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; + BYTE *out_bound_data_str = NULL; + int decoded_input_str_length = NULL; + // Status of operation + SECURITY_STATUS status; + + // We need 3 parameters + if(args.Length() != 2) + return VException("Initialize must be called with [servicePrincipalName:string, input:string]"); + + // Second parameter must be a string + if(!args[0]->IsString()) + return VException("First parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[1]->IsString()) + return VException("Second parameter for Initialize must be a string"); + + // Let's unpack the values + Local service_principal_name = args[0]->ToString(); + service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); + service_principal_name->WriteUtf8(service_principal_name_str); + + // Unpack the user name + Local input = args[1]->ToString(); + + if(input->Utf8Length() > 0) { + input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); + input->WriteUtf8(input_str); + // Now let's get the base64 decoded string + decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); + } + + // Unpack the long object + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + SecurityCredentials *security_credentials = security_context->security_credentials; + + // Structures used for c calls + SecBufferDesc ibd, obd; + SecBuffer ib, ob; + + // + // Prepare data structure for returned data from SSPI + ob.BufferType = SECBUFFER_TOKEN; + ob.cbBuffer = security_context->m_PkgInfo->cbMaxToken; + // Allocate space for return data + out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; + ob.pvBuffer = out_bound_data_str; + // prepare buffer description + obd.cBuffers = 1; + obd.ulVersion = SECBUFFER_VERSION; + obd.pBuffers = &ob; + + // + // Prepare the data we are passing to the SSPI method + if(input->Utf8Length() > 0) { + ib.BufferType = SECBUFFER_TOKEN; + ib.cbBuffer = decoded_input_str_length; + ib.pvBuffer = decoded_input_str; + // prepare buffer description + ibd.cBuffers = 1; + ibd.ulVersion = SECBUFFER_VERSION; + ibd.pBuffers = &ib; + } + + // Perform initialization step + status = _sspi_initializeSecurityContext( + &security_credentials->m_Credentials + , security_context->hasContext == true ? &security_context->m_Context : NULL + , const_cast(service_principal_name_str) + , 0x02 // MUTUAL + , 0 + , 0 // Network + , input->Utf8Length() > 0 ? &ibd : NULL + , 0 + , &security_context->m_Context + , &obd + , &security_context->CtxtAttr + , &security_context->Expiration + ); + + // If we have a ok or continue let's prepare the result + if(status == SEC_E_OK + || status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_CONTINUE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE + ) { + // Set the new payload + if(security_context->payload != NULL) free(security_context->payload); + security_context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); + } else { + LPSTR err_message = DisplaySECError(status); + + if(err_message != NULL) { + return VExceptionErrNo(err_message, status); + } else { + return VExceptionErrNo("Unknown error", status); + } + } + + return scope.Close(Null()); +} + +// +// Async EncryptMessage +// +typedef struct SecurityContextEncryptMessageCall { + SecurityContext *context; + SecurityBufferDescriptor *descriptor; + unsigned long flags; +} SecurityContextEncryptMessageCall; + +static void _encryptMessage(Worker *worker) { + SECURITY_STATUS status; + // Unpack call + SecurityContextEncryptMessageCall *call = (SecurityContextEncryptMessageCall *)worker->parameters; + // Unpack the security context + SecurityContext *context = call->context; + SecurityBufferDescriptor *descriptor = call->descriptor; + + // Let's execute encryption + status = _sspi_EncryptMessage( + &context->m_Context + , call->flags + , &descriptor->secBufferDesc + , 0 + ); + + // We've got ok + if(status == SEC_E_OK) { + int bytesToAllocate = (int)descriptor->bufferSize(); + // Free up existing payload + if(context->payload != NULL) free(context->payload); + // Save the payload + context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); + // Set result + worker->return_code = status; + worker->return_value = context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } +} + +static Handle _map_encryptMessage(Worker *worker) { + HandleScope scope; + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return scope.Close(context->handle_); +} + +Handle SecurityContext::EncryptMessage(const Arguments &args) { + HandleScope scope; + + if(args.Length() != 3) + return VException("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + if(!SecurityBufferDescriptor::HasInstance(args[0])) + return VException("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + if(!args[1]->IsUint32()) + return VException("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + if(!args[2]->IsFunction()) + return VException("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Unpack the descriptor + SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); + + // Create call structure + SecurityContextEncryptMessageCall *call = (SecurityContextEncryptMessageCall *)calloc(1, sizeof(SecurityContextEncryptMessageCall)); + call->context = security_context; + call->descriptor = descriptor; + call->flags = (unsigned long)args[1]->ToInteger()->Value(); + + // Callback + Local callback = Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _encryptMessage; + worker->mapper = _map_encryptMessage; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return undefined + return scope.Close(Undefined()); +} + +Handle SecurityContext::EncryptMessageSync(const Arguments &args) { + HandleScope scope; + SECURITY_STATUS status; + + if(args.Length() != 2) + return VException("EncryptMessageSync takes an instance of SecurityBufferDescriptor and an integer flag"); + if(!SecurityBufferDescriptor::HasInstance(args[0])) + return VException("EncryptMessageSync takes an instance of SecurityBufferDescriptor and an integer flag"); + if(!args[1]->IsUint32()) + return VException("EncryptMessageSync takes an instance of SecurityBufferDescriptor and an integer flag"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Unpack the descriptor + SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); + + // Let's execute encryption + status = _sspi_EncryptMessage( + &security_context->m_Context + , (unsigned long)args[1]->ToInteger()->Value() + , &descriptor->secBufferDesc + , 0 + ); + + // We've got ok + if(status == SEC_E_OK) { + int bytesToAllocate = (int)descriptor->bufferSize(); + // Free up existing payload + if(security_context->payload != NULL) free(security_context->payload); + // Save the payload + security_context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); + } else { + LPSTR err_message = DisplaySECError(status); + + if(err_message != NULL) { + return VExceptionErrNo(err_message, status); + } else { + return VExceptionErrNo("Unknown error", status); + } + } + + return scope.Close(Null()); +} + +// +// Async DecryptMessage +// +typedef struct SecurityContextDecryptMessageCall { + SecurityContext *context; + SecurityBufferDescriptor *descriptor; +} SecurityContextDecryptMessageCall; + +static void _decryptMessage(Worker *worker) { + unsigned long quality = 0; + SECURITY_STATUS status; + + // Unpack parameters + SecurityContextDecryptMessageCall *call = (SecurityContextDecryptMessageCall *)worker->parameters; + SecurityContext *context = call->context; + SecurityBufferDescriptor *descriptor = call->descriptor; + + // Let's execute encryption + status = _sspi_DecryptMessage( + &context->m_Context + , &descriptor->secBufferDesc + , 0 + , (unsigned long)&quality + ); + + // We've got ok + if(status == SEC_E_OK) { + int bytesToAllocate = (int)descriptor->bufferSize(); + // Free up existing payload + if(context->payload != NULL) free(context->payload); + // Save the payload + context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); + // Set return values + worker->return_code = status; + worker->return_value = context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } +} + +static Handle _map_decryptMessage(Worker *worker) { + HandleScope scope; + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return scope.Close(context->handle_); +} + +Handle SecurityContext::DecryptMessage(const Arguments &args) { + HandleScope scope; + + if(args.Length() != 2) + return VException("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); + if(!SecurityBufferDescriptor::HasInstance(args[0])) + return VException("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); + if(!args[1]->IsFunction()) + return VException("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + // Unpack the descriptor + SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); + // Create call structure + SecurityContextDecryptMessageCall *call = (SecurityContextDecryptMessageCall *)calloc(1, sizeof(SecurityContextDecryptMessageCall)); + call->context = security_context; + call->descriptor = descriptor; + + // Callback + Local callback = Local::Cast(args[1]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _decryptMessage; + worker->mapper = _map_decryptMessage; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return undefined + return scope.Close(Undefined()); +} + +Handle SecurityContext::DecryptMessageSync(const Arguments &args) { + HandleScope scope; + unsigned long quality = 0; + SECURITY_STATUS status; + + if(args.Length() != 1) + return VException("DecryptMessageSync takes an instance of SecurityBufferDescriptor"); + if(!SecurityBufferDescriptor::HasInstance(args[0])) + return VException("DecryptMessageSync takes an instance of SecurityBufferDescriptor"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Unpack the descriptor + SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); + + // Let's execute encryption + status = _sspi_DecryptMessage( + &security_context->m_Context + , &descriptor->secBufferDesc + , 0 + , (unsigned long)&quality + ); + + // We've got ok + if(status == SEC_E_OK) { + int bytesToAllocate = (int)descriptor->bufferSize(); + // Free up existing payload + if(security_context->payload != NULL) free(security_context->payload); + // Save the payload + security_context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); + } else { + LPSTR err_message = DisplaySECError(status); + + if(err_message != NULL) { + return VExceptionErrNo(err_message, status); + } else { + return VExceptionErrNo("Unknown error", status); + } + } + + return scope.Close(Null()); +} + +// +// Async QueryContextAttributes +// +typedef struct SecurityContextQueryContextAttributesCall { + SecurityContext *context; + uint32_t attribute; +} SecurityContextQueryContextAttributesCall; + +static void _queryContextAttributes(Worker *worker) { + SECURITY_STATUS status; + + // Cast to data structure + SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)worker->parameters; + + // Allocate some space + SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)calloc(1, sizeof(SecPkgContext_Sizes)); + // Let's grab the query context attribute + status = _sspi_QueryContextAttributes( + &call->context->m_Context, + call->attribute, + sizes + ); + + if(status == SEC_E_OK) { + worker->return_code = status; + worker->return_value = sizes; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } +} + +static Handle _map_queryContextAttributes(Worker *worker) { + HandleScope scope; + + // Cast to data structure + SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)worker->parameters; + // Unpack the attribute + uint32_t attribute = call->attribute; + + // Convert data + if(attribute == SECPKG_ATTR_SIZES) { + SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)worker->return_value; + // Create object + Local value = Object::New(); + value->Set(String::New("maxToken"), Integer::New(sizes->cbMaxToken)); + value->Set(String::New("maxSignature"), Integer::New(sizes->cbMaxSignature)); + value->Set(String::New("blockSize"), Integer::New(sizes->cbBlockSize)); + value->Set(String::New("securityTrailer"), Integer::New(sizes->cbSecurityTrailer)); + return scope.Close(value); + } + + // Return the value + return scope.Close(Null()); +} + +Handle SecurityContext::QueryContextAttributes(const Arguments &args) { + HandleScope scope; + + if(args.Length() != 2) + return VException("QueryContextAttributesSync method takes a an integer Attribute specifier and a callback function"); + if(!args[0]->IsInt32()) + return VException("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); + if(!args[1]->IsFunction()) + return VException("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Unpack the int value + uint32_t attribute = args[0]->ToInt32()->Value(); + + // Check that we have a supported attribute + if(attribute != SECPKG_ATTR_SIZES) + return VException("QueryContextAttributes only supports the SECPKG_ATTR_SIZES attribute"); + + // Create call structure + SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)calloc(1, sizeof(SecurityContextQueryContextAttributesCall)); + call->attribute = attribute; + call->context = security_context; + + // Callback + Local callback = Local::Cast(args[1]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _queryContextAttributes; + worker->mapper = _map_queryContextAttributes; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return undefined + return scope.Close(Undefined()); +} + +Handle SecurityContext::QueryContextAttributesSync(const Arguments &args) { + HandleScope scope; + SECURITY_STATUS status; + + if(args.Length() != 1) + return VException("QueryContextAttributesSync method takes a an integer Attribute specifier"); + if(!args[0]->IsInt32()) + return VException("QueryContextAttributesSync method takes a an integer Attribute specifier"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + uint32_t attribute = args[0]->ToInt32()->Value(); + + if(attribute != SECPKG_ATTR_SIZES) + return VException("QueryContextAttributes only supports the SECPKG_ATTR_SIZES attribute"); + + // Check what attribute we are asking for + if(attribute == SECPKG_ATTR_SIZES) { + SecPkgContext_Sizes sizes; + + // Let's grab the query context attribute + status = _sspi_QueryContextAttributes( + &security_context->m_Context, + attribute, + &sizes + ); + + if(status == SEC_E_OK) { + Local value = Object::New(); + value->Set(String::New("maxToken"), Integer::New(sizes.cbMaxToken)); + value->Set(String::New("maxSignature"), Integer::New(sizes.cbMaxSignature)); + value->Set(String::New("blockSize"), Integer::New(sizes.cbBlockSize)); + value->Set(String::New("securityTrailer"), Integer::New(sizes.cbSecurityTrailer)); + return scope.Close(value); + } else { + LPSTR err_message = DisplaySECError(status); + + if(err_message != NULL) { + return VExceptionErrNo(err_message, status); + } else { + return VExceptionErrNo("Unknown error", status); + } + } + } + + return scope.Close(Null()); +} + +void SecurityContext::Initialize(Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("SecurityContext")); + + // Class methods + NODE_SET_METHOD(constructor_template, "initializeSync", InitializeContextSync); + NODE_SET_METHOD(constructor_template, "initialize", InitializeContext); + + // Set up method for the instance + NODE_SET_PROTOTYPE_METHOD(constructor_template, "initializeSync", InitalizeStepSync); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "initialize", InitalizeStep); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "decryptMessageSync", DecryptMessageSync); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "decryptMessage", DecryptMessage); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "queryContextAttributesSync", QueryContextAttributesSync); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "queryContextAttributes", QueryContextAttributes); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "encryptMessageSync", EncryptMessageSync); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "encryptMessage", EncryptMessage); + + // Getters for correct serialization of the object + constructor_template->InstanceTemplate()->SetAccessor(String::NewSymbol("payload"), PayloadGetter); + // Getters for correct serialization of the object + constructor_template->InstanceTemplate()->SetAccessor(String::NewSymbol("hasContext"), HasContextGetter); + + // Set template class name + target->Set(String::NewSymbol("SecurityContext"), constructor_template->GetFunction()); +} + +static LPSTR DisplaySECError(DWORD ErrCode) { + LPSTR pszName = NULL; // WinError.h + + switch(ErrCode) { + case SEC_E_BUFFER_TOO_SMALL: + pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; + break; + + case SEC_E_CRYPTO_SYSTEM_INVALID: + pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; + break; + case SEC_E_INCOMPLETE_MESSAGE: + pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessageSync (General) again."; + break; + + case SEC_E_INVALID_HANDLE: + pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_INVALID_TOKEN: + pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; + break; + + case SEC_E_MESSAGE_ALTERED: + pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_OUT_OF_SEQUENCE: + pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; + break; + + case SEC_E_QOP_NOT_SUPPORTED: + pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; + break; + + case SEC_I_CONTEXT_EXPIRED: + pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; + break; + + case SEC_I_RENEGOTIATE: + pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; + break; + + case SEC_E_ENCRYPT_FAILURE: + pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; + break; + + case SEC_E_DECRYPT_FAILURE: + pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; + break; + case -1: + pszName = "Failed to load security.dll library"; + break; + } + + return pszName; +} + diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h new file mode 100644 index 0000000..b0059e3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h @@ -0,0 +1,85 @@ +#ifndef SECURITY_CONTEXT_H +#define SECURITY_CONTEXT_H + +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include +#include +#include "security_credentials.h" +#include "../worker.h" + +extern "C" { + #include "../kerberos_sspi.h" + #include "../base64.h" +} + +using namespace v8; +using namespace node; + +class SecurityContext : public ObjectWrap { + public: + SecurityContext(); + ~SecurityContext(); + + // Security info package + PSecPkgInfo m_PkgInfo; + // Do we have a context + bool hasContext; + // Reference to security credentials + SecurityCredentials *security_credentials; + // Security context + CtxtHandle m_Context; + // Attributes + DWORD CtxtAttr; + // Expiry time for ticket + TimeStamp Expiration; + // Payload + char *payload; + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return constructor_template->HasInstance(obj); + }; + + // Functions available from V8 + static void Initialize(Handle target); + + static Handle InitializeContext(const Arguments &args); + static Handle InitializeContextSync(const Arguments &args); + + static Handle InitalizeStep(const Arguments &args); + static Handle InitalizeStepSync(const Arguments &args); + + static Handle DecryptMessage(const Arguments &args); + static Handle DecryptMessageSync(const Arguments &args); + + static Handle QueryContextAttributesSync(const Arguments &args); + static Handle QueryContextAttributes(const Arguments &args); + + static Handle EncryptMessageSync(const Arguments &args); + static Handle EncryptMessage(const Arguments &args); + + // Payload getter + static Handle PayloadGetter(Local property, const AccessorInfo& info); + // hasContext getter + static Handle HasContextGetter(Local property, const AccessorInfo& info); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + // Create a new instance + static Handle New(const Arguments &args); + // // Handles the uv calls + // static void Process(uv_work_t* work_req); + // // Called after work is done + // static void After(uv_work_t* work_req); +}; + +#endif diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js new file mode 100644 index 0000000..ef04e92 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js @@ -0,0 +1,3 @@ +var SecurityContextNative = require('../../../build/Release/kerberos').SecurityContext; +// Export the modified class +exports.SecurityContext = SecurityContextNative; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc new file mode 100644 index 0000000..14c1cdc --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc @@ -0,0 +1,468 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "security_credentials.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#endif + +static LPSTR DisplaySECError(DWORD ErrCode); + +static Handle VException(const char *msg) { + HandleScope scope; + return ThrowException(Exception::Error(String::New(msg))); +}; + +static Handle VExceptionErrNo(const char *msg, const int errorNumber) { + HandleScope scope; + + Local err = Exception::Error(String::New(msg)); + Local obj = err->ToObject(); + obj->Set(NODE_PSYMBOL("code"), Int32::New(errorNumber)); + return ThrowException(err); +}; + +Persistent SecurityCredentials::constructor_template; + +SecurityCredentials::SecurityCredentials() : ObjectWrap() { +} + +SecurityCredentials::~SecurityCredentials() { +} + +Handle SecurityCredentials::New(const Arguments &args) { + HandleScope scope; + + // Create security credentials instance + SecurityCredentials *security_credentials = new SecurityCredentials(); + // Wrap it + security_credentials->Wrap(args.This()); + // Return the object + return args.This(); +} + +Handle SecurityCredentials::AquireSync(const Arguments &args) { + HandleScope scope; + char *package_str = NULL, *username_str = NULL, *password_str = NULL, *domain_str = NULL; + // Status of operation + SECURITY_STATUS status; + + // Unpack the variables + if(args.Length() != 2 && args.Length() != 3 && args.Length() != 4) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string]]"); + + if(!args[0]->IsString()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string]]"); + + if(!args[1]->IsString()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string]]"); + + if(args.Length() == 3 && !args[2]->IsString()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string]]"); + + if(args.Length() == 4 && (!args[3]->IsString() && !args[3]->IsUndefined() && !args[3]->IsNull())) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string]]"); + + // Unpack the package + Local package = args[0]->ToString(); + package_str = (char *)calloc(package->Utf8Length() + 1, sizeof(char)); + package->WriteUtf8(package_str); + + // Unpack the user name + Local username = args[1]->ToString(); + username_str = (char *)calloc(username->Utf8Length() + 1, sizeof(char)); + username->WriteUtf8(username_str); + + // If we have a password + if(args.Length() == 3 || args.Length() == 4) { + Local password = args[2]->ToString(); + password_str = (char *)calloc(password->Utf8Length() + 1, sizeof(char)); + password->WriteUtf8(password_str); + } + + // If we have a domain + if(args.Length() == 4 && args[3]->IsString()) { + Local domain = args[3]->ToString(); + domain_str = (char *)calloc(domain->Utf8Length() + 1, sizeof(char)); + domain->WriteUtf8(domain_str); + } + + // Create Security instance + Local security_credentials_value = constructor_template->GetFunction()->NewInstance(); + + // Unwrap the credentials + SecurityCredentials *security_credentials = ObjectWrap::Unwrap(security_credentials_value); + + // If we have domain string + if(domain_str != NULL) { + security_credentials->m_Identity.Domain = USTR(_tcsdup(domain_str)); + security_credentials->m_Identity.DomainLength = (unsigned long)_tcslen(domain_str); + } else { + security_credentials->m_Identity.Domain = NULL; + security_credentials->m_Identity.DomainLength = 0; + } + + // Set up the user + security_credentials->m_Identity.User = USTR(_tcsdup(username_str)); + security_credentials->m_Identity.UserLength = (unsigned long)_tcslen(username_str); + + // If we have a password string + if(password_str != NULL) { + // Set up the password + security_credentials->m_Identity.Password = USTR(_tcsdup(password_str)); + security_credentials->m_Identity.PasswordLength = (unsigned long)_tcslen(password_str); + } + + #ifdef _UNICODE + security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + #else + security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; + #endif + + // Attempt to acquire credentials + status = _sspi_AcquireCredentialsHandle( + NULL, + package_str, + SECPKG_CRED_OUTBOUND, + NULL, + password_str != NULL ? &security_credentials->m_Identity : NULL, + NULL, NULL, + &security_credentials->m_Credentials, + &security_credentials->Expiration + ); + + // We have an error + if(status != SEC_E_OK) { + LPSTR err_message = DisplaySECError(status); + + if(err_message != NULL) { + return VExceptionErrNo(err_message, status); + } else { + return VExceptionErrNo("Unknown error", status); + } + } + + // Make object persistent + Persistent persistent = Persistent::New(security_credentials_value); + // Return the object + return scope.Close(persistent); +} + +// Call structs +typedef struct SecurityCredentialCall { + char *package_str; + char *username_str; + char *password_str; + char *domain_str; + SecurityCredentials *credentials; +} SecurityCredentialCall; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientInit +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authSSPIAquire(Worker *worker) { + // Status of operation + SECURITY_STATUS status; + + // Unpack data + SecurityCredentialCall *call = (SecurityCredentialCall *)worker->parameters; + + // Unwrap the credentials + SecurityCredentials *security_credentials = (SecurityCredentials *)call->credentials; + + // If we have domain string + if(call->domain_str != NULL) { + security_credentials->m_Identity.Domain = USTR(_tcsdup(call->domain_str)); + security_credentials->m_Identity.DomainLength = (unsigned long)_tcslen(call->domain_str); + } else { + security_credentials->m_Identity.Domain = NULL; + security_credentials->m_Identity.DomainLength = 0; + } + + // Set up the user + security_credentials->m_Identity.User = USTR(_tcsdup(call->username_str)); + security_credentials->m_Identity.UserLength = (unsigned long)_tcslen(call->username_str); + + // If we have a password string + if(call->password_str != NULL) { + // Set up the password + security_credentials->m_Identity.Password = USTR(_tcsdup(call->password_str)); + security_credentials->m_Identity.PasswordLength = (unsigned long)_tcslen(call->password_str); + } + + #ifdef _UNICODE + security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + #else + security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; + #endif + + // Attempt to acquire credentials + status = _sspi_AcquireCredentialsHandle( + NULL, + call->package_str, + SECPKG_CRED_OUTBOUND, + NULL, + call->password_str != NULL ? &security_credentials->m_Identity : NULL, + NULL, NULL, + &security_credentials->m_Credentials, + &security_credentials->Expiration + ); + + // We have an error + if(status != SEC_E_OK) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } else { + worker->return_code = status; + worker->return_value = security_credentials; + } + + // Free up parameter structure + if(call->package_str != NULL) free(call->package_str); + if(call->domain_str != NULL) free(call->domain_str); + if(call->password_str != NULL) free(call->password_str); + if(call->username_str != NULL) free(call->username_str); + free(call); +} + +static Handle _map_authSSPIAquire(Worker *worker) { + HandleScope scope; + + // Unpack the credentials + SecurityCredentials *security_credentials = (SecurityCredentials *)worker->return_value; + // Make object persistent + Persistent persistent = Persistent::New(security_credentials->handle_); + // Return the object + return scope.Close(persistent); +} + +Handle SecurityCredentials::Aquire(const Arguments &args) { + HandleScope scope; + char *package_str = NULL, *username_str = NULL, *password_str = NULL, *domain_str = NULL; + // Unpack the variables + if(args.Length() != 2 && args.Length() != 3 && args.Length() != 4 && args.Length() != 5) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(!args[0]->IsString()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(!args[1]->IsString()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(args.Length() == 3 && (!args[2]->IsString() && !args[2]->IsFunction())) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(args.Length() == 4 && (!args[3]->IsString() && !args[3]->IsUndefined() && !args[3]->IsNull()) && !args[3]->IsFunction()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(args.Length() == 5 && !args[4]->IsFunction()) + return VException("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + Local callback; + + // Figure out which parameter is the callback + if(args.Length() == 5) { + callback = Local::Cast(args[4]); + } else if(args.Length() == 4) { + callback = Local::Cast(args[3]); + } else if(args.Length() == 3) { + callback = Local::Cast(args[2]); + } + + // Unpack the package + Local package = args[0]->ToString(); + package_str = (char *)calloc(package->Utf8Length() + 1, sizeof(char)); + package->WriteUtf8(package_str); + + // Unpack the user name + Local username = args[1]->ToString(); + username_str = (char *)calloc(username->Utf8Length() + 1, sizeof(char)); + username->WriteUtf8(username_str); + + // If we have a password + if(args.Length() == 3 || args.Length() == 4 || args.Length() == 5) { + Local password = args[2]->ToString(); + password_str = (char *)calloc(password->Utf8Length() + 1, sizeof(char)); + password->WriteUtf8(password_str); + } + + // If we have a domain + if((args.Length() == 4 || args.Length() == 5) && args[3]->IsString()) { + Local domain = args[3]->ToString(); + domain_str = (char *)calloc(domain->Utf8Length() + 1, sizeof(char)); + domain->WriteUtf8(domain_str); + } + + // Create reference object + Local security_credentials_value = constructor_template->GetFunction()->NewInstance(); + // Unwrap object + SecurityCredentials *security_credentials = ObjectWrap::Unwrap(security_credentials_value); + + // Allocate call structure + SecurityCredentialCall *call = (SecurityCredentialCall *)calloc(1, sizeof(SecurityCredentialCall)); + call->domain_str = domain_str; + call->package_str = package_str; + call->password_str = password_str; + call->username_str = username_str; + call->credentials = security_credentials; + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = Persistent::New(callback); + worker->parameters = call; + worker->execute = _authSSPIAquire; + worker->mapper = _map_authSSPIAquire; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, SecurityCredentials::Process, (uv_after_work_cb)SecurityCredentials::After); + + // Return the undefined value + return scope.Close(Undefined()); +} + +void SecurityCredentials::Initialize(Handle target) { + // Grab the scope of the call from Node + HandleScope scope; + // Define a new function template + Local t = FunctionTemplate::New(New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("SecurityCredentials")); + + // Class methods + NODE_SET_METHOD(constructor_template, "aquireSync", AquireSync); + NODE_SET_METHOD(constructor_template, "aquire", Aquire); + + // Set the class on the target module + target->Set(String::NewSymbol("SecurityCredentials"), constructor_template->GetFunction()); + + // Attempt to load the security.dll library + load_library(); +} + +static LPSTR DisplaySECError(DWORD ErrCode) { + LPSTR pszName = NULL; // WinError.h + + switch(ErrCode) { + case SEC_E_BUFFER_TOO_SMALL: + pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; + break; + + case SEC_E_CRYPTO_SYSTEM_INVALID: + pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; + break; + case SEC_E_INCOMPLETE_MESSAGE: + pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessage (General) again."; + break; + + case SEC_E_INVALID_HANDLE: + pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_INVALID_TOKEN: + pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; + break; + + case SEC_E_MESSAGE_ALTERED: + pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_OUT_OF_SEQUENCE: + pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; + break; + + case SEC_E_QOP_NOT_SUPPORTED: + pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; + break; + + case SEC_I_CONTEXT_EXPIRED: + pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; + break; + + case SEC_I_RENEGOTIATE: + pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; + break; + + case SEC_E_ENCRYPT_FAILURE: + pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; + break; + + case SEC_E_DECRYPT_FAILURE: + pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; + break; + case -1: + pszName = "Failed to load security.dll library"; + break; + + } + + return pszName; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// UV Lib callbacks +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +void SecurityCredentials::Process(uv_work_t* work_req) { + // Grab the worker + Worker *worker = static_cast(work_req->data); + // Execute the worker code + worker->execute(worker); +} + +void SecurityCredentials::After(uv_work_t* work_req) { + // Grab the scope of the call from Node + v8::HandleScope scope; + + // Get the worker reference + Worker *worker = static_cast(work_req->data); + + // If we have an error + if(worker->error) { + v8::Local err = v8::Exception::Error(v8::String::New(worker->error_message)); + Local obj = err->ToObject(); + obj->Set(NODE_PSYMBOL("code"), Int32::New(worker->error_code)); + v8::Local args[2] = { err, v8::Local::New(v8::Null()) }; + // Execute the error + v8::TryCatch try_catch; + // Call the callback + worker->callback->Call(v8::Context::GetCurrent()->Global(), ARRAY_SIZE(args), args); + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } else { + // // Map the data + v8::Handle result = worker->mapper(worker); + // Set up the callback with a null first + v8::Handle args[2] = { v8::Local::New(v8::Null()), result}; + // Wrap the callback function call in a TryCatch so that we can call + // node's FatalException afterwards. This makes it possible to catch + // the exception from JavaScript land using the + // process.on('uncaughtException') event. + v8::TryCatch try_catch; + // Call the callback + worker->callback->Call(v8::Context::GetCurrent()->Global(), ARRAY_SIZE(args), args); + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + // Clean up the memory + worker->callback.Dispose(); + delete worker; +} + diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h new file mode 100644 index 0000000..10b3eda --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h @@ -0,0 +1,67 @@ +#ifndef SECURITY_CREDENTIALS_H +#define SECURITY_CREDENTIALS_H + +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include +#include +#include +#include "../worker.h" +#include + +extern "C" { + #include "../kerberos_sspi.h" +} + +// SEC_WINNT_AUTH_IDENTITY makes it unusually hard +// to compile for both Unicode and ansi, so I use this macro: +#ifdef _UNICODE +#define USTR(str) (str) +#else +#define USTR(str) ((unsigned char*)(str)) +#endif + +using namespace v8; +using namespace node; + +class SecurityCredentials : public ObjectWrap { + public: + SecurityCredentials(); + ~SecurityCredentials(); + + // Pointer to context object + SEC_WINNT_AUTH_IDENTITY m_Identity; + // credentials + CredHandle m_Credentials; + // Expiry time for ticket + TimeStamp Expiration; + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return constructor_template->HasInstance(obj); + }; + + // Functions available from V8 + static void Initialize(Handle target); + static Handle AquireSync(const Arguments &args); + static Handle Aquire(const Arguments &args); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + // Create a new instance + static Handle New(const Arguments &args); + // Handles the uv calls + static void Process(uv_work_t* work_req); + // Called after work is done + static void After(uv_work_t* work_req); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js new file mode 100644 index 0000000..4215c92 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js @@ -0,0 +1,22 @@ +var SecurityCredentialsNative = require('../../../build/Release/kerberos').SecurityCredentials; + +// Add simple kebros helper +SecurityCredentialsNative.aquire_kerberos = function(username, password, domain, callback) { + if(typeof password == 'function') { + callback = password; + password = null; + } else if(typeof domain == 'function') { + callback = domain; + domain = null; + } + + // We are going to use the async version + if(typeof callback == 'function') { + return SecurityCredentialsNative.aquire('Kerberos', username, password, domain, callback); + } else { + return SecurityCredentialsNative.aquireSync('Kerberos', username, password, domain); + } +} + +// Export the modified class +exports.SecurityCredentials = SecurityCredentialsNative; \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.cc b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.cc new file mode 100644 index 0000000..e7a472f --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.cc @@ -0,0 +1,7 @@ +#include "worker.h" + +Worker::Worker() { +} + +Worker::~Worker() { +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.h b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.h new file mode 100644 index 0000000..c5f86f5 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/worker.h @@ -0,0 +1,39 @@ +#ifndef WORKER_H_ +#define WORKER_H_ + +#include +#include +#include + +using namespace node; +using namespace v8; + +class Worker { + public: + Worker(); + virtual ~Worker(); + + // libuv's request struct. + uv_work_t request; + // Callback + v8::Persistent callback; + // // Arguments + // v8::Persistent arguments; + // Parameters + void *parameters; + // Results + void *return_value; + // Did we raise an error + bool error; + // The error message + char *error_message; + // Error code if not message + int error_code; + // Any return code + int return_code; + // Method we are going to fire + void (*execute)(Worker *worker); + Handle (*mapper)(Worker *worker); +}; + +#endif // WORKER_H_ diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/package.json b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/package.json new file mode 100644 index 0000000..c67ea28 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/package.json @@ -0,0 +1,35 @@ +{ + "name": "kerberos", + "version": "0.0.3", + "description": "Kerberos library for Node.js", + "main": "index.js", + "scripts": { + "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", + "test": "nodeunit ./test" + }, + "repository": { + "type": "git", + "url": "https://github.com/christkv/kerberos.git" + }, + "keywords": [ + "kerberos", + "security", + "authentication" + ], + "devDependencies": { + "nodeunit": "latest" + }, + "author": { + "name": "Christian Amor Kvalheim" + }, + "license": "Apache 2.0", + "readmeFilename": "README.md", + "gitHead": "bb01d4fe322e022999aca19da564e7d9db59a8ed", + "readme": "kerberos\n========\n\nKerberos library for node.js", + "_id": "kerberos@0.0.3", + "dist": { + "shasum": "90150368076e274d831fba93412bd7c3e7f24b40" + }, + "_from": "kerberos@0.0.3", + "_resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.3.tgz" +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js new file mode 100644 index 0000000..a06c5fd --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js @@ -0,0 +1,34 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Simple initialize of Kerberos object'] = function(test) { + var Kerberos = require('../lib/kerberos.js').Kerberos; + var kerberos = new Kerberos(); + // console.dir(kerberos) + + // Initiate kerberos client + kerberos.authGSSClientInit('mongodb@kdc.10gen.me', Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) { + console.log("===================================== authGSSClientInit") + test.equal(null, err); + test.ok(context != null && typeof context == 'object'); + // console.log("===================================== authGSSClientInit") + console.dir(err) + console.dir(context) + // console.dir(typeof result) + + // Perform the first step + kerberos.authGSSClientStep(context, function(err, result) { + console.log("===================================== authGSSClientStep") + console.dir(err) + console.dir(result) + console.dir(context) + + test.done(); + }); + }); +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js new file mode 100644 index 0000000..d2f7046 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js @@ -0,0 +1,19 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Simple initialize of Kerberos win32 object'] = function(test) { + var KerberosNative = require('../build/Release/kerberos').Kerberos; + // console.dir(KerberosNative) + var kerberos = new KerberosNative(); + console.log("=========================================== 0") + console.dir(kerberos.acquireAlternateCredentials("dev1@10GEN.ME", "a")); + console.log("=========================================== 1") + console.dir(kerberos.prepareOutboundPackage("mongodb/kdc.10gen.com")); + console.log("=========================================== 2") + test.done(); +} diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js new file mode 100644 index 0000000..3531b6b --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js @@ -0,0 +1,41 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Initialize a security Buffer Descriptor'] = function(test) { + var SecurityBufferDescriptor = require('../../lib/sspi.js').SecurityBufferDescriptor + SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; + + // Create descriptor with single Buffer + var securityDescriptor = new SecurityBufferDescriptor(100); + try { + // Fail to work due to no valid Security Buffer + securityDescriptor = new SecurityBufferDescriptor(["hello"]); + test.ok(false); + } catch(err){} + + // Should Correctly construct SecurityBuffer + var buffer = new SecurityBuffer(SecurityBuffer.DATA, 100); + securityDescriptor = new SecurityBufferDescriptor([buffer]); + // Should correctly return a buffer + var result = securityDescriptor.toBuffer(); + test.equal(100, result.length); + + // Should Correctly construct SecurityBuffer + var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + securityDescriptor = new SecurityBufferDescriptor([buffer]); + var result = securityDescriptor.toBuffer(); + test.equal("hello world", result.toString()); + + // Test passing in more than one Buffer + var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + var buffer2 = new SecurityBuffer(SecurityBuffer.STREAM, new Buffer("adam and eve")); + securityDescriptor = new SecurityBufferDescriptor([buffer, buffer2]); + var result = securityDescriptor.toBuffer(); + test.equal("hello worldadam and eve", result.toString()); + test.done(); +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js new file mode 100644 index 0000000..b52b959 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js @@ -0,0 +1,22 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Initialize a security Buffer'] = function(test) { + var SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; + // Create empty buffer + var securityBuffer = new SecurityBuffer(SecurityBuffer.DATA, 100); + var buffer = securityBuffer.toBuffer(); + test.equal(100, buffer.length); + + // Access data passed in + var allocated_buffer = new Buffer(256); + securityBuffer = new SecurityBuffer(SecurityBuffer.DATA, allocated_buffer); + buffer = securityBuffer.toBuffer(); + test.deepEqual(allocated_buffer, buffer); + test.done(); +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js new file mode 100644 index 0000000..7758180 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js @@ -0,0 +1,55 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Initialize a set of security credentials'] = function(test) { + var SecurityCredentials = require('../../lib/sspi.js').SecurityCredentials; + + // Aquire some credentials + try { + var credentials = SecurityCredentials.aquire('Kerberos', 'dev1@10GEN.ME', 'a'); + } catch(err) { + console.dir(err) + test.ok(false); + } + + + + // console.dir(SecurityCredentials); + + // var SecurityBufferDescriptor = require('../../lib/sspi.js').SecurityBufferDescriptor + // SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; + + // // Create descriptor with single Buffer + // var securityDescriptor = new SecurityBufferDescriptor(100); + // try { + // // Fail to work due to no valid Security Buffer + // securityDescriptor = new SecurityBufferDescriptor(["hello"]); + // test.ok(false); + // } catch(err){} + + // // Should Correctly construct SecurityBuffer + // var buffer = new SecurityBuffer(SecurityBuffer.DATA, 100); + // securityDescriptor = new SecurityBufferDescriptor([buffer]); + // // Should correctly return a buffer + // var result = securityDescriptor.toBuffer(); + // test.equal(100, result.length); + + // // Should Correctly construct SecurityBuffer + // var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + // securityDescriptor = new SecurityBufferDescriptor([buffer]); + // var result = securityDescriptor.toBuffer(); + // test.equal("hello world", result.toString()); + + // // Test passing in more than one Buffer + // var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + // var buffer2 = new SecurityBuffer(SecurityBuffer.STREAM, new Buffer("adam and eve")); + // securityDescriptor = new SecurityBufferDescriptor([buffer, buffer2]); + // var result = securityDescriptor.toBuffer(); + // test.equal("hello worldadam and eve", result.toString()); + test.done(); +} \ No newline at end of file diff --git a/node_modules/mongoose/node_modules/mongodb/package.json b/node_modules/mongoose/node_modules/mongodb/package.json new file mode 100755 index 0000000..d183ff2 --- /dev/null +++ b/node_modules/mongoose/node_modules/mongodb/package.json @@ -0,0 +1,229 @@ +{ + "name": "mongodb", + "description": "A node.js driver for MongoDB", + "keywords": [ + "mongodb", + "mongo", + "driver", + "db" + ], + "version": "1.3.11", + "author": { + "name": "Christian Amor Kvalheim", + "email": "christkv@gmail.com" + }, + "contributors": [ + { + "name": "Aaron Heckmann" + }, + { + "name": "Christoph Pojer" + }, + { + "name": "Pau Ramon Revilla" + }, + { + "name": "Nathan White" + }, + { + "name": "Emmerman" + }, + { + "name": "Seth LaForge" + }, + { + "name": "Boris Filipov" + }, + { + "name": "Stefan Schärmeli" + }, + { + "name": "Tedde Lundgren" + }, + { + "name": "renctan" + }, + { + "name": "Sergey Ukustov" + }, + { + "name": "Ciaran Jessup" + }, + { + "name": "kuno" + }, + { + "name": "srimonti" + }, + { + "name": "Erik Abele" + }, + { + "name": "Pratik Daga" + }, + { + "name": "Slobodan Utvic" + }, + { + "name": "Kristina Chodorow" + }, + { + "name": "Yonathan Randolph" + }, + { + "name": "Brian Noguchi" + }, + { + "name": "Sam Epstein" + }, + { + "name": "James Harrison Fisher" + }, + { + "name": "Vladimir Dronnikov" + }, + { + "name": "Ben Hockey" + }, + { + "name": "Henrik Johansson" + }, + { + "name": "Simon Weare" + }, + { + "name": "Alex Gorbatchev" + }, + { + "name": "Shimon Doodkin" + }, + { + "name": "Kyle Mueller" + }, + { + "name": "Eran Hammer-Lahav" + }, + { + "name": "Marcin Ciszak" + }, + { + "name": "François de Metz" + }, + { + "name": "Vinay Pulim" + }, + { + "name": "nstielau" + }, + { + "name": "Adam Wiggins" + }, + { + "name": "entrinzikyl" + }, + { + "name": "Jeremy Selier" + }, + { + "name": "Ian Millington" + }, + { + "name": "Public Keating" + }, + { + "name": "andrewjstone" + }, + { + "name": "Christopher Stott" + }, + { + "name": "Corey Jewett" + }, + { + "name": "brettkiefer" + }, + { + "name": "Rob Holland" + }, + { + "name": "Senmiao Liu" + }, + { + "name": "heroic" + }, + { + "name": "gitfy" + }, + { + "name": "Andrew Stone" + }, + { + "name": "John Le Drew" + }, + { + "name": "Lucasfilm Singapore" + }, + { + "name": "Roman Shtylman" + }, + { + "name": "Matt Self" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mongodb/node-mongodb-native.git" + }, + "bugs": { + "mail": "node-mongodb-native@googlegroups.com", + "url": "http://github.com/mongodb/node-mongodb-native/issues" + }, + "dependencies": { + "bson": "0.1.9", + "kerberos": "0.0.3" + }, + "devDependencies": { + "dox": "0.2.0", + "uglify-js": "1.2.5", + "ejs": "0.6.1", + "request": "2.12.0", + "nodeunit": "0.7.4", + "markdown": "0.3.1", + "gleak": "0.2.3", + "step": "0.0.5", + "async": "0.1.22", + "integra": "latest", + "optimist": "latest" + }, + "optionalDependencies": { + "kerberos": "0.0.3" + }, + "config": { + "native": false + }, + "main": "./lib/mongodb/index", + "homepage": "http://mongodb.github.com/node-mongodb-native/", + "directories": { + "lib": "./lib/mongodb" + }, + "engines": { + "node": ">=0.6.19" + }, + "scripts": { + "test": "make test_functional" + }, + "licenses": [ + { + "type": "Apache License, Version 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], + "readme": "Up to date documentation\n========================\n\n[Documentation](http://mongodb.github.com/node-mongodb-native/)\n\nInstall\n=======\n\nTo install the most recent release from npm, run:\n\n npm install mongodb\n\nThat may give you a warning telling you that bugs['web'] should be bugs['url'], it would be safe to ignore it (this has been fixed in the development version)\n\nTo install the latest from the repository, run::\n\n npm install path/to/node-mongodb-native\n\nCommunity\n=========\nCheck out the google group [node-mongodb-native](http://groups.google.com/group/node-mongodb-native) for questions/answers from users of the driver.\n\nLive Examples\n============\n\n\nIntroduction\n============\n\nThis is a node.js driver for MongoDB. It's a port (or close to a port) of the library for ruby at http://github.com/mongodb/mongo-ruby-driver/.\n\nA simple example of inserting a document.\n\n```javascript\n var MongoClient = require('mongodb').MongoClient\n , format = require('util').format; \n\n MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {\n if(err) throw err;\n\n var collection = db.collection('test_insert');\n collection.insert({a:2}, function(err, docs) {\n \n collection.count(function(err, count) {\n console.log(format(\"count = %s\", count));\n });\n\n // Locate all the entries using find\n collection.find().toArray(function(err, results) {\n console.dir(results);\n // Let's close the db\n db.close();\n }); \n });\n })\n```\n\nData types\n==========\n\nTo store and retrieve the non-JSON MongoDb primitives ([ObjectID](http://www.mongodb.org/display/DOCS/Object+IDs), Long, Binary, [Timestamp](http://www.mongodb.org/display/DOCS/Timestamp+data+type), [DBRef](http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef), Code).\n\nIn particular, every document has a unique `_id` which can be almost any type, and by default a 12-byte ObjectID is created. ObjectIDs can be represented as 24-digit hexadecimal strings, but you must convert the string back into an ObjectID before you can use it in the database. For example:\n\n```javascript\n // Get the objectID type\n var ObjectID = require('mongodb').ObjectID;\n\n var idString = '4e4e1638c85e808431000003';\n collection.findOne({_id: new ObjectID(idString)}, console.log) // ok\n collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined\n```\n\nHere are the constructors the non-Javascript BSON primitive types:\n\n```javascript\n // Fetch the library\n var mongo = require('mongodb');\n // Create new instances of BSON types\n new mongo.Long(numberString)\n new mongo.ObjectID(hexString)\n new mongo.Timestamp() // the actual unique number is generated on insert.\n new mongo.DBRef(collectionName, id, dbName)\n new mongo.Binary(buffer) // takes a string or Buffer\n new mongo.Code(code, [context])\n new mongo.Symbol(string)\n new mongo.MinKey()\n new mongo.MaxKey()\n new mongo.Double(number)\t// Force double storage\n```\n\nThe C/C++ bson parser/serializer\n--------------------------------\n\nIf you are running a version of this library has the C/C++ parser compiled, to enable the driver to use the C/C++ bson parser pass it the option native_parser:true like below\n\n```javascript\n // using native_parser:\n MongoClient.connect('mongodb://127.0.0.1:27017/test'\n , {db: {native_parser: true}}, function(err, db) {})\n```\n\nThe C++ parser uses the js objects both for serialization and deserialization.\n\nGitHub information\n==================\n\nThe source code is available at http://github.com/mongodb/node-mongodb-native.\nYou can either clone the repository or download a tarball of the latest release.\n\nOnce you have the source you can test the driver by running\n\n $ make test\n\nin the main directory. You will need to have a mongo instance running on localhost for the integration tests to pass.\n\nExamples\n========\n\nFor examples look in the examples/ directory. You can execute the examples using node.\n\n $ cd examples\n $ node queries.js\n\nGridStore\n=========\n\nThe GridStore class allows for storage of binary files in mongoDB using the mongoDB defined files and chunks collection definition.\n\nFor more information have a look at [Gridstore](https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md)\n\nReplicasets\n===========\nFor more information about how to connect to a replicaset have a look at [Replicasets](https://github.com/mongodb/node-mongodb-native/blob/master/docs/replicaset.md)\n\nPrimary Key Factories\n---------------------\n\nDefining your own primary key factory allows you to generate your own series of id's\n(this could f.ex be to use something like ISBN numbers). The generated the id needs to be a 12 byte long \"string\".\n\nSimple example below\n\n```javascript\n var MongoClient = require('mongodb').MongoClient\n , format = require('util').format; \n\n // Custom factory (need to provide a 12 byte array);\n CustomPKFactory = function() {}\n CustomPKFactory.prototype = new Object();\n CustomPKFactory.createPk = function() {\n return new ObjectID(\"aaaaaaaaaaaa\");\n }\n\n MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {\n if(err) throw err;\n\n db.dropDatabase(function(err, done) {\n \n db.createCollection('test_custom_key', function(err, collection) {\n \n collection.insert({'a':1}, function(err, docs) {\n \n collection.find({'_id':new ObjectID(\"aaaaaaaaaaaa\")}).toArray(function(err, items) {\n console.dir(items);\n // Let's close the db\n db.close();\n });\n });\n });\n });\n });\n```\n\nDocumentation\n=============\n\nIf this document doesn't answer your questions, see the source of\n[Collection](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/collection.js)\nor [Cursor](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/cursor.js),\nor the documentation at MongoDB for query and update formats.\n\nFind\n----\n\nThe find method is actually a factory method to create\nCursor objects. A Cursor lazily uses the connection the first time\nyou call `nextObject`, `each`, or `toArray`.\n\nThe basic operation on a cursor is the `nextObject` method\nthat fetches the next matching document from the database. The convenience\nmethods `each` and `toArray` call `nextObject` until the cursor is exhausted.\n\nSignatures:\n\n```javascript\n var cursor = collection.find(query, [fields], options);\n cursor.sort(fields).limit(n).skip(m).\n\n cursor.nextObject(function(err, doc) {});\n cursor.each(function(err, doc) {});\n cursor.toArray(function(err, docs) {});\n\n cursor.rewind() // reset the cursor to its initial state.\n```\n\nUseful chainable methods of cursor. These can optionally be options of `find` instead of method calls:\n\n * `.limit(n).skip(m)` to control paging.\n * `.sort(fields)` Order by the given fields. There are several equivalent syntaxes:\n * `.sort({field1: -1, field2: 1})` descending by field1, then ascending by field2.\n * `.sort([['field1', 'desc'], ['field2', 'asc']])` same as above\n * `.sort([['field1', 'desc'], 'field2'])` same as above\n * `.sort('field1')` ascending by field1\n\nOther options of `find`:\n\n* `fields` the fields to fetch (to avoid transferring the entire document)\n* `tailable` if true, makes the cursor [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors).\n* `batchSize` The number of the subset of results to request the database\nto return for every request. This should initially be greater than 1 otherwise\nthe database will automatically close the cursor. The batch size can be set to 1\nwith `batchSize(n, function(err){})` after performing the initial query to the database.\n* `hint` See [Optimization: hint](http://www.mongodb.org/display/DOCS/Optimization#Optimization-Hint).\n* `explain` turns this into an explain query. You can also call\n`explain()` on any cursor to fetch the explanation.\n* `snapshot` prevents documents that are updated while the query is active\nfrom being returned multiple times. See more\n[details about query snapshots](http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database).\n* `timeout` if false, asks MongoDb not to time out this cursor after an\ninactivity period.\n\n\nFor information on how to create queries, see the\n[MongoDB section on querying](http://www.mongodb.org/display/DOCS/Querying).\n\n```javascript\n var MongoClient = require('mongodb').MongoClient\n , format = require('util').format; \n\n MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {\n if(err) throw err;\n\n var collection = db\n .collection('test')\n .find({})\n .limit(10)\n .toArray(function(err, docs) {\n console.dir(docs);\n });\n });\n```\n\nInsert\n------\n\nSignature:\n\n```javascript\n collection.insert(docs, options, [callback]);\n```\n\nwhere `docs` can be a single document or an array of documents.\n\nUseful options:\n\n* `safe:true` Should always set if you have a callback.\n\nSee also: [MongoDB docs for insert](http://www.mongodb.org/display/DOCS/Inserting).\n\n```javascript\n var MongoClient = require('mongodb').MongoClient\n , format = require('util').format; \n\n MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {\n if(err) throw err;\n \n db.collection('test').insert({hello: 'world'}, {w:1}, function(err, objects) {\n if (err) console.warn(err.message);\n if (err && err.message.indexOf('E11000 ') !== -1) {\n // this _id was already inserted in the database\n }\n });\n });\n```\n\nNote that there's no reason to pass a callback to the insert or update commands\nunless you use the `safe:true` option. If you don't specify `safe:true`, then\nyour callback will be called immediately.\n\nUpdate; update and insert (upsert)\n----------------------------------\n\nThe update operation will update the first document that matches your query\n(or all documents that match if you use `multi:true`).\nIf `safe:true`, `upsert` is not set, and no documents match, your callback will return 0 documents updated.\n\nSee the [MongoDB docs](http://www.mongodb.org/display/DOCS/Updating) for\nthe modifier (`$inc`, `$set`, `$push`, etc.) formats.\n\nSignature:\n\n```javascript\n collection.update(criteria, objNew, options, [callback]);\n```\n\nUseful options:\n\n* `safe:true` Should always set if you have a callback.\n* `multi:true` If set, all matching documents are updated, not just the first.\n* `upsert:true` Atomically inserts the document if no documents matched.\n\nExample for `update`:\n\n```javascript\n var MongoClient = require('mongodb').MongoClient\n , format = require('util').format; \n\n MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {\n if(err) throw err;\n\n db.collection('test').update({hi: 'here'}, {$set: {hi: 'there'}}, {w:1}, function(err) {\n if (err) console.warn(err.message);\n else console.log('successfully updated');\n });\n });\n```\n\nFind and modify\n---------------\n\n`findAndModify` is like `update`, but it also gives the updated document to\nyour callback. But there are a few key differences between findAndModify and\nupdate:\n\n 1. The signatures differ.\n 2. You can only findAndModify a single item, not multiple items.\n\nSignature:\n\n```javascript\n collection.findAndModify(query, sort, update, options, callback)\n```\n\nThe sort parameter is used to specify which object to operate on, if more than\none document matches. It takes the same format as the cursor sort (see\nConnection.find above).\n\nSee the\n[MongoDB docs for findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command)\nfor more details.\n\nUseful options:\n\n* `remove:true` set to a true to remove the object before returning\n* `new:true` set to true if you want to return the modified object rather than the original. Ignored for remove.\n* `upsert:true` Atomically inserts the document if no documents matched.\n\nExample for `findAndModify`:\n\n```javascript\n var MongoClient = require('mongodb').MongoClient\n , format = require('util').format; \n\n MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {\n if(err) throw err;\n db.collection('test').findAndModify({hello: 'world'}, [['_id','asc']], {$set: {hi: 'there'}}, {}, function(err, object) {\n if (err) console.warn(err.message);\n else console.dir(object); // undefined if no matching object exists.\n });\n });\n```\n\nSave\n----\n\nThe `save` method is a shorthand for upsert if the document contains an\n`_id`, or an insert if there is no `_id`.\n\nSponsors\n========\nJust as Felix Geisendörfer I'm also working on the driver for my own startup and this driver is a big project that also benefits other companies who are using MongoDB.\n\nIf your company could benefit from a even better-engineered node.js mongodb driver I would appreciate any type of sponsorship you may be able to provide. All the sponsors will get a lifetime display in this readme, priority support and help on problems and votes on the roadmap decisions for the driver. If you are interested contact me on [christkv AT g m a i l.com](mailto:christkv@gmail.com) for details.\n\nAnd I'm very thankful for code contributions. If you are interested in working on features please contact me so we can discuss API design and testing.\n\nRelease Notes\n=============\n\nSee HISTORY\n\nCredits\n=======\n\n1. [10gen](http://github.com/mongodb/mongo-ruby-driver/)\n2. [Google Closure Library](http://code.google.com/closure/library/)\n3. [Jonas Raoni Soares Silva](http://jsfromhell.com/classes/binary-parser)\n\nContributors\n============\n\nAaron Heckmann, Christoph Pojer, Pau Ramon Revilla, Nathan White, Emmerman, Seth LaForge, Boris Filipov, Stefan Schärmeli, Tedde Lundgren, renctan, Sergey Ukustov, Ciaran Jessup, kuno, srimonti, Erik Abele, Pratik Daga, Slobodan Utvic, Kristina Chodorow, Yonathan Randolph, Brian Noguchi, Sam Epstein, James Harrison Fisher, Vladimir Dronnikov, Ben Hockey, Henrik Johansson, Simon Weare, Alex Gorbatchev, Shimon Doodkin, Kyle Mueller, Eran Hammer-Lahav, Marcin Ciszak, François de Metz, Vinay Pulim, nstielau, Adam Wiggins, entrinzikyl, Jeremy Selier, Ian Millington, Public Keating, andrewjstone, Christopher Stott, Corey Jewett, brettkiefer, Rob Holland, Senmiao Liu, heroic, gitfy\n\nLicense\n=======\n\n Copyright 2009 - 2012 Christian Amor Kvalheim.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n", + "readmeFilename": "Readme.md", + "_id": "mongodb@1.3.11", + "dist": { + "shasum": "1478791b4b5e3f04f1c8257c0e6cf4b69744d02f" + }, + "_from": "mongodb@1.3.11", + "_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-1.3.11.tgz" +} diff --git a/node_modules/mongoose/node_modules/mpath/.npmignore b/node_modules/mongoose/node_modules/mpath/.npmignore new file mode 100644 index 0000000..be106ca --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/.npmignore @@ -0,0 +1,2 @@ +*.sw* +node_modules/ diff --git a/node_modules/mongoose/node_modules/mpath/.travis.yml b/node_modules/mongoose/node_modules/mpath/.travis.yml new file mode 100644 index 0000000..09c230f --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/mongoose/node_modules/mpath/History.md b/node_modules/mongoose/node_modules/mpath/History.md new file mode 100644 index 0000000..4fbf338 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/History.md @@ -0,0 +1,16 @@ + +0.1.1 / 2012-12-21 +================== + + * added; map support + +0.1.0 / 2012-12-13 +================== + + * added; set('array.property', val, object) support + * added; get('array.property', object) support + +0.0.1 / 2012-11-03 +================== + + * initial release diff --git a/node_modules/mongoose/node_modules/mpath/LICENSE b/node_modules/mongoose/node_modules/mpath/LICENSE new file mode 100644 index 0000000..38c529d --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012 [Aaron Heckmann](aaron.heckmann+github@gmail.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/mongoose/node_modules/mpath/Makefile b/node_modules/mongoose/node_modules/mpath/Makefile new file mode 100644 index 0000000..b0bb081 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/Makefile @@ -0,0 +1,5 @@ + +test: + @node_modules/mocha/bin/mocha -A $(T) + +.PHONY: test diff --git a/node_modules/mongoose/node_modules/mpath/README.md b/node_modules/mongoose/node_modules/mpath/README.md new file mode 100644 index 0000000..9831dd0 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/README.md @@ -0,0 +1,278 @@ +#mpath + +{G,S}et javascript object values using MongoDB-like path notation. + +###Getting + +```js +var mpath = require('mpath'); + +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.get('comments.1.title', obj) // 'exciting!' +``` + +`mpath.get` supports array property notation as well. + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.get('comments.title', obj) // ['funny', 'exciting!'] +``` + +Array property and indexing syntax, when used together, are very powerful. + +```js +var obj = { + array: [ + { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }} + , { o: { array: [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: 'Turkey Day' }] }} + , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }} + , { o: { array: [{x: null }] }} + , { o: { array: [{y: 3 }] }} + , { o: { array: [3, 0, null] }} + , { o: { name: 'ha' }} + ]; +} + +var found = mpath.get('array.o.array.x.b.1', obj); + +console.log(found); // prints.. + + [ [6, undefined] + , [2, undefined, undefined] + , [null, 1] + , [null] + , [undefined] + , [undefined, undefined, undefined] + , undefined + ] + +``` + +#####Field selection rules: + +The following rules are iteratively applied to each `segment` in the passed `path`. For example: + +```js +var path = 'one.two.14'; // path +'one' // segment 0 +'two' // segment 1 +14 // segment 2 +``` + +- 1) when value of the segment parent is not an array, return the value of `parent.segment` +- 2) when value of the segment parent is an array + - a) if the segment is an integer, replace the parent array with the value at `parent[segment]` + - b) if not an integer, keep the array but replace each array `item` with the value returned from calling `get(remainingSegments, item)` or undefined if falsey. + +#####Maps + +`mpath.get` also accepts an optional `map` argument which receives each individual found value. The value returned from the `map` function will be used in the original found values place. + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.get('comments.title', obj, function (val) { + return 'funny' == val + ? 'amusing' + : val; +}); +// ['amusing', 'exciting!'] +``` + +###Setting + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.set('comments.1.title', 'hilarious', obj) +console.log(obj.comments[1].title) // 'hilarious' +``` + +`mpath.set` supports the same array property notation as `mpath.get`. + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.set('comments.title', ['hilarious', 'fruity'], obj); + +console.log(obj); // prints.. + + { comments: [ + { title: 'hilarious' }, + { title: 'fruity' } + ]} +``` + +Array property and indexing syntax can be used together also when setting. + +```js +var obj = { + array: [ + { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }} + , { o: { array: [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: 'Turkey Day' }] }} + , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }} + , { o: { array: [{x: null }] }} + , { o: { array: [{y: 3 }] }} + , { o: { array: [3, 0, null] }} + , { o: { name: 'ha' }} + ] +} + +mpath.set('array.1.o', 'this was changed', obj); + +console.log(require('util').inspect(obj, false, 1000)); // prints.. + +{ + array: [ + { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }} + , { o: 'this was changed' } + , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }} + , { o: { array: [{x: null }] }} + , { o: { array: [{y: 3 }] }} + , { o: { array: [3, 0, null] }} + , { o: { name: 'ha' }} + ]; +} + +mpath.set('array.o.array.x', 'this was changed too', obj); + +console.log(require('util').inspect(obj, false, 1000)); // prints.. + +{ + array: [ + { o: { array: [{x: 'this was changed too'}, { y: 10, x: 'this was changed too'} ] }} + , { o: 'this was changed' } + , { o: { array: [{x: 'this was changed too'}, { x: 'this was changed too'}] }} + , { o: { array: [{x: 'this was changed too'}] }} + , { o: { array: [{x: 'this was changed too', y: 3 }] }} + , { o: { array: [3, 0, null] }} + , { o: { name: 'ha' }} + ]; +} +``` + +####Setting arrays + +By default, setting a property within an array to another array results in each element of the new array being set to the item in the destination array at the matching index. An example is helpful. + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.set('comments.title', ['hilarious', 'fruity'], obj); + +console.log(obj); // prints.. + + { comments: [ + { title: 'hilarious' }, + { title: 'fruity' } + ]} +``` + +If we do not desire this destructuring-like assignment behavior we may instead specify the `$` operator in the path being set to force the array to be copied directly. + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.set('comments.$.title', ['hilarious', 'fruity'], obj); + +console.log(obj); // prints.. + + { comments: [ + { title: ['hilarious', 'fruity'] }, + { title: ['hilarious', 'fruity'] } + ]} +``` + +####Field assignment rules + +The rules utilized mirror those used on `mpath.get`, meaning we can take values returned from `mpath.get`, update them, and reassign them using `mpath.set`. Note that setting nested arrays of arrays can get unweildy quickly. Check out the [tests](https://github.com/aheckmann/mpath/blob/master/test/index.js) for more extreme examples. + +#####Maps + +`mpath.set` also accepts an optional `map` argument which receives each individual value being set. The value returned from the `map` function will be used in the original values place. + +```js +var obj = { + comments: [ + { title: 'funny' }, + { title: 'exciting!' } + ] +} + +mpath.set('comments.title', ['hilarious', 'fruity'], obj, function (val) { + return val.length; +}); + +console.log(obj); // prints.. + + { comments: [ + { title: 9 }, + { title: 6 } + ]} +``` + +### Custom object types + +Sometimes you may want to enact the same functionality on custom object types that store all their real data internally, say for an ODM type object. No fear, `mpath` has you covered. Simply pass the name of the property being used to store the internal data and it will be traversed instead: + +```js +var mpath = require('mpath'); + +var obj = { + comments: [ + { title: 'exciting!', _doc: { title: 'great!' }} + ] +} + +mpath.get('comments.0.title', obj, '_doc') // 'great!' +mpath.set('comments.0.title', 'nov 3rd', obj, '_doc') +mpath.get('comments.0.title', obj, '_doc') // 'nov 3rd' +mpath.get('comments.0.title', obj) // 'exciting' +``` + +When used with a `map`, the `map` argument comes last. + +```js +mpath.get(path, obj, '_doc', map); +mpath.set(path, val, obj, '_doc', map); +``` + +[LICENSE](https://github.com/aheckmann/mpath/blob/master/LICENSE) + diff --git a/node_modules/mongoose/node_modules/mpath/index.js b/node_modules/mongoose/node_modules/mpath/index.js new file mode 100644 index 0000000..f7b65dd --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/index.js @@ -0,0 +1 @@ +module.exports = exports = require('./lib'); diff --git a/node_modules/mongoose/node_modules/mpath/lib/index.js b/node_modules/mongoose/node_modules/mpath/lib/index.js new file mode 100644 index 0000000..24e1e83 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/lib/index.js @@ -0,0 +1,183 @@ + +/** + * Returns the value of object `o` at the given `path`. + * + * ####Example: + * + * var obj = { + * comments: [ + * { title: 'exciting!', _doc: { title: 'great!' }} + * , { title: 'number dos' } + * ] + * } + * + * mpath.get('comments.0.title', o) // 'exciting!' + * mpath.get('comments.0.title', o, '_doc') // 'great!' + * mpath.get('comments.title', o) // ['exciting!', 'number dos'] + * + * // summary + * mpath.get(path, o) + * mpath.get(path, o, special) + * mpath.get(path, o, map) + * mpath.get(path, o, special, map) + * + * @param {String} path + * @param {Object} o + * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property. + * @param {Function} [map] Optional function which receives each individual found value. The value returned from `map` is used in the original values place. + */ + +exports.get = function (path, o, special, map) { + if ('function' == typeof special) { + map = special; + special = undefined; + } + + map || (map = K); + + var parts = 'string' == typeof path + ? path.split('.') + : path + + if (!Array.isArray(parts)) { + throw new TypeError('Invalid `path`. Must be either string or array'); + } + + var obj = o + , part; + + for (var i = 0; i < parts.length; ++i) { + part = parts[i]; + + if (Array.isArray(obj) && !/^\d+$/.test(part)) { + // reading a property from the array items + var paths = parts.slice(i); + + return obj.map(function (item) { + return item + ? exports.get(paths, item, special, map) + : map(undefined); + }); + } + + obj = special && obj[special] + ? obj[special][part] + : obj[part]; + + if (!obj) return map(obj); + } + + return map(obj); +} + +/** + * Sets the `val` at the given `path` of object `o`. + * + * @param {String} path + * @param {Anything} val + * @param {Object} o + * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property. + * @param {Function} [map] Optional function which is passed each individual value before setting it. The value returned from `map` is used in the original values place. + + */ + +exports.set = function (path, val, o, special, map, _copying) { + if ('function' == typeof special) { + map = special; + special = undefined; + } + + map || (map = K); + + var parts = 'string' == typeof path + ? path.split('.') + : path + + if (!Array.isArray(parts)) { + throw new TypeError('Invalid `path`. Must be either string or array'); + } + + if (null == o) return; + + // the existance of $ in a path tells us if the user desires + // the copying of an array instead of setting each value of + // the array to the one by one to matching positions of the + // current array. + var copy = _copying || /\$/.test(path) + , obj = o + , part + + for (var i = 0, len = parts.length - 1; i < len; ++i) { + part = parts[i]; + + if ('$' == part) { + if (i == len - 1) { + break; + } else { + continue; + } + } + + if (Array.isArray(obj) && !/^\d+$/.test(part)) { + var paths = parts.slice(i); + if (!copy && Array.isArray(val)) { + for (var j = 0; j < obj.length && j < val.length; ++j) { + // assignment of single values of array + exports.set(paths, val[j], obj[j], special, map, copy); + } + } else { + for (var j = 0; j < obj.length; ++j) { + // assignment of entire value + exports.set(paths, val, obj[j], special, map, copy); + } + } + return; + } + + obj = special && obj[special] + ? obj[special][part] + : obj[part]; + + if (!obj) return; + } + + // process the last property of the path + + part = parts[len]; + + // use the special property if exists + if (special && obj[special]) { + obj = obj[special]; + } + + // set the value on the last branch + if (Array.isArray(obj) && !/^\d+$/.test(part)) { + if (!copy && Array.isArray(val)) { + for (var item, j = 0; j < obj.length && j < val.length; ++j) { + item = obj[j]; + if (item) { + if (item[special]) item = item[special]; + item[part] = map(val[j]); + } + } + } else { + for (var j = 0; j < obj.length; ++j) { + item = obj[j]; + if (item) { + if (item[special]) item = item[special]; + item[part] = map(val); + } + } + } + } else { + obj[part] = map(val); + } +} + +/*! + * Returns the value passed to it. + */ + +function K (v) { + return v; +} diff --git a/node_modules/mongoose/node_modules/mpath/package.json b/node_modules/mongoose/node_modules/mpath/package.json new file mode 100644 index 0000000..61f35d7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/package.json @@ -0,0 +1,35 @@ +{ + "name": "mpath", + "version": "0.1.1", + "description": "{G,S}et object values using MongoDB path notation", + "main": "index.js", + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/aheckmann/mpath.git" + }, + "keywords": [ + "mongodb", + "path", + "get", + "set" + ], + "author": { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + "license": "MIT", + "devDependencies": { + "mocha": "1.6.0" + }, + "readme": "#mpath\n\n{G,S}et javascript object values using MongoDB-like path notation.\n\n###Getting\n\n```js\nvar mpath = require('mpath');\n\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.get('comments.1.title', obj) // 'exciting!'\n```\n\n`mpath.get` supports array property notation as well.\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.get('comments.title', obj) // ['funny', 'exciting!']\n```\n\nArray property and indexing syntax, when used together, are very powerful.\n\n```js\nvar obj = {\n array: [\n { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }}\n , { o: { array: [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: 'Turkey Day' }] }}\n , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }}\n , { o: { array: [{x: null }] }}\n , { o: { array: [{y: 3 }] }}\n , { o: { array: [3, 0, null] }}\n , { o: { name: 'ha' }}\n ];\n}\n\nvar found = mpath.get('array.o.array.x.b.1', obj);\n\nconsole.log(found); // prints..\n\n [ [6, undefined]\n , [2, undefined, undefined]\n , [null, 1]\n , [null]\n , [undefined]\n , [undefined, undefined, undefined]\n , undefined\n ]\n\n```\n\n#####Field selection rules:\n\nThe following rules are iteratively applied to each `segment` in the passed `path`. For example:\n\n```js\nvar path = 'one.two.14'; // path\n'one' // segment 0\n'two' // segment 1\n14 // segment 2\n```\n\n- 1) when value of the segment parent is not an array, return the value of `parent.segment`\n- 2) when value of the segment parent is an array\n - a) if the segment is an integer, replace the parent array with the value at `parent[segment]`\n - b) if not an integer, keep the array but replace each array `item` with the value returned from calling `get(remainingSegments, item)` or undefined if falsey.\n\n#####Maps\n\n`mpath.get` also accepts an optional `map` argument which receives each individual found value. The value returned from the `map` function will be used in the original found values place.\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.get('comments.title', obj, function (val) {\n return 'funny' == val\n ? 'amusing'\n : val;\n});\n// ['amusing', 'exciting!']\n```\n\n###Setting\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.set('comments.1.title', 'hilarious', obj)\nconsole.log(obj.comments[1].title) // 'hilarious'\n```\n\n`mpath.set` supports the same array property notation as `mpath.get`.\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.set('comments.title', ['hilarious', 'fruity'], obj);\n\nconsole.log(obj); // prints..\n\n { comments: [\n { title: 'hilarious' },\n { title: 'fruity' }\n ]}\n```\n\nArray property and indexing syntax can be used together also when setting.\n\n```js\nvar obj = {\n array: [\n { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }}\n , { o: { array: [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: 'Turkey Day' }] }}\n , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }}\n , { o: { array: [{x: null }] }}\n , { o: { array: [{y: 3 }] }}\n , { o: { array: [3, 0, null] }}\n , { o: { name: 'ha' }}\n ]\n}\n\nmpath.set('array.1.o', 'this was changed', obj);\n\nconsole.log(require('util').inspect(obj, false, 1000)); // prints..\n\n{\n array: [\n { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }}\n , { o: 'this was changed' }\n , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }}\n , { o: { array: [{x: null }] }}\n , { o: { array: [{y: 3 }] }}\n , { o: { array: [3, 0, null] }}\n , { o: { name: 'ha' }}\n ];\n}\n\nmpath.set('array.o.array.x', 'this was changed too', obj);\n\nconsole.log(require('util').inspect(obj, false, 1000)); // prints..\n\n{\n array: [\n { o: { array: [{x: 'this was changed too'}, { y: 10, x: 'this was changed too'} ] }}\n , { o: 'this was changed' }\n , { o: { array: [{x: 'this was changed too'}, { x: 'this was changed too'}] }}\n , { o: { array: [{x: 'this was changed too'}] }}\n , { o: { array: [{x: 'this was changed too', y: 3 }] }}\n , { o: { array: [3, 0, null] }}\n , { o: { name: 'ha' }}\n ];\n}\n```\n\n####Setting arrays\n\nBy default, setting a property within an array to another array results in each element of the new array being set to the item in the destination array at the matching index. An example is helpful.\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.set('comments.title', ['hilarious', 'fruity'], obj);\n\nconsole.log(obj); // prints..\n\n { comments: [\n { title: 'hilarious' },\n { title: 'fruity' }\n ]}\n```\n\nIf we do not desire this destructuring-like assignment behavior we may instead specify the `$` operator in the path being set to force the array to be copied directly.\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.set('comments.$.title', ['hilarious', 'fruity'], obj);\n\nconsole.log(obj); // prints..\n\n { comments: [\n { title: ['hilarious', 'fruity'] },\n { title: ['hilarious', 'fruity'] }\n ]}\n```\n\n####Field assignment rules\n\nThe rules utilized mirror those used on `mpath.get`, meaning we can take values returned from `mpath.get`, update them, and reassign them using `mpath.set`. Note that setting nested arrays of arrays can get unweildy quickly. Check out the [tests](https://github.com/aheckmann/mpath/blob/master/test/index.js) for more extreme examples.\n\n#####Maps\n\n`mpath.set` also accepts an optional `map` argument which receives each individual value being set. The value returned from the `map` function will be used in the original values place.\n\n```js\nvar obj = {\n comments: [\n { title: 'funny' },\n { title: 'exciting!' }\n ]\n}\n\nmpath.set('comments.title', ['hilarious', 'fruity'], obj, function (val) {\n return val.length;\n});\n\nconsole.log(obj); // prints..\n\n { comments: [\n { title: 9 },\n { title: 6 }\n ]}\n```\n\n### Custom object types\n\nSometimes you may want to enact the same functionality on custom object types that store all their real data internally, say for an ODM type object. No fear, `mpath` has you covered. Simply pass the name of the property being used to store the internal data and it will be traversed instead:\n\n```js\nvar mpath = require('mpath');\n\nvar obj = {\n comments: [\n { title: 'exciting!', _doc: { title: 'great!' }}\n ]\n}\n\nmpath.get('comments.0.title', obj, '_doc') // 'great!'\nmpath.set('comments.0.title', 'nov 3rd', obj, '_doc')\nmpath.get('comments.0.title', obj, '_doc') // 'nov 3rd'\nmpath.get('comments.0.title', obj) // 'exciting'\n```\n\nWhen used with a `map`, the `map` argument comes last.\n\n```js\nmpath.get(path, obj, '_doc', map);\nmpath.set(path, val, obj, '_doc', map);\n```\n\n[LICENSE](https://github.com/aheckmann/mpath/blob/master/LICENSE)\n\n", + "readmeFilename": "README.md", + "_id": "mpath@0.1.1", + "dist": { + "shasum": "692e6ac6f50d43f08320847272b5aaa47295f2eb" + }, + "_from": "mpath@0.1.1", + "_resolved": "https://registry.npmjs.org/mpath/-/mpath-0.1.1.tgz" +} diff --git a/node_modules/mongoose/node_modules/mpath/test/index.js b/node_modules/mongoose/node_modules/mpath/test/index.js new file mode 100644 index 0000000..98e119a --- /dev/null +++ b/node_modules/mongoose/node_modules/mpath/test/index.js @@ -0,0 +1,1630 @@ + +/** + * Test dependencies. + */ + +var mpath = require('../') +var assert = require('assert') + +/** + * logging helper + */ + +function log (o) { + console.log(); + console.log(require('util').inspect(o, false, 1000)); +} + +/** + * special path for override tests + */ + +var special = '_doc'; + +/** + * Tests + */ + +describe('mpath', function(){ + + /** + * test doc creator + */ + + function doc () { + var o = { first: { second: { third: [3,{ name: 'aaron' }, 9] }}}; + o.comments = [ + { name: 'one' } + , { name: 'two', _doc: { name: '2' }} + , { name: 'three' + , comments: [{},{ comments: [{val: 'twoo'}]}] + , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}] }} + ]; + o.name = 'jiro'; + o.array = [ + { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }} + , { o: { array: [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: {b: 'hi'}}] }} + , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }} + , { o: { array: [{x: null }] }} + , { o: { array: [{y: 3 }] }} + , { o: { array: [3, 0, null] }} + , { o: { name: 'ha' }} + ]; + o.arr = [ + { arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true } + ] + return o; + } + + describe('get', function(){ + var o = doc(); + + it('`path` must be a string or array', function(done){ + assert.throws(function () { + mpath.get({}, o); + }, /Must be either string or array/); + assert.throws(function () { + mpath.get(4, o); + }, /Must be either string or array/); + assert.throws(function () { + mpath.get(function(){}, o); + }, /Must be either string or array/); + assert.throws(function () { + mpath.get(/asdf/, o); + }, /Must be either string or array/); + assert.throws(function () { + mpath.get(Math, o); + }, /Must be either string or array/); + assert.throws(function () { + mpath.get(Buffer, o); + }, /Must be either string or array/); + assert.doesNotThrow(function () { + mpath.get('string', o); + }); + assert.doesNotThrow(function () { + mpath.get([], o); + }); + done(); + }) + + describe('without `special`', function(){ + it('works', function(done){ + assert.equal('jiro', mpath.get('name', o)); + + assert.deepEqual( + { second: { third: [3,{ name: 'aaron' }, 9] }} + , mpath.get('first', o) + ); + + assert.deepEqual( + { third: [3,{ name: 'aaron' }, 9] } + , mpath.get('first.second', o) + ); + + assert.deepEqual( + [3,{ name: 'aaron' }, 9] + , mpath.get('first.second.third', o) + ); + + assert.deepEqual( + 3 + , mpath.get('first.second.third.0', o) + ); + + assert.deepEqual( + 9 + , mpath.get('first.second.third.2', o) + ); + + assert.deepEqual( + { name: 'aaron' } + , mpath.get('first.second.third.1', o) + ); + + assert.deepEqual( + 'aaron' + , mpath.get('first.second.third.1.name', o) + ); + + assert.deepEqual([ + { name: 'one' } + , { name: 'two', _doc: { name: '2' }} + , { name: 'three' + , comments: [{},{ comments: [{val: 'twoo'}]}] + , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}]}}], + mpath.get('comments', o)); + + assert.deepEqual({ name: 'one' }, mpath.get('comments.0', o)); + assert.deepEqual('one', mpath.get('comments.0.name', o)); + assert.deepEqual('two', mpath.get('comments.1.name', o)); + assert.deepEqual('three', mpath.get('comments.2.name', o)); + + assert.deepEqual([{},{ comments: [{val: 'twoo'}]}] + , mpath.get('comments.2.comments', o)); + + assert.deepEqual({ comments: [{val: 'twoo'}]} + , mpath.get('comments.2.comments.1', o)); + + assert.deepEqual('twoo', mpath.get('comments.2.comments.1.comments.0.val', o)); + + done(); + }) + + it('handles array.property dot-notation', function(done){ + assert.deepEqual( + ['one', 'two', 'three'] + , mpath.get('comments.name', o) + ); + done(); + }) + + it('handles array.array notation', function(done){ + assert.deepEqual( + [undefined, undefined, [{}, {comments:[{val:'twoo'}]}]] + , mpath.get('comments.comments', o) + ); + done(); + }) + + it('handles prop.prop.prop.arrayProperty notation', function(done){ + assert.deepEqual( + [undefined, 'aaron', undefined] + , mpath.get('first.second.third.name', o) + ); + assert.deepEqual( + [1, 'aaron', 1] + , mpath.get('first.second.third.name', o, function (v) { + return undefined === v ? 1 : v; + }) + ); + done(); + }) + + it('handles array.prop.array', function(done){ + assert.deepEqual( + [ [{x: {b: [4,6,8]}}, { y: 10} ] + , [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: {b: 'hi'}}] + , [{x: {b: null }}, { x: { b: [null, 1]}}] + , [{x: null }] + , [{y: 3 }] + , [3, 0, null] + , undefined + ] + , mpath.get('array.o.array', o) + ); + done(); + }) + + it('handles array.prop.array.index', function(done){ + assert.deepEqual( + [ {x: {b: [4,6,8]}} + , {x: {b: [1,2,3]}} + , {x: {b: null }} + , {x: null } + , {y: 3 } + , 3 + , undefined + ] + , mpath.get('array.o.array.0', o) + ); + done(); + }) + + it('handles array.prop.array.index.prop', function(done){ + assert.deepEqual( + [ {b: [4,6,8]} + , {b: [1,2,3]} + , {b: null } + , null + , undefined + , undefined + , undefined + ] + , mpath.get('array.o.array.0.x', o) + ); + done(); + }) + + it('handles array.prop.array.prop', function(done){ + assert.deepEqual( + [ [undefined, 10 ] + , [undefined, undefined, undefined] + , [undefined, undefined] + , [undefined] + , [3] + , [undefined, undefined, undefined] + , undefined + ] + , mpath.get('array.o.array.y', o) + ); + assert.deepEqual( + [ [{b: [4,6,8]}, undefined] + , [{b: [1,2,3]}, {z: 10 }, {b: 'hi'}] + , [{b: null }, { b: [null, 1]}] + , [null] + , [undefined] + , [undefined, undefined, undefined] + , undefined + ] + , mpath.get('array.o.array.x', o) + ); + done(); + }) + + it('handles array.prop.array.prop.prop', function(done){ + assert.deepEqual( + [ [[4,6,8], undefined] + , [[1,2,3], undefined, 'hi'] + , [null, [null, 1]] + , [null] + , [undefined] + , [undefined, undefined, undefined] + , undefined + ] + , mpath.get('array.o.array.x.b', o) + ); + done(); + }) + + it('handles array.prop.array.prop.prop.index', function(done){ + assert.deepEqual( + [ [6, undefined] + , [2, undefined, 'i'] // undocumented feature (string indexing) + , [null, 1] + , [null] + , [undefined] + , [undefined, undefined, undefined] + , undefined + ] + , mpath.get('array.o.array.x.b.1', o) + ); + assert.deepEqual( + [ [6, 0] + , [2, 0, 'i'] // undocumented feature (string indexing) + , [null, 1] + , [null] + , [0] + , [0, 0, 0] + , 0 + ] + , mpath.get('array.o.array.x.b.1', o, function (v) { + return undefined === v ? 0 : v; + }) + ); + done(); + }) + + it('handles array.index.prop.prop', function(done){ + assert.deepEqual( + [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: {b: 'hi'}}] + , mpath.get('array.1.o.array', o) + ); + assert.deepEqual( + ['hi','hi','hi'] + , mpath.get('array.1.o.array', o, function (v) { + if (Array.isArray(v)) { + return v.map(function (val) { + return 'hi'; + }) + } + return v; + }) + ); + done(); + }) + + it('handles array.array.index', function(done){ + assert.deepEqual( + [{ a: { c: 48 }}, undefined] + , mpath.get('arr.arr.1', o) + ); + assert.deepEqual( + ['woot', undefined] + , mpath.get('arr.arr.1', o, function (v) { + if (v && v.a && v.a.c) return 'woot'; + return v; + }) + ); + done(); + }) + + it('handles array.array.index.prop', function(done){ + assert.deepEqual( + [{ c: 48 }, 'woot'] + , mpath.get('arr.arr.1.a', o, function (v) { + if (undefined === v) return 'woot'; + return v; + }) + ); + assert.deepEqual( + [{ c: 48 }, undefined] + , mpath.get('arr.arr.1.a', o) + ); + mpath.set('arr.arr.1.a', [{c:49},undefined], o) + assert.deepEqual( + [{ c: 49 }, undefined] + , mpath.get('arr.arr.1.a', o) + ); + mpath.set('arr.arr.1.a', [{c:48},undefined], o) + done(); + }) + + it('handles array.array.index.prop.prop', function(done){ + assert.deepEqual( + [48, undefined] + , mpath.get('arr.arr.1.a.c', o) + ); + assert.deepEqual( + [48, 'woot'] + , mpath.get('arr.arr.1.a.c', o, function (v) { + if (undefined === v) return 'woot'; + return v; + }) + ); + done(); + }) + + }) + + describe('with `special`', function(){ + it('works', function(done){ + assert.equal('jiro', mpath.get('name', o, special)); + + assert.deepEqual( + { second: { third: [3,{ name: 'aaron' }, 9] }} + , mpath.get('first', o, special) + ); + + assert.deepEqual( + { third: [3,{ name: 'aaron' }, 9] } + , mpath.get('first.second', o, special) + ); + + assert.deepEqual( + [3,{ name: 'aaron' }, 9] + , mpath.get('first.second.third', o, special) + ); + + assert.deepEqual( + 3 + , mpath.get('first.second.third.0', o, special) + ); + + assert.deepEqual( + 4 + , mpath.get('first.second.third.0', o, special, function (v) { + return 3 === v ? 4 : v; + }) + ); + + assert.deepEqual( + 9 + , mpath.get('first.second.third.2', o, special) + ); + + assert.deepEqual( + { name: 'aaron' } + , mpath.get('first.second.third.1', o, special) + ); + + assert.deepEqual( + 'aaron' + , mpath.get('first.second.third.1.name', o, special) + ); + + assert.deepEqual([ + { name: 'one' } + , { name: 'two', _doc: { name: '2' }} + , { name: 'three' + , comments: [{},{ comments: [{val: 'twoo'}]}] + , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}]}}], + mpath.get('comments', o, special)); + + assert.deepEqual({ name: 'one' }, mpath.get('comments.0', o, special)); + assert.deepEqual('one', mpath.get('comments.0.name', o, special)); + assert.deepEqual('2', mpath.get('comments.1.name', o, special)); + assert.deepEqual('3', mpath.get('comments.2.name', o, special)); + assert.deepEqual('nice', mpath.get('comments.2.name', o, special, function (v) { + return '3' === v ? 'nice' : v; + })); + + assert.deepEqual([{},{ _doc: { comments: [{ val: 2 }] }}] + , mpath.get('comments.2.comments', o, special)); + + assert.deepEqual({ _doc: { comments: [{val: 2}]}} + , mpath.get('comments.2.comments.1', o, special)); + + assert.deepEqual(2, mpath.get('comments.2.comments.1.comments.0.val', o, special)); + done(); + }) + + it('handles array.property dot-notation', function(done){ + assert.deepEqual( + ['one', '2', '3'] + , mpath.get('comments.name', o, special) + ); + assert.deepEqual( + ['one', 2, '3'] + , mpath.get('comments.name', o, special, function (v) { + return '2' === v ? 2 : v + }) + ); + done(); + }) + + it('handles array.array notation', function(done){ + assert.deepEqual( + [undefined, undefined, [{}, {_doc: { comments:[{val:2}]}}]] + , mpath.get('comments.comments', o, special) + ); + done(); + }) + + it('handles array.array.index.array', function(done){ + assert.deepEqual( + [undefined, undefined, [{val:2}]] + , mpath.get('comments.comments.1.comments', o, special) + ); + done(); + }) + + it('handles array.array.index.array.prop', function(done){ + assert.deepEqual( + [undefined, undefined, [2]] + , mpath.get('comments.comments.1.comments.val', o, special) + ); + assert.deepEqual( + ['nil', 'nil', [2]] + , mpath.get('comments.comments.1.comments.val', o, special, function (v) { + return undefined === v ? 'nil' : v; + }) + ); + done(); + }) + }) + + }) + + describe('set', function(){ + describe('without `special`', function(){ + var o = doc(); + + it('works', function(done){ + mpath.set('name', 'a new val', o, function (v) { + return 'a new val' === v ? 'changed' : v; + }); + assert.deepEqual('changed', o.name); + + mpath.set('name', 'changed', o); + assert.deepEqual('changed', o.name); + + mpath.set('first.second.third', [1,{name:'x'},9], o); + assert.deepEqual([1,{name:'x'},9], o.first.second.third); + + mpath.set('first.second.third.1.name', 'y', o) + assert.deepEqual([1,{name:'y'},9], o.first.second.third); + + mpath.set('comments.1.name', 'ttwwoo', o); + assert.deepEqual({ name: 'ttwwoo', _doc: { name: '2' }}, o.comments[1]); + + mpath.set('comments.2.comments.1.comments.0.expand', 'added', o); + assert.deepEqual( + { val: 'twoo', expand: 'added'} + , o.comments[2].comments[1].comments[0]); + + mpath.set('comments.2.comments.1.comments.2', 'added', o); + assert.equal(3, o.comments[2].comments[1].comments.length); + assert.deepEqual( + { val: 'twoo', expand: 'added'} + , o.comments[2].comments[1].comments[0]); + assert.deepEqual( + undefined + , o.comments[2].comments[1].comments[1]); + assert.deepEqual( + 'added' + , o.comments[2].comments[1].comments[2]); + + done(); + }) + + describe('array.path', function(){ + describe('with single non-array value', function(){ + it('works', function(done){ + mpath.set('arr.yep', false, o, function (v) { + return false === v ? true: v; + }); + assert.deepEqual([ + { yep: true, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true } + ], o.arr); + + mpath.set('arr.yep', false, o); + + assert.deepEqual([ + { yep: false, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: false } + ], o.arr); + + done(); + }) + }) + describe('with array of values', function(){ + it('that are equal in length', function(done){ + mpath.set('arr.yep', ['one',2], o, function (v) { + return 'one' === v ? 1 : v; + }); + assert.deepEqual([ + { yep: 1, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 2 } + ], o.arr); + mpath.set('arr.yep', ['one',2], o); + + assert.deepEqual([ + { yep: 'one', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 2 } + ], o.arr); + + done(); + }) + + it('that is less than length', function(done){ + mpath.set('arr.yep', [47], o, function (v) { + return 47 === v ? 4 : v; + }); + assert.deepEqual([ + { yep: 4, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 2 } + ], o.arr); + + mpath.set('arr.yep', [47], o); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 2 } + ], o.arr); + + done(); + }) + + it('that is greater than length', function(done){ + mpath.set('arr.yep', [5,6,7], o, function (v) { + return 5 === v ? 'five' : v; + }); + assert.deepEqual([ + { yep: 'five', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 6 } + ], o.arr); + + mpath.set('arr.yep', [5,6,7], o); + assert.deepEqual([ + { yep: 5, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 6 } + ], o.arr); + + done(); + }) + }) + }) + + describe('array.$.path', function(){ + describe('with single non-array value', function(){ + it('copies the value to each item in array', function(done){ + mpath.set('arr.$.yep', {xtra: 'double good'}, o, function (v) { + return v && v.xtra ? 'hi' : v; + }); + assert.deepEqual([ + { yep: 'hi', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 'hi'} + ], o.arr); + + mpath.set('arr.$.yep', {xtra: 'double good'}, o); + assert.deepEqual([ + { yep: {xtra:'double good'}, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: {xtra:'double good'}} + ], o.arr); + + done(); + }) + }) + describe('with array of values', function(){ + it('copies the value to each item in array', function(done){ + mpath.set('arr.$.yep', [15], o, function (v) { + return v.length === 1 ? [] : v; + }); + assert.deepEqual([ + { yep: [], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: []} + ], o.arr); + + mpath.set('arr.$.yep', [15], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: [15]} + ], o.arr); + + done(); + }) + }) + }) + + describe('array.index.path', function(){ + it('works', function(done){ + mpath.set('arr.1.yep', 0, o, function (v) { + return 0 === v ? 'zero' : v; + }); + assert.deepEqual([ + { yep: [15] , arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 'zero' } + ], o.arr); + + mpath.set('arr.1.yep', 0, o); + assert.deepEqual([ + { yep: [15] , arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + }) + + describe('array.index.array.path', function(){ + it('with single value', function(done){ + mpath.set('arr.0.arr.e', 35, o, function (v) { + return 35 === v ? 3 : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 47 }, e: 3}, { a: { c: 48 }, e: 3}, { d: 'yep', e: 3 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.0.arr.e', 35, o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 47 }, e: 35}, { a: { c: 48 }, e: 35}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.0.arr.e', ['a','b'], o, function (v) { + return 'a' === v ? 'x' : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 47 }, e: 'x'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.0.arr.e', ['a','b'], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 47 }, e: 'a'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + }) + + describe('array.index.array.path.path', function(){ + it('with single value', function(done){ + mpath.set('arr.0.arr.a.b', 36, o, function (v) { + return 36 === v ? 3 : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 3 }, e: 'a'}, { a: { c: 48, b: 3 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.0.arr.a.b', 36, o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 36 }, e: 'a'}, { a: { c: 48, b: 36 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.0.arr.a.b', [1,2,3,4], o, function (v) { + return 2 === v ? 'two' : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 1 }, e: 'a'}, { a: { c: 48, b: 'two' }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.0.arr.a.b', [1,2,3,4], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 1 }, e: 'a'}, { a: { c: 48, b: 2 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + }) + + describe('array.index.array.$.path.path', function(){ + it('with single value', function(done){ + mpath.set('arr.0.arr.$.a.b', '$', o, function (v) { + return '$' === v ? 'dolla billz' : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: 'dolla billz' }, e: 'a'}, { a: { c: 48, b: 'dolla billz' }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.0.arr.$.a.b', '$', o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: '$' }, e: 'a'}, { a: { c: 48, b: '$' }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.0.arr.$.a.b', [1], o, function (v) { + return Array.isArray(v) ? {} : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: {} }, e: 'a'}, { a: { c: 48, b: {} }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.0.arr.$.a.b', [1], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: { b: [1] }, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + }) + + describe('array.array.index.path', function(){ + it('with single value', function(done){ + mpath.set('arr.arr.0.a', 'single', o, function (v) { + return 'single' === v ? 'double' : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: 'double', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.arr.0.a', 'single', o); + assert.deepEqual([ + { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o, function (v) { + return 4 === v ? 3 : v; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: 3, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: false } + ], o.arr); + + mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: 4, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: false } + ], o.arr); + + done(); + }) + }) + + describe('array.array.$.index.path', function(){ + it('with single value', function(done){ + mpath.set('arr.arr.$.0.a', 'singles', o, function (v) { + return 0; + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: 0, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('arr.arr.$.0.a', 'singles', o); + assert.deepEqual([ + { yep: [15], arr: [{ a: 'singles', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + mpath.set('$.arr.arr.0.a', 'single', o); + assert.deepEqual([ + { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0 } + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.arr.$.0.a', [4,8,15,16,23,42], o, function (v) { + return 'nope' + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: 'nope', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0} + ], o.arr); + + mpath.set('arr.arr.$.0.a', [4,8,15,16,23,42], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: [4,8,15,16,23,42], e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0} + ], o.arr); + + mpath.set('arr.$.arr.0.a', [4,8,15,16,23,42,108], o); + assert.deepEqual([ + { yep: [15], arr: [{ a: [4,8,15,16,23,42,108], e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0} + ], o.arr); + + done(); + }) + }) + + describe('array.array.path.index', function(){ + it('with single value', function(done){ + mpath.set('arr.arr.a.7', 47, o, function (v) { + return 1 + }); + assert.deepEqual([ + { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,1], e: 'a'}, { a: { c: 48, b: [1], '7': 1 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0} + ], o.arr); + + mpath.set('arr.arr.a.7', 47, o); + assert.deepEqual([ + { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,47], e: 'a'}, { a: { c: 48, b: [1], '7': 47 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0} + ], o.arr); + + done(); + }) + it('with array', function(done){ + o.arr[1].arr = [{ a: [] }, { a: [] }, { a: null }]; + mpath.set('arr.arr.a.7', [[null,46], [undefined, 'woot']], o); + + var a1 = []; + var a2 = []; + a1[7] = undefined; + a2[7] = 'woot'; + + assert.deepEqual([ + { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,null], e: 'a'}, { a: { c: 48, b: [1], '7': 46 }, e: 'b'}, { d: 'yep', e: 35 }] } + , { yep: 0, arr: [{a:a1},{a:a2},{a:null}] } + ], o.arr); + + done(); + }) + }) + + describe('handles array.array.path', function(){ + it('with single', function(done){ + o.arr[1].arr = [{},{}]; + assert.deepEqual([{},{}], o.arr[1].arr); + o.arr.push({ arr: 'something else' }); + o.arr.push({ arr: ['something else'] }); + o.arr.push({ arr: [[]] }); + o.arr.push({ arr: [5] }); + + var weird = []; + weird.e = 'xmas'; + + // test + mpath.set('arr.arr.e', 47, o, function (v) { + return 'xmas' + }); + assert.deepEqual([ + { yep: [15], arr: [ + { a: [4,8,15,16,23,42,108,null], e: 'xmas'} + , { a: { c: 48, b: [1], '7': 46 }, e: 'xmas'} + , { d: 'yep', e: 'xmas' } + ] + } + , { yep: 0, arr: [{e: 'xmas'}, {e:'xmas'}] } + , { arr: 'something else' } + , { arr: ['something else'] } + , { arr: [weird] } + , { arr: [5] } + ] + , o.arr); + + weird.e = 47; + + mpath.set('arr.arr.e', 47, o); + assert.deepEqual([ + { yep: [15], arr: [ + { a: [4,8,15,16,23,42,108,null], e: 47} + , { a: { c: 48, b: [1], '7': 46 }, e: 47} + , { d: 'yep', e: 47 } + ] + } + , { yep: 0, arr: [{e: 47}, {e:47}] } + , { arr: 'something else' } + , { arr: ['something else'] } + , { arr: [weird] } + , { arr: [5] } + ] + , o.arr); + + done(); + }) + it('with arrays', function(done){ + mpath.set('arr.arr.e', [[1,2,3],[4,5],null,[],[6], [7,8,9]], o, function (v) { + return 10; + }); + + var weird = []; + weird.e = 10; + + assert.deepEqual([ + { yep: [15], arr: [ + { a: [4,8,15,16,23,42,108,null], e: 10} + , { a: { c: 48, b: [1], '7': 46 }, e: 10} + , { d: 'yep', e: 10 } + ] + } + , { yep: 0, arr: [{e: 10}, {e:10}] } + , { arr: 'something else' } + , { arr: ['something else'] } + , { arr: [weird] } + , { arr: [5] } + ] + , o.arr); + + mpath.set('arr.arr.e', [[1,2,3],[4,5],null,[],[6], [7,8,9]], o); + + weird.e = 6; + + assert.deepEqual([ + { yep: [15], arr: [ + { a: [4,8,15,16,23,42,108,null], e: 1} + , { a: { c: 48, b: [1], '7': 46 }, e: 2} + , { d: 'yep', e: 3 } + ] + } + , { yep: 0, arr: [{e: 4}, {e:5}] } + , { arr: 'something else' } + , { arr: ['something else'] } + , { arr: [weird] } + , { arr: [5] } + ] + , o.arr); + + done(); + }) + }) + }) + + describe('with `special`', function(){ + var o = doc(); + + it('works', function(done){ + mpath.set('name', 'chan', o, special, function (v) { + return 'hi'; + }); + assert.deepEqual('hi', o.name); + + mpath.set('name', 'changer', o, special); + assert.deepEqual('changer', o.name); + + mpath.set('first.second.third', [1,{name:'y'},9], o, special); + assert.deepEqual([1,{name:'y'},9], o.first.second.third); + + mpath.set('first.second.third.1.name', 'z', o, special) + assert.deepEqual([1,{name:'z'},9], o.first.second.third); + + mpath.set('comments.1.name', 'ttwwoo', o, special); + assert.deepEqual({ name: 'two', _doc: { name: 'ttwwoo' }}, o.comments[1]); + + mpath.set('comments.2.comments.1.comments.0.expander', 'adder', o, special, function (v) { + return 'super' + }); + assert.deepEqual( + { val: 2, expander: 'super'} + , o.comments[2]._doc.comments[1]._doc.comments[0]); + + mpath.set('comments.2.comments.1.comments.0.expander', 'adder', o, special); + assert.deepEqual( + { val: 2, expander: 'adder'} + , o.comments[2]._doc.comments[1]._doc.comments[0]); + + mpath.set('comments.2.comments.1.comments.2', 'set', o, special); + assert.equal(3, o.comments[2]._doc.comments[1]._doc.comments.length); + assert.deepEqual( + { val: 2, expander: 'adder'} + , o.comments[2]._doc.comments[1]._doc.comments[0]); + assert.deepEqual( + undefined + , o.comments[2]._doc.comments[1]._doc.comments[1]); + assert.deepEqual( + 'set' + , o.comments[2]._doc.comments[1]._doc.comments[2]); + done(); + }) + + describe('array.path', function(){ + describe('with single non-array value', function(){ + it('works', function(done){ + o.arr[1]._doc = { special: true } + + mpath.set('arr.yep', false, o, special, function (v) { + return 'yes'; + }); + assert.deepEqual([ + { yep: 'yes', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true, _doc: { special: true, yep: 'yes'}} + ], o.arr); + + mpath.set('arr.yep', false, o, special); + assert.deepEqual([ + { yep: false, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true, _doc: { special: true, yep: false }} + ], o.arr); + + done(); + }) + }) + describe('with array of values', function(){ + it('that are equal in length', function(done){ + mpath.set('arr.yep', ['one',2], o, special, function (v) { + return 2 === v ? 20 : v; + }); + assert.deepEqual([ + { yep: 'one', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true, _doc: { special: true, yep: 20}} + ], o.arr); + + mpath.set('arr.yep', ['one',2], o, special); + assert.deepEqual([ + { yep: 'one', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true, _doc: { special: true, yep: 2}} + ], o.arr); + + done(); + }) + + it('that is less than length', function(done){ + mpath.set('arr.yep', [47], o, special, function (v) { + return 80; + }); + assert.deepEqual([ + { yep: 80, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true, _doc: { special: true, yep: 2}} + ], o.arr); + + mpath.set('arr.yep', [47], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + , { yep: true, _doc: { special: true, yep: 2}} + ], o.arr); + + // add _doc to first element + o.arr[0]._doc = { yep: 46, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } + + mpath.set('arr.yep', [20], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }], _doc: { yep: 20, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 2}} + ], o.arr); + + done(); + }) + + it('that is greater than length', function(done){ + mpath.set('arr.yep', [5,6,7], o, special, function () { + return 'x'; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }], _doc: { yep: 'x', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 'x'}} + ], o.arr); + + mpath.set('arr.yep', [5,6,7], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }], _doc: { yep: 5, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 6}} + ], o.arr); + + done(); + }) + }) + }) + + describe('array.$.path', function(){ + describe('with single non-array value', function(){ + it('copies the value to each item in array', function(done){ + mpath.set('arr.$.yep', {xtra: 'double good'}, o, special, function (v) { + return 9; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: 9, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 9}} + ], o.arr); + + mpath.set('arr.$.yep', {xtra: 'double good'}, o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: {xtra:'double good'}, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: {xtra:'double good'}}} + ], o.arr); + + done(); + }) + }) + describe('with array of values', function(){ + it('copies the value to each item in array', function(done){ + mpath.set('arr.$.yep', [15], o, special, function (v) { + return 'array' + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: 'array', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 'array'}} + ], o.arr); + + mpath.set('arr.$.yep', [15], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: [15]}} + ], o.arr); + + done(); + }) + }) + }) + + describe('array.index.path', function(){ + it('works', function(done){ + mpath.set('arr.1.yep', 0, o, special, function (v) { + return 1; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 1}} + ], o.arr); + + mpath.set('arr.1.yep', 0, o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('array.index.array.path', function(){ + it('with single value', function(done){ + mpath.set('arr.0.arr.e', 35, o, special, function (v) { + return 30 + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 30}, { a: { c: 48 }, e: 30}, { d: 'yep', e: 30 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.0.arr.e', 35, o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 35}, { a: { c: 48 }, e: 35}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.0.arr.e', ['a','b'], o, special, function (v) { + return 'a' === v ? 'A' : v; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 'A'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.0.arr.e', ['a','b'], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 'a'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('array.index.array.path.path', function(){ + it('with single value', function(done){ + mpath.set('arr.0.arr.a.b', 36, o, special, function (v) { + return 20 + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 20 }, e: 'a'}, { a: { c: 48, b: 20 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.0.arr.a.b', 36, o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 36 }, e: 'a'}, { a: { c: 48, b: 36 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.0.arr.a.b', [1,2,3,4], o, special, function (v) { + return v*2; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 2 }, e: 'a'}, { a: { c: 48, b: 4 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.0.arr.a.b', [1,2,3,4], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 1 }, e: 'a'}, { a: { c: 48, b: 2 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('array.index.array.$.path.path', function(){ + it('with single value', function(done){ + mpath.set('arr.0.arr.$.a.b', '$', o, special, function (v) { + return 'dollaz' + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: 'dollaz' }, e: 'a'}, { a: { c: 48, b: 'dollaz' }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.0.arr.$.a.b', '$', o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: '$' }, e: 'a'}, { a: { c: 48, b: '$' }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.0.arr.$.a.b', [1], o, special, function (v) { + return {}; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: {} }, e: 'a'}, { a: { c: 48, b: {} }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.0.arr.$.a.b', [1], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: { b: [1] }, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('array.array.index.path', function(){ + it('with single value', function(done){ + mpath.set('arr.arr.0.a', 'single', o, special, function (v) { + return 88; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 88, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.arr.0.a', 'single', o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o, special, function (v) { + return v*2; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 8, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 4, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('array.array.$.index.path', function(){ + it('with single value', function(done){ + mpath.set('arr.arr.$.0.a', 'singles', o, special, function (v) { + return v.toUpperCase(); + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 'SINGLES', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.arr.$.0.a', 'singles', o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 'singles', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('$.arr.arr.0.a', 'single', o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + it('with array', function(done){ + mpath.set('arr.arr.$.0.a', [4,8,15,16,23,42], o, special, function (v) { + return Array + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: Array, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.arr.$.0.a', [4,8,15,16,23,42], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: [4,8,15,16,23,42], e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.$.arr.0.a', [4,8,15,16,23,42,108], o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: [4,8,15,16,23,42,108], e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('array.array.path.index', function(){ + it('with single value', function(done){ + mpath.set('arr.arr.a.7', 47, o, special, function (v) { + return Object; + }); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,Object], e: 'a'}, { a: { c: 48, b: [1], '7': Object }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.arr.a.7', 47, o, special); + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,47], e: 'a'}, { a: { c: 48, b: [1], '7': 47 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { special: true, yep: 0}} + ], o.arr); + + done(); + }) + it('with array', function(done){ + o.arr[1]._doc.arr = [{ a: [] }, { a: [] }, { a: null }]; + mpath.set('arr.arr.a.7', [[null,46], [undefined, 'woot']], o, special, function (v) { + return undefined === v ? 'nope' : v; + }); + + var a1 = []; + var a2 = []; + a1[7] = 'nope'; + a2[7] = 'woot'; + + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,null], e: 'a'}, { a: { c: 48, b: [1], '7': 46 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { arr: [{a:a1},{a:a2},{a:null}], special: true, yep: 0}} + ], o.arr); + + mpath.set('arr.arr.a.7', [[null,46], [undefined, 'woot']], o, special); + + a1[7] = undefined; + + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,null], e: 'a'}, { a: { c: 48, b: [1], '7': 46 }, e: 'b'}, { d: 'yep', e: 35 }] } } + , { yep: true, _doc: { arr: [{a:a1},{a:a2},{a:null}], special: true, yep: 0}} + ], o.arr); + + done(); + }) + }) + + describe('handles array.array.path', function(){ + it('with single', function(done){ + o.arr[1]._doc.arr = [{},{}]; + assert.deepEqual([{},{}], o.arr[1]._doc.arr); + o.arr.push({ _doc: { arr: 'something else' }}); + o.arr.push({ _doc: { arr: ['something else'] }}); + o.arr.push({ _doc: { arr: [[]] }}); + o.arr.push({ _doc: { arr: [5] }}); + + // test + mpath.set('arr.arr.e', 47, o, special); + + var weird = []; + weird.e = 47; + + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { + yep: [15] + , arr: [ + { a: [4,8,15,16,23,42,108,null], e: 47} + , { a: { c: 48, b: [1], '7': 46 }, e: 47} + , { d: 'yep', e: 47 } + ] + } + } + , { yep: true + , _doc: { + arr: [ + {e:47} + , {e:47} + ] + , special: true + , yep: 0 + } + } + , { _doc: { arr: 'something else' }} + , { _doc: { arr: ['something else'] }} + , { _doc: { arr: [weird] }} + , { _doc: { arr: [5] }} + ] + , o.arr); + + done(); + }) + it('with arrays', function(done){ + mpath.set('arr.arr.e', [[1,2,3],[4,5],null,[],[6], [7,8,9]], o, special); + + var weird = []; + weird.e = 6; + + assert.deepEqual([ + { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] + , _doc: { + yep: [15] + , arr: [ + { a: [4,8,15,16,23,42,108,null], e: 1} + , { a: { c: 48, b: [1], '7': 46 }, e: 2} + , { d: 'yep', e: 3 } + ] + } + } + , { yep: true + , _doc: { + arr: [ + {e:4} + , {e:5} + ] + , special: true + , yep: 0 + } + } + , { _doc: { arr: 'something else' }} + , { _doc: { arr: ['something else'] }} + , { _doc: { arr: [weird] }} + , { _doc: { arr: [5] }} + ] + , o.arr); + + done(); + }) + }) + + }) + + describe('get/set integration', function(){ + var o = doc(); + + it('works', function(done){ + var vals = mpath.get('array.o.array.x.b', o); + + vals[0][0][2] = 10; + vals[1][0][1] = 0; + vals[1][1] = 'Rambaldi'; + vals[1][2] = [12,14]; + vals[2] = [{changed:true}, [null, ['changed','to','array']]]; + + mpath.set('array.o.array.x.b', vals, o); + + var t = [ + { o: { array: [{x: {b: [4,6,10]}}, { y: 10} ] }} + , { o: { array: [{x: {b: [1,0,3]}}, { x: {b:'Rambaldi',z: 10 }}, { x: {b: [12,14]}}] }} + , { o: { array: [{x: {b: {changed:true}}}, { x: { b: [null, ['changed','to','array']]}}]}} + , { o: { array: [{x: null }] }} + , { o: { array: [{y: 3 }] }} + , { o: { array: [3, 0, null] }} + , { o: { name: 'ha' }} + ]; + assert.deepEqual(t, o.array); + done(); + }) + + it('array.prop', function(done){ + mpath.set('comments.name', ['this', 'was', 'changed'], o); + + assert.deepEqual([ + { name: 'this' } + , { name: 'was', _doc: { name: '2' }} + , { name: 'changed' + , comments: [{},{ comments: [{val: 'twoo'}]}] + , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}] }} + ], o.comments); + + mpath.set('comments.name', ['also', 'changed', 'this'], o, special); + + assert.deepEqual([ + { name: 'also' } + , { name: 'was', _doc: { name: 'changed' }} + , { name: 'changed' + , comments: [{},{ comments: [{val: 'twoo'}]}] + , _doc: { name: 'this', comments: [{},{ _doc: { comments: [{ val: 2 }] }}] }} + ], o.comments); + + done(); + }) + + }) + + describe('multiple $ use', function(){ + var o = doc(); + it('is ok', function(done){ + assert.doesNotThrow(function () { + mpath.set('arr.$.arr.$.a', 35, o); + }); + done(); + }) + }) + + it('ignores setting a nested path that doesnt exist', function(done){ + var o = doc(); + assert.doesNotThrow(function(){ + mpath.set('thing.that.is.new', 10, o); + }) + done(); + }) + }) + +}) diff --git a/node_modules/mongoose/node_modules/mpromise/.npmignore b/node_modules/mongoose/node_modules/mpromise/.npmignore new file mode 100644 index 0000000..be106ca --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/.npmignore @@ -0,0 +1,2 @@ +*.sw* +node_modules/ diff --git a/node_modules/mongoose/node_modules/mpromise/.travis.yml b/node_modules/mongoose/node_modules/mpromise/.travis.yml new file mode 100644 index 0000000..09c230f --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/mongoose/node_modules/mpromise/History.md b/node_modules/mongoose/node_modules/mpromise/History.md new file mode 100644 index 0000000..f157b69 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/History.md @@ -0,0 +1,24 @@ + +0.2.1 / 2013-02-09 +================== + + * fixed; conformancy with A+ 1.2 + +0.2.0 / 2013-01-09 +================== + + * added; .end() + * fixed; only catch handler executions + +0.1.0 / 2013-01-08 +================== + + * cleaned up API + * customizable event names + * docs + +0.0.1 / 2013-01-07 +================== + + * original release + diff --git a/node_modules/mongoose/node_modules/mpromise/LICENSE b/node_modules/mongoose/node_modules/mpromise/LICENSE new file mode 100644 index 0000000..38c529d --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012 [Aaron Heckmann](aaron.heckmann+github@gmail.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/mongoose/node_modules/mpromise/Makefile b/node_modules/mongoose/node_modules/mpromise/Makefile new file mode 100644 index 0000000..717a796 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/Makefile @@ -0,0 +1,12 @@ +TESTS = $(shell find test/ -name '*.test.js') + +test: + @make test-unit && echo "testing promises-A+ implementation ..." && make test-promises-A + +test-unit: + @./node_modules/.bin/mocha $(T) --async-only $(TESTS) + +test-promises-A: + @node test/promises-A.js + +.PHONY: test test-unit test-promises-A diff --git a/node_modules/mongoose/node_modules/mpromise/README.md b/node_modules/mongoose/node_modules/mpromise/README.md new file mode 100644 index 0000000..7da2725 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/README.md @@ -0,0 +1,200 @@ +#mpromise +========== + +A [promises/A+](https://github.com/promises-aplus/promises-spec) conformant implementation, written for [mongoose](http://mongoosejs.com). + +## installation + +``` +$ npm install mpromise +``` + +## docs + +An `mpromise` can be in any of three states, pending, fulfilled (success), or rejected (error). Once it is either fulfilled or rejected it's state can no longer be changed. + +The exports object is the Promise constructor. + +```js +var Promise = require('mpromise'); +``` + +The constructor accepts an optional function which is executed when the promise is first resolved (either fulfilled or rejected). + +```js +var promise = new Promise(fn); +``` + +This is the same as passing the `fn` to `onResolve` directly. + +```js +var promise = new Promise; +promise.onResolve(function (err, args..) { + ... +}); +``` + +### Methods + +####fulfill + +Fulfilling a promise with values: + +```js +var promise = new Promise; +promise.fulfill(args...); +``` + +If the promise has already been fulfilled or rejected, no action is taken. + +####reject + +Rejecting a promise with a reason: + +```js +var promise = new Promise; +promise.reject(reason); +``` + +If the promise has already been fulfilled or rejected, no action is taken. + +####resolve + +Node.js callback style promise resolution `(err, args...)`: + +```js +var promise = new Promise; +promise.resolve([reason], [arg1, arg2, ...]); +``` + +If the promise has already been fulfilled or rejected, no action is taken. + +####onFulfill + +To register a function for execution when the promise is fulfilled, pass it to `onFulfill`. When executed it will receive the arguments passed to `fulfill()`. + +```js +var promise = new Promise; +promise.onFulfill(function (a, b) { + assert.equal(3, a + b); +}); +promise.fulfill(1, 2); +``` + +The function will only be called once when the promise is fulfilled, never when rejected. + +Registering a function with `onFulfill` after the promise has already been fulfilled results in the immediate execution of the function with the original arguments used to fulfill the promise. + +```js +var promise = new Promise; +promise.fulfill(" :D "); +promise.onFulfill(function (arg) { + console.log(arg); // logs " :D " +}) +``` + +####onReject + +To register a function for execution when the promise is rejected, pass it to `onReject`. When executed it will receive the argument passed to `reject()`. + +```js +var promise = new Promise; +promise.onReject(function (reason) { + assert.equal('sad', reason); +}); +promise.reject('sad'); +``` + +The function will only be called once when the promise is rejected, never when fulfilled. + +Registering a function with `onReject` after the promise has already been rejected results in the immediate execution of the function with the original argument used to reject the promise. + +```js +var promise = new Promise; +promise.reject(" :( "); +promise.onReject(function (reason) { + console.log(reason); // logs " :( " +}) +``` + +####onResolve + +Allows registration of node.js style callbacks `(err, args..)` to handle either promise resolution type (fulfill or reject). + +```js +// fulfillment +var promise = new Promise; +promise.onResolve(function (err, a, b) { + console.log(a + b); // logs 3 +}); +promise.fulfill(1, 2); + +// rejection +var promise = new Promise; +promise.onResolve(function (err) { + if (err) { + console.log(err.message); // logs "failed" + } +}); +promise.reject(new Error('failed')); +``` + +####then + +Creates a new promise and returns it. If `onFulfill` or `onReject` are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick. + +Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification and passes its [tests](https://github.com/promises-aplus/promises-tests). + +```js +// promise.then(onFulfill, onReject); + +var p = new Promise; + +p.then(function (arg) { + return arg + 1; +}).then(function (arg) { + throw new Error(arg + ' is an error!'); +}).then(null, function (err) { + assert.ok(err instanceof Error); + assert.equal('2 is an error', err.message); +}); +p.complete(1); +``` + +####end + +Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught. + +```js +var p = new Promise; +p.then(function(){ throw new Error('shucks') }); +setTimeout(function () { + p.fulfill(); + // error was caught and swallowed by the promise returned from + // p.then(). we either have to always register handlers on + // the returned promises or we can do the following... +}, 10); + +// this time we use .end() which prevents catching thrown errors +var p = new Promise; +var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- +setTimeout(function () { + p.fulfill(); // throws "shucks" +}, 10); +``` + +###Event names + +If you'd like to alter this implementations event names used to signify success and failure you may do so by setting `Promise.SUCCESS` or `Promise.FAILURE` respectively. + +```js +Promise.SUCCESS = 'complete'; +Promise.FAILURE = 'err'; +``` + +###Luke, use the Source +For more ideas read the [source](https://github.com/aheckmann/mpromise/blob/master/lib), [tests](https://github.com/aheckmann/mpromise/blob/master/test), or the [mongoose implementation](https://github.com/LearnBoost/mongoose/blob/3.6x/lib/promise.js). + +## license + +[MIT](https://github.com/aheckmann/mpromise/blob/master/LICENSE) diff --git a/node_modules/mongoose/node_modules/mpromise/index.js b/node_modules/mongoose/node_modules/mpromise/index.js new file mode 100644 index 0000000..0b3669d --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/index.js @@ -0,0 +1 @@ +module.exports = exports = require('./lib/promise'); diff --git a/node_modules/mongoose/node_modules/mpromise/lib/promise.js b/node_modules/mongoose/node_modules/mpromise/lib/promise.js new file mode 100644 index 0000000..be992c3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/lib/promise.js @@ -0,0 +1,268 @@ + +/*! + * Module dependencies. + */ + +var slice = require('sliced'); +var EventEmitter = require('events').EventEmitter; + +/** + * Promise constructor. + * + * _NOTE: The success and failure event names can be overridden by setting `Promise.SUCCESS` and `Promise.FAILURE` respectively._ + * + * @param {Function} back a function that accepts `fn(err, ...){}` as signature + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `reject`: Emits when the promise is rejected (event name may be overridden) + * @event `fulfill`: Emits when the promise is fulfilled (event name may be overridden) + * @api public + */ + +function Promise (back) { + this.emitted = {}; + this.ended = false; + if ('function' == typeof back) + this.onResolve(back); +} + +/*! + * event names + */ + +Promise.SUCCESS = 'fulfill'; +Promise.FAILURE = 'reject'; + +/*! + * Inherits from EventEmitter. + */ + +Promise.prototype.__proto__ = EventEmitter.prototype; + +/** + * Adds `listener` to the `event`. + * + * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event. + * + * @param {String} event + * @param {Function} callback + * @return {Promise} this + * @api public + */ + +Promise.prototype.on = function (event, callback) { + if (this.emitted[event]) + callback.apply(this, this.emitted[event]); + else + EventEmitter.prototype.on.call(this, event, callback); + + return this; +} + +/** + * Keeps track of emitted events to run them on `on`. + * + * @api private + */ + +Promise.prototype.emit = function (event) { + // ensures a promise can't be fulfill() or reject() more than once + var success = this.constructor.SUCCESS; + var failure = this.constructor.FAILURE; + + if (event == success || event == failure) { + if (this.emitted[success] || this.emitted[failure]) { + return this; + } + this.emitted[event] = slice(arguments, 1); + } + + return EventEmitter.prototype.emit.apply(this, arguments); +} + +/** + * Fulfills this promise with passed arguments. + * + * If this promise has already been fulfilled or rejected, no action is taken. + * + * @api public + */ + +Promise.prototype.fulfill = function () { + var args = slice(arguments); + return this.emit.apply(this, [this.constructor.SUCCESS].concat(args)); +} + +/** + * Rejects this promise with `reason`. + * + * If this promise has already been fulfilled or rejected, no action is taken. + * + * @api public + * @param {Object|String} reason + * @return {Promise} this + */ + +Promise.prototype.reject = function (reason) { + return this.emit(this.constructor.FAILURE, reason); +} + +/** + * Resolves this promise to a rejected state if `err` is passed or + * fulfilled state if no `err` is passed. + * + * @param {Error} [err] error or null + * @param {Object} [val] value to fulfill the promise with + * @api public + */ + +Promise.prototype.resolve = function (err, val) { + if (err) return this.reject(err); + return this.fulfill(val); +} + +/** + * Adds a listener to the SUCCESS event. + * + * @return {Promise} this + * @api public + */ + +Promise.prototype.onFulfill = function (fn) { + return this.on(this.constructor.SUCCESS, fn); +} + +/** + * Adds a listener to the FAILURE event. + * + * @return {Promise} this + * @api public + */ + +Promise.prototype.onReject = function (fn) { + return this.on(this.constructor.FAILURE, fn); +} + +/** + * Adds a single function as a listener to both SUCCESS and FAILURE. + * + * It will be executed with traditional node.js argument position: + * function (err, args...) {} + * + * @param {Function} fn + * @return {Promise} this + */ + +Promise.prototype.onResolve = function (fn) { + this.on(this.constructor.FAILURE, function(err){ + fn.call(this, err); + }); + + this.on(this.constructor.SUCCESS, function(){ + var args = slice(arguments); + fn.apply(this, [null].concat(args)); + }); + + return this; +} + +/** + * Creates a new promise and returns it. If `onFulfill` or + * `onReject` are passed, they are added as SUCCESS/ERROR callbacks + * to this promise after the nextTick. + * + * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification. Read for more detail how to use this method. + * + * ####Example: + * + * var p = new Promise; + * p.then(function (arg) { + * return arg + 1; + * }).then(function (arg) { + * throw new Error(arg + ' is an error!'); + * }).then(null, function (err) { + * assert.ok(err instanceof Error); + * assert.equal('2 is an error', err.message); + * }); + * p.complete(1); + * + * @see promises-A+ https://github.com/promises-aplus/promises-spec + * @param {Function} onFulFill + * @param {Function} onReject + * @return {Promise} newPromise + */ + +Promise.prototype.then = function (onFulfill, onReject) { + var self = this + , retPromise = new Promise; + + function handler (fn) { + return function handle (arg) { + var val; + + try { + val = fn(arg); + } catch (err) { + if (retPromise.ended) throw err; + return retPromise.reject(err); + } + + if (val && 'function' == typeof val.then) { + val.then( + retPromise.fulfill.bind(retPromise) + , retPromise.reject.bind(retPromise)) + } else { + retPromise.fulfill(val); + } + } + } + + process.nextTick(function () { + if ('function' == typeof onReject) { + self.onReject(handler(onReject)); + } else { + self.onReject(retPromise.reject.bind(retPromise)); + } + + if ('function' == typeof onFulfill) { + self.onFulfill(handler(onFulfill)); + } else { + self.onFulfill(retPromise.fulfill.bind(retPromise)); + } + }) + + return retPromise; +} + +/** + * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught. + * + * ####Example: + * + * var p = new Promise; + * p.then(function(){ throw new Error('shucks') }); + * setTimeout(function () { + * p.fulfill(); + * // error was caught and swallowed by the promise returned from + * // p.then(). we either have to always register handlers on + * // the returned promises or we can do the following... + * }, 10); + * + * // this time we use .end() which prevents catching thrown errors + * var p = new Promise; + * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- + * setTimeout(function () { + * p.fulfill(); // throws "shucks" + * }, 10); + * + * @api public + */ + +Promise.prototype.end = function () { + this.ended = true; +} + +/*! + * Module exports. + */ + +module.exports = Promise; diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.npmignore b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.npmignore new file mode 100644 index 0000000..be106ca --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.npmignore @@ -0,0 +1,2 @@ +*.sw* +node_modules/ diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.travis.yml b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/History.md b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/History.md new file mode 100644 index 0000000..8132c95 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/History.md @@ -0,0 +1,23 @@ + +0.0.4 / 2013-01-07 +================== + + * added component.json #1 [jkroso](https://github.com/jkroso) + * reversed array loop #1 [jkroso](https://github.com/jkroso) + * remove fn params + +0.0.3 / 2012-09-29 +================== + + * faster with negative start args + +0.0.2 / 2012-09-29 +================== + + * support full [].slice semantics + +0.0.1 / 2012-09-29 +=================== + + * initial release + diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/LICENSE b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/LICENSE new file mode 100644 index 0000000..38c529d --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012 [Aaron Heckmann](aaron.heckmann+github@gmail.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/mongoose/node_modules/mpromise/node_modules/sliced/Makefile b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/Makefile new file mode 100644 index 0000000..3dd8a2d --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/Makefile @@ -0,0 +1,5 @@ + +test: + @time ./node_modules/.bin/mocha $(T) $(TESTS) + +.PHONY: test diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/README.md b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/README.md new file mode 100644 index 0000000..6605c39 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/README.md @@ -0,0 +1,62 @@ +#sliced +========== + +A faster alternative to `[].slice.call(arguments)`. + +[![Build Status](https://secure.travis-ci.org/aheckmann/sliced.png)](http://travis-ci.org/aheckmann/sliced) + +Example output from [benchmark.js](https://github.com/bestiejs/benchmark.js) + + Array.prototype.slice.call x 1,320,205 ops/sec ±2.35% (92 runs sampled) + [].slice.call x 1,314,605 ops/sec ±1.60% (95 runs sampled) + cached slice.call x 10,468,380 ops/sec ±1.45% (95 runs sampled) + sliced x 16,608,237 ops/sec ±1.40% (92 runs sampled) + fastest is sliced + + Array.prototype.slice.call(arguments, 1) x 1,383,584 ops/sec ±1.73% (97 runs sampled) + [].slice.call(arguments, 1) x 1,494,735 ops/sec ±1.33% (95 runs sampled) + cached slice.call(arguments, 1) x 10,085,270 ops/sec ±1.51% (97 runs sampled) + sliced(arguments, 1) x 16,620,480 ops/sec ±1.29% (95 runs sampled) + fastest is sliced(arguments, 1) + + Array.prototype.slice.call(arguments, -1) x 1,303,262 ops/sec ±1.62% (94 runs sampled) + [].slice.call(arguments, -1) x 1,325,615 ops/sec ±1.36% (97 runs sampled) + cached slice.call(arguments, -1) x 9,673,603 ops/sec ±1.70% (96 runs sampled) + sliced(arguments, -1) x 16,384,575 ops/sec ±1.06% (91 runs sampled) + fastest is sliced(arguments, -1) + + Array.prototype.slice.call(arguments, -2, -10) x 1,404,390 ops/sec ±1.61% (95 runs sampled) + [].slice.call(arguments, -2, -10) x 1,514,367 ops/sec ±1.21% (96 runs sampled) + cached slice.call(arguments, -2, -10) x 9,836,017 ops/sec ±1.21% (95 runs sampled) + sliced(arguments, -2, -10) x 18,544,882 ops/sec ±1.30% (91 runs sampled) + fastest is sliced(arguments, -2, -10) + + Array.prototype.slice.call(arguments, -2, -1) x 1,458,604 ops/sec ±1.41% (97 runs sampled) + [].slice.call(arguments, -2, -1) x 1,536,547 ops/sec ±1.63% (99 runs sampled) + cached slice.call(arguments, -2, -1) x 10,060,633 ops/sec ±1.37% (96 runs sampled) + sliced(arguments, -2, -1) x 18,608,712 ops/sec ±1.08% (93 runs sampled) + fastest is sliced(arguments, -2, -1) + +_Benchmark [source](https://github.com/aheckmann/sliced/blob/master/bench.js)._ + +##Usage + +`sliced` accepts the same arguments as `Array#slice` so you can easily swap it out. + +```js +function zing () { + var slow = [].slice.call(arguments, 1, 8); + var args = slice(arguments, 1, 8); + + var slow = Array.prototype.slice.call(arguments); + var args = slice(arguments); + // etc +} +``` + +## install + + npm install sliced + + +[LICENSE](https://github.com/aheckmann/sliced/blob/master/LICENSE) diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/bench.js b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/bench.js new file mode 100644 index 0000000..f201d16 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/bench.js @@ -0,0 +1,95 @@ + +var sliced = require('./') +var Bench = require('benchmark'); +var s = new Bench.Suite; +var slice = [].slice; + +s.add('Array.prototype.slice.call', function () { + Array.prototype.slice.call(arguments); +}).add('[].slice.call', function () { + [].slice.call(arguments); +}).add('cached slice.call', function () { + slice.call(arguments) +}).add('sliced', function () { + sliced(arguments) +}).on('cycle', function (evt) { + console.log(String(evt.target)); +}).on('complete', function () { + console.log('fastest is %s', this.filter('fastest').pluck('name')); +}) +.run(); + +var s = new Bench.Suite; +s.add('Array.prototype.slice.call(arguments, 1)', function () { + Array.prototype.slice.call(arguments, 1); +}).add('[].slice.call(arguments, 1)', function () { + [].slice.call(arguments, 1); +}).add('cached slice.call(arguments, 1)', function () { + slice.call(arguments, 1) +}).add('sliced(arguments, 1)', function () { + sliced(arguments, 1) +}).on('cycle', function (evt) { + console.log(String(evt.target)); +}).on('complete', function () { + console.log('fastest is %s', this.filter('fastest').pluck('name')); +}) +.run(); + +var s = new Bench.Suite; +s.add('Array.prototype.slice.call(arguments, -1)', function () { + Array.prototype.slice.call(arguments, -1); +}).add('[].slice.call(arguments, -1)', function () { + [].slice.call(arguments, -1); +}).add('cached slice.call(arguments, -1)', function () { + slice.call(arguments, -1) +}).add('sliced(arguments, -1)', function () { + sliced(arguments, -1) +}).on('cycle', function (evt) { + console.log(String(evt.target)); +}).on('complete', function () { + console.log('fastest is %s', this.filter('fastest').pluck('name')); +}) +.run(); + +var s = new Bench.Suite; +s.add('Array.prototype.slice.call(arguments, -2, -10)', function () { + Array.prototype.slice.call(arguments, -2, -10); +}).add('[].slice.call(arguments, -2, -10)', function () { + [].slice.call(arguments, -2, -10); +}).add('cached slice.call(arguments, -2, -10)', function () { + slice.call(arguments, -2, -10) +}).add('sliced(arguments, -2, -10)', function () { + sliced(arguments, -2, -10) +}).on('cycle', function (evt) { + console.log(String(evt.target)); +}).on('complete', function () { + console.log('fastest is %s', this.filter('fastest').pluck('name')); +}) +.run(); + +var s = new Bench.Suite; +s.add('Array.prototype.slice.call(arguments, -2, -1)', function () { + Array.prototype.slice.call(arguments, -2, -1); +}).add('[].slice.call(arguments, -2, -1)', function () { + [].slice.call(arguments, -2, -1); +}).add('cached slice.call(arguments, -2, -1)', function () { + slice.call(arguments, -2, -1) +}).add('sliced(arguments, -2, -1)', function () { + sliced(arguments, -2, -1) +}).on('cycle', function (evt) { + console.log(String(evt.target)); +}).on('complete', function () { + console.log('fastest is %s', this.filter('fastest').pluck('name')); +}) +.run(); + +/** + * Output: + * + * Array.prototype.slice.call x 1,289,592 ops/sec ±2.88% (87 runs sampled) + * [].slice.call x 1,345,451 ops/sec ±1.68% (97 runs sampled) + * cached slice.call x 10,719,886 ops/sec ±1.04% (99 runs sampled) + * sliced x 15,809,545 ops/sec ±1.46% (93 runs sampled) + * fastest is sliced + * + */ diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/component.json b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/component.json new file mode 100644 index 0000000..a7ac7f2 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/component.json @@ -0,0 +1,13 @@ +{ + "name": "sliced", + "version": "0.0.3", + "description": "A faster Node.js alternative to Array.prototype.slice.call(arguments)", + "repo" : "aheckmann/sliced", + "keywords": [ + "arguments", + "slice", + "array" + ], + "author": "Aaron Heckmann ", + "license": "MIT" +} diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/index.js b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/index.js new file mode 100644 index 0000000..3b90ae7 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/index.js @@ -0,0 +1 @@ +module.exports = exports = require('./lib/sliced'); diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/lib/sliced.js b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/lib/sliced.js new file mode 100644 index 0000000..d8c15bc --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/lib/sliced.js @@ -0,0 +1,37 @@ + +/** + * An Array.prototype.slice.call(arguments) alternative + * + * @param {Object} args something with a length + * @param {Number} slice + * @param {Number} sliceEnd + * @api public + */ + +module.exports = function () { + var args = arguments[0]; + var slice = arguments[1]; + var sliceEnd = arguments[2]; + + var ret = []; + var len = args.length; + + if (0 === len) return ret; + + var start = slice < 0 + ? Math.max(0, slice + len) + : slice || 0; + + var end = 3 === arguments.length + ? sliceEnd < 0 + ? sliceEnd + len + : sliceEnd + : len; + + while (end-- > start) { + ret[end - start] = args[end]; + } + + return ret; +} + diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/package.json b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/package.json new file mode 100644 index 0000000..66adccb --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/package.json @@ -0,0 +1,35 @@ +{ + "name": "sliced", + "version": "0.0.4", + "description": "A faster Node.js alternative to Array.prototype.slice.call(arguments)", + "main": "index.js", + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/aheckmann/sliced" + }, + "keywords": [ + "arguments", + "slice", + "array" + ], + "author": { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + "license": "MIT", + "devDependencies": { + "mocha": "1.5.0", + "benchmark": "~1.0.0" + }, + "readme": "#sliced\n==========\n\nA faster alternative to `[].slice.call(arguments)`.\n\n[![Build Status](https://secure.travis-ci.org/aheckmann/sliced.png)](http://travis-ci.org/aheckmann/sliced)\n\nExample output from [benchmark.js](https://github.com/bestiejs/benchmark.js)\n\n Array.prototype.slice.call x 1,320,205 ops/sec ±2.35% (92 runs sampled)\n [].slice.call x 1,314,605 ops/sec ±1.60% (95 runs sampled)\n cached slice.call x 10,468,380 ops/sec ±1.45% (95 runs sampled)\n sliced x 16,608,237 ops/sec ±1.40% (92 runs sampled)\n fastest is sliced\n\n Array.prototype.slice.call(arguments, 1) x 1,383,584 ops/sec ±1.73% (97 runs sampled)\n [].slice.call(arguments, 1) x 1,494,735 ops/sec ±1.33% (95 runs sampled)\n cached slice.call(arguments, 1) x 10,085,270 ops/sec ±1.51% (97 runs sampled)\n sliced(arguments, 1) x 16,620,480 ops/sec ±1.29% (95 runs sampled)\n fastest is sliced(arguments, 1)\n\n Array.prototype.slice.call(arguments, -1) x 1,303,262 ops/sec ±1.62% (94 runs sampled)\n [].slice.call(arguments, -1) x 1,325,615 ops/sec ±1.36% (97 runs sampled)\n cached slice.call(arguments, -1) x 9,673,603 ops/sec ±1.70% (96 runs sampled)\n sliced(arguments, -1) x 16,384,575 ops/sec ±1.06% (91 runs sampled)\n fastest is sliced(arguments, -1)\n\n Array.prototype.slice.call(arguments, -2, -10) x 1,404,390 ops/sec ±1.61% (95 runs sampled)\n [].slice.call(arguments, -2, -10) x 1,514,367 ops/sec ±1.21% (96 runs sampled)\n cached slice.call(arguments, -2, -10) x 9,836,017 ops/sec ±1.21% (95 runs sampled)\n sliced(arguments, -2, -10) x 18,544,882 ops/sec ±1.30% (91 runs sampled)\n fastest is sliced(arguments, -2, -10)\n\n Array.prototype.slice.call(arguments, -2, -1) x 1,458,604 ops/sec ±1.41% (97 runs sampled)\n [].slice.call(arguments, -2, -1) x 1,536,547 ops/sec ±1.63% (99 runs sampled)\n cached slice.call(arguments, -2, -1) x 10,060,633 ops/sec ±1.37% (96 runs sampled)\n sliced(arguments, -2, -1) x 18,608,712 ops/sec ±1.08% (93 runs sampled)\n fastest is sliced(arguments, -2, -1)\n\n_Benchmark [source](https://github.com/aheckmann/sliced/blob/master/bench.js)._\n\n##Usage\n\n`sliced` accepts the same arguments as `Array#slice` so you can easily swap it out.\n\n```js\nfunction zing () {\n var slow = [].slice.call(arguments, 1, 8);\n var args = slice(arguments, 1, 8);\n\n var slow = Array.prototype.slice.call(arguments);\n var args = slice(arguments);\n // etc\n}\n```\n\n## install\n\n npm install sliced\n\n\n[LICENSE](https://github.com/aheckmann/sliced/blob/master/LICENSE)\n", + "readmeFilename": "README.md", + "_id": "sliced@0.0.4", + "dist": { + "shasum": "5967e7e0ccd738e29c7f4f0e43859f65527385fa" + }, + "_from": "sliced@0.0.4", + "_resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.4.tgz" +} diff --git a/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/test/index.js b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/test/index.js new file mode 100644 index 0000000..33d36a1 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/node_modules/sliced/test/index.js @@ -0,0 +1,80 @@ + +var sliced = require('../') +var assert = require('assert') + +describe('sliced', function(){ + it('exports a function', function(){ + assert.equal('function', typeof sliced); + }) + describe('with 1 arg', function(){ + it('returns an array of the arg', function(){ + var o = [3, "4", {}]; + var r = sliced(o); + assert.equal(3, r.length); + assert.equal(o[0], r[0]); + assert.equal(o[1], r[1]); + assert.equal(o[1], r[1]); + }) + }) + describe('with 2 args', function(){ + it('returns an array of the arg starting at the 2nd arg', function(){ + var o = [3, "4", 5, null]; + var r = sliced(o, 2); + assert.equal(2, r.length); + assert.equal(o[2], r[0]); + assert.equal(o[3], r[1]); + }) + }) + describe('with 3 args', function(){ + it('returns an array of the arg from the 2nd to the 3rd arg', function(){ + var o = [3, "4", 5, null]; + var r = sliced(o, 1, 2); + assert.equal(1, r.length); + assert.equal(o[1], r[0]); + }) + }) + describe('with negative start and no end', function(){ + it('begins at an offset from the end and includes all following elements', function(){ + var o = [3, "4", 5, null]; + var r = sliced(o, -2); + assert.equal(2, r.length); + assert.equal(o[2], r[0]); + assert.equal(o[3], r[1]); + + var r = sliced(o, -12); + assert.equal(4, r.length); + assert.equal(o[0], r[0]); + assert.equal(o[1], r[1]); + }) + }) + describe('with negative start and positive end', function(){ + it('begins at an offset from the end and includes `end` elements', function(){ + var o = [3, "4", {x:1}, null]; + + var r = sliced(o, -2, 1); + assert.equal(0, r.length); + + var r = sliced(o, -2, 2); + assert.equal(0, r.length); + + var r = sliced(o, -2, 3); + assert.equal(1, r.length); + assert.equal(o[2], r[0]); + }) + }) + describe('with negative start and negative end', function(){ + it('begins at `start` offset from the end and includes all elements up to `end` offset from the end', function(){ + var o = [3, "4", {x:1}, null]; + var r = sliced(o, -3, -1); + assert.equal(2, r.length); + assert.equal(o[1], r[0]); + assert.equal(o[2], r[1]); + + var r = sliced(o, -3, -3); + assert.equal(0, r.length); + + var r = sliced(o, -3, -4); + assert.equal(0, r.length); + }) + }) +}) diff --git a/node_modules/mongoose/node_modules/mpromise/package.json b/node_modules/mongoose/node_modules/mpromise/package.json new file mode 100644 index 0000000..9577054 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/package.json @@ -0,0 +1,40 @@ +{ + "name": "mpromise", + "version": "0.2.1", + "description": "Promises A+ conformant implementation", + "main": "index.js", + "scripts": { + "test": "make test" + }, + "dependencies": { + "sliced": "0.0.4" + }, + "devDependencies": { + "mocha": "1.7.4", + "promises-aplus-tests": ">= 1.2" + }, + "repository": { + "type": "git", + "url": "git://github.com/aheckmann/mpromise" + }, + "keywords": [ + "promise", + "mongoose", + "aplus", + "a+", + "plus" + ], + "author": { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + "license": "MIT", + "readme": "#mpromise\n==========\n\nA [promises/A+](https://github.com/promises-aplus/promises-spec) conformant implementation, written for [mongoose](http://mongoosejs.com).\n\n## installation\n\n```\n$ npm install mpromise\n```\n\n## docs\n\nAn `mpromise` can be in any of three states, pending, fulfilled (success), or rejected (error). Once it is either fulfilled or rejected it's state can no longer be changed.\n\nThe exports object is the Promise constructor.\n\n```js\nvar Promise = require('mpromise');\n```\n\nThe constructor accepts an optional function which is executed when the promise is first resolved (either fulfilled or rejected).\n\n```js\nvar promise = new Promise(fn);\n```\n\nThis is the same as passing the `fn` to `onResolve` directly.\n\n```js\nvar promise = new Promise;\npromise.onResolve(function (err, args..) {\n ...\n});\n```\n\n### Methods\n\n####fulfill\n\nFulfilling a promise with values:\n\n```js\nvar promise = new Promise;\npromise.fulfill(args...);\n```\n\nIf the promise has already been fulfilled or rejected, no action is taken.\n\n####reject\n\nRejecting a promise with a reason:\n\n```js\nvar promise = new Promise;\npromise.reject(reason);\n```\n\nIf the promise has already been fulfilled or rejected, no action is taken.\n\n####resolve\n\nNode.js callback style promise resolution `(err, args...)`:\n\n```js\nvar promise = new Promise;\npromise.resolve([reason], [arg1, arg2, ...]);\n```\n\nIf the promise has already been fulfilled or rejected, no action is taken.\n\n####onFulfill\n\nTo register a function for execution when the promise is fulfilled, pass it to `onFulfill`. When executed it will receive the arguments passed to `fulfill()`.\n\n```js\nvar promise = new Promise;\npromise.onFulfill(function (a, b) {\n assert.equal(3, a + b);\n});\npromise.fulfill(1, 2);\n```\n\nThe function will only be called once when the promise is fulfilled, never when rejected.\n\nRegistering a function with `onFulfill` after the promise has already been fulfilled results in the immediate execution of the function with the original arguments used to fulfill the promise.\n\n```js\nvar promise = new Promise;\npromise.fulfill(\" :D \");\npromise.onFulfill(function (arg) {\n console.log(arg); // logs \" :D \"\n})\n```\n\n####onReject\n\nTo register a function for execution when the promise is rejected, pass it to `onReject`. When executed it will receive the argument passed to `reject()`.\n\n```js\nvar promise = new Promise;\npromise.onReject(function (reason) {\n assert.equal('sad', reason);\n});\npromise.reject('sad');\n```\n\nThe function will only be called once when the promise is rejected, never when fulfilled.\n\nRegistering a function with `onReject` after the promise has already been rejected results in the immediate execution of the function with the original argument used to reject the promise.\n\n```js\nvar promise = new Promise;\npromise.reject(\" :( \");\npromise.onReject(function (reason) {\n console.log(reason); // logs \" :( \"\n})\n```\n\n####onResolve\n\nAllows registration of node.js style callbacks `(err, args..)` to handle either promise resolution type (fulfill or reject).\n\n```js\n// fulfillment\nvar promise = new Promise;\npromise.onResolve(function (err, a, b) {\n console.log(a + b); // logs 3\n});\npromise.fulfill(1, 2);\n\n// rejection\nvar promise = new Promise;\npromise.onResolve(function (err) {\n if (err) {\n console.log(err.message); // logs \"failed\"\n }\n});\npromise.reject(new Error('failed'));\n```\n\n####then\n\nCreates a new promise and returns it. If `onFulfill` or `onReject` are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.\n\nConforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification and passes its [tests](https://github.com/promises-aplus/promises-tests).\n\n```js\n// promise.then(onFulfill, onReject);\n\nvar p = new Promise;\n\np.then(function (arg) {\n return arg + 1;\n}).then(function (arg) {\n throw new Error(arg + ' is an error!');\n}).then(null, function (err) {\n assert.ok(err instanceof Error);\n assert.equal('2 is an error', err.message);\n});\np.complete(1);\n```\n\n####end\n\nSignifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught.\n\n```js\nvar p = new Promise;\np.then(function(){ throw new Error('shucks') });\nsetTimeout(function () {\n p.fulfill();\n // error was caught and swallowed by the promise returned from\n // p.then(). we either have to always register handlers on\n // the returned promises or we can do the following...\n}, 10);\n\n// this time we use .end() which prevents catching thrown errors\nvar p = new Promise;\nvar p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--\nsetTimeout(function () {\n p.fulfill(); // throws \"shucks\"\n}, 10);\n```\n\n###Event names\n\nIf you'd like to alter this implementations event names used to signify success and failure you may do so by setting `Promise.SUCCESS` or `Promise.FAILURE` respectively.\n\n```js\nPromise.SUCCESS = 'complete';\nPromise.FAILURE = 'err';\n```\n\n###Luke, use the Source\nFor more ideas read the [source](https://github.com/aheckmann/mpromise/blob/master/lib), [tests](https://github.com/aheckmann/mpromise/blob/master/test), or the [mongoose implementation](https://github.com/LearnBoost/mongoose/blob/3.6x/lib/promise.js).\n\n## license\n\n[MIT](https://github.com/aheckmann/mpromise/blob/master/LICENSE)\n", + "readmeFilename": "README.md", + "_id": "mpromise@0.2.1", + "dist": { + "shasum": "5ef4d7f6a014dda57066397523d320eb52154cec" + }, + "_from": "mpromise@0.2.1", + "_resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.2.1.tgz" +} diff --git a/node_modules/mongoose/node_modules/mpromise/test/promise.test.js b/node_modules/mongoose/node_modules/mpromise/test/promise.test.js new file mode 100644 index 0000000..45f6e29 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/test/promise.test.js @@ -0,0 +1,201 @@ + +/** + * Module dependencies. + */ + +var assert = require('assert') +var Promise = require('../lib/promise'); + +/** + * Test. + */ + +describe('promise', function(){ + it('events fire right after fulfill()', function(done){ + var promise = new Promise() + , called = 0; + + promise.on('fulfill', function (a, b) { + assert.equal(a, '1'); + assert.equal(b, '2'); + called++; + }); + + promise.fulfill('1', '2'); + + promise.on('fulfill', function (a, b) { + assert.equal(a, '1'); + assert.equal(b, '2'); + called++; + }); + + assert.equal(2, called); + done(); + }); + + it('events fire right after reject()', function(done){ + var promise = new Promise() + , called = 0; + + promise.on('reject', function (err) { + assert.ok(err instanceof Error); + called++; + }); + + promise.reject(new Error('booyah')); + + promise.on('reject', function (err) { + assert.ok(err instanceof Error); + called++; + }); + + assert.equal(2, called); + done() + }); + + describe('onResolve()', function(){ + it('from constructor works', function(done){ + var called = 0; + + var promise = new Promise(function (err) { + assert.ok(err instanceof Error); + called++; + }) + + promise.reject(new Error('dawg')); + + assert.equal(1, called); + done(); + }); + + it('after fulfill()', function(done){ + var promise = new Promise() + , called = 0; + + promise.fulfill('woot'); + + promise.onResolve(function (err, data){ + assert.equal(data,'woot'); + called++; + }); + + promise.onResolve(function (err, data){ + assert.strictEqual(err, null); + called++; + }); + + assert.equal(2, called); + done(); + }) + }); + + describe('onFulfill shortcut', function(){ + it('works', function(done){ + var promise = new Promise() + , called = 0; + + promise.onFulfill(function (woot) { + assert.strictEqual(woot, undefined); + called++; + }); + + promise.fulfill(); + + assert.equal(1, called); + done(); + }) + }) + + describe('onReject shortcut', function(){ + it('works', function(done){ + var promise = new Promise() + , called = 0; + + promise.onReject(function (err) { + assert.ok(err instanceof Error); + called++; + }); + + promise.reject(new Error); + assert.equal(1, called); + done(); + }) + }); + + describe('return values', function(){ + it('on()', function(done){ + var promise = new Promise() + assert.ok(promise.on('jump', function(){}) instanceof Promise); + done() + }); + + it('onFulfill()', function(done){ + var promise = new Promise() + assert.ok(promise.onFulfill(function(){}) instanceof Promise); + done(); + }) + it('onReject()', function(done){ + var promise = new Promise() + assert.ok(promise.onReject(function(){}) instanceof Promise); + done(); + }) + it('onResolve()', function(done){ + var promise = new Promise() + assert.ok(promise.onResolve(function(){}) instanceof Promise); + done(); + }) + }) + + describe('casting errors', function(){ + describe('reject()', function(){ + it('does not cast arguments to Error', function(done){ + var p = new Promise(function (err, arg) { + assert.equal(3, err); + done(); + }); + + p.reject(3); + }) + }) + }) + + describe('then catching', function(){ + it('should not catch returned promise fulfillments', function(done){ + var p1 = new Promise; + + var p2 = p1.then(function () { return 'step 1' }) + + p2.onFulfill(function () { throw new Error('fulfill threw me') }) + p2.reject = assert.ifError.bind(assert, new Error('reject should not have been called')); + + setTimeout(function () { + assert.throws(function () { + p1.fulfill(); + }, /fulfill threw me/) + done(); + }, 10); + + }) + + it('can be disabled using .end()', function(done){ + var p = new Promise; + + var p2 = p.then(function () { throw new Error('shucks') }) + p2.end(); + + setTimeout(function () { + try { + p.fulfill(); + } catch (err) { + assert.ok(/shucks/.test(err)) + done(); + } + + setTimeout(function () { + done(new Error('error was swallowed')); + }, 10); + + }, 10); + }) + }) +}) diff --git a/node_modules/mongoose/node_modules/mpromise/test/promises-A.js b/node_modules/mongoose/node_modules/mpromise/test/promises-A.js new file mode 100644 index 0000000..ebb4626 --- /dev/null +++ b/node_modules/mongoose/node_modules/mpromise/test/promises-A.js @@ -0,0 +1,35 @@ + +/** + * Module dependencies. + */ + +var assert = require('assert') +var Promise = require('../lib/promise'); +var aplus = require('promises-aplus-tests'); + +// tests + +var adapter = {}; +adapter.fulfilled = function (value) { + var p = new Promise; + p.fulfill(value); + return p; +}; +adapter.rejected = function (reason) { + var p = new Promise; + p.reject(reason); + return p; +} +adapter.pending = function () { + var p = new Promise; + return { + promise: p + , fulfill: p.fulfill.bind(p) + , reject: p.reject.bind(p) + } +} + +aplus(adapter, function (err) { + assert.ifError(err); +}); + diff --git a/node_modules/mongoose/node_modules/ms/.npmignore b/node_modules/mongoose/node_modules/ms/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/mongoose/node_modules/ms/Makefile b/node_modules/mongoose/node_modules/ms/Makefile new file mode 100644 index 0000000..dded504 --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/Makefile @@ -0,0 +1,8 @@ + +test: + ./node_modules/.bin/mocha test/test.js + +test-browser: + ./node_modules/.bin/serve test/ + +.PHONY: test diff --git a/node_modules/mongoose/node_modules/ms/README.md b/node_modules/mongoose/node_modules/ms/README.md new file mode 100644 index 0000000..c93d43f --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/README.md @@ -0,0 +1,65 @@ + +# ms.js + +Ever find yourself doing math in your head or writing `1000 * 60 * 60 …`? +Don't want to add obstrusive `Number` prototype extensions to your reusable +/ distributable modules and projects? + +`ms` is a tiny utility that you can leverage when your application needs to +accept a number of miliseconds as a parameter. + +If a number is supplied to `ms`, it returns it immediately (e.g: +If a string that contains the number is supplied, it returns it immediately as +a number (e.g: it returns `100` for `'100'`). + +However, if you pass a string with a number and a valid unit, hte number of +equivalent ms is returned. + +```js +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5ms') // 5000 +ms('100') // '100' +ms(100) // 100 +``` + +## How to use + +### Node + +```js +require('ms') +``` + +### Browser + +```html + +``` + +## Credits + +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch <guillermo@learnboost.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/mongoose/node_modules/ms/ms.js b/node_modules/mongoose/node_modules/ms/ms.js new file mode 100644 index 0000000..b4621bc --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/ms.js @@ -0,0 +1,35 @@ +/** + +# ms.js + +No more painful `setTimeout(fn, 60 * 4 * 3 * 2 * 1 * Infinity * NaN * '☃')`. + + ms('2d') // 172800000 + ms('1.5h') // 5400000 + ms('1h') // 3600000 + ms('1m') // 60000 + ms('5s') // 5000 + ms('500ms') // 500 + ms('100') // '100' + ms(100) // 100 + +**/ + +(function (g) { + var r = /(\d*.?\d+)([mshd]+)/ + , _ = {} + + _.ms = 1; + _.s = 1000; + _.m = _.s * 60; + _.h = _.m * 60; + _.d = _.h * 24; + + function ms (s) { + if (s == Number(s)) return Number(s); + r.exec(s.toLowerCase()); + return RegExp.$1 * _[RegExp.$2]; + } + + g.top ? g.ms = ms : module.exports = ms; +})(this); diff --git a/node_modules/mongoose/node_modules/ms/package.json b/node_modules/mongoose/node_modules/ms/package.json new file mode 100644 index 0000000..cf46aea --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/package.json @@ -0,0 +1,19 @@ +{ + "name": "ms", + "version": "0.1.0", + "description": "Tiny ms conversion utility", + "main": "./ms", + "devDependencies": { + "mocha": "*", + "expect.js": "*", + "serve": "*" + }, + "readme": "\n# ms.js\n\nEver find yourself doing math in your head or writing `1000 * 60 * 60 …`?\nDon't want to add obstrusive `Number` prototype extensions to your reusable\n/ distributable modules and projects?\n\n`ms` is a tiny utility that you can leverage when your application needs to\naccept a number of miliseconds as a parameter.\n\nIf a number is supplied to `ms`, it returns it immediately (e.g:\nIf a string that contains the number is supplied, it returns it immediately as\na number (e.g: it returns `100` for `'100'`).\n\nHowever, if you pass a string with a number and a valid unit, hte number of\nequivalent ms is returned.\n\n```js\nms('1d') // 86400000\nms('10h') // 36000000\nms('2h') // 7200000\nms('1m') // 60000\nms('5ms') // 5000\nms('100') // '100'\nms(100) // 100\n```\n\n## How to use\n\n### Node\n\n```js\nrequire('ms')\n```\n\n### Browser\n\n```html\n\n```\n\n## Credits\n\n(The MIT License)\n\nCopyright (c) 2011 Guillermo Rauch <guillermo@learnboost.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "_id": "ms@0.1.0", + "dist": { + "shasum": "471e00f49f7a3b6e84e124aefe2c6d66f0a438ba" + }, + "_from": "ms@0.1.0", + "_resolved": "https://registry.npmjs.org/ms/-/ms-0.1.0.tgz" +} diff --git a/node_modules/mongoose/node_modules/ms/test/index.html b/node_modules/mongoose/node_modules/ms/test/index.html new file mode 100644 index 0000000..79edc40 --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/test/index.html @@ -0,0 +1,19 @@ + + + + ms.js tests + + + + + + + + + + + + +
    + + diff --git a/node_modules/mongoose/node_modules/ms/test/support/jquery.js b/node_modules/mongoose/node_modules/ms/test/support/jquery.js new file mode 100644 index 0000000..8ccd0ea --- /dev/null +++ b/node_modules/mongoose/node_modules/ms/test/support/jquery.js @@ -0,0 +1,9266 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!memory; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + marginDiv, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
    a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = marginDiv = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + conMarginTop, ptlm, vb, style, html, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; + vb = "visibility:hidden;border:0;"; + style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; + html = "
    " + + "" + + "
    "; + + container = document.createElement("div"); + container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Figure out if the W3C box model works as expected + div.innerHTML = ""; + div.style.width = div.style.paddingLeft = "1px"; + jQuery.boxModel = support.boxModel = div.offsetWidth === 2; + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.style.cssText = ptlm + vb; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + body.removeChild( container ); + div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, attr, name, + data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { + attr = this[0].attributes; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + jQuery._data( this[0], "parsedAttrs", true ); + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var self = jQuery( this ), + args = [ parts[0], value ]; + + self.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + + // See #9699 for explanation of this approach (setting first, then removal) + jQuery.attr( elem, name, "" ); + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /\bhover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Determine handlers that should run if there are delegated events + // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on.call( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + +``` + +in development mode, but in production it will render to + +```html + + +``` + +So debugging should be as easy as directly using script-tags. Line numbers +will match your real files in the filesystem. No need to debug huge Javascript +bundle! + + + +## Examples + +Visit +[this](https://github.com/epeli/piler/blob/master/examples/simple/app.js) +directory to see a simple example using ExpressJS 2.x. + +This +[example](https://github.com/epeli/piler/blob/master/examples/simple/app.js) +uses ExpressJS 3.x a custom logger (winston) and a global socket.io instance +together with Piler. + +## API summary + +Code will be rendered in the order you call these functions with the exception +of *addUrl* which will be rendered as first. + +### createJSManager and createCSSManager + +Can take an optional configuration object as an argument with following keys. + + var jsclient = piler.createJSManager({ + outputDirectory: __dirname + "/mydir", + urlRoot: "/my/root" + }); + +#### urlRoot + +Url root to which Piler's paths are appended. For example urlRoot "/my/root" +will result in following script tag: + + + +#### outputDirectory + +If specified *Piler* will write the minified assets to this folder. Useful if +you want to share you assets from Apache etc. instead of directly serving from +Piler's Connect middleware. + + +### JavaScript pile + +#### addFile( [namespace], path to a asset file ) + +File on filesystem. + +#### addUrl( [namespace], url to a asset file ) + +Useful for CDNs and for dynamic assets in other libraries such as socket.io. + +#### addOb( [namespace string], any Javascript object ) + +Keys of the object will be added to the global window object. So take care when +choosing those. Also remember that parent scope of functions will be lost. + +You can also give a nested namespace for it + + clientjs.addOb({"foo.bar": "my thing"}); + +Now on the client "my thing" string will be found from window.foo.bar. + +The object will be serialized at the second it is passed to this method so you +won't be able modify it other than between server restarts. This is usefull for +sharing utility functions etc. + +Use *res.addOb* to share more dynamically objects. + +#### addExec( [namespace], Javascript function ) + +A function that will executed immediately in browser as it is parsed. Parent +scope is also lost here. + +#### addRaw( [namespace], raw Javascript string ) + +Any valid Javascript string. + + + +### CSS pile + +These are similar to ones in JS pile. + + +#### addFile( [namespace], path to a asset file ) + +CSS asset on your filesystem. + +#### addUrl( [namespace], url to a asset file ) + +CSS asset behind a url. Can be remote too. This will be directly linked to you +page. Use addFile if you want it be minified. + +#### addRaw( [namespace], raw CSS string ) + +Any valid CSS string. + + +## Supported preprocessors + +### JavaScript + +For JavaScript the only supported one is [CoffeeScript][] and the compiler is +included in *Piler*. + +### CSS + +CSS-compilers are not included in *Piler*. Just install what you need using +[npm][]. + + * [Stylus][] with [nib][] (npm install stylus nib) + * [LESS][] (npm install less) + +Adding support for new compilers should be +[easy](https://github.com/epeli/pile/blob/master/lib/compilers.coffee). + +Feel free to contribute! + +## Installing + +From [npm][] + + npm install piler + +## Source code + +Source code is licenced under [The MIT +License](https://github.com/epeli/piler/blob/master/LICENSE) and it is hosted +on [Github](https://github.com/epeli/piler). + +## Changelog + +v0.4.2 - 2013-04-16 + + * Fixes to work with ExpressJS 3.x + * Unit test fixes + * Make console output configurable + + +v0.4.1 - 2012-06-12 + + * Add getSources + * Put cache key to resource url instead of query string + +v0.4.0 - 2012-06-17 + + * Remove Dynamic Helpers. + +Dynamic Helpers where an Express 2.0 only API. This makes Piler more framework +agnostic and it will work with Express 3.0. This also removes support for +response object functions. We'll add those back if there is a need for them +(open up a issue if you miss them!) and we'll find good framework agnostic way +to implement them. + +v0.3.6 - 2012-06-17 + + * Bind all production dependency versions + +v0.3.5 - 2012-06-17 + + * Fix LESS @imports + * Fix Stylus without nib + * Use path module for Windows compatibility + +v0.3.4 - 2012-03-29 + + * Fix Stylus @imports + +v0.3.3 - noop + +v0.3.2 - 2011-12-11 + + * Workaround compiler bug in CoffeeScript + +v0.3.1 - 2011-11-17 + + * Fix CSS namespaces + +v0.3.0 - 2011-10-13 + + * Rename to Piler + * Really minify CSS + * Implemented res.addOb + * Implement outputDirectory and urlRoot options. + * addOb can now take nested namespace string and it won't override existing + namespaces. + +## Contact + +Questions and suggestions are very welcome + +- [Esa-Matti Suuronen](http://esa-matti.suuronen.org/) +- esa-matti [aet] suuronen dot org +- [EsaMatti](https://twitter.com/#!/EsaMatti) @ Twitter +- Epeli @ freenode/IRCnet + +[Express]: http://expressjs.com/ +[Node.js]: http://nodejs.org/ +[Live.js]: http://livejs.com/ +[LESS]: http://lesscss.org/ +[Stylus]: http://learnboost.github.com/stylus/ +[nib]: https://github.com/visionmedia/nib +[npm]: http://npmjs.org/ +[CoffeeScript]: http://jashkenas.github.com/coffee-script/ + + diff --git a/node_modules/piler/examples/logger/.npmignore b/node_modules/piler/examples/logger/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/piler/examples/logger/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/piler/examples/logger/README.md b/node_modules/piler/examples/logger/README.md new file mode 100644 index 0000000..e06c3eb --- /dev/null +++ b/node_modules/piler/examples/logger/README.md @@ -0,0 +1,12 @@ +# This is a port of the simple example using ExpressJS 3.x custom logger and socket.io configuration + +Install dependencies + + npm install express@3.x winston socket.io stylus less + +And run it + + node app.js + +Then open up http://localhost:8001/ and try editing `style.css`. + diff --git a/node_modules/piler/examples/logger/app.js b/node_modules/piler/examples/logger/app.js new file mode 100644 index 0000000..a5c8c84 --- /dev/null +++ b/node_modules/piler/examples/logger/app.js @@ -0,0 +1,115 @@ +var express = require('express'); +var app = express(); +var http = require('http'); +var socketio = require('socket.io'); +var pile = require("../../index"); +var logger = {}; +var share = require("./share"); + +console.log(share.test()); + +function isEmail(s) { + return !! s.match(/.\w+@\w+\.\w/); +} + +var loggerConf = { + levels: { + debug: 0, + info: 1, + notice: 2, + warn: 3, + warning: 3, + error: 4, + critical: 5, + crit: 5, + alert: 6, + emerg: 7 + }, + colors: { + debug: 'grey', + info: 'blue', + notice: 'green', + warn: 'yellow', + warning: 'yellow', + error: 'red', + critical: 'red', + crit: 'red', + alert: 'red', + emerg: 'red' + }, + transports: [ + new (require('winston').transports.Console)({ + colorize: true, + timestampe: true, + "level": 'debug', + "silent": false + }) + ] +}; + +var logger = new (require('winston').Logger)(loggerConf); + +var srv = http.createServer(app); + +// Socket.IO +var io = socketio.listen(srv,{"logger":logger}); + +io.configure(function(){ + io.enable('browser client gzip'); + io.enable('browser client minification'); + io.disable('flash policy server'); +}); + +// Piler config +var js = pile.createJSManager({ outputDirectory: __dirname + "/out", "logger":logger }); +var css = pile.createCSSManager({ outputDirectory: __dirname + "/out", "logger":logger }); + +js.bind(app,srv); +css.bind(app,srv); + +app.configure(function() { + app.set('views', __dirname + "/views"); +}); + +app.configure("development", function() { + js.liveUpdate(css,io); +}); + +css.addFile(__dirname + "/style.css"); +css.addFile(__dirname + "/style.styl"); +css.addFile(__dirname + "/style.less"); + +js.addOb({MY: { + isEmail: isEmail + } +}); + +js.addOb({FOO: "bar"}); +js.addUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"); + +js.addFile(__dirname + "/client/underscore.js"); +js.addFile(__dirname + "/client/backbone.js"); +js.addFile(__dirname + "/client/hello.js"); +js.addFile(__dirname + "/client/hello.coffee"); +js.addFile("foo", __dirname + "/client/foo.coffee"); +js.addFile("bar", __dirname + "/client/bar.coffee"); +js.addFile(__dirname + "/share.js"); + + +app.get("/", function(req, res){ + + res.exec(function() { + console.log("Run client code from the response", FOO); + console.log(share.test()); + }); + + res.render("index.jade", { + layout: false, + js: js.renderTags("foo"), + css: css.renderTags() + }); +}); + +srv.listen(8001, function(){ + logger.notice("listening on 8001"); +}); diff --git a/node_modules/piler/examples/logger/client/backbone.js b/node_modules/piler/examples/logger/client/backbone.js new file mode 100644 index 0000000..b2e4932 --- /dev/null +++ b/node_modules/piler/examples/logger/client/backbone.js @@ -0,0 +1,1158 @@ +// Backbone.js 0.5.3 +// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://documentcloud.github.com/backbone + +(function(){ + + // Initial Setup + // ------------- + + // Save a reference to the global object. + var root = this; + + // Save the previous value of the `Backbone` variable. + var previousBackbone = root.Backbone; + + // The top-level namespace. All public Backbone classes and modules will + // be attached to this. Exported for both CommonJS and the browser. + var Backbone; + if (typeof exports !== 'undefined') { + Backbone = exports; + } else { + Backbone = root.Backbone = {}; + } + + // Current version of the library. Keep in sync with `package.json`. + Backbone.VERSION = '0.5.3'; + + // Require Underscore, if we're on the server, and it's not already present. + var _ = root._; + if (!_ && (typeof require !== 'undefined')) _ = require('underscore')._; + + // For Backbone's purposes, jQuery or Zepto owns the `$` variable. + var $ = root.jQuery || root.Zepto; + + // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable + // to its previous owner. Returns a reference to this Backbone object. + Backbone.noConflict = function() { + root.Backbone = previousBackbone; + return this; + }; + + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option will + // fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and set a + // `X-Http-Method-Override` header. + Backbone.emulateHTTP = false; + + // Turn on `emulateJSON` to support legacy servers that can't deal with direct + // `application/json` requests ... will encode the body as + // `application/x-www-form-urlencoded` instead and will send the model in a + // form param named `model`. + Backbone.emulateJSON = false; + + // Backbone.Events + // ----------------- + + // A module that can be mixed in to *any object* in order to provide it with + // custom events. You may `bind` or `unbind` a callback function to an event; + // `trigger`-ing an event fires all callbacks in succession. + // + // var object = {}; + // _.extend(object, Backbone.Events); + // object.bind('expand', function(){ alert('expanded'); }); + // object.trigger('expand'); + // + Backbone.Events = { + + // Bind an event, specified by a string name, `ev`, to a `callback` function. + // Passing `"all"` will bind the callback to all events fired. + bind : function(ev, callback, context) { + var calls = this._callbacks || (this._callbacks = {}); + var list = calls[ev] || (calls[ev] = []); + list.push([callback, context]); + return this; + }, + + // Remove one or many callbacks. If `callback` is null, removes all + // callbacks for the event. If `ev` is null, removes all bound callbacks + // for all events. + unbind : function(ev, callback) { + var calls; + if (!ev) { + this._callbacks = {}; + } else if (calls = this._callbacks) { + if (!callback) { + calls[ev] = []; + } else { + var list = calls[ev]; + if (!list) return this; + for (var i = 0, l = list.length; i < l; i++) { + if (list[i] && callback === list[i][0]) { + list[i] = null; + break; + } + } + } + } + return this; + }, + + // Trigger an event, firing all bound callbacks. Callbacks are passed the + // same arguments as `trigger` is, apart from the event name. + // Listening for `"all"` passes the true event name as the first argument. + trigger : function(eventName) { + var list, calls, ev, callback, args; + var both = 2; + if (!(calls = this._callbacks)) return this; + while (both--) { + ev = both ? eventName : 'all'; + if (list = calls[ev]) { + for (var i = 0, l = list.length; i < l; i++) { + if (!(callback = list[i])) { + list.splice(i, 1); i--; l--; + } else { + args = both ? Array.prototype.slice.call(arguments, 1) : arguments; + callback[0].apply(callback[1] || this, args); + } + } + } + } + return this; + } + + }; + + // Backbone.Model + // -------------- + + // Create a new model, with defined attributes. A client id (`cid`) + // is automatically generated and assigned for you. + Backbone.Model = function(attributes, options) { + var defaults; + attributes || (attributes = {}); + if (defaults = this.defaults) { + if (_.isFunction(defaults)) defaults = defaults.call(this); + attributes = _.extend({}, defaults, attributes); + } + this.attributes = {}; + this._escapedAttributes = {}; + this.cid = _.uniqueId('c'); + this.set(attributes, {silent : true}); + this._changed = false; + this._previousAttributes = _.clone(this.attributes); + if (options && options.collection) this.collection = options.collection; + this.initialize(attributes, options); + }; + + // Attach all inheritable methods to the Model prototype. + _.extend(Backbone.Model.prototype, Backbone.Events, { + + // A snapshot of the model's previous attributes, taken immediately + // after the last `"change"` event was fired. + _previousAttributes : null, + + // Has the item been changed since the last `"change"` event? + _changed : false, + + // The default name for the JSON `id` attribute is `"id"`. MongoDB and + // CouchDB users may want to set this to `"_id"`. + idAttribute : 'id', + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize : function(){}, + + // Return a copy of the model's `attributes` object. + toJSON : function() { + return _.clone(this.attributes); + }, + + // Get the value of an attribute. + get : function(attr) { + return this.attributes[attr]; + }, + + // Get the HTML-escaped value of an attribute. + escape : function(attr) { + var html; + if (html = this._escapedAttributes[attr]) return html; + var val = this.attributes[attr]; + return this._escapedAttributes[attr] = escapeHTML(val == null ? '' : '' + val); + }, + + // Returns `true` if the attribute contains a value that is not null + // or undefined. + has : function(attr) { + return this.attributes[attr] != null; + }, + + // Set a hash of model attributes on the object, firing `"change"` unless you + // choose to silence it. + set : function(attrs, options) { + + // Extract attributes and options. + options || (options = {}); + if (!attrs) return this; + if (attrs.attributes) attrs = attrs.attributes; + var now = this.attributes, escaped = this._escapedAttributes; + + // Run validation. + if (!options.silent && this.validate && !this._performValidation(attrs, options)) return false; + + // Check for changes of `id`. + if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; + + // We're about to start triggering change events. + var alreadyChanging = this._changing; + this._changing = true; + + // Update attributes. + for (var attr in attrs) { + var val = attrs[attr]; + if (!_.isEqual(now[attr], val)) { + now[attr] = val; + delete escaped[attr]; + this._changed = true; + if (!options.silent) this.trigger('change:' + attr, this, val, options); + } + } + + // Fire the `"change"` event, if the model has been changed. + if (!alreadyChanging && !options.silent && this._changed) this.change(options); + this._changing = false; + return this; + }, + + // Remove an attribute from the model, firing `"change"` unless you choose + // to silence it. `unset` is a noop if the attribute doesn't exist. + unset : function(attr, options) { + if (!(attr in this.attributes)) return this; + options || (options = {}); + var value = this.attributes[attr]; + + // Run validation. + var validObj = {}; + validObj[attr] = void 0; + if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false; + + // Remove the attribute. + delete this.attributes[attr]; + delete this._escapedAttributes[attr]; + if (attr == this.idAttribute) delete this.id; + this._changed = true; + if (!options.silent) { + this.trigger('change:' + attr, this, void 0, options); + this.change(options); + } + return this; + }, + + // Clear all attributes on the model, firing `"change"` unless you choose + // to silence it. + clear : function(options) { + options || (options = {}); + var attr; + var old = this.attributes; + + // Run validation. + var validObj = {}; + for (attr in old) validObj[attr] = void 0; + if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false; + + this.attributes = {}; + this._escapedAttributes = {}; + this._changed = true; + if (!options.silent) { + for (attr in old) { + this.trigger('change:' + attr, this, void 0, options); + } + this.change(options); + } + return this; + }, + + // Fetch the model from the server. If the server's representation of the + // model differs from its current attributes, they will be overriden, + // triggering a `"change"` event. + fetch : function(options) { + options || (options = {}); + var model = this; + var success = options.success; + options.success = function(resp, status, xhr) { + if (!model.set(model.parse(resp, xhr), options)) return false; + if (success) success(model, resp); + }; + options.error = wrapError(options.error, model, options); + return (this.sync || Backbone.sync).call(this, 'read', this, options); + }, + + // Set a hash of model attributes, and sync the model to the server. + // If the server returns an attributes hash that differs, the model's + // state will be `set` again. + save : function(attrs, options) { + options || (options = {}); + if (attrs && !this.set(attrs, options)) return false; + var model = this; + var success = options.success; + options.success = function(resp, status, xhr) { + if (!model.set(model.parse(resp, xhr), options)) return false; + if (success) success(model, resp, xhr); + }; + options.error = wrapError(options.error, model, options); + var method = this.isNew() ? 'create' : 'update'; + return (this.sync || Backbone.sync).call(this, method, this, options); + }, + + // Destroy this model on the server if it was already persisted. Upon success, the model is removed + // from its collection, if it has one. + destroy : function(options) { + options || (options = {}); + if (this.isNew()) return this.trigger('destroy', this, this.collection, options); + var model = this; + var success = options.success; + options.success = function(resp) { + model.trigger('destroy', model, model.collection, options); + if (success) success(model, resp); + }; + options.error = wrapError(options.error, model, options); + return (this.sync || Backbone.sync).call(this, 'delete', this, options); + }, + + // Default URL for the model's representation on the server -- if you're + // using Backbone's restful methods, override this to change the endpoint + // that will be called. + url : function() { + var base = getUrl(this.collection) || this.urlRoot || urlError(); + if (this.isNew()) return base; + return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id); + }, + + // **parse** converts a response into the hash of attributes to be `set` on + // the model. The default implementation is just to pass the response along. + parse : function(resp, xhr) { + return resp; + }, + + // Create a new model with identical attributes to this one. + clone : function() { + return new this.constructor(this); + }, + + // A model is new if it has never been saved to the server, and lacks an id. + isNew : function() { + return this.id == null; + }, + + // Call this method to manually fire a `change` event for this model. + // Calling this will cause all objects observing the model to update. + change : function(options) { + this.trigger('change', this, options); + this._previousAttributes = _.clone(this.attributes); + this._changed = false; + }, + + // Determine if the model has changed since the last `"change"` event. + // If you specify an attribute name, determine if that attribute has changed. + hasChanged : function(attr) { + if (attr) return this._previousAttributes[attr] != this.attributes[attr]; + return this._changed; + }, + + // Return an object containing all the attributes that have changed, or false + // if there are no changed attributes. Useful for determining what parts of a + // view need to be updated and/or what attributes need to be persisted to + // the server. + changedAttributes : function(now) { + now || (now = this.attributes); + var old = this._previousAttributes; + var changed = false; + for (var attr in now) { + if (!_.isEqual(old[attr], now[attr])) { + changed = changed || {}; + changed[attr] = now[attr]; + } + } + return changed; + }, + + // Get the previous value of an attribute, recorded at the time the last + // `"change"` event was fired. + previous : function(attr) { + if (!attr || !this._previousAttributes) return null; + return this._previousAttributes[attr]; + }, + + // Get all of the attributes of the model at the time of the previous + // `"change"` event. + previousAttributes : function() { + return _.clone(this._previousAttributes); + }, + + // Run validation against a set of incoming attributes, returning `true` + // if all is well. If a specific `error` callback has been passed, + // call that instead of firing the general `"error"` event. + _performValidation : function(attrs, options) { + var error = this.validate(attrs); + if (error) { + if (options.error) { + options.error(this, error, options); + } else { + this.trigger('error', this, error, options); + } + return false; + } + return true; + } + + }); + + // Backbone.Collection + // ------------------- + + // Provides a standard collection class for our sets of models, ordered + // or unordered. If a `comparator` is specified, the Collection will maintain + // its models in sort order, as they're added and removed. + Backbone.Collection = function(models, options) { + options || (options = {}); + if (options.comparator) this.comparator = options.comparator; + _.bindAll(this, '_onModelEvent', '_removeReference'); + this._reset(); + if (models) this.reset(models, {silent: true}); + this.initialize.apply(this, arguments); + }; + + // Define the Collection's inheritable methods. + _.extend(Backbone.Collection.prototype, Backbone.Events, { + + // The default model for a collection is just a **Backbone.Model**. + // This should be overridden in most cases. + model : Backbone.Model, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize : function(){}, + + // The JSON representation of a Collection is an array of the + // models' attributes. + toJSON : function() { + return this.map(function(model){ return model.toJSON(); }); + }, + + // Add a model, or list of models to the set. Pass **silent** to avoid + // firing the `added` event for every new model. + add : function(models, options) { + if (_.isArray(models)) { + for (var i = 0, l = models.length; i < l; i++) { + this._add(models[i], options); + } + } else { + this._add(models, options); + } + return this; + }, + + // Remove a model, or a list of models from the set. Pass silent to avoid + // firing the `removed` event for every model removed. + remove : function(models, options) { + if (_.isArray(models)) { + for (var i = 0, l = models.length; i < l; i++) { + this._remove(models[i], options); + } + } else { + this._remove(models, options); + } + return this; + }, + + // Get a model from the set by id. + get : function(id) { + if (id == null) return null; + return this._byId[id.id != null ? id.id : id]; + }, + + // Get a model from the set by client id. + getByCid : function(cid) { + return cid && this._byCid[cid.cid || cid]; + }, + + // Get the model at the given index. + at: function(index) { + return this.models[index]; + }, + + // Force the collection to re-sort itself. You don't need to call this under normal + // circumstances, as the set will maintain sort order as each item is added. + sort : function(options) { + options || (options = {}); + if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); + this.models = this.sortBy(this.comparator); + if (!options.silent) this.trigger('reset', this, options); + return this; + }, + + // Pluck an attribute from each model in the collection. + pluck : function(attr) { + return _.map(this.models, function(model){ return model.get(attr); }); + }, + + // When you have more items than you want to add or remove individually, + // you can reset the entire set with a new list of models, without firing + // any `added` or `removed` events. Fires `reset` when finished. + reset : function(models, options) { + models || (models = []); + options || (options = {}); + this.each(this._removeReference); + this._reset(); + this.add(models, {silent: true}); + if (!options.silent) this.trigger('reset', this, options); + return this; + }, + + // Fetch the default set of models for this collection, resetting the + // collection when they arrive. If `add: true` is passed, appends the + // models to the collection instead of resetting. + fetch : function(options) { + options || (options = {}); + var collection = this; + var success = options.success; + options.success = function(resp, status, xhr) { + collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options); + if (success) success(collection, resp); + }; + options.error = wrapError(options.error, collection, options); + return (this.sync || Backbone.sync).call(this, 'read', this, options); + }, + + // Create a new instance of a model in this collection. After the model + // has been created on the server, it will be added to the collection. + // Returns the model, or 'false' if validation on a new model fails. + create : function(model, options) { + var coll = this; + options || (options = {}); + model = this._prepareModel(model, options); + if (!model) return false; + var success = options.success; + options.success = function(nextModel, resp, xhr) { + coll.add(nextModel, options); + if (success) success(nextModel, resp, xhr); + }; + model.save(null, options); + return model; + }, + + // **parse** converts a response into a list of models to be added to the + // collection. The default implementation is just to pass it through. + parse : function(resp, xhr) { + return resp; + }, + + // Proxy to _'s chain. Can't be proxied the same way the rest of the + // underscore methods are proxied because it relies on the underscore + // constructor. + chain: function () { + return _(this.models).chain(); + }, + + // Reset all internal state. Called when the collection is reset. + _reset : function(options) { + this.length = 0; + this.models = []; + this._byId = {}; + this._byCid = {}; + }, + + // Prepare a model to be added to this collection + _prepareModel: function(model, options) { + if (!(model instanceof Backbone.Model)) { + var attrs = model; + model = new this.model(attrs, {collection: this}); + if (model.validate && !model._performValidation(attrs, options)) model = false; + } else if (!model.collection) { + model.collection = this; + } + return model; + }, + + // Internal implementation of adding a single model to the set, updating + // hash indexes for `id` and `cid` lookups. + // Returns the model, or 'false' if validation on a new model fails. + _add : function(model, options) { + options || (options = {}); + model = this._prepareModel(model, options); + if (!model) return false; + var already = this.getByCid(model); + if (already) throw new Error(["Can't add the same model to a set twice", already.id]); + this._byId[model.id] = model; + this._byCid[model.cid] = model; + var index = options.at != null ? options.at : + this.comparator ? this.sortedIndex(model, this.comparator) : + this.length; + this.models.splice(index, 0, model); + model.bind('all', this._onModelEvent); + this.length++; + if (!options.silent) model.trigger('add', model, this, options); + return model; + }, + + // Internal implementation of removing a single model from the set, updating + // hash indexes for `id` and `cid` lookups. + _remove : function(model, options) { + options || (options = {}); + model = this.getByCid(model) || this.get(model); + if (!model) return null; + delete this._byId[model.id]; + delete this._byCid[model.cid]; + this.models.splice(this.indexOf(model), 1); + this.length--; + if (!options.silent) model.trigger('remove', model, this, options); + this._removeReference(model); + return model; + }, + + // Internal method to remove a model's ties to a collection. + _removeReference : function(model) { + if (this == model.collection) { + delete model.collection; + } + model.unbind('all', this._onModelEvent); + }, + + // Internal method called every time a model in the set fires an event. + // Sets need to update their indexes when models change ids. All other + // events simply proxy through. "add" and "remove" events that originate + // in other collections are ignored. + _onModelEvent : function(ev, model, collection, options) { + if ((ev == 'add' || ev == 'remove') && collection != this) return; + if (ev == 'destroy') { + this._remove(model, options); + } + if (model && ev === 'change:' + model.idAttribute) { + delete this._byId[model.previous(model.idAttribute)]; + this._byId[model.id] = model; + } + this.trigger.apply(this, arguments); + } + + }); + + // Underscore methods that we want to implement on the Collection. + var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find', 'detect', + 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include', + 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size', + 'first', 'rest', 'last', 'without', 'indexOf', 'lastIndexOf', 'isEmpty', 'groupBy']; + + // Mix in each Underscore method as a proxy to `Collection#models`. + _.each(methods, function(method) { + Backbone.Collection.prototype[method] = function() { + return _[method].apply(_, [this.models].concat(_.toArray(arguments))); + }; + }); + + // Backbone.Router + // ------------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + Backbone.Router = function(options) { + options || (options = {}); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var namedParam = /:([\w\d]+)/g; + var splatParam = /\*([\w\d]+)/g; + var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Backbone.Router.prototype, Backbone.Events, { + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize : function(){}, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route : function(route, name, callback) { + Backbone.history || (Backbone.history = new Backbone.History); + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + Backbone.history.route(route, _.bind(function(fragment) { + var args = this._extractParameters(route, fragment); + callback.apply(this, args); + this.trigger.apply(this, ['route:' + name].concat(args)); + }, this)); + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate : function(fragment, triggerRoute) { + Backbone.history.navigate(fragment, triggerRoute); + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes : function() { + if (!this.routes) return; + var routes = []; + for (var route in this.routes) { + routes.unshift([route, this.routes[route]]); + } + for (var i = 0, l = routes.length; i < l; i++) { + this.route(routes[i][0], routes[i][1], this[routes[i][1]]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp : function(route) { + route = route.replace(escapeRegExp, "\\$&") + .replace(namedParam, "([^\/]*)") + .replace(splatParam, "(.*?)"); + return new RegExp('^' + route + '$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted parameters. + _extractParameters : function(route, fragment) { + return route.exec(fragment).slice(1); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on URL fragments. If the + // browser does not support `onhashchange`, falls back to polling. + Backbone.History = function() { + this.handlers = []; + _.bindAll(this, 'checkUrl'); + }; + + // Cached regex for cleaning hashes. + var hashStrip = /^#*/; + + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Has the history handling already been started? + var historyStarted = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(Backbone.History.prototype, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval: 50, + + // Get the cross-browser normalized URL fragment, either from the URL, + // the hash, or the override. + getFragment : function(fragment, forcePushState) { + if (fragment == null) { + if (this._hasPushState || forcePushState) { + fragment = window.location.pathname; + var search = window.location.search; + if (search) fragment += search; + if (fragment.indexOf(this.options.root) == 0) fragment = fragment.substr(this.options.root.length); + } else { + fragment = window.location.hash; + } + } + return decodeURIComponent(fragment.replace(hashStrip, '')); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start : function(options) { + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + if (historyStarted) throw new Error("Backbone.history has already been started"); + this.options = _.extend({}, {root: '/'}, this.options, options); + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.options.pushState && window.history && window.history.pushState); + var fragment = this.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); + if (oldIE) { + this.iframe = $(' \ + \ + Powered by JSLitmus \ + '; + + /** + * The public API for creating and running tests + */ + window.JSLitmus = { + /** The list of all tests that have been registered with JSLitmus.test */ + _tests: [], + /** The queue of tests that need to be run */ + _queue: [], + + /** + * The parsed query parameters the current page URL. This is provided as a + * convenience for test functions - it's not used by JSLitmus proper + */ + params: {}, + + /** + * Initialize + */ + _init: function() { + // Parse query params into JSLitmus.params[] hash + var match = (location + '').match(/([^?#]*)(#.*)?$/); + if (match) { + var pairs = match[1].split('&'); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split('='); + if (pair.length > 1) { + var key = pair.shift(); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + this.params[key] = value; + } + } + } + + // Write out the stylesheet. We have to do this here because IE + // doesn't honor sheets written after the document has loaded. + document.write(STYLESHEET); + + // Setup the rest of the UI once the document is loaded + if (window.addEventListener) { + window.addEventListener('load', this._setup, false); + } else if (document.addEventListener) { + document.addEventListener('load', this._setup, false); + } else if (window.attachEvent) { + window.attachEvent('onload', this._setup); + } + + return this; + }, + + /** + * Set up the UI + */ + _setup: function() { + var el = jsl.$('jslitmus_container'); + if (!el) document.body.appendChild(el = document.createElement('div')); + + el.innerHTML = MARKUP; + + // Render the UI for all our tests + for (var i=0; i < JSLitmus._tests.length; i++) + JSLitmus.renderTest(JSLitmus._tests[i]); + }, + + /** + * (Re)render all the test results + */ + renderAll: function() { + for (var i = 0; i < JSLitmus._tests.length; i++) + JSLitmus.renderTest(JSLitmus._tests[i]); + JSLitmus.renderChart(); + }, + + /** + * (Re)render the chart graphics + */ + renderChart: function() { + var url = JSLitmus.chartUrl(); + jsl.$('chart_link').href = url; + jsl.$('chart_image').src = url; + jsl.$('chart').style.display = ''; + + // Update the tiny URL + jsl.$('tiny_url').src = 'http://tinyurl.com/api-create.php?url='+escape(url); + }, + + /** + * (Re)render the results for a specific test + */ + renderTest: function(test) { + // Make a new row if needed + if (!test._row) { + var trow = jsl.$('test_row_template'); + if (!trow) return; + + test._row = trow.cloneNode(true); + test._row.style.display = ''; + test._row.id = ''; + test._row.onclick = function() {JSLitmus._queueTest(test);}; + test._row.title = 'Run ' + test.name + ' test'; + trow.parentNode.appendChild(test._row); + test._row.cells[0].innerHTML = test.name; + } + + var cell = test._row.cells[1]; + var cns = [test.loopArg ? 'test_looping' : 'test_nonlooping']; + + if (test.error) { + cns.push('test_error'); + cell.innerHTML = + '
    ' + test.error + '
    ' + + '
    • ' + + jsl.join(test.error, ': ', '
    • ') + + '
    '; + } else { + if (test.running) { + cns.push('test_running'); + cell.innerHTML = 'running'; + } else if (jsl.indexOf(JSLitmus._queue, test) >= 0) { + cns.push('test_pending'); + cell.innerHTML = 'pending'; + } else if (test.count) { + cns.push('test_done'); + var hz = test.getHz(jsl.$('test_normalize').checked); + cell.innerHTML = hz != Infinity ? hz : '∞'; + } else { + cell.innerHTML = 'ready'; + } + } + cell.className = cns.join(' '); + }, + + /** + * Create a new test + */ + test: function(name, f) { + // Create the Test object + var test = new Test(name, f); + JSLitmus._tests.push(test); + + // Re-render if the test state changes + test.onChange = JSLitmus.renderTest; + + // Run the next test if this one finished + test.onStop = function(test) { + if (JSLitmus.onTestFinish) JSLitmus.onTestFinish(test); + JSLitmus.currentTest = null; + JSLitmus._nextTest(); + }; + + // Render the new test + this.renderTest(test); + }, + + /** + * Add all tests to the run queue + */ + runAll: function(e) { + e = e || window.event; + var reverse = e && e.shiftKey, len = JSLitmus._tests.length; + for (var i = 0; i < len; i++) { + JSLitmus._queueTest(JSLitmus._tests[!reverse ? i : (len - i - 1)]); + } + }, + + /** + * Remove all tests from the run queue. The current test has to finish on + * it's own though + */ + stop: function() { + while (JSLitmus._queue.length) { + var test = JSLitmus._queue.shift(); + JSLitmus.renderTest(test); + } + }, + + /** + * Run the next test in the run queue + */ + _nextTest: function() { + if (!JSLitmus.currentTest) { + var test = JSLitmus._queue.shift(); + if (test) { + jsl.$('stop_button').disabled = false; + JSLitmus.currentTest = test; + test.run(); + JSLitmus.renderTest(test); + if (JSLitmus.onTestStart) JSLitmus.onTestStart(test); + } else { + jsl.$('stop_button').disabled = true; + JSLitmus.renderChart(); + } + } + }, + + /** + * Add a test to the run queue + */ + _queueTest: function(test) { + if (jsl.indexOf(JSLitmus._queue, test) >= 0) return; + JSLitmus._queue.push(test); + JSLitmus.renderTest(test); + JSLitmus._nextTest(); + }, + + /** + * Generate a Google Chart URL that shows the data for all tests + */ + chartUrl: function() { + var n = JSLitmus._tests.length, markers = [], data = []; + var d, min = 0, max = -1e10; + var normalize = jsl.$('test_normalize').checked; + + // Gather test data + for (var i=0; i < JSLitmus._tests.length; i++) { + var test = JSLitmus._tests[i]; + if (test.count) { + var hz = test.getHz(normalize); + var v = hz != Infinity ? hz : 0; + data.push(v); + markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' + + markers.length + ',10'); + max = Math.max(v, max); + } + } + if (markers.length <= 0) return null; + + // Build chart title + var title = document.getElementsByTagName('title'); + title = (title && title.length) ? title[0].innerHTML : null; + var chart_title = []; + if (title) chart_title.push(title); + chart_title.push('Ops/sec (' + platform + ')'); + + // Build labels + var labels = [jsl.toLabel(min), jsl.toLabel(max)]; + + var w = 250, bw = 15; + var bs = 5; + var h = markers.length*(bw + bs) + 30 + chart_title.length*20; + + var params = { + chtt: escape(chart_title.join('|')), + chts: '000000,10', + cht: 'bhg', // chart type + chd: 't:' + data.join(','), // data set + chds: min + ',' + max, // max/min of data + chxt: 'x', // label axes + chxl: '0:|' + labels.join('|'), // labels + chsp: '0,1', + chm: markers.join('|'), // test names + chbh: [bw, 0, bs].join(','), // bar widths + // chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient + chs: w + 'x' + h + }; + return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&'); + } + }; + + JSLitmus._init(); +})(); \ No newline at end of file diff --git a/node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.css b/node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.css new file mode 100644 index 0000000..8d0d3a2 --- /dev/null +++ b/node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.css @@ -0,0 +1,196 @@ +/** Font Family and Sizes */ + +#qunit-tests, #qunit-header, .qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { + font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; +} + +#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } +#qunit-tests { font-size: smaller; } + + +/** Resets */ + +#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { + margin: 0; + padding: 0; +} + + +/** Header */ + +#qunit-header, .qunit-header { + padding: 0.5em 0 0.5em 1em; + + color: #8699a4; + background-color: #0d3349; + + font-size: 1.5em; + line-height: 1em; + font-weight: normal; + + border-radius: 15px 15px 0 0; + -moz-border-radius: 15px 15px 0 0; + -webkit-border-top-right-radius: 15px; + -webkit-border-top-left-radius: 15px; +} + +#qunit-header a { + text-decoration: none; + color: #c2ccd1; +} + +#qunit-header a:hover, +#qunit-header a:focus { + color: #fff; +} + +#qunit-banner { + height: 5px; +} + +#qunit-testrunner-toolbar { + padding: 0em 0 0.5em 2em; +} + +#qunit-userAgent { + padding: 0.5em 0 0.5em 2.5em; + background-color: #2b81af; + color: #fff; + text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; +} + + +/** Tests: Pass/Fail */ + +#qunit-tests { + list-style-position: inside; +} + +#qunit-tests li { + padding: 0.4em 0.5em 0.4em 2.5em; + border-bottom: 1px solid #fff; + list-style-position: inside; +} + +#qunit-tests li strong { + cursor: pointer; +} + +#qunit-tests ol { + margin-top: 0.5em; + padding: 0.5em; + + background-color: #fff; + + border-radius: 15px; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; + + box-shadow: inset 0px 2px 13px #999; + -moz-box-shadow: inset 0px 2px 13px #999; + -webkit-box-shadow: inset 0px 2px 13px #999; +} + +#qunit-tests table { + border-collapse: collapse; + margin-top: .2em; +} + +#qunit-tests th { + text-align: right; + vertical-align: top; + padding: 0 .5em 0 0; +} + +#qunit-tests td { + vertical-align: top; +} + +#qunit-tests pre { + margin: 0; + white-space: pre-wrap; + word-wrap: break-word; +} + +#qunit-tests del { + background-color: #e0f2be; + color: #374e0c; + text-decoration: none; +} + +#qunit-tests ins { + background-color: #ffcaca; + color: #500; + text-decoration: none; +} + +/*** Test Counts */ + +#qunit-tests b.counts { color: black; } +#qunit-tests b.passed { color: #5E740B; } +#qunit-tests b.failed { color: #710909; } + +#qunit-tests li li { + margin: 0.5em; + padding: 0.4em 0.5em 0.4em 0.5em; + background-color: #fff; + border-bottom: none; + list-style-position: inside; +} + +/*** Passing Styles */ + +#qunit-tests li li.pass { + color: #5E740B; + background-color: #fff; + border-left: 26px solid #C6E746; +} + +#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } +#qunit-tests .pass .test-name { color: #366097; } + +#qunit-tests .pass .test-actual, +#qunit-tests .pass .test-expected { color: #999999; } + +#qunit-banner.qunit-pass { background-color: #C6E746; } + +/*** Failing Styles */ + +#qunit-tests li li.fail { + color: #710909; + background-color: #fff; + border-left: 26px solid #EE5757; +} + +#qunit-tests .fail { color: #000000; background-color: #EE5757; } +#qunit-tests .fail .test-name, +#qunit-tests .fail .module-name { color: #000000; } + +#qunit-tests .fail .test-actual { color: #EE5757; } +#qunit-tests .fail .test-expected { color: green; } + +#qunit-banner.qunit-fail, +#qunit-testrunner-toolbar { background-color: #EE5757; } + + +/** Footer */ + +#qunit-testresult { + padding: 0.5em 0.5em 0.5em 2.5em; + + color: #2b81af; + background-color: #D2E0E6; + + border-radius: 0 0 15px 15px; + -moz-border-radius: 0 0 15px 15px; + -webkit-border-bottom-right-radius: 15px; + -webkit-border-bottom-left-radius: 15px; +} + +/** Fixture */ + +#qunit-fixture { + position: absolute; + top: -10000px; + left: -10000px; +} \ No newline at end of file diff --git a/node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.js b/node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.js new file mode 100644 index 0000000..345630b --- /dev/null +++ b/node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.js @@ -0,0 +1,2360 @@ +/* + * QUnit - A JavaScript Unit Testing Framework + * + * http://docs.jquery.com/QUnit + * + * Copyright (c) 2009 John Resig, Jörn Zaefferer + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ + +(function(window) { + +var QUnit = { + + // Initialize the configuration options + init: function init() { + config = { + stats: { all: 0, bad: 0 }, + moduleStats: { all: 0, bad: 0 }, + started: +new Date, + blocking: false, + autorun: false, + assertions: [], + filters: [], + queue: [] + }; + + var tests = id("qunit-tests"), + banner = id("qunit-banner"), + result = id("qunit-testresult"); + + if ( tests ) { + tests.innerHTML = ""; + } + + if ( banner ) { + banner.className = ""; + } + + if ( result ) { + result.parentNode.removeChild( result ); + } + }, + + // call on start of module test to prepend name to all tests + module: function module(name, testEnvironment) { + + synchronize(function() { + if ( config.currentModule ) { + QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); + } + + config.currentModule = name; + config.moduleTestEnvironment = testEnvironment; + config.moduleStats = { all: 0, bad: 0 }; + + QUnit.moduleStart( name, testEnvironment ); + }); + }, + + asyncTest: function asyncTest(testName, expected, callback) { + if ( arguments.length === 2 ) { + callback = expected; + expected = 0; + } + + QUnit.test(testName, expected, callback, true); + }, + + test: function test(testName, expected, callback, async) { + var name = testName, testEnvironment = {}; + + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + if ( config.currentModule ) { + name = config.currentModule + " module: " + name; + } + + if ( !validTest(name) ) { + return; + } + + synchronize(function() { + QUnit.testStart( testName ); + + testEnvironment = extend({ + setup: function() {}, + teardown: function() {} + }, config.moduleTestEnvironment); + + config.assertions = []; + config.expected = null; + + if ( arguments.length >= 3 ) { + config.expected = callback; + callback = arguments[2]; + } + + try { + if ( !config.pollution ) { + saveGlobal(); + } + + testEnvironment.setup.call(testEnvironment); + } catch(e) { + QUnit.ok( false, "Setup failed on " + name + ": " + e.message ); + } + + if ( async ) { + QUnit.stop(); + } + + try { + callback.call(testEnvironment); + } catch(e) { + fail("Test " + name + " died, exception and test follows", e, callback); + QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message ); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if ( config.blocking ) { + start(); + } + } + }); + + synchronize(function() { + try { + checkPollution(); + testEnvironment.teardown.call(testEnvironment); + } catch(e) { + QUnit.ok( false, "Teardown failed on " + name + ": " + e.message ); + } + + try { + QUnit.reset(); + } catch(e) { + fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset); + } + + if ( config.expected && config.expected != config.assertions.length ) { + QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" ); + } + + var good = 0, bad = 0, + tests = id("qunit-tests"); + + config.stats.all += config.assertions.length; + config.moduleStats.all += config.assertions.length; + + if ( tests ) { + var ol = document.createElement("ol"); + ol.style.display = "none"; + + for ( var i = 0; i < config.assertions.length; i++ ) { + var assertion = config.assertions[i]; + + var li = document.createElement("li"); + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || "(no message)"; + ol.appendChild( li ); + + if ( assertion.result ) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + + var b = document.createElement("strong"); + b.innerHTML = name + " (" + bad + ", " + good + ", " + config.assertions.length + ")"; + + addEvent(b, "click", function() { + var next = b.nextSibling, display = next.style.display; + next.style.display = display === "none" ? "block" : "none"; + }); + + addEvent(b, "dblclick", function(e) { + var target = (e || window.event).target; + if ( target.nodeName.toLowerCase() === "strong" ) { + var text = "", node = target.firstChild; + + while ( node.nodeType === 3 ) { + text += node.nodeValue; + node = node.nextSibling; + } + + text = text.replace(/(^\s*|\s*$)/g, ""); + + if ( window.location ) { + window.location.href = window.location.href.match(/^(.+?)(\?.*)?$/)[1] + "?" + encodeURIComponent(text); + } + } + }); + + var li = document.createElement("li"); + li.className = bad ? "fail" : "pass"; + li.appendChild( b ); + li.appendChild( ol ); + tests.appendChild( li ); + + if ( bad ) { + var toolbar = id("qunit-testrunner-toolbar"); + if ( toolbar ) { + toolbar.style.display = "block"; + id("qunit-filter-pass").disabled = null; + id("qunit-filter-missing").disabled = null; + } + } + + } else { + for ( var i = 0; i < config.assertions.length; i++ ) { + if ( !config.assertions[i].result ) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + } + + QUnit.testDone( testName, bad, config.assertions.length ); + + if ( !window.setTimeout && !config.queue.length ) { + done(); + } + }); + + if ( window.setTimeout && !config.doneTimer ) { + config.doneTimer = window.setTimeout(function(){ + if ( !config.queue.length ) { + done(); + } else { + synchronize( done ); + } + }, 13); + } + }, + + /** + * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. + */ + expect: function expect(asserts) { + config.expected = asserts; + }, + + /** + * Asserts true. + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); + */ + ok: function ok(a, msg) { + QUnit.log(a, msg); + + config.assertions.push({ + result: !!a, + message: msg + }); + }, + + /** + * Checks that the first two arguments are equal, with an optional message. + * Prints out both actual and expected values. + * + * Prefered to ok( actual == expected, message ) + * + * @example equals( format("Received {0} bytes.", 2), "Received 2 bytes." ); + * + * @param Object actual + * @param Object expected + * @param String message (optional) + */ + equals: function equals(actual, expected, message) { + push(expected == actual, actual, expected, message); + }, + + same: function(a, b, message) { + push(QUnit.equiv(a, b), a, b, message); + }, + + start: function start() { + // A slight delay, to avoid any current callbacks + if ( window.setTimeout ) { + window.setTimeout(function() { + if ( config.timeout ) { + clearTimeout(config.timeout); + } + + config.blocking = false; + process(); + }, 13); + } else { + config.blocking = false; + process(); + } + }, + + stop: function stop(timeout) { + config.blocking = true; + + if ( timeout && window.setTimeout ) { + config.timeout = window.setTimeout(function() { + QUnit.ok( false, "Test timed out" ); + QUnit.start(); + }, timeout); + } + }, + + /** + * Resets the test setup. Useful for tests that modify the DOM. + */ + reset: function reset() { + if ( window.jQuery ) { + jQuery("#main").html( config.fixture ); + jQuery.event.global = {}; + jQuery.ajaxSettings = extend({}, config.ajaxSettings); + } + }, + + /** + * Trigger an event on an element. + * + * @example triggerEvent( document.body, "click" ); + * + * @param DOMElement elem + * @param String type + */ + triggerEvent: function triggerEvent( elem, type, event ) { + if ( document.createEvent ) { + event = document.createEvent("MouseEvents"); + event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent( event ); + + } else if ( elem.fireEvent ) { + elem.fireEvent("on"+type); + } + }, + + // Logging callbacks + done: function done(failures, total) {}, + log: function log(result, message) {}, + testStart: function testStart(name) {}, + testDone: function testDone(name, failures, total) {}, + moduleStart: function moduleStart(name, testEnvironment) {}, + moduleDone: function moduleDone(name, failures, total) {} +}; + +// Maintain internal state +var config = { + // The queue of tests to run + queue: [], + + // block until document ready + blocking: true +}; + +// Load paramaters +(function() { + var location = window.location || { search: "", protocol: "file:" }, + GETParams = location.search.slice(1).split('&'); + + for ( var i = 0; i < GETParams.length; i++ ) { + GETParams[i] = decodeURIComponent( GETParams[i] ); + if ( GETParams[i] === "noglobals" ) { + GETParams.splice( i, 1 ); + i--; + config.noglobals = true; + } + } + + // restrict modules/tests by get parameters + config.filters = GETParams; + + // Figure out if we're running the tests from a server or not + QUnit.isLocal = !!(location.protocol === 'file:'); +})(); + +// Expose the API as global variables, unless an 'exports' +// object exists, in that case we assume we're in CommonJS +if ( typeof exports === "undefined" || typeof require === "undefined" ) { + extend(window, QUnit); + window.QUnit = QUnit; +} else { + extend(exports, QUnit); + exports.QUnit = QUnit; +} + +if ( typeof document === "undefined" || document.readyState === "complete" ) { + config.autorun = true; +} + +addEvent(window, "load", function() { + // Initialize the config, saving the execution queue + var oldconfig = extend({}, config); + QUnit.init(); + extend(config, oldconfig); + + config.blocking = false; + + var userAgent = id("qunit-userAgent"); + if ( userAgent ) { + userAgent.innerHTML = navigator.userAgent; + } + + var toolbar = id("qunit-testrunner-toolbar"); + if ( toolbar ) { + toolbar.style.display = "none"; + + var filter = document.createElement("input"); + filter.type = "checkbox"; + filter.id = "qunit-filter-pass"; + filter.disabled = true; + addEvent( filter, "click", function() { + var li = document.getElementsByTagName("li"); + for ( var i = 0; i < li.length; i++ ) { + if ( li[i].className.indexOf("pass") > -1 ) { + li[i].style.display = filter.checked ? "none" : "block"; + } + } + }); + toolbar.appendChild( filter ); + + var label = document.createElement("label"); + label.setAttribute("for", "filter-pass"); + label.innerHTML = "Hide passed tests"; + toolbar.appendChild( label ); + + var missing = document.createElement("input"); + missing.type = "checkbox"; + missing.id = "qunit-filter-missing"; + missing.disabled = true; + addEvent( missing, "click", function() { + var li = document.getElementsByTagName("li"); + for ( var i = 0; i < li.length; i++ ) { + if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) { + li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block"; + } + } + }); + toolbar.appendChild( missing ); + + label = document.createElement("label"); + label.setAttribute("for", "filter-missing"); + label.innerHTML = "Hide missing tests (untested code is broken code)"; + toolbar.appendChild( label ); + } + + var main = id('main'); + if ( main ) { + config.fixture = main.innerHTML; + } + + if ( window.jQuery ) { + config.ajaxSettings = window.jQuery.ajaxSettings; + } + + QUnit.start(); +}); + +function done() { + if ( config.doneTimer && window.clearTimeout ) { + window.clearTimeout( config.doneTimer ); + config.doneTimer = null; + } + + if ( config.queue.length ) { + config.doneTimer = window.setTimeout(function(){ + if ( !config.queue.length ) { + done(); + } else { + synchronize( done ); + } + }, 13); + + return; + } + + config.autorun = true; + + // Log the last module results + if ( config.currentModule ) { + QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); + } + + var banner = id("qunit-banner"), + tests = id("qunit-tests"), + html = ['Tests completed in ', + +new Date - config.started, ' milliseconds.
    ', + '', config.stats.all - config.stats.bad, ' tests of ', config.stats.all, ' passed, ', config.stats.bad,' failed.'].join(''); + + if ( banner ) { + banner.className += " " + (config.stats.bad ? "fail" : "pass"); + } + + if ( tests ) { + var result = id("qunit-testresult"); + + if ( !result ) { + result = document.createElement("p"); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore( result, tests.nextSibling ); + } + + result.innerHTML = html; + } + + QUnit.done( config.stats.bad, config.stats.all ); +} + +function validTest( name ) { + var i = config.filters.length, + run = false; + + if ( !i ) { + return true; + } + + while ( i-- ) { + var filter = config.filters[i], + not = filter.charAt(0) == '!'; + + if ( not ) { + filter = filter.slice(1); + } + + if ( name.indexOf(filter) !== -1 ) { + return !not; + } + + if ( not ) { + run = true; + } + } + + return run; +} + +function push(result, actual, expected, message) { + message = message || (result ? "okay" : "failed"); + QUnit.ok( result, result ? message + ": " + expected : message + ", expected: " + QUnit.jsDump.parse(expected) + " result: " + QUnit.jsDump.parse(actual) ); +} + +function synchronize( callback ) { + config.queue.push( callback ); + + if ( config.autorun && !config.blocking ) { + process(); + } +} + +function process() { + while ( config.queue.length && !config.blocking ) { + config.queue.shift()(); + } +} + +function saveGlobal() { + config.pollution = []; + + if ( config.noglobals ) { + for ( var key in window ) { + config.pollution.push( key ); + } + } +} + +function checkPollution( name ) { + var old = config.pollution; + saveGlobal(); + + var newGlobals = diff( old, config.pollution ); + if ( newGlobals.length > 0 ) { + ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); + config.expected++; + } + + var deletedGlobals = diff( config.pollution, old ); + if ( deletedGlobals.length > 0 ) { + ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); + config.expected++; + } +} + +// returns a new Array with the elements that are in a but not in b +function diff( a, b ) { + var result = a.slice(); + for ( var i = 0; i < result.length; i++ ) { + for ( var j = 0; j < b.length; j++ ) { + if ( result[i] === b[j] ) { + result.splice(i, 1); + i--; + break; + } + } + } + return result; +} + +function fail(message, exception, callback) { + if ( typeof console !== "undefined" && console.error && console.warn ) { + console.error(message); + console.error(exception); + console.warn(callback.toString()); + + } else if ( window.opera && opera.postError ) { + opera.postError(message, exception, callback.toString); + } +} + +function extend(a, b) { + for ( var prop in b ) { + a[prop] = b[prop]; + } + + return a; +} + +function addEvent(elem, type, fn) { + if ( elem.addEventListener ) { + elem.addEventListener( type, fn, false ); + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, fn ); + } else { + fn(); + } +} + +function id(name) { + return !!(typeof document !== "undefined" && document && document.getElementById) && + document.getElementById( name ); +} + +// Test for equality any JavaScript type. +// Discussions and reference: http://philrathe.com/articles/equiv +// Test suites: http://philrathe.com/tests/equiv +// Author: Philippe Rathé +QUnit.equiv = function () { + + var innerEquiv; // the real equiv function + var callers = []; // stack to decide between skip/abort functions + + + // Determine what is o. + function hoozit(o) { + if (o.constructor === String) { + return "string"; + + } else if (o.constructor === Boolean) { + return "boolean"; + + } else if (o.constructor === Number) { + + if (isNaN(o)) { + return "nan"; + } else { + return "number"; + } + + } else if (typeof o === "undefined") { + return "undefined"; + + // consider: typeof null === object + } else if (o === null) { + return "null"; + + // consider: typeof [] === object + } else if (o instanceof Array) { + return "array"; + + // consider: typeof new Date() === object + } else if (o instanceof Date) { + return "date"; + + // consider: /./ instanceof Object; + // /./ instanceof RegExp; + // typeof /./ === "function"; // => false in IE and Opera, + // true in FF and Safari + } else if (o instanceof RegExp) { + return "regexp"; + + } else if (typeof o === "object") { + return "object"; + + } else if (o instanceof Function) { + return "function"; + } else { + return undefined; + } + } + + // Call the o related callback with the given arguments. + function handleEvents(o, callbacks, args) { + var prop = hoozit(o); + if (prop) { + if (hoozit(callbacks[prop]) === "function") { + return callbacks[prop].apply(callbacks, args); + } else { + return callbacks[prop]; // or undefined + } + } + } + + var callbacks = function () { + + // for string, boolean, number and null + function useStrictEquality(b, a) { + if (b instanceof a.constructor || a instanceof b.constructor) { + // to catch short annotaion VS 'new' annotation of a declaration + // e.g. var i = 1; + // var j = new Number(1); + return a == b; + } else { + return a === b; + } + } + + return { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + + "nan": function (b) { + return isNaN(b); + }, + + "date": function (b, a) { + return hoozit(b) === "date" && a.valueOf() === b.valueOf(); + }, + + "regexp": function (b, a) { + return hoozit(b) === "regexp" && + a.source === b.source && // the regex itself + a.global === b.global && // and its modifers (gmi) ... + a.ignoreCase === b.ignoreCase && + a.multiline === b.multiline; + }, + + // - skip when the property is a method of an instance (OOP) + // - abort otherwise, + // initial === would have catch identical references anyway + "function": function () { + var caller = callers[callers.length - 1]; + return caller !== Object && + typeof caller !== "undefined"; + }, + + "array": function (b, a) { + var i; + var len; + + // b could be an object literal here + if ( ! (hoozit(b) === "array")) { + return false; + } + + len = a.length; + if (len !== b.length) { // safe and faster + return false; + } + for (i = 0; i < len; i++) { + if ( ! innerEquiv(a[i], b[i])) { + return false; + } + } + return true; + }, + + "object": function (b, a) { + var i; + var eq = true; // unless we can proove it + var aProperties = [], bProperties = []; // collection of strings + + // comparing constructors is more strict than using instanceof + if ( a.constructor !== b.constructor) { + return false; + } + + // stack constructor before traversing properties + callers.push(a.constructor); + + for (i in a) { // be strict: don't ensures hasOwnProperty and go deep + + aProperties.push(i); // collect a's properties + + if ( ! innerEquiv(a[i], b[i])) { + eq = false; + } + } + + callers.pop(); // unstack, we are done + + for (i in b) { + bProperties.push(i); // collect b's properties + } + + // Ensures identical properties name + return eq && innerEquiv(aProperties.sort(), bProperties.sort()); + } + }; + }(); + + innerEquiv = function () { // can take multiple arguments + var args = Array.prototype.slice.apply(arguments); + if (args.length < 2) { + return true; // end transition + } + + return (function (a, b) { + if (a === b) { + return true; // catch the most you can + } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || hoozit(a) !== hoozit(b)) { + return false; // don't lose time with error prone cases + } else { + return handleEvents(a, callbacks, [b, a]); + } + + // apply transition with (1..n) arguments + })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1)); + }; + + return innerEquiv; + +}(); + +/** + * jsDump + * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php) + * Date: 5/15/2008 + * @projectDescription Advanced and extensible data dumping for Javascript. + * @version 1.0.0 + * @author Ariel Flesler + * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} + */ +QUnit.jsDump = (function() { + function quote( str ) { + return '"' + str.toString().replace(/"/g, '\\"') + '"'; + }; + function literal( o ) { + return o + ''; + }; + function join( pre, arr, post ) { + var s = jsDump.separator(), + base = jsDump.indent(), + inner = jsDump.indent(1); + if ( arr.join ) + arr = arr.join( ',' + s + inner ); + if ( !arr ) + return pre + post; + return [ pre, inner + arr, base + post ].join(s); + }; + function array( arr ) { + var i = arr.length, ret = Array(i); + this.up(); + while ( i-- ) + ret[i] = this.parse( arr[i] ); + this.down(); + return join( '[', ret, ']' ); + }; + + var reName = /^function (\w+)/; + + var jsDump = { + parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance + var parser = this.parsers[ type || this.typeOf(obj) ]; + type = typeof parser; + + return type == 'function' ? parser.call( this, obj ) : + type == 'string' ? parser : + this.parsers.error; + }, + typeOf:function( obj ) { + var type = typeof obj, + f = 'function';//we'll use it 3 times, save it + return type != 'object' && type != f ? type : + !obj ? 'null' : + obj.exec ? 'regexp' :// some browsers (FF) consider regexps functions + obj.getHours ? 'date' : + obj.scrollBy ? 'window' : + obj.nodeName == '#document' ? 'document' : + obj.nodeName ? 'node' : + obj.item ? 'nodelist' : // Safari reports nodelists as functions + obj.callee ? 'arguments' : + obj.call || obj.constructor != Array && //an array would also fall on this hack + (obj+'').indexOf(f) != -1 ? f : //IE reports functions like alert, as objects + 'length' in obj ? 'array' : + type; + }, + separator:function() { + return this.multiline ? this.HTML ? '
    ' : '\n' : this.HTML ? ' ' : ' '; + }, + indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing + if ( !this.multiline ) + return ''; + var chr = this.indentChar; + if ( this.HTML ) + chr = chr.replace(/\t/g,' ').replace(/ /g,' '); + return Array( this._depth_ + (extra||0) ).join(chr); + }, + up:function( a ) { + this._depth_ += a || 1; + }, + down:function( a ) { + this._depth_ -= a || 1; + }, + setParser:function( name, parser ) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote:quote, + literal:literal, + join:join, + // + _depth_: 1, + // This is the list of parsers, to modify them, use jsDump.setParser + parsers:{ + window: '[Window]', + document: '[Document]', + error:'[ERROR]', //when no parser is found, shouldn't happen + unknown: '[Unknown]', + 'null':'null', + undefined:'undefined', + 'function':function( fn ) { + var ret = 'function', + name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE + if ( name ) + ret += ' ' + name; + ret += '('; + + ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join(''); + return join( ret, this.parse(fn,'functionCode'), '}' ); + }, + array: array, + nodelist: array, + arguments: array, + object:function( map ) { + var ret = [ ]; + this.up(); + for ( var key in map ) + ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) ); + this.down(); + return join( '{', ret, '}' ); + }, + node:function( node ) { + var open = this.HTML ? '<' : '<', + close = this.HTML ? '>' : '>'; + + var tag = node.nodeName.toLowerCase(), + ret = open + tag; + + for ( var a in this.DOMAttrs ) { + var val = node[this.DOMAttrs[a]]; + if ( val ) + ret += ' ' + a + '=' + this.parse( val, 'attribute' ); + } + return ret + close + open + '/' + tag + close; + }, + functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function + var l = fn.length; + if ( !l ) return ''; + + var args = Array(l); + while ( l-- ) + args[l] = String.fromCharCode(97+l);//97 is 'a' + return ' ' + args.join(', ') + ' '; + }, + key:quote, //object calls it internally, the key part of an item in a map + functionCode:'[code]', //function calls it internally, it's the content of the function + attribute:quote, //node calls it internally, it's an html attribute value + string:quote, + date:quote, + regexp:literal, //regex + number:literal, + 'boolean':literal + }, + DOMAttrs:{//attributes to dump from nodes, name=>realName + id:'id', + name:'name', + 'class':'className' + }, + HTML:true,//if true, entities are escaped ( <, >, \t, space and \n ) + indentChar:' ',//indentation unit + multiline:true //if true, items in a collection, are separated by a \n, else just a space. + }; + + return jsDump; +})(); + +})(this);/* + * QUnit - A JavaScript Unit Testing Framework + * + * http://docs.jquery.com/QUnit + * + * Copyright (c) 2009 John Resig, Jörn Zaefferer + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ + +(function(window) { + +var defined = { + setTimeout: typeof window.setTimeout !== "undefined", + sessionStorage: (function() { + try { + return !!sessionStorage.getItem; + } catch(e){ + return false; + } + })() +} + +var testId = 0; + +var Test = function(name, testName, expected, testEnvironmentArg, async, callback) { + this.name = name; + this.testName = testName; + this.expected = expected; + this.testEnvironmentArg = testEnvironmentArg; + this.async = async; + this.callback = callback; + this.assertions = []; +}; +Test.prototype = { + init: function() { + var tests = id("qunit-tests"); + if (tests) { + var b = document.createElement("strong"); + b.innerHTML = "Running " + this.name; + var li = document.createElement("li"); + li.appendChild( b ); + li.id = this.id = "test-output" + testId++; + tests.appendChild( li ); + } + }, + setup: function() { + if (this.module != config.previousModule) { + if ( this.previousModule ) { + QUnit.moduleDone( this.module, config.moduleStats.bad, config.moduleStats.all ); + } + config.previousModule = this.module; + config.moduleStats = { all: 0, bad: 0 }; + QUnit.moduleStart( this.module, this.moduleTestEnvironment ); + } + + config.current = this; + this.testEnvironment = extend({ + setup: function() {}, + teardown: function() {} + }, this.moduleTestEnvironment); + if (this.testEnvironmentArg) { + extend(this.testEnvironment, this.testEnvironmentArg); + } + + QUnit.testStart( this.testName, this.testEnvironment ); + + // allow utility functions to access the current test environment + // TODO why?? + QUnit.current_testEnvironment = this.testEnvironment; + + try { + if ( !config.pollution ) { + saveGlobal(); + } + + this.testEnvironment.setup.call(this.testEnvironment); + } catch(e) { + // TODO use testName instead of name for no-markup message? + QUnit.ok( false, "Setup failed on " + this.name + ": " + e.message ); + } + }, + run: function() { + if ( this.async ) { + QUnit.stop(); + } + + try { + this.callback.call(this.testEnvironment); + } catch(e) { + // TODO use testName instead of name for no-markup message? + fail("Test " + this.name + " died, exception and test follows", e, this.callback); + QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) ); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if ( config.blocking ) { + start(); + } + } + }, + teardown: function() { + try { + checkPollution(); + this.testEnvironment.teardown.call(this.testEnvironment); + } catch(e) { + // TODO use testName instead of name for no-markup message? + QUnit.ok( false, "Teardown failed on " + this.name + ": " + e.message ); + } + }, + finish: function() { + if ( this.expected && this.expected != this.assertions.length ) { + QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); + } + + var good = 0, bad = 0, + tests = id("qunit-tests"); + + config.stats.all += this.assertions.length; + config.moduleStats.all += this.assertions.length; + + if ( tests ) { + var ol = document.createElement("ol"); + + for ( var i = 0; i < this.assertions.length; i++ ) { + var assertion = this.assertions[i]; + + var li = document.createElement("li"); + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); + ol.appendChild( li ); + + if ( assertion.result ) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + + // store result when possible + defined.sessionStorage && sessionStorage.setItem("qunit-" + this.testName, bad); + + if (bad == 0) { + ol.style.display = "none"; + } + + var b = document.createElement("strong"); + b.innerHTML = this.name + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; + + addEvent(b, "click", function() { + var next = b.nextSibling, display = next.style.display; + next.style.display = display === "none" ? "block" : "none"; + }); + + addEvent(b, "dblclick", function(e) { + var target = e && e.target ? e.target : window.event.srcElement; + if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { + target = target.parentNode; + } + if ( window.location && target.nodeName.toLowerCase() === "strong" ) { + window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, "")); + } + }); + + var li = id(this.id); + li.className = bad ? "fail" : "pass"; + li.style.display = resultDisplayStyle(!bad); + li.removeChild( li.firstChild ); + li.appendChild( b ); + li.appendChild( ol ); + + if ( bad ) { + var toolbar = id("qunit-testrunner-toolbar"); + if ( toolbar ) { + toolbar.style.display = "block"; + id("qunit-filter-pass").disabled = null; + } + } + + } else { + for ( var i = 0; i < this.assertions.length; i++ ) { + if ( !this.assertions[i].result ) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + } + + try { + QUnit.reset(); + } catch(e) { + // TODO use testName instead of name for no-markup message? + fail("reset() failed, following Test " + this.name + ", exception and reset fn follows", e, QUnit.reset); + } + + QUnit.testDone( this.testName, bad, this.assertions.length ); + }, + + queue: function() { + var test = this; + synchronize(function() { + test.init(); + }); + function run() { + // each of these can by async + synchronize(function() { + test.setup(); + }); + synchronize(function() { + test.run(); + }); + synchronize(function() { + test.teardown(); + }); + synchronize(function() { + test.finish(); + }); + } + // defer when previous test run passed, if storage is available + var bad = defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.testName); + if (bad) { + run(); + } else { + synchronize(run); + }; + } + +} + +var QUnit = { + + // call on start of module test to prepend name to all tests + module: function(name, testEnvironment) { + config.previousModule = config.currentModule; + config.currentModule = name; + config.currentModuleTestEnviroment = testEnvironment; + }, + + asyncTest: function(testName, expected, callback) { + if ( arguments.length === 2 ) { + callback = expected; + expected = 0; + } + + QUnit.test(testName, expected, callback, true); + }, + + test: function(testName, expected, callback, async) { + var name = '' + testName + '', testEnvironmentArg; + + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + // is 2nd argument a testEnvironment? + if ( expected && typeof expected === 'object') { + testEnvironmentArg = expected; + expected = null; + } + + if ( config.currentModule ) { + name = '' + config.currentModule + ": " + name; + } + + if ( !validTest(config.currentModule + ": " + testName) ) { + return; + } + + var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); + test.previousModule = config.previousModule; + test.module = config.currentModule; + test.moduleTestEnvironment = config.currentModuleTestEnviroment; + test.queue(); + }, + + /** + * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. + */ + expect: function(asserts) { + config.current.expected = asserts; + }, + + /** + * Asserts true. + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); + */ + ok: function(a, msg) { + a = !!a; + var details = { + result: a, + message: msg + }; + msg = escapeHtml(msg); + QUnit.log(a, msg, details); + config.current.assertions.push({ + result: a, + message: msg + }); + }, + + /** + * Checks that the first two arguments are equal, with an optional message. + * Prints out both actual and expected values. + * + * Prefered to ok( actual == expected, message ) + * + * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); + * + * @param Object actual + * @param Object expected + * @param String message (optional) + */ + equal: function(actual, expected, message) { + QUnit.push(expected == actual, actual, expected, message); + }, + + notEqual: function(actual, expected, message) { + QUnit.push(expected != actual, actual, expected, message); + }, + + deepEqual: function(actual, expected, message) { + QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); + }, + + notDeepEqual: function(actual, expected, message) { + QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); + }, + + strictEqual: function(actual, expected, message) { + QUnit.push(expected === actual, actual, expected, message); + }, + + notStrictEqual: function(actual, expected, message) { + QUnit.push(expected !== actual, actual, expected, message); + }, + + raises: function(block, expected, message) { + var actual, ok = false; + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + if (actual) { + // we don't want to validate thrown error + if (!expected) { + ok = true; + // expected is a regexp + } else if (QUnit.objectType(expected) === "regexp") { + ok = expected.test(actual); + // expected is a constructor + } else if (actual instanceof expected) { + ok = true; + // expected is a validation function which returns true is validation passed + } else if (expected.call({}, actual) === true) { + ok = true; + } + } + + QUnit.ok(ok, message); + }, + + start: function() { + // A slight delay, to avoid any current callbacks + if ( defined.setTimeout ) { + window.setTimeout(function() { + if ( config.timeout ) { + clearTimeout(config.timeout); + } + + config.blocking = false; + process(); + }, 13); + } else { + config.blocking = false; + process(); + } + }, + + stop: function(timeout) { + config.blocking = true; + + if ( timeout && defined.setTimeout ) { + config.timeout = window.setTimeout(function() { + QUnit.ok( false, "Test timed out" ); + QUnit.start(); + }, timeout); + } + } + +}; + +// Backwards compatibility, deprecated +QUnit.equals = QUnit.equal; +QUnit.same = QUnit.deepEqual; + +// Maintain internal state +var config = { + // The queue of tests to run + queue: [], + + // block until document ready + blocking: true +}; + +// Load paramaters +(function() { + var location = window.location || { search: "", protocol: "file:" }, + GETParams = location.search.slice(1).split('&'); + + for ( var i = 0; i < GETParams.length; i++ ) { + GETParams[i] = decodeURIComponent( GETParams[i] ); + if ( GETParams[i] === "noglobals" ) { + GETParams.splice( i, 1 ); + i--; + config.noglobals = true; + } else if ( GETParams[i].search('=') > -1 ) { + GETParams.splice( i, 1 ); + i--; + } + } + + // restrict modules/tests by get parameters + config.filters = GETParams; + + // Figure out if we're running the tests from a server or not + QUnit.isLocal = !!(location.protocol === 'file:'); +})(); + +// Expose the API as global variables, unless an 'exports' +// object exists, in that case we assume we're in CommonJS +if ( typeof exports === "undefined" || typeof require === "undefined" ) { + extend(window, QUnit); + window.QUnit = QUnit; +} else { + extend(exports, QUnit); + exports.QUnit = QUnit; +} + +// define these after exposing globals to keep them in these QUnit namespace only +extend(QUnit, { + config: config, + + // Initialize the configuration options + init: function() { + extend(config, { + stats: { all: 0, bad: 0 }, + moduleStats: { all: 0, bad: 0 }, + started: +new Date, + updateRate: 1000, + blocking: false, + autostart: true, + autorun: false, + filters: [], + queue: [] + }); + + var tests = id("qunit-tests"), + banner = id("qunit-banner"), + result = id("qunit-testresult"); + + if ( tests ) { + tests.innerHTML = ""; + } + + if ( banner ) { + banner.className = ""; + } + + if ( result ) { + result.parentNode.removeChild( result ); + } + }, + + /** + * Resets the test setup. Useful for tests that modify the DOM. + * + * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. + */ + reset: function() { + if ( window.jQuery ) { + jQuery( "#main, #qunit-fixture" ).html( config.fixture ); + } else { + var main = id( 'main' ) || id( 'qunit-fixture' ); + if ( main ) { + main.innerHTML = config.fixture; + } + } + }, + + /** + * Trigger an event on an element. + * + * @example triggerEvent( document.body, "click" ); + * + * @param DOMElement elem + * @param String type + */ + triggerEvent: function( elem, type, event ) { + if ( document.createEvent ) { + event = document.createEvent("MouseEvents"); + event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent( event ); + + } else if ( elem.fireEvent ) { + elem.fireEvent("on"+type); + } + }, + + // Safe object type checking + is: function( type, obj ) { + return QUnit.objectType( obj ) == type; + }, + + objectType: function( obj ) { + if (typeof obj === "undefined") { + return "undefined"; + + // consider: typeof null === object + } + if (obj === null) { + return "null"; + } + + var type = Object.prototype.toString.call( obj ) + .match(/^\[object\s(.*)\]$/)[1] || ''; + + switch (type) { + case 'Number': + if (isNaN(obj)) { + return "nan"; + } else { + return "number"; + } + case 'String': + case 'Boolean': + case 'Array': + case 'Date': + case 'RegExp': + case 'Function': + return type.toLowerCase(); + } + if (typeof obj === "object") { + return "object"; + } + return undefined; + }, + + push: function(result, actual, expected, message) { + var details = { + result: result, + message: message, + actual: actual, + expected: expected + }; + + message = escapeHtml(message) || (result ? "okay" : "failed"); + message = '' + message + ""; + expected = escapeHtml(QUnit.jsDump.parse(expected)); + actual = escapeHtml(QUnit.jsDump.parse(actual)); + var output = message + ''; + if (actual != expected) { + output += ''; + output += ''; + } + if (!result) { + var source = sourceFromStacktrace(); + if (source) { + details.source = source; + output += ''; + } + } + output += "
    Expected:
    ' + expected + '
    Result:
    ' + actual + '
    Diff:
    ' + QUnit.diff(expected, actual) +'
    Source:
    ' + source +'
    "; + + QUnit.log(result, message, details); + + config.current.assertions.push({ + result: !!result, + message: output + }); + }, + + // Logging callbacks + begin: function() {}, + done: function(failures, total) {}, + log: function(result, message) {}, + testStart: function(name, testEnvironment) {}, + testDone: function(name, failures, total) {}, + moduleStart: function(name, testEnvironment) {}, + moduleDone: function(name, failures, total) {} +}); + +if ( typeof document === "undefined" || document.readyState === "complete" ) { + config.autorun = true; +} + +addEvent(window, "load", function() { + QUnit.begin(); + + // Initialize the config, saving the execution queue + var oldconfig = extend({}, config); + QUnit.init(); + extend(config, oldconfig); + + config.blocking = false; + + var userAgent = id("qunit-userAgent"); + if ( userAgent ) { + userAgent.innerHTML = navigator.userAgent; + } + var banner = id("qunit-header"); + if ( banner ) { + var paramsIndex = location.href.lastIndexOf(location.search); + if ( paramsIndex > -1 ) { + var mainPageLocation = location.href.slice(0, paramsIndex); + if ( mainPageLocation == location.href ) { + banner.innerHTML = ' ' + banner.innerHTML + ' '; + } else { + var testName = decodeURIComponent(location.search.slice(1)); + banner.innerHTML = '' + banner.innerHTML + '' + testName + ''; + } + } + } + + var toolbar = id("qunit-testrunner-toolbar"); + if ( toolbar ) { + toolbar.style.display = "none"; + + var filter = document.createElement("input"); + filter.type = "checkbox"; + filter.id = "qunit-filter-pass"; + filter.disabled = true; + addEvent( filter, "click", function() { + var li = document.getElementsByTagName("li"); + for ( var i = 0; i < li.length; i++ ) { + if ( li[i].className.indexOf("pass") > -1 ) { + li[i].style.display = filter.checked ? "none" : ""; + } + } + }); + toolbar.appendChild( filter ); + + var label = document.createElement("label"); + label.setAttribute("for", "qunit-filter-pass"); + label.innerHTML = "Hide passed tests"; + toolbar.appendChild( label ); + } + + var main = id('main') || id('qunit-fixture'); + if ( main ) { + config.fixture = main.innerHTML; + } + + if (config.autostart) { + QUnit.start(); + } +}); + +function done() { + config.autorun = true; + + // Log the last module results + if ( config.currentModule ) { + QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all ); + } + + var banner = id("qunit-banner"), + tests = id("qunit-tests"), + html = ['Tests completed in ', + +new Date - config.started, ' milliseconds.
    ', + '', config.stats.all - config.stats.bad, ' tests of ', config.stats.all, ' passed, ', config.stats.bad,' failed.'].join(''); + + if ( banner ) { + banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); + } + + if ( tests ) { + var result = id("qunit-testresult"); + + if ( !result ) { + result = document.createElement("p"); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore( result, tests.nextSibling ); + } + + result.innerHTML = html; + } + + QUnit.done( config.stats.bad, config.stats.all ); +} + +function validTest( name ) { + var i = config.filters.length, + run = false; + + if ( !i ) { + return true; + } + + while ( i-- ) { + var filter = config.filters[i], + not = filter.charAt(0) == '!'; + + if ( not ) { + filter = filter.slice(1); + } + + if ( name.indexOf(filter) !== -1 ) { + return !not; + } + + if ( not ) { + run = true; + } + } + + return run; +} + +// so far supports only Firefox, Chrome and Opera (buggy) +// could be extended in the future to use something like https://github.com/csnover/TraceKit +function sourceFromStacktrace() { + try { + throw new Error(); + } catch ( e ) { + if (e.stacktrace) { + // Opera + return e.stacktrace.split("\n")[6]; + } else if (e.stack) { + // Firefox, Chrome + return e.stack.split("\n")[4]; + } + } +} + +function resultDisplayStyle(passed) { + return passed && id("qunit-filter-pass") && id("qunit-filter-pass").checked ? 'none' : ''; +} + +function escapeHtml(s) { + if (!s) { + return ""; + } + s = s + ""; + return s.replace(/[\&"<>\\]/g, function(s) { + switch(s) { + case "&": return "&"; + case "\\": return "\\\\"; + case '"': return '\"'; + case "<": return "<"; + case ">": return ">"; + default: return s; + } + }); +} + +function synchronize( callback ) { + config.queue.push( callback ); + + if ( config.autorun && !config.blocking ) { + process(); + } +} + +function process() { + var start = (new Date()).getTime(); + + while ( config.queue.length && !config.blocking ) { + if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) { + config.queue.shift()(); + } else { + window.setTimeout( process, 13 ); + break; + } + } + if (!config.blocking && !config.queue.length) { + done(); + } +} + +function saveGlobal() { + config.pollution = []; + + if ( config.noglobals ) { + for ( var key in window ) { + config.pollution.push( key ); + } + } +} + +function checkPollution( name ) { + var old = config.pollution; + saveGlobal(); + + var newGlobals = diff( old, config.pollution ); + if ( newGlobals.length > 0 ) { + ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); + config.current.expected++; + } + + var deletedGlobals = diff( config.pollution, old ); + if ( deletedGlobals.length > 0 ) { + ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); + config.current.expected++; + } +} + +// returns a new Array with the elements that are in a but not in b +function diff( a, b ) { + var result = a.slice(); + for ( var i = 0; i < result.length; i++ ) { + for ( var j = 0; j < b.length; j++ ) { + if ( result[i] === b[j] ) { + result.splice(i, 1); + i--; + break; + } + } + } + return result; +} + +function fail(message, exception, callback) { + if ( typeof console !== "undefined" && console.error && console.warn ) { + console.error(message); + console.error(exception); + console.warn(callback.toString()); + + } else if ( window.opera && opera.postError ) { + opera.postError(message, exception, callback.toString); + } +} + +function extend(a, b) { + for ( var prop in b ) { + a[prop] = b[prop]; + } + + return a; +} + +function addEvent(elem, type, fn) { + if ( elem.addEventListener ) { + elem.addEventListener( type, fn, false ); + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, fn ); + } else { + fn(); + } +} + +function id(name) { + return !!(typeof document !== "undefined" && document && document.getElementById) && + document.getElementById( name ); +} + +// Test for equality any JavaScript type. +// Discussions and reference: http://philrathe.com/articles/equiv +// Test suites: http://philrathe.com/tests/equiv +// Author: Philippe Rathé +QUnit.equiv = function () { + + var innerEquiv; // the real equiv function + var callers = []; // stack to decide between skip/abort functions + var parents = []; // stack to avoiding loops from circular referencing + + // Call the o related callback with the given arguments. + function bindCallbacks(o, callbacks, args) { + var prop = QUnit.objectType(o); + if (prop) { + if (QUnit.objectType(callbacks[prop]) === "function") { + return callbacks[prop].apply(callbacks, args); + } else { + return callbacks[prop]; // or undefined + } + } + } + + var callbacks = function () { + + // for string, boolean, number and null + function useStrictEquality(b, a) { + if (b instanceof a.constructor || a instanceof b.constructor) { + // to catch short annotaion VS 'new' annotation of a declaration + // e.g. var i = 1; + // var j = new Number(1); + return a == b; + } else { + return a === b; + } + } + + return { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + + "nan": function (b) { + return isNaN(b); + }, + + "date": function (b, a) { + return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); + }, + + "regexp": function (b, a) { + return QUnit.objectType(b) === "regexp" && + a.source === b.source && // the regex itself + a.global === b.global && // and its modifers (gmi) ... + a.ignoreCase === b.ignoreCase && + a.multiline === b.multiline; + }, + + // - skip when the property is a method of an instance (OOP) + // - abort otherwise, + // initial === would have catch identical references anyway + "function": function () { + var caller = callers[callers.length - 1]; + return caller !== Object && + typeof caller !== "undefined"; + }, + + "array": function (b, a) { + var i, j, loop; + var len; + + // b could be an object literal here + if ( ! (QUnit.objectType(b) === "array")) { + return false; + } + + len = a.length; + if (len !== b.length) { // safe and faster + return false; + } + + //track reference to avoid circular references + parents.push(a); + for (i = 0; i < len; i++) { + loop = false; + for(j=0;j= 0) { + type = "array"; + } else { + type = typeof obj; + } + return type; + }, + separator:function() { + return this.multiline ? this.HTML ? '
    ' : '\n' : this.HTML ? ' ' : ' '; + }, + indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing + if ( !this.multiline ) + return ''; + var chr = this.indentChar; + if ( this.HTML ) + chr = chr.replace(/\t/g,' ').replace(/ /g,' '); + return Array( this._depth_ + (extra||0) ).join(chr); + }, + up:function( a ) { + this._depth_ += a || 1; + }, + down:function( a ) { + this._depth_ -= a || 1; + }, + setParser:function( name, parser ) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote:quote, + literal:literal, + join:join, + // + _depth_: 1, + // This is the list of parsers, to modify them, use jsDump.setParser + parsers:{ + window: '[Window]', + document: '[Document]', + error:'[ERROR]', //when no parser is found, shouldn't happen + unknown: '[Unknown]', + 'null':'null', + undefined:'undefined', + 'function':function( fn ) { + var ret = 'function', + name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE + if ( name ) + ret += ' ' + name; + ret += '('; + + ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); + return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); + }, + array: array, + nodelist: array, + arguments: array, + object:function( map ) { + var ret = [ ]; + QUnit.jsDump.up(); + for ( var key in map ) + ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) ); + QUnit.jsDump.down(); + return join( '{', ret, '}' ); + }, + node:function( node ) { + var open = QUnit.jsDump.HTML ? '<' : '<', + close = QUnit.jsDump.HTML ? '>' : '>'; + + var tag = node.nodeName.toLowerCase(), + ret = open + tag; + + for ( var a in QUnit.jsDump.DOMAttrs ) { + var val = node[QUnit.jsDump.DOMAttrs[a]]; + if ( val ) + ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' ); + } + return ret + close + open + '/' + tag + close; + }, + functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function + var l = fn.length; + if ( !l ) return ''; + + var args = Array(l); + while ( l-- ) + args[l] = String.fromCharCode(97+l);//97 is 'a' + return ' ' + args.join(', ') + ' '; + }, + key:quote, //object calls it internally, the key part of an item in a map + functionCode:'[code]', //function calls it internally, it's the content of the function + attribute:quote, //node calls it internally, it's an html attribute value + string:quote, + date:quote, + regexp:literal, //regex + number:literal, + 'boolean':literal + }, + DOMAttrs:{//attributes to dump from nodes, name=>realName + id:'id', + name:'name', + 'class':'className' + }, + HTML:false,//if true, entities are escaped ( <, >, \t, space and \n ) + indentChar:' ',//indentation unit + multiline:true //if true, items in a collection, are separated by a \n, else just a space. + }; + + return jsDump; +})(); + +// from Sizzle.js +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +}; + +/* + * Javascript Diff Algorithm + * By John Resig (http://ejohn.org/) + * Modified by Chu Alan "sprite" + * + * Released under the MIT license. + * + * More Info: + * http://ejohn.org/projects/javascript-diff-algorithm/ + * + * Usage: QUnit.diff(expected, actual) + * + * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick brown fox jumped jumps over" + */ +QUnit.diff = (function() { + function diff(o, n){ + var ns = new Object(); + var os = new Object(); + + for (var i = 0; i < n.length; i++) { + if (ns[n[i]] == null) + ns[n[i]] = { + rows: new Array(), + o: null + }; + ns[n[i]].rows.push(i); + } + + for (var i = 0; i < o.length; i++) { + if (os[o[i]] == null) + os[o[i]] = { + rows: new Array(), + n: null + }; + os[o[i]].rows.push(i); + } + + for (var i in ns) { + if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { + n[ns[i].rows[0]] = { + text: n[ns[i].rows[0]], + row: os[i].rows[0] + }; + o[os[i].rows[0]] = { + text: o[os[i].rows[0]], + row: ns[i].rows[0] + }; + } + } + + for (var i = 0; i < n.length - 1; i++) { + if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && + n[i + 1] == o[n[i].row + 1]) { + n[i + 1] = { + text: n[i + 1], + row: n[i].row + 1 + }; + o[n[i].row + 1] = { + text: o[n[i].row + 1], + row: i + 1 + }; + } + } + + for (var i = n.length - 1; i > 0; i--) { + if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && + n[i - 1] == o[n[i].row - 1]) { + n[i - 1] = { + text: n[i - 1], + row: n[i].row - 1 + }; + o[n[i].row - 1] = { + text: o[n[i].row - 1], + row: i - 1 + }; + } + } + + return { + o: o, + n: n + }; + } + + return function(o, n){ + o = o.replace(/\s+$/, ''); + n = n.replace(/\s+$/, ''); + var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); + + var str = ""; + + var oSpace = o.match(/\s+/g); + if (oSpace == null) { + oSpace = [" "]; + } + else { + oSpace.push(" "); + } + var nSpace = n.match(/\s+/g); + if (nSpace == null) { + nSpace = [" "]; + } + else { + nSpace.push(" "); + } + + if (out.n.length == 0) { + for (var i = 0; i < out.o.length; i++) { + str += '' + out.o[i] + oSpace[i] + ""; + } + } + else { + if (out.n[0].text == null) { + for (n = 0; n < out.o.length && out.o[n].text == null; n++) { + str += '' + out.o[n] + oSpace[n] + ""; + } + } + + for (var i = 0; i < out.n.length; i++) { + if (out.n[i].text == null) { + str += '' + out.n[i] + nSpace[i] + ""; + } + else { + var pre = ""; + + for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { + pre += '' + out.o[n] + oSpace[n] + ""; + } + str += " " + out.n[i].text + nSpace[i] + pre; + } + } + } + + return str; + }; +})(); + +})(this); \ No newline at end of file diff --git a/node_modules/piler/node_modules/underscore.string/test/underscore.js b/node_modules/piler/node_modules/underscore.string/test/underscore.js new file mode 100644 index 0000000..e4a0aba --- /dev/null +++ b/node_modules/piler/node_modules/underscore.string/test/underscore.js @@ -0,0 +1,999 @@ +// Underscore.js 1.3.1 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var slice = ArrayProto.slice, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root['_'] = _; + } + + // Current version. + _.VERSION = '1.3.1'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + if (obj.length === +obj.length) results.length = obj.length; + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (_.isFunction(method) ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + if (_.isArray(iterable)) return slice.call(iterable); + if (_.isArguments(iterable)) return slice.call(iterable); + return _.values(iterable); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.toArray(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head`. The **guard** check allows it to work + // with `_.map`. + _.first = _.head = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } + return memo; + }, []); + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = _.flatten(slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(func, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. + _.debounce = function(func, wait) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func].concat(slice.call(arguments, 0)); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType == 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return obj !== obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Has own property? + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = idCounter++; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /.^/; + + // Within an interpolation, evaluation, or escaping, remove HTML escaping + // that had been previously added. + var unescape = function(code) { + return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'"); + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(str, data) { + var c = _.templateSettings; + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + + 'with(obj||{}){__p.push(\'' + + str.replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(c.escape || noMatch, function(match, code) { + return "',_.escape(" + unescape(code) + "),'"; + }) + .replace(c.interpolate || noMatch, function(match, code) { + return "'," + unescape(code) + ",'"; + }) + .replace(c.evaluate || noMatch, function(match, code) { + return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('"; + }) + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + + "');}return __p.join('');"; + var func = new Function('obj', '_', tmpl); + if (data) return func(data, _); + return function(data) { + return func.call(this, data, _); + }; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // The OOP Wrapper + // --------------- + + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + var wrapped = this._wrapped; + method.apply(wrapped, arguments); + var length = wrapped.length; + if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0]; + return result(wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); \ No newline at end of file diff --git a/node_modules/piler/node_modules/underscore/.npmignore b/node_modules/piler/node_modules/underscore/.npmignore new file mode 100644 index 0000000..2ce2684 --- /dev/null +++ b/node_modules/piler/node_modules/underscore/.npmignore @@ -0,0 +1,3 @@ +test/ +Rakefile +docs/ \ No newline at end of file diff --git a/node_modules/piler/node_modules/underscore/CNAME b/node_modules/piler/node_modules/underscore/CNAME new file mode 100644 index 0000000..a007e65 --- /dev/null +++ b/node_modules/piler/node_modules/underscore/CNAME @@ -0,0 +1 @@ +underscorejs.org diff --git a/node_modules/piler/node_modules/underscore/LICENSE b/node_modules/piler/node_modules/underscore/LICENSE new file mode 100644 index 0000000..61d28c0 --- /dev/null +++ b/node_modules/piler/node_modules/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud + +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. \ No newline at end of file diff --git a/node_modules/piler/node_modules/underscore/README.md b/node_modules/piler/node_modules/underscore/README.md new file mode 100644 index 0000000..a6564a2 --- /dev/null +++ b/node_modules/piler/node_modules/underscore/README.md @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ + /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ + \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore.js is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://documentcloud.github.com/underscore/ + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/node_modules/piler/node_modules/underscore/favicon.ico b/node_modules/piler/node_modules/underscore/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..03049683875ee7207b4ee62241fc6977956723c7 GIT binary patch literal 1406 zcmZQzU<5(|0R|w+!H~hqz#zuJz@P!dKp_SNAO?x!16vCj7#y|msTh?T4S~@R7;Yi( a|NnmmMkru{0(Aax^D{300E2>o91H*{%ptM> literal 0 HcmV?d00001 diff --git a/node_modules/piler/node_modules/underscore/index.html b/node_modules/piler/node_modules/underscore/index.html new file mode 100644 index 0000000..01c18ac --- /dev/null +++ b/node_modules/piler/node_modules/underscore/index.html @@ -0,0 +1,2109 @@ + + + + + + + Underscore.js + + + + + + +
    + +

    + Underscore.js +

    + +

    + Underscore is a + utility-belt library for JavaScript that provides a lot of the + functional programming support that you would expect in + Prototype.js + (or Ruby), + but without extending any of the built-in JavaScript objects. It's the + tie to go along with jQuery's tux, + and Backbone.js's suspenders. +

    + +

    + Underscore provides 60-odd functions that support both the usual + functional suspects: map, select, invoke — + as well as more specialized helpers: function binding, javascript + templating, deep equality testing, and so on. It delegates to built-in + functions, if present, so modern browsers will use the + native implementations of forEach, map, reduce, + filter, every, some and indexOf. +

    + +

    + A complete Test & Benchmark Suite + is included for your perusal. +

    + +

    + You may also read through the annotated source code. +

    + +

    + The project is + hosted on GitHub. + You can report bugs and discuss features on the + issues page, + on Freenode in the #documentcloud channel, + or send tweets to @documentcloud. +

    + +

    + Underscore is an open-source component of DocumentCloud. +

    + +

    Downloads (Right-click, and use "Save As")

    + + + + + + + + + + +
    Development Version (1.3.3)37kb, Uncompressed with Plentiful Comments
    Production Version (1.3.3)4kb, Minified and Gzipped
    + +
    Upgrade warning: versions 1.3.0 and higher remove AMD (RequireJS) support.
    + +
    + +

    Collection Functions (Arrays or Objects)

    + +

    + each_.each(list, iterator, [context]) + Alias: forEach +
    + Iterates over a list of elements, yielding each in turn to an iterator + function. The iterator is bound to the context object, if one is + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). Delegates to the native + forEach function if it exists. +

    +
    +_.each([1, 2, 3], function(num){ alert(num); });
    +=> alerts each number in turn...
    +_.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
    +=> alerts each number in turn...
    + +

    + map_.map(list, iterator, [context]) + Alias: collect +
    + Produces a new array of values by mapping each value in list + through a transformation function (iterator). If the native map method + exists, it will be used instead. If list is a JavaScript object, + iterator's arguments will be (value, key, list). +

    +
    +_.map([1, 2, 3], function(num){ return num * 3; });
    +=> [3, 6, 9]
    +_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
    +=> [3, 6, 9]
    + +

    + reduce_.reduce(list, iterator, memo, [context]) + Aliases: inject, foldl +
    + Also known as inject and foldl, reduce boils down a + list of values into a single value. Memo is the initial state + of the reduction, and each successive step of it should be returned by + iterator. +

    +
    +var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
    +=> 6
    +
    + +

    + reduceRight_.reduceRight(list, iterator, memo, [context]) + Alias: foldr +
    + The right-associative version of reduce. Delegates to the + JavaScript 1.8 version of reduceRight, if it exists. Foldr + is not as useful in JavaScript as it would be in a language with lazy + evaluation. +

    +
    +var list = [[0, 1], [2, 3], [4, 5]];
    +var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
    +=> [4, 5, 2, 3, 0, 1]
    +
    + +

    + find_.find(list, iterator, [context]) + Alias: detect +
    + Looks through each value in the list, returning the first one that + passes a truth test (iterator). The function returns as + soon as it finds an acceptable element, and doesn't traverse the + entire list. +

    +
    +var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    +=> 2
    +
    + +

    + filter_.filter(list, iterator, [context]) + Alias: select +
    + Looks through each value in the list, returning an array of all + the values that pass a truth test (iterator). Delegates to the + native filter method, if it exists. +

    +
    +var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    +=> [2, 4, 6]
    +
    + +

    + reject_.reject(list, iterator, [context]) +
    + Returns the values in list without the elements that the truth + test (iterator) passes. The opposite of filter. +

    +
    +var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    +=> [1, 3, 5]
    +
    + +

    + all_.all(list, iterator, [context]) + Alias: every +
    + Returns true if all of the values in the list pass the iterator + truth test. Delegates to the native method every, if present. +

    +
    +_.all([true, 1, null, 'yes'], _.identity);
    +=> false
    +
    + +

    + any_.any(list, [iterator], [context]) + Alias: some +
    + Returns true if any of the values in the list pass the + iterator truth test. Short-circuits and stops traversing the list + if a true element is found. Delegates to the native method some, + if present. +

    +
    +_.any([null, 0, 'yes', false]);
    +=> true
    +
    + +

    + include_.include(list, value) + Alias: contains +
    + Returns true if the value is present in the list, using + === to test equality. Uses indexOf internally, if list + is an Array. +

    +
    +_.include([1, 2, 3], 3);
    +=> true
    +
    + +

    + invoke_.invoke(list, methodName, [*arguments]) +
    + Calls the method named by methodName on each value in the list. + Any extra arguments passed to invoke will be forwarded on to the + method invocation. +

    +
    +_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
    +=> [[1, 5, 7], [1, 2, 3]]
    +
    + +

    + pluck_.pluck(list, propertyName) +
    + A convenient version of what is perhaps the most common use-case for + map: extracting a list of property values. +

    +
    +var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
    +_.pluck(stooges, 'name');
    +=> ["moe", "larry", "curly"]
    +
    + +

    + max_.max(list, [iterator], [context]) +
    + Returns the maximum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

    +
    +var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
    +_.max(stooges, function(stooge){ return stooge.age; });
    +=> {name : 'curly', age : 60};
    +
    + +

    + min_.min(list, [iterator], [context]) +
    + Returns the minimum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

    +
    +var numbers = [10, 5, 100, 2, 1000];
    +_.min(numbers);
    +=> 2
    +
    + +

    + sortBy_.sortBy(list, iterator, [context]) +
    + Returns a sorted copy of list, ranked in ascending order by the + results of running each value through iterator. Iterator may + also be the string name of the property to sort by (eg. length). +

    +
    +_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
    +=> [5, 4, 6, 3, 1, 2]
    +
    + +

    + groupBy_.groupBy(list, iterator) +
    + Splits a collection into sets, grouped by the result of running each + value through iterator. If iterator is a string instead of + a function, groups by the property named by iterator on each of + the values. +

    +
    +_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
    +=> {1: [1.3], 2: [2.1, 2.4]}
    +
    +_.groupBy(['one', 'two', 'three'], 'length');
    +=> {3: ["one", "two"], 5: ["three"]}
    +
    + +

    + sortedIndex_.sortedIndex(list, value, [iterator]) +
    + Uses a binary search to determine the index at which the value + should be inserted into the list in order to maintain the list's + sorted order. If an iterator is passed, it will be used to compute + the sort ranking of each value. +

    +
    +_.sortedIndex([10, 20, 30, 40, 50], 35);
    +=> 3
    +
    + +

    + shuffle_.shuffle(list) +
    + Returns a shuffled copy of the list, using a version of the + Fisher-Yates shuffle. +

    +
    +_.shuffle([1, 2, 3, 4, 5, 6]);
    +=> [4, 1, 6, 3, 5, 2]
    +
    + +

    + toArray_.toArray(list) +
    + Converts the list (anything that can be iterated over), into a + real Array. Useful for transmuting the arguments object. +

    +
    +(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
    +=> [2, 3, 4]
    +
    + +

    + size_.size(list) +
    + Return the number of values in the list. +

    +
    +_.size({one : 1, two : 2, three : 3});
    +=> 3
    +
    + +

    Array Functions

    + +

    + Note: All array functions will also work on the arguments object. +

    + +

    + first_.first(array, [n]) + Alias: head +
    + Returns the first element of an array. Passing n will + return the first n elements of the array. +

    +
    +_.first([5, 4, 3, 2, 1]);
    +=> 5
    +
    + +

    + initial_.initial(array, [n]) +
    + Returns everything but the last entry of the array. Especially useful on + the arguments object. Pass n to exclude the last n elements + from the result. +

    +
    +_.initial([5, 4, 3, 2, 1]);
    +=> [5, 4, 3, 2]
    +
    + +

    + last_.last(array, [n]) +
    + Returns the last element of an array. Passing n will return + the last n elements of the array. +

    +
    +_.last([5, 4, 3, 2, 1]);
    +=> 1
    +
    + +

    + rest_.rest(array, [index]) + Alias: tail +
    + Returns the rest of the elements in an array. Pass an index + to return the values of the array from that index onward. +

    +
    +_.rest([5, 4, 3, 2, 1]);
    +=> [4, 3, 2, 1]
    +
    + +

    + compact_.compact(array) +
    + Returns a copy of the array with all falsy values removed. + In JavaScript, false, null, 0, "", + undefined and NaN are all falsy. +

    +
    +_.compact([0, 1, false, 2, '', 3]);
    +=> [1, 2, 3]
    +
    + +

    + flatten_.flatten(array, [shallow]) +
    + Flattens a nested array (the nesting can be to any depth). If you + pass shallow, the array will only be flattened a single level. +

    +
    +_.flatten([1, [2], [3, [[4]]]]);
    +=> [1, 2, 3, 4];
    +
    +_.flatten([1, [2], [3, [[4]]]], true);
    +=> [1, 2, 3, [[4]]];
    +
    + +

    + without_.without(array, [*values]) +
    + Returns a copy of the array with all instances of the values + removed. === is used for the equality test. +

    +
    +_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
    +=> [2, 3, 4]
    +
    + +

    + union_.union(*arrays) +
    + Computes the union of the passed-in arrays: the list of unique items, + in order, that are present in one or more of the arrays. +

    +
    +_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
    +=> [1, 2, 3, 101, 10]
    +
    + +

    + intersection_.intersection(*arrays) +
    + Computes the list of values that are the intersection of all the arrays. + Each value in the result is present in each of the arrays. +

    +
    +_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
    +=> [1, 2]
    +
    + +

    + difference_.difference(array, *others) +
    + Similar to without, but returns the values from array that + are not present in the other arrays. +

    +
    +_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
    +=> [1, 3, 4]
    +
    + +

    + uniq_.uniq(array, [isSorted], [iterator]) + Alias: unique +
    + Produces a duplicate-free version of the array, using === to test + object equality. If you know in advance that the array is sorted, + passing true for isSorted will run a much faster algorithm. + If you want to compute unique items based on a transformation, pass an + iterator function. +

    +
    +_.uniq([1, 2, 1, 3, 1, 4]);
    +=> [1, 2, 3, 4]
    +
    + +

    + zip_.zip(*arrays) +
    + Merges together the values of each of the arrays with the + values at the corresponding position. Useful when you have separate + data sources that are coordinated through matching array indexes. + If you're working with a matrix of nested arrays, zip.apply + can transpose the matrix in a similar fashion. +

    +
    +_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
    +=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
    +
    + +

    + indexOf_.indexOf(array, value, [isSorted]) +
    + Returns the index at which value can be found in the array, + or -1 if value is not present in the array. Uses the native + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search. +

    +
    +_.indexOf([1, 2, 3], 2);
    +=> 1
    +
    + +

    + lastIndexOf_.lastIndexOf(array, value) +
    + Returns the index of the last occurrence of value in the array, + or -1 if value is not present. Uses the native lastIndexOf + function if possible. +

    +
    +_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
    +=> 4
    +
    + +

    + range_.range([start], stop, [step]) +
    + A function to create flexibly-numbered lists of integers, handy for + each and map loops. start, if omitted, defaults + to 0; step defaults to 1. Returns a list of integers + from start to stop, incremented (or decremented) by step, + exclusive. +

    +
    +_.range(10);
    +=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    +_.range(1, 11);
    +=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    +_.range(0, 30, 5);
    +=> [0, 5, 10, 15, 20, 25]
    +_.range(0, -10, -1);
    +=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
    +_.range(0);
    +=> []
    +
    + +

    Function (uh, ahem) Functions

    + +

    + bind_.bind(function, object, [*arguments]) +
    + Bind a function to an object, meaning that whenever + the function is called, the value of this will be the object. + Optionally, bind arguments to the function to pre-fill them, + also known as partial application. +

    +
    +var func = function(greeting){ return greeting + ': ' + this.name };
    +func = _.bind(func, {name : 'moe'}, 'hi');
    +func();
    +=> 'hi: moe'
    +
    + +

    + bindAll_.bindAll(object, [*methodNames]) +
    + Binds a number of methods on the object, specified by + methodNames, to be run in the context of that object whenever they + are invoked. Very handy for binding functions that are going to be used + as event handlers, which would otherwise be invoked with a fairly useless + this. If no methodNames are provided, all of the object's + function properties will be bound to it. +

    +
    +var buttonView = {
    +  label   : 'underscore',
    +  onClick : function(){ alert('clicked: ' + this.label); },
    +  onHover : function(){ console.log('hovering: ' + this.label); }
    +};
    +_.bindAll(buttonView);
    +jQuery('#underscore_button').bind('click', buttonView.onClick);
    +=> When the button is clicked, this.label will have the correct value...
    +
    + +

    + memoize_.memoize(function, [hashFunction]) +
    + Memoizes a given function by caching the computed result. Useful + for speeding up slow-running computations. If passed an optional + hashFunction, it will be used to compute the hash key for storing + the result, based on the arguments to the original function. The default + hashFunction just uses the first argument to the memoized function + as the key. +

    +
    +var fibonacci = _.memoize(function(n) {
    +  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
    +});
    +
    + +

    + delay_.delay(function, wait, [*arguments]) +
    + Much like setTimeout, invokes function after wait + milliseconds. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

    +
    +var log = _.bind(console.log, console);
    +_.delay(log, 1000, 'logged later');
    +=> 'logged later' // Appears after one second.
    +
    + +

    + defer_.defer(function) +
    + Defers invoking the function until the current call stack has cleared, + similar to using setTimeout with a delay of 0. Useful for performing + expensive computations or HTML rendering in chunks without blocking the UI thread + from updating. +

    +
    +_.defer(function(){ alert('deferred'); });
    +// Returns from the function before the alert runs.
    +
    + +

    + throttle_.throttle(function, wait) +
    + Creates and returns a new, throttled version of the passed function, + that, when invoked repeatedly, will only actually call the original function + at most once per every wait + milliseconds. Useful for rate-limiting events that occur faster than you + can keep up with. +

    +
    +var throttled = _.throttle(updatePosition, 100);
    +$(window).scroll(throttled);
    +
    + +

    + debounce_.debounce(function, wait, [immediate]) +
    + Creates and returns a new debounced version of the passed function that + will postpone its execution until after + wait milliseconds have elapsed since the last time it + was invoked. Useful for implementing behavior that should only happen + after the input has stopped arriving. For example: rendering a + preview of a Markdown comment, recalculating a layout after the window + has stopped being resized, and so on. +

    + +

    + Pass true for the immediate parameter to cause + debounce to trigger the function on the leading intead of the + trailing edge of the wait interval. Useful in circumstances like + preventing accidental double-clicks on a "submit" button from firing a + second time. +

    + +
    +var lazyLayout = _.debounce(calculateLayout, 300);
    +$(window).resize(lazyLayout);
    +
    + +

    + once_.once(function) +
    + Creates a version of the function that can only be called one time. + Repeated calls to the modified function will have no effect, returning + the value from the original call. Useful for initialization functions, + instead of having to set a boolean flag and then check it later. +

    +
    +var initialize = _.once(createApplication);
    +initialize();
    +initialize();
    +// Application is only created once.
    +
    + +

    + after_.after(count, function) +
    + Creates a version of the function that will only be run after first + being called count times. Useful for grouping asynchronous responses, + where you want to be sure that all the async calls have finished, before + proceeding. +

    +
    +var renderNotes = _.after(notes.length, render);
    +_.each(notes, function(note) {
    +  note.asyncSave({success: renderNotes});
    +});
    +// renderNotes is run once, after all notes have saved.
    +
    + +

    + wrap_.wrap(function, wrapper) +
    + Wraps the first function inside of the wrapper function, + passing it as the first argument. This allows the wrapper to + execute code before and after the function runs, adjust the arguments, + and execute it conditionally. +

    +
    +var hello = function(name) { return "hello: " + name; };
    +hello = _.wrap(hello, function(func) {
    +  return "before, " + func("moe") + ", after";
    +});
    +hello();
    +=> 'before, hello: moe, after'
    +
    + +

    + compose_.compose(*functions) +
    + Returns the composition of a list of functions, where each function + consumes the return value of the function that follows. In math terms, + composing the functions f(), g(), and h() produces + f(g(h())). +

    +
    +var greet    = function(name){ return "hi: " + name; };
    +var exclaim  = function(statement){ return statement + "!"; };
    +var welcome = _.compose(exclaim, greet);
    +welcome('moe');
    +=> 'hi: moe!'
    +
    + +

    Object Functions

    + +

    + keys_.keys(object) +
    + Retrieve all the names of the object's properties. +

    +
    +_.keys({one : 1, two : 2, three : 3});
    +=> ["one", "two", "three"]
    +
    + +

    + values_.values(object) +
    + Return all of the values of the object's properties. +

    +
    +_.values({one : 1, two : 2, three : 3});
    +=> [1, 2, 3]
    +
    + +

    + functions_.functions(object) + Alias: methods +
    + Returns a sorted list of the names of every method in an object — + that is to say, the name of every function property of the object. +

    +
    +_.functions(_);
    +=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
    +
    + +

    + extend_.extend(destination, *sources) +
    + Copy all of the properties in the source objects over to the + destination object, and return the destination object. + It's in-order, so the last source will override properties of the same + name in previous arguments. +

    +
    +_.extend({name : 'moe'}, {age : 50});
    +=> {name : 'moe', age : 50}
    +
    + +

    + pick_.pick(object, *keys) +
    + Return a copy of the object, filtered to only have values for + the whitelisted keys (or array of valid keys). +

    +
    +_.pick({name : 'moe', age: 50, userid : 'moe1'}, 'name', 'age');
    +=> {name : 'moe', age : 50}
    +
    + +

    + defaults_.defaults(object, *defaults) +
    + Fill in missing properties in object with default values from the + defaults objects, and return the object. As soon as the + property is filled, further defaults will have no effect. +

    +
    +var iceCream = {flavor : "chocolate"};
    +_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
    +=> {flavor : "chocolate", sprinkles : "lots"}
    +
    + +

    + clone_.clone(object) +
    + Create a shallow-copied clone of the object. Any nested objects + or arrays will be copied by reference, not duplicated. +

    +
    +_.clone({name : 'moe'});
    +=> {name : 'moe'};
    +
    + +

    + tap_.tap(object, interceptor) +
    + Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

    +
    +_.chain([1,2,3,200])
    +  .filter(function(num) { return num % 2 == 0; })
    +  .tap(alert)
    +  .map(function(num) { return num * num })
    +  .value();
    +=> // [2, 200] (alerted)
    +=> [4, 40000]
    +
    + +

    + has_.has(object, key) +
    + Does the object contain the given key? Identical to + object.hasOwnProperty(key), but uses a safe reference to the + hasOwnProperty function, in case it's been + overridden accidentally. +

    +
    +_.has({a: 1, b: 2, c: 3}, "b");
    +=> true
    +
    + +

    + isEqual_.isEqual(object, other) +
    + Performs an optimized deep comparison between the two objects, to determine + if they should be considered equal. +

    +
    +var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
    +var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
    +moe == clone;
    +=> false
    +_.isEqual(moe, clone);
    +=> true
    +
    + +

    + isEmpty_.isEmpty(object) +
    + Returns true if object contains no values. +

    +
    +_.isEmpty([1, 2, 3]);
    +=> false
    +_.isEmpty({});
    +=> true
    +
    + +

    + isElement_.isElement(object) +
    + Returns true if object is a DOM element. +

    +
    +_.isElement(jQuery('body')[0]);
    +=> true
    +
    + +

    + isArray_.isArray(object) +
    + Returns true if object is an Array. +

    +
    +(function(){ return _.isArray(arguments); })();
    +=> false
    +_.isArray([1,2,3]);
    +=> true
    +
    + +

    + isObject_.isObject(value) +
    + Returns true if value is an Object. +

    +
    +_.isObject({});
    +=> true
    +_.isObject(1);
    +=> false
    +
    + +

    + isArguments_.isArguments(object) +
    + Returns true if object is an Arguments object. +

    +
    +(function(){ return _.isArguments(arguments); })(1, 2, 3);
    +=> true
    +_.isArguments([1,2,3]);
    +=> false
    +
    + +

    + isFunction_.isFunction(object) +
    + Returns true if object is a Function. +

    +
    +_.isFunction(alert);
    +=> true
    +
    + +

    + isString_.isString(object) +
    + Returns true if object is a String. +

    +
    +_.isString("moe");
    +=> true
    +
    + +

    + isNumber_.isNumber(object) +
    + Returns true if object is a Number (including NaN). +

    +
    +_.isNumber(8.4 * 5);
    +=> true
    +
    + +

    + isFinite_.isFinite(object) +
    + Returns true if object is a finite Number. +

    +
    +_.isFinite(-101);
    +=> true
    +
    +_.isFinite(-Infinity);
    +=> false
    +
    + +

    + isBoolean_.isBoolean(object) +
    + Returns true if object is either true or false. +

    +
    +_.isBoolean(null);
    +=> false
    +
    + +

    + isDate_.isDate(object) +
    + Returns true if object is a Date. +

    +
    +_.isDate(new Date());
    +=> true
    +
    + +

    + isRegExp_.isRegExp(object) +
    + Returns true if object is a RegExp. +

    +
    +_.isRegExp(/moe/);
    +=> true
    +
    + +

    + isNaN_.isNaN(object) +
    + Returns true if object is NaN.
    Note: this is not + the same as the native isNaN function, which will also return + true if the variable is undefined. +

    +
    +_.isNaN(NaN);
    +=> true
    +isNaN(undefined);
    +=> true
    +_.isNaN(undefined);
    +=> false
    +
    + +

    + isNull_.isNull(object) +
    + Returns true if the value of object is null. +

    +
    +_.isNull(null);
    +=> true
    +_.isNull(undefined);
    +=> false
    +
    + +

    + isUndefined_.isUndefined(variable) +
    + Returns true if variable is undefined. +

    +
    +_.isUndefined(window.missingVariable);
    +=> true
    +
    + +

    Utility Functions

    + +

    + noConflict_.noConflict() +
    + Give control of the "_" variable back to its previous owner. Returns + a reference to the Underscore object. +

    +
    +var underscore = _.noConflict();
    + +

    + identity_.identity(value) +
    + Returns the same value that is used as the argument. In math: + f(x) = x
    + This function looks useless, but is used throughout Underscore as + a default iterator. +

    +
    +var moe = {name : 'moe'};
    +moe === _.identity(moe);
    +=> true
    + +

    + times_.times(n, iterator) +
    + Invokes the given iterator function n times. +

    +
    +_(3).times(function(){ genie.grantWish(); });
    + +

    + mixin_.mixin(object) +
    + Allows you to extend Underscore with your own utility functions. Pass + a hash of {name: function} definitions to have your functions + added to the Underscore object, as well as the OOP wrapper. +

    +
    +_.mixin({
    +  capitalize : function(string) {
    +    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
    +  }
    +});
    +_("fabio").capitalize();
    +=> "Fabio"
    +
    + +

    + uniqueId_.uniqueId([prefix]) +
    + Generate a globally-unique id for client-side models or DOM elements + that need one. If prefix is passed, the id will be appended to it. + Without prefix, returns an integer. +

    +
    +_.uniqueId('contact_');
    +=> 'contact_104'
    + +

    + escape_.escape(string) +
    + Escapes a string for insertion into HTML, replacing + &, <, >, ", ', and / characters. +

    +
    +_.escape('Curly, Larry & Moe');
    +=> "Curly, Larry &amp; Moe"
    + +

    + result_.result(object, property) +
    + If the value of the named property is a function then invoke it; otherwise, return it. +

    +
    +var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
    +_.result(object, 'cheese');
    +=> "crumpets"
    +_.result(object, 'stuff');
    +=> "nonsense"
    + +

    + template_.template(templateString, [data], [settings]) +
    + Compiles JavaScript templates into functions that can be evaluated + for rendering. Useful for rendering complicated bits of HTML from JSON + data sources. Template functions can both interpolate variables, using + <%= … %>, as well as execute arbitrary JavaScript code, with + <% … %>. If you wish to interpolate a value, and have + it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a + data object that has properties corresponding to the template's free + variables. If you're writing a one-off, you can pass the data + object as the second parameter to template in order to render + immediately instead of returning a template function. The settings argument + should be a hash containing any _.templateSettings that should be overriden. +

    + +
    +var compiled = _.template("hello: <%= name %>");
    +compiled({name : 'moe'});
    +=> "hello: moe"
    +
    +var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
    +_.template(list, {people : ['moe', 'curly', 'larry']});
    +=> "<li>moe</li><li>curly</li><li>larry</li>"
    +
    +var template = _.template("<b><%- value %></b>");
    +template({value : '<script>'});
    +=> "<b>&lt;script&gt;</b>"
    + +

    + You can also use print from within JavaScript code. This is + sometimes more convenient than using <%= ... %>. +

    + +
    +var compiled = _.template("<% print('Hello ' + epithet); %>");
    +compiled({epithet: "stooge"});
    +=> "Hello stooge."
    + +

    + If ERB-style delimiters aren't your cup of tea, you can change Underscore's + template settings to use different symbols to set off interpolated code. + Define an interpolate regex to match expressions that should be + interpolated verbatim, an escape regex to match expressions that should + be inserted after being HTML escaped, and an evaluate regex to match + expressions that should be evaluated without insertion into the resulting + string. You may define or omit any combination of the three. + For example, to perform + Mustache.js + style templating: +

    + +
    +_.templateSettings = {
    +  interpolate : /\{\{(.+?)\}\}/g
    +};
    +
    +var template = _.template("Hello {{ name }}!");
    +template({name : "Mustache"});
    +=> "Hello Mustache!"
    + +

    + By default, template places the values from your data in the local scope + via the with statement. However, you can specify a single variable name + with the variable setting. This can significantly improve the speed + at which a template is able to render. +

    + +
    +_.template("<%= data.hasWith %>", {hasWith: 'no'}, {variable: 'data'});
    +=> "no"
    + +

    + Precompiling your templates can be a big help when debugging errors you can't + reproduce. This is because precompiled templates can provide line numbers and + a stack trace, something that is not possible when compiling templates on the client. + The source property is available on the compiled template + function for easy precompilation. +

    + +
    <script>
    +  JST.project = <%= _.template(jstText).source %>;
    +</script>
    + + +

    Chaining

    + +

    + You can use Underscore in either an object-oriented or a functional style, + depending on your preference. The following two lines of code are + identical ways to double a list of numbers. +

    + +
    +_.map([1, 2, 3], function(n){ return n * 2; });
    +_([1, 2, 3]).map(function(n){ return n * 2; });
    + +

    + Calling chain on a wrapped object will cause all future method calls to + return wrapped objects as well. When you've finished the computation, + use value to retrieve the final value. Here's an example of chaining + together a map/flatten/reduce, in order to get the word count of + every word in a song. +

    + +
    +var lyrics = [
    +  {line : 1, words : "I'm a lumberjack and I'm okay"},
    +  {line : 2, words : "I sleep all night and I work all day"},
    +  {line : 3, words : "He's a lumberjack and he's okay"},
    +  {line : 4, words : "He sleeps all night and he works all day"}
    +];
    +
    +_.chain(lyrics)
    +  .map(function(line) { return line.words.split(' '); })
    +  .flatten()
    +  .reduce(function(counts, word) {
    +    counts[word] = (counts[word] || 0) + 1;
    +    return counts;
    +}, {}).value();
    +
    +=> {lumberjack : 2, all : 4, night : 2 ... }
    + +

    + In addition, the + Array prototype's methods + are proxied through the chained Underscore object, so you can slip a + reverse or a push into your chain, and continue to + modify the array. +

    + +

    + chain_.chain(obj) +
    + Returns a wrapped object. Calling methods on this object will continue + to return wrapped objects until value is used. +

    +
    +var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
    +var youngest = _.chain(stooges)
    +  .sortBy(function(stooge){ return stooge.age; })
    +  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
    +  .first()
    +  .value();
    +=> "moe is 21"
    +
    + +

    + value_(obj).value() +
    + Extracts the value of a wrapped object. +

    +
    +_([1, 2, 3]).value();
    +=> [1, 2, 3]
    +
    + + + +

    + Underscore.lua, + a Lua port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

    + +

    + Underscore.php, + a PHP port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + The source is + available on GitHub. +

    + +

    + Underscore-perl, + a Perl port of many of the Underscore.js functions, + aimed at on Perl hashes and arrays, also + available on GitHub. +

    + +

    + Underscore.string, + an Underscore extension that adds functions for string-manipulation: + trim, startsWith, contains, capitalize, + reverse, sprintf, and more. +

    + +

    + Ruby's Enumerable module. +

    + +

    + Prototype.js, which provides + JavaScript with collection functions in the manner closest to Ruby's Enumerable. +

    + +

    + Oliver Steele's + Functional JavaScript, + which includes comprehensive higher-order function support as well as string lambdas. +

    + +

    + Michael Aufreiter's Data.js, + a data manipulation + persistence library for JavaScript. +

    + +

    + Python's itertools. +

    + +

    Change Log

    + +

    + 1.3.3April 10, 2012
    +

      +
    • + Many improvements to _.template, which now provides the + source of the template function as a property, for potentially + even more efficient pre-compilation on the server-side. You may now + also set the variable option when creating a template, + which will cause your passed-in data to be made available under the + variable you named, instead of using a with statement — + significantly improving the speed of rendering the template. +
    • +
    • + Added the pick function, which allows you to filter an + object literal with a whitelist of allowed property names. +
    • +
    • + Added the result function, for convenience when working + with APIs that allow either functions or raw properties. +
    • +
    • + Added the isFinite function, because sometimes knowing that + a value is a number just ain't quite enough. +
    • +
    • + The sortBy function may now also be passed the string name + of a property to use as the sort order on each object. +
    • +
    • + Fixed uniq to work with sparse arrays. +
    • +
    • + The difference function now performs a shallow flatten + instead of a deep one when computing array differences. +
    • +
    • + The debounce function now takes an immediate + parameter, which will cause the callback to fire on the leading + instead of the trailing edge. +
    • +
    +

    + +

    + 1.3.1Jan. 23, 2012
    +

      +
    • + Added an _.has function, as a safer way to use hasOwnProperty. +
    • +
    • + Added _.collect as an alias for _.map. Smalltalkers, rejoice. +
    • +
    • + Reverted an old change so that _.extend will correctly copy + over keys with undefined values again. +
    • +
    • + Bugfix to stop escaping slashes within interpolations in _.template. +
    • +
    +

    + +

    + 1.3.0Jan. 11, 2012
    +

      +
    • + Removed AMD (RequireJS) support from Underscore. If you'd like to use + Underscore with RequireJS, you can load it as a normal script, wrap + or patch your copy, or download a forked version. +
    • +
    +

    + +

    + 1.2.4Jan. 4, 2012
    +

      +
    • + You now can (and probably should, as it's simpler) + write _.chain(list) + instead of _(list).chain(). +
    • +
    • + Fix for escaped characters in Underscore templates, and for supporting + customizations of _.templateSettings that only define one or + two of the required regexes. +
    • +
    • + Fix for passing an array as the first argument to an _.wrap'd function. +
    • +
    • + Improved compatibility with ClojureScript, which adds a call + function to String.prototype. +
    • +
    +

    + +

    + 1.2.3Dec. 7, 2011
    +

      +
    • + Dynamic scope is now preserved for compiled _.template functions, + so you can use the value of this if you like. +
    • +
    • + Sparse array support of _.indexOf, _.lastIndexOf. +
    • +
    • + Both _.reduce and _.reduceRight can now be passed an + explicitly undefined value. (There's no reason why you'd + want to do this.) +
    • +
    +

    + +

    + 1.2.2Nov. 14, 2011
    +

      +
    • + Continued tweaks to _.isEqual semantics. Now JS primitives are + considered equivalent to their wrapped versions, and arrays are compared + by their numeric properties only (#351). +
    • +
    • + _.escape no longer tries to be smart about not double-escaping + already-escaped HTML entities. Now it just escapes regardless (#350). +
    • +
    • + In _.template, you may now leave semicolons out of evaluated + statements if you wish: <% }) %> (#369). +
    • +
    • + _.after(callback, 0) will now trigger the callback immediately, + making "after" easier to use with asynchronous APIs (#366). +
    • +
    +

    + +

    + 1.2.1Oct. 24, 2011
    +

      +
    • + Several important bug fixes for _.isEqual, which should now + do better on mutated Arrays, and on non-Array objects with + length properties. (#329) +
    • +
    • + jrburke contributed Underscore exporting for AMD module loaders, + and tonylukasavage for Appcelerator Titanium. + (#335, #338) +
    • +
    • + You can now _.groupBy(list, 'property') as a shortcut for + grouping values by a particular common property. +
    • +
    • + _.throttle'd functions now fire immediately upon invocation, + and are rate-limited thereafter (#170, #266). +
    • +
    • + Most of the _.is[Type] checks no longer ducktype. +
    • +
    • + The _.bind function now also works on constructors, a-la + ES5 ... but you would never want to use _.bind on a + constructor function. +
    • +
    • + _.clone no longer wraps non-object types in Objects. +
    • +
    • + _.find and _.filter are now the preferred names for + _.detect and _.select. +
    • +
    +

    + +

    + 1.2.0Oct. 5, 2011
    +

      +
    • + The _.isEqual function now + supports true deep equality comparisons, with checks for cyclic structures, + thanks to Kit Cambridge. +
    • +
    • + Underscore templates now support HTML escaping interpolations, using + <%- ... %> syntax. +
    • +
    • + Ryan Tenney contributed _.shuffle, which uses a modified + Fisher-Yates to give you a shuffled copy of an array. +
    • +
    • + _.uniq can now be passed an optional iterator, to determine by + what criteria an object should be considered unique. +
    • +
    • + _.last now takes an optional argument which will return the last + N elements of the list. +
    • +
    • + A new _.initial function was added, as a mirror of _.rest, + which returns all the initial values of a list (except the last N). +
    • +
    +

    + +

    + 1.1.7July 13, 2011
    + Added _.groupBy, which aggregates a collection into groups of like items. + Added _.union and _.difference, to complement the + (re-named) _.intersection. + Various improvements for support of sparse arrays. + _.toArray now returns a clone, if directly passed an array. + _.functions now also returns the names of functions that are present + in the prototype chain. +

    + +

    + 1.1.6April 18, 2011
    + Added _.after, which will return a function that only runs after + first being called a specified number of times. + _.invoke can now take a direct function reference. + _.every now requires an iterator function to be passed, which + mirrors the ECMA5 API. + _.extend no longer copies keys when the value is undefined. + _.bind now errors when trying to bind an undefined value. +

    + +

    + 1.1.5Mar 20, 2011
    + Added an _.defaults function, for use merging together JS objects + representing default options. + Added an _.once function, for manufacturing functions that should + only ever execute a single time. + _.bind now delegates to the native ECMAScript 5 version, + where available. + _.keys now throws an error when used on non-Object values, as in + ECMAScript 5. + Fixed a bug with _.keys when used over sparse arrays. +

    + +

    + 1.1.4Jan 9, 2011
    + Improved compliance with ES5's Array methods when passing null + as a value. _.wrap now correctly sets this for the + wrapped function. _.indexOf now takes an optional flag for + finding the insertion index in an array that is guaranteed to already + be sorted. Avoiding the use of .callee, to allow _.isArray + to work properly in ES5's strict mode. +

    + +

    + 1.1.3Dec 1, 2010
    + In CommonJS, Underscore may now be required with just:
    + var _ = require("underscore"). + Added _.throttle and _.debounce functions. + Removed _.breakLoop, in favor of an ECMA5-style un-break-able + each implementation — this removes the try/catch, and you'll now have + better stack traces for exceptions that are thrown within an Underscore iterator. + Improved the isType family of functions for better interoperability + with Internet Explorer host objects. + _.template now correctly escapes backslashes in templates. + Improved _.reduce compatibility with the ECMA5 version: + if you don't pass an initial value, the first item in the collection is used. + _.each no longer returns the iterated collection, for improved + consistency with ES5's forEach. +

    + +

    + 1.1.2
    + Fixed _.contains, which was mistakenly pointing at + _.intersect instead of _.include, like it should + have been. Added _.unique as an alias for _.uniq. +

    + +

    + 1.1.1
    + Improved the speed of _.template, and its handling of multiline + interpolations. Ryan Tenney contributed optimizations to many Underscore + functions. An annotated version of the source code is now available. +

    + +

    + 1.1.0
    + The method signature of _.reduce has been changed to match + the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. + This is a backwards-incompatible change. _.template may now be + called with no arguments, and preserves whitespace. _.contains + is a new alias for _.include. +

    + +

    + 1.0.4
    + Andri Möll contributed the _.memoize + function, which can be used to speed up expensive repeated computations + by caching the results. +

    + +

    + 1.0.3
    + Patch that makes _.isEqual return false if any property + of the compared object has a NaN value. Technically the correct + thing to do, but of questionable semantics. Watch out for NaN comparisons. +

    + +

    + 1.0.2
    + Fixes _.isArguments in recent versions of Opera, which have + arguments objects as real Arrays. +

    + +

    + 1.0.1
    + Bugfix for _.isEqual, when comparing two objects with the same + number of undefined keys, but with different names. +

    + +

    + 1.0.0
    + Things have been stable for many months now, so Underscore is now + considered to be out of beta, at 1.0. Improvements since 0.6 + include _.isBoolean, and the ability to have _.extend + take multiple source objects. +

    + +

    + 0.6.0
    + Major release. Incorporates a number of + Mile Frawley's refactors for + safer duck-typing on collection functions, and cleaner internals. A new + _.mixin method that allows you to extend Underscore with utility + functions of your own. Added _.times, which works the same as in + Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, + and Object.keys. +

    + +

    + 0.5.8
    + Fixed Underscore's collection functions to work on + NodeLists and + HTMLCollections + once more, thanks to + Justin Tulloss. +

    + +

    + 0.5.7
    + A safer implementation of _.isArguments, and a + faster _.isNumber,
    thanks to + Jed Schmidt. +

    + +

    + 0.5.6
    + Customizable delimiters for _.template, contributed by + Noah Sloan. +

    + +

    + 0.5.5
    + Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object. +

    + +

    + 0.5.4
    + Fix for multiple single quotes within a template string for + _.template. See: + Rick Strahl's blog post. +

    + +

    + 0.5.2
    + New implementations of isArray, isDate, isFunction, + isNumber, isRegExp, and isString, thanks to + a suggestion from + Robert Kieffer. + Instead of doing Object#toString + comparisons, they now check for expected properties, which is less safe, + but more than an order of magnitude faster. Most other Underscore + functions saw minor speed improvements as a result. + Evgeniy Dolzhenko + contributed _.tap, + similar to Ruby 1.9's, + which is handy for injecting side effects (like logging) into chained calls. +

    + +

    + 0.5.1
    + Added an _.isArguments function. Lots of little safety checks + and optimizations contributed by + Noah Sloan and + Andri Möll. +

    + +

    + 0.5.0
    + [API Changes] _.bindAll now takes the context object as + its first parameter. If no method names are passed, all of the context + object's methods are bound to it, enabling chaining and easier binding. + _.functions now takes a single argument and returns the names + of its Function properties. Calling _.functions(_) will get you + the previous behavior. + Added _.isRegExp so that isEqual can now test for RegExp equality. + All of the "is" functions have been shrunk down into a single definition. + Karl Guertin contributed patches. +

    + +

    + 0.4.7
    + Added isDate, isNaN, and isNull, for completeness. + Optimizations for isEqual when checking equality between Arrays + or Dates. _.keys is now 25%–2X faster (depending on your + browser) which speeds up the functions that rely on it, such as _.each. +

    + +

    + 0.4.6
    + Added the range function, a port of the + Python + function of the same name, for generating flexibly-numbered lists + of integers. Original patch contributed by + Kirill Ishanov. +

    + +

    + 0.4.5
    + Added rest for Arrays and arguments objects, and aliased + first as head, and rest as tail, + thanks to Luke Sutton's patches. + Added tests ensuring that all Underscore Array functions also work on + arguments objects. +

    + +

    + 0.4.4
    + Added isString, and isNumber, for consistency. Fixed + _.isEqual(NaN, NaN) to return true (which is debatable). +

    + +

    + 0.4.3
    + Started using the native StopIteration object in browsers that support it. + Fixed Underscore setup for CommonJS environments. +

    + +

    + 0.4.2
    + Renamed the unwrapping function to value, for clarity. +

    + +

    + 0.4.1
    + Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

    + +

    + 0.4.0
    + All Underscore functions can now be called in an object-oriented style, + like so: _([1, 2, 3]).map(...);. Original patch provided by + Marc-André Cournoyer. + Wrapped objects can be chained through multiple + method invocations. A functions method + was added, providing a sorted list of all the functions in Underscore. +

    + +

    + 0.3.3
    + Added the JavaScript 1.8 function reduceRight. Aliased it + as foldr, and aliased reduce as foldl. +

    + +

    + 0.3.2
    + Now runs on stock Rhino + interpreters with: load("underscore.js"). + Added identity as a utility function. +

    + +

    + 0.3.1
    + All iterators are now passed in the original collection as their third + argument, the same as JavaScript 1.6's forEach. Iterating over + objects is now called with (value, key, collection), for details + see _.each. +

    + +

    + 0.3.0
    + Added Dmitry Baranovskiy's + comprehensive optimizations, merged in + Kris Kowal's patches to make Underscore + CommonJS and + Narwhal compliant. +

    + +

    + 0.2.0
    + Added compose and lastIndexOf, renamed inject to + reduce, added aliases for inject, filter, + every, some, and forEach. +

    + +

    + 0.1.1
    + Added noConflict, so that the "Underscore" object can be assigned to + other variables. +

    + +

    + 0.1.0
    + Initial release of Underscore.js. +

    + +

    + + A DocumentCloud Project + +

    + +
    + +
    + + + + + + diff --git a/node_modules/piler/node_modules/underscore/index.js b/node_modules/piler/node_modules/underscore/index.js new file mode 100644 index 0000000..2cf0ca5 --- /dev/null +++ b/node_modules/piler/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/node_modules/piler/node_modules/underscore/package.json b/node_modules/piler/node_modules/underscore/package.json new file mode 100644 index 0000000..4e69b80 --- /dev/null +++ b/node_modules/piler/node_modules/underscore/package.json @@ -0,0 +1,30 @@ +{ + "name": "underscore", + "description": "JavaScript's functional programming helper library.", + "homepage": "http://documentcloud.github.com/underscore/", + "keywords": [ + "util", + "functional", + "server", + "client", + "browser" + ], + "author": { + "name": "Jeremy Ashkenas", + "email": "jeremy@documentcloud.org" + }, + "repository": { + "type": "git", + "url": "git://github.com/documentcloud/underscore.git" + }, + "main": "underscore.js", + "version": "1.3.3", + "readme": " __ \n /\\ \\ __ \n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____ \n /\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\ \n \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/ \n \\ \\____/ \n \\/___/\n \nUnderscore.js is a utility-belt library for JavaScript that provides \nsupport for the usual functional suspects (each, map, reduce, filter...) \nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://documentcloud.github.com/underscore/\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n", + "readmeFilename": "README.md", + "_id": "underscore@1.3.3", + "dist": { + "shasum": "d068e19cbd1ad414d0496baf6c417f6ffb19efce" + }, + "_from": "underscore@1.3.x", + "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.3.3.tgz" +} diff --git a/node_modules/piler/node_modules/underscore/raw/underscore.psd b/node_modules/piler/node_modules/underscore/raw/underscore.psd new file mode 100644 index 0000000000000000000000000000000000000000..73ad2d7c8eebce69b4f46f31c0a1a8c2d523bc0d GIT binary patch literal 215540 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 literal 0 HcmV?d00001 diff --git a/node_modules/piler/node_modules/underscore/underscore-min.js b/node_modules/piler/node_modules/underscore/underscore-min.js new file mode 100644 index 0000000..5a0cb3b --- /dev/null +++ b/node_modules/piler/node_modules/underscore/underscore-min.js @@ -0,0 +1,32 @@ +// Underscore.js 1.3.3 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break; +g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a, +c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(A&& +a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a, +c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b, +a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= +function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]}; +j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a= +i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&& +c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty= +function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"}; +b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a, +b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId= +function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape|| +u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c}; +b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d, +this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/node_modules/piler/node_modules/underscore/underscore.js b/node_modules/piler/node_modules/underscore/underscore.js new file mode 100644 index 0000000..f6f7e2f --- /dev/null +++ b/node_modules/piler/node_modules/underscore/underscore.js @@ -0,0 +1,1059 @@ +// Underscore.js 1.3.3 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var slice = ArrayProto.slice, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root['_'] = _; + } + + // Current version. + _.VERSION = '1.3.3'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + if (obj.length === +obj.length) results.length = obj.length; + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (_.isFunction(method) ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, val, context) { + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + if (a === void 0) return 1; + if (b === void 0) return -1; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (_.isArguments(obj)) return slice.call(obj); + if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray(); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.isArray(obj) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var results = []; + // The `isSorted` flag is irrelevant if the array only contains two elements. + if (array.length < 3) isSorted = true; + _.reduce(initial, function (memo, value, index) { + if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) { + memo.push(value); + results.push(array[index]); + } + return memo; + }, []); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = _.flatten(slice.call(arguments, 1), true); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more, result; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + result = func.apply(context, args); + } + whenDone(); + throttling = true; + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + if (immediate && !timeout) func.apply(context, args); + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func].concat(slice.call(arguments, 0)); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var result = {}; + each(_.flatten(slice.call(arguments, 1)), function(key) { + if (key in obj) result[key] = obj[key]; + }); + return result; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType == 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is a given object a finite number? + _.isFinite = function(obj) { + return _.isNumber(obj) && isFinite(obj); + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return obj !== obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Has own property? + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = idCounter++; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /.^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + '\\': '\\', + "'": "'", + 'r': '\r', + 'n': '\n', + 't': '\t', + 'u2028': '\u2028', + 'u2029': '\u2029' + }; + + for (var p in escapes) escapes[escapes[p]] = p; + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g; + + // Within an interpolation, evaluation, or escaping, remove HTML escaping + // that had been previously added. + var unescape = function(code) { + return code.replace(unescaper, function(match, escape) { + return escapes[escape]; + }); + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + settings = _.defaults(settings || {}, _.templateSettings); + + // Compile the template source, taking care to escape characters that + // cannot be included in a string literal and then unescape them in code + // blocks. + var source = "__p+='" + text + .replace(escaper, function(match) { + return '\\' + escapes[match]; + }) + .replace(settings.escape || noMatch, function(match, code) { + return "'+\n_.escape(" + unescape(code) + ")+\n'"; + }) + .replace(settings.interpolate || noMatch, function(match, code) { + return "'+\n(" + unescape(code) + ")+\n'"; + }) + .replace(settings.evaluate || noMatch, function(match, code) { + return "';\n" + unescape(code) + "\n;__p+='"; + }) + "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __p='';" + + "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" + + source + "return __p;\n"; + + var render = new Function(settings.variable || 'obj', '_', source); + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for build time + // precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // The OOP Wrapper + // --------------- + + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + var wrapped = this._wrapped; + method.apply(wrapped, arguments); + var length = wrapped.length; + if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0]; + return result(wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); diff --git a/node_modules/piler/package.json b/node_modules/piler/package.json new file mode 100644 index 0000000..7775c02 --- /dev/null +++ b/node_modules/piler/package.json @@ -0,0 +1,55 @@ +{ + "name": "piler", + "version": "0.5.0", + "author": { + "name": "Esa-Matti Suuronen" + }, + "maintainers": [ + { + "name": "Alexander Pirsig", + "email": "self@pirsig.net" + } + ], + "homepage": "http://epeli.github.com/piler/", + "description": "Awesome Asset Manager for Node.js", + "bugs": { + "url": "https://github.com/epeli/piler/issues/" + }, + "repository": { + "type": "git", + "url": "https://github.com/epeli/piler.git" + }, + "scripts": { + "test": "./run-tests-travis.sh" + }, + "main": "./lib/index", + "dependencies": { + "coffee-script": "1.3.x", + "underscore": "1.3.x", + "underscore.string": "2.2.0rc", + "uglify-js": "1.3.x", + "async": "0.1.22", + "csso": "1.2.x" + }, + "devDependencies": { + "jasmine-node": "", + "express": "2.x", + "zombie": "1.2.x", + "supervisor": "", + "jade": "", + "stylus": "", + "nib": "", + "less": "", + "request": "", + "csslint": "", + "socket.io": "" + }, + "readme": "# Piler\n\n[![Build Status](https://secure.travis-ci.org/epeli/piler.png)](http://travis-ci.org/epeli/piler)\n\nFeature highlights\n\n * Minify and concatenate JS and CSS for fast page loads\n * Tag rendering\n * Namespaces\n * Transparent preprocessor\n * Push CSS changes to the browser using Socket.IO\n * Easy code sharing with server\n\n## Awesome Asset Manager for Node.js\n\n*Piler* allows you to manage all your JavaScript and CSS assets cleanly and\ndirectly from code. It will concatenate and minify them in production and it\ntakes care of rendering the tags. The idea is to make your pages load as\nquickly as possible.\n\nSo why create a yet another asset manager? Because Node.js is special. In\nNode.js a JavaScript asset isn't just a pile of bits that are sent to the\nbrowser. It's code. It's code that can be also used in the server and I think\nthat it's the job of asset managers to help with it. So in *Piler* you can take\ncode directly from your Javascript objects, not just from JavaScript files.\nCopying things from Rails is just not enough. This is just a one reason why\n*Piler* was created.\n\nServer-side code:\n\n```javascript\nclientjs.addOb({BROWSER_GLOBAL: {\n aFunction: function() {\n console.log(\"Hello I'm in the browser also. Here I have\", window, \"and other friends\");\n }\n}});\n```\n\nYou can also tell *Piler* to directly execute some function in the browser:\n\n```javascript\nclientjs.addExec(function() {\n BROWSER_GLOBAL.aFunction();\n alert(\"Hello\" + window.navigator.appVersion);\n});\n```\n\n\nCurrently *Piler* works only with [Express], but other frameworks are planned\nas well.\n\n\n*Piler* is written following principles in mind:\n\n * Creating best possible production setup for assets should be as easy as\n including script/link to a page.\n * Namespaces. You don't want to serve huge blob of admin view code for all\n anonymous users.\n * Support any JS- or CSS-files. No need to create special structure for your\n assets. Just include your jQueries or whatever.\n * Preprocessor languages are first class citizens. Eg. Just change the file\n extension to .coffee to use CoffeeScript. That's it. No need to worry about\n compiled files.\n * Use heavy caching. Browser caches are killed automatically using the hash\n sum of the assets.\n * Awesome development mode. Build-in support for pushing CSS changes to\n browsr using Socket.IO.\n\n\n**Full example Express 2.x**\n```javascript\nvar createServer = require(\"express\").createServer;\nvar piler = require(\"piler\");\n\nvar app = createServer();\nvar clientjs = piler.createJSManager();\nvar clientcss = piler.createCSSManager();\n\napp.configure(function() {\n clientjs.bind(app);\n clientcss.bind(app);\n\n clientcss.addFile(__dirname + \"/style.css\");\n\n clientjs.addUrl(\"http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js\");\n clientjs.addFile(__dirname + \"/client/hello.js\");\n});\n\napp.configure(\"development\", function() {\n clientjs.liveUpdate(clientcss);\n});\n\nclientjs.addOb({ VERSION: \"1.0.0\" });\n\nclientjs.addExec(function() {\n alert(\"Hello browser\" + window.navigator.appVersion);\n});\n\napp.get(\"/\", function(req, res){\n res.render(\"index.jade\", {\n layout: false,\n js: clientjs.renderTags(),\n css: clientcss.renderTags()\n });\n});\n\napp.listen(8080);\n```\n\n\n**Full example Express 3.x**\n```javascript\nvar express = require('express'),\n http = require('http'),\n piler = require(\"piler\"),\n app = express();\n\nvar clientjs = piler.createJSManager();\nvar clientcss = piler.createCSSManager();\nvar srv = require('http').createServer(app);\n\napp.configure(function(){\n\n clientjs.bind(app,srv);\n clientcss.bind(app,srv);\n\n clientcss.addFile(__dirname + \"/style.css\");\n\n clientjs.addUrl(\"http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js\");\n clientjs.addFile(__dirname + \"/client/hello.js\");\n});\n\napp.configure(\"development\", function() {\n clientjs.liveUpdate(clientcss);\n});\n\nclientjs.addOb({ VERSION: \"1.0.0\" });\n\nclientjs.addExec(function() {\n alert(\"Hello browser\" + window.navigator.appVersion);\n});\n\napp.get(\"/\", function(req, res){\n res.render(\"index.jade\", {\n layout: false,\n js: clientjs.renderTags(),\n css: clientcss.renderTags()\n });\n});\n\nsrv.listen(8080);\n```\n\n\nindex.jade:\n\n```jade\n!!! 5\nhtml\n head\n !{css}\n !{js}\n body\n h1 Hello Piler\n```\n\n\n## Namespaces\n\nThe example above uses just a one pile. The global pile.\n\nIf you for example want to add big editor files only for administration pages\nyou can create a pile for it:\n\n```javascript\nclientjs.addFile(\"admin\", __dirname + \"/editor.js\");\nclientjs.addFile(\"admin\", __dirname + \"/editor.extension.js\");\n```\n\nThis will add file editor.js and editor.extension.js to a admin pile. Now you\ncan add that to your admin pages by using giving it as parameter for\n*renderTags*.\n\n```javascript\njs.renderTags(\"admin\");\n```\n\nThis will render script-tags for the global pile and the admin-pile.\n*js.renderTags* and *css.renderTags* can take variable amount of arguments.\nUse *js.renderTags(\"pile1\", \"pile2\", ....)* to render multiple namespaces\n\nPiling works just the same with css.\n\n\n## Sharing code with the server\n\nOk, that's pretty much what every asset manager does, but with *Piler* you can\nshare code directly from your server code.\n\nLet's say that you want to share a email-validating function with a server and\nthe client\n\n```javascript\nfunction isEmail(s) {\n return !! s.match(/.\\w+@\\w+\\.\\w/);\n}\n```\n\nYou can share it with *addOb* -method:\n\n```javascript\nclientjs.addOb({MY: {\n isEmail: isEmail\n }\n});\n```\n\nNow on the client you can find the isEmail-function from MY.isEmail.\n\n*addOb* takes an object which will be merged to global window-object on the\nclient. So be carefull when choosing the keys. The object can be almost any\nJavaScript object. It will be serialized and sent to the browser. Few caveats:\n\n 1. No circural references\n 1. Functions will be serialized using Function.prototype.toString. So closures\n won't transferred to the client!\n\n\n### Pattern for sharing full modules\n\nThis is nothing specific to *Piler*, but this is a nice pattern which can be\nused to share modules between the server and the client.\n\nshare.js\n\n```javascript\n(function(exports){\n\n exports.test = function(){\n return 'This is a function from shared module';\n };\n\n}(typeof exports === 'undefined' ? this.share = {} : exports));\n```\n\nIn Node.js you can use it by just requiring it as any other module\n\n```javascript\nvar share = require(\"./share.js\");\n```\n\nand you can share it the client using *addFile*:\n\n```javascript\nclientjs.addFile(__dirname + \"./share.js\");\n```\n\nNow you can use it in both as you would expect\n\n```javascript\nshare.test();\n```\n\nYou can read more about the pattern from [here](http://caolanmcmahon.com/posts/writing_for_node_and_the_browser)\n\n## Logging\nSometimes it is nessesary to control pilers output based on the system environment your running your application in. \nIn default mode Pilers logger will output any information it has by using the \"console\" javascript object. The following example shows\nhow to configure a custom logger \n\n### Logger interface\nThe basic logger facility implements the following methods.\n```javascript\nexports.debug = console.debug\nexports.notice = console.log\nexports.info = console.info\nexports.warn = console.warn\nexports.warning = console.warn\nexports.error = console.error\nexports.critical = console.error\n```\n\n### Inject a custom logger\nThe following example injects \"winston\", a multi-transport async logging library into pilers logging mechanism.\n```javascript\nvar piler = require('piler');\nvar logger = require('winston');\n// [More logger configuration can take place here]\n\nglobal.js = js = piler.createJSManager({ outputDirectory: assetTmpDir , \"logger\": logger});\nglobal.css = css = piler.createCSSManager({ outputDirectory: assetTmpDir, \"logger\": logger});\n```\n\nMore information about winston can be found [here](https://github.com/flatiron/winston).\n\n## Awesome development mode!\n\nDevelopment and production modes works as in Express. By default the\ndevelopment mode is active. To activate production mode set NODE\\_ENV\nenvironment variable to *production*.\n\n### Live CSS editing\n\nThis is really cool! You don't want to edit CSS at all without this after you\ntry it!\n\nBecause *Piler* handles the script-tag rendering it can add some development\ntools when in development mode.\n\nUsing Express you can add Live CSS editing in development mode:\n\n```javascript\napp.configure(\"development\", function() {\n clientjs.liveUpdate(clientcss);\n});\n```\n\nThis is similar to [Live.js][], but it does not use polling. It will add\nSocket.IO which will push the CSS-changes to your browser as you edit them.\n\nIf your app already uses Socket.IO you need to add the *io*-object as second\nparameter to liveUpdate:\n\n\n```javascript\nvar io = require('socket.io').listen(app);\nclientjs.liveUpdate(clientcss, io);\n```\n\n### Script-tag rendering\n\nIn development mode every JS- and CSS-file will be rendered as a separate tag.\n\nFor example js.renderTags(\"admin\") will render\n\n```javascript\nclientjs.addFile(__dirname + \"/helpers.js\");\nclientjs.addFile(\"admin\", __dirname + \"/editor.js\");\nclientjs.addFile(\"admin\", __dirname + \"/editor.extension.js\");\n```\n\nto\n\n```html\n\n\n\n```\n\nin development mode, but in production it will render to\n\n```html\n\n\n```\n\nSo debugging should be as easy as directly using script-tags. Line numbers\nwill match your real files in the filesystem. No need to debug huge Javascript\nbundle!\n\n\n\n## Examples\n\nVisit\n[this](https://github.com/epeli/piler/blob/master/examples/simple/app.js)\ndirectory to see a simple example using ExpressJS 2.x.\n\nThis\n[example](https://github.com/epeli/piler/blob/master/examples/simple/app.js)\nuses ExpressJS 3.x a custom logger (winston) and a global socket.io instance\ntogether with Piler.\n\n## API summary\n\nCode will be rendered in the order you call these functions with the exception\nof *addUrl* which will be rendered as first.\n\n### createJSManager and createCSSManager\n\nCan take an optional configuration object as an argument with following keys.\n\n var jsclient = piler.createJSManager({\n outputDirectory: __dirname + \"/mydir\",\n urlRoot: \"/my/root\"\n });\n\n#### urlRoot\n\nUrl root to which Piler's paths are appended. For example urlRoot \"/my/root\"\nwill result in following script tag:\n\n \n\n#### outputDirectory\n\nIf specified *Piler* will write the minified assets to this folder. Useful if\nyou want to share you assets from Apache etc. instead of directly serving from\nPiler's Connect middleware.\n\n\n### JavaScript pile\n\n#### addFile( [namespace], path to a asset file )\n\nFile on filesystem.\n\n#### addUrl( [namespace], url to a asset file )\n\nUseful for CDNs and for dynamic assets in other libraries such as socket.io.\n\n#### addOb( [namespace string], any Javascript object )\n\nKeys of the object will be added to the global window object. So take care when\nchoosing those. Also remember that parent scope of functions will be lost.\n\nYou can also give a nested namespace for it\n\n clientjs.addOb({\"foo.bar\": \"my thing\"});\n\nNow on the client \"my thing\" string will be found from window.foo.bar.\n\nThe object will be serialized at the second it is passed to this method so you\nwon't be able modify it other than between server restarts. This is usefull for\nsharing utility functions etc.\n\nUse *res.addOb* to share more dynamically objects.\n\n#### addExec( [namespace], Javascript function )\n\nA function that will executed immediately in browser as it is parsed. Parent\nscope is also lost here.\n\n#### addRaw( [namespace], raw Javascript string )\n\nAny valid Javascript string.\n\n\n\n### CSS pile\n\nThese are similar to ones in JS pile.\n\n\n#### addFile( [namespace], path to a asset file )\n\nCSS asset on your filesystem.\n\n#### addUrl( [namespace], url to a asset file )\n\nCSS asset behind a url. Can be remote too. This will be directly linked to you\npage. Use addFile if you want it be minified.\n\n#### addRaw( [namespace], raw CSS string )\n\nAny valid CSS string.\n\n\n## Supported preprocessors\n\n### JavaScript\n\nFor JavaScript the only supported one is [CoffeeScript][] and the compiler is\nincluded in *Piler*.\n\n### CSS\n\nCSS-compilers are not included in *Piler*. Just install what you need using\n[npm][].\n\n * [Stylus][] with [nib][] (npm install stylus nib)\n * [LESS][] (npm install less)\n\nAdding support for new compilers should be\n[easy](https://github.com/epeli/pile/blob/master/lib/compilers.coffee).\n\nFeel free to contribute!\n\n## Installing\n\nFrom [npm][]\n\n npm install piler\n\n## Source code\n\nSource code is licenced under [The MIT\nLicense](https://github.com/epeli/piler/blob/master/LICENSE) and it is hosted\non [Github](https://github.com/epeli/piler).\n\n## Changelog\n\nv0.4.2 - 2013-04-16\n\n * Fixes to work with ExpressJS 3.x\n * Unit test fixes\n * Make console output configurable\n\n\nv0.4.1 - 2012-06-12\n\n * Add getSources\n * Put cache key to resource url instead of query string\n\nv0.4.0 - 2012-06-17\n\n * Remove Dynamic Helpers.\n\nDynamic Helpers where an Express 2.0 only API. This makes Piler more framework\nagnostic and it will work with Express 3.0. This also removes support for\nresponse object functions. We'll add those back if there is a need for them\n(open up a issue if you miss them!) and we'll find good framework agnostic way\nto implement them.\n\nv0.3.6 - 2012-06-17\n\n * Bind all production dependency versions\n\nv0.3.5 - 2012-06-17\n\n * Fix LESS @imports\n * Fix Stylus without nib\n * Use path module for Windows compatibility\n\nv0.3.4 - 2012-03-29\n\n * Fix Stylus @imports\n\nv0.3.3 - noop\n\nv0.3.2 - 2011-12-11\n\n * Workaround compiler bug in CoffeeScript\n\nv0.3.1 - 2011-11-17\n\n * Fix CSS namespaces\n\nv0.3.0 - 2011-10-13\n\n * Rename to Piler\n * Really minify CSS\n * Implemented res.addOb\n * Implement outputDirectory and urlRoot options.\n * addOb can now take nested namespace string and it won't override existing\n namespaces.\n\n## Contact\n\nQuestions and suggestions are very welcome\n\n- [Esa-Matti Suuronen](http://esa-matti.suuronen.org/)\n- esa-matti [aet] suuronen dot org\n- [EsaMatti](https://twitter.com/#!/EsaMatti) @ Twitter\n- Epeli @ freenode/IRCnet\n\n[Express]: http://expressjs.com/\n[Node.js]: http://nodejs.org/\n[Live.js]: http://livejs.com/\n[LESS]: http://lesscss.org/\n[Stylus]: http://learnboost.github.com/stylus/\n[nib]: https://github.com/visionmedia/nib\n[npm]: http://npmjs.org/\n[CoffeeScript]: http://jashkenas.github.com/coffee-script/\n\n\n", + "readmeFilename": "README.md", + "_id": "piler@0.5.0", + "dist": { + "shasum": "3307b42b33ec2011eddc84f688e69d3410dfe89f" + }, + "_from": "piler@", + "_resolved": "https://registry.npmjs.org/piler/-/piler-0.5.0.tgz" +} diff --git a/node_modules/piler/run-tests-travis.sh b/node_modules/piler/run-tests-travis.sh new file mode 100755 index 0000000..ecd34f2 --- /dev/null +++ b/node_modules/piler/run-tests-travis.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +(cd spec/testapp && coffee app.coffee) & +(cd spec/testapp && NODE_ENV=production coffee app.coffee) & + +sleep 1 + +node_modules/.bin/jasmine-node --coffee spec/ + +echo "Also review the visual tests" +echo " cd spec/testapp/" +echo " coffee app.coffee" +echo "and open http://localhost:7000/" diff --git a/node_modules/piler/run-tests.sh b/node_modules/piler/run-tests.sh new file mode 100755 index 0000000..280ab1e --- /dev/null +++ b/node_modules/piler/run-tests.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +(cd spec/testapp && coffee app.coffee) & +(cd spec/testapp && NODE_ENV=production coffee app.coffee) & + +sleep 1 + +node_modules/.bin/jasmine-node --coffee spec/ + +kill 0 diff --git a/node_modules/piler/spec/acceptance.spec.coffee b/node_modules/piler/spec/acceptance.spec.coffee new file mode 100644 index 0000000..00f94db --- /dev/null +++ b/node_modules/piler/spec/acceptance.spec.coffee @@ -0,0 +1,115 @@ +util = require "util" + +async = require "async" +request = require "request" +zombie = require "zombie" + +{CSSLint} = require "csslint" + +rules = CSSLint.getRules().filter (rule) -> rule.id is "errors" +CSSLint.clearRules() +CSSLint.addRule r for r in rules + +validateCSS = CSSLint.verify + +servers = + development: 7000 + production: 7001 + + +for type, port of servers then do (type, port) -> + + fetchPage = (path) -> -> + jasmine.asyncSpecWait() + @browser = new zombie.Browser() + @httpRoot = "http://localhost:#{ port }" + @browser.visit @httpRoot + path, (err, browser) -> + throw err if err + jasmine.asyncSpecDone() + + describe "JS assets in #{ type } server", -> + + beforeEach fetchPage "/" + + it "Can share plain js files from fs", -> + expect(@browser.window["js fs"]).toEqual true + + it "can share raw js strings", -> + expect(@browser.window["raw js"]).toEqual true + + it "has no namespaced raw js here", -> + expect(@browser.window["raw namespace js"]).toBeUndefined() + + it "Coffee script files get compiled transparently", -> + expect(@browser.window["coffee fs"]).toEqual true + + it "addOb adds global variables", -> + expect(@browser.window["addOb global"]).toEqual true + + it "addOb does not override namespace objects", -> + expect(@browser.window.namespaceob.second).toEqual true, "second addOb missing" + expect(@browser.window.namespaceob.first).toEqual true, "first addOb missing" + + it "js.addExec gets executed", -> + expect(@browser.window["js exec"]).toEqual true + + it "addUrl can load assets from remote servers", -> + expect(@browser.window["remote script"]).toEqual true + + it "No namespaced js here", -> + expect(@browser.window["namespace"]).toBeUndefined() + + + describe "Namespaced JS assets in #{ type } server", -> + + beforeEach fetchPage "/namespace" + + it "We have namaspaced js here", -> + expect(@browser.window["namespace"]).toEqual true + + it "We have also global js", -> + expect(@browser.window["js fs"]).toEqual true + + it "namespaced js.addExec gets executed", -> + expect(@browser.window["namespace js exec"]).toEqual true + + it "can share raw js strings in namespaces", -> + expect(@browser.window["raw namespace js"]).toEqual true + + describe "CSS assets in #{ type } server", -> + + beforeEach fetchPage "/" + + it "We have css links", -> + $ = @browser.window.jQuery + expect($("link[rel='stylesheet']").size()).toBeGreaterThan 0 + + it "has valid CSS", -> + $ = @browser.window.jQuery + + cssUrls = $("link[rel='stylesheet']").map -> this.href + + jasmine.asyncSpecWait() + + async.reduce cssUrls, "", (memo, path, cb) => + request @httpRoot + path, (err, res, body) -> + # console.log res.statusCode, path + expect(res.statusCode).toBe 200, "#{ path } is missing" + return cb err if err + cb null, memo + body + , (err, css) -> + expect(err).toBeFalsy() + + # Just use csslint to validate that we have sane css here until we come + # up with something better. This will at least confirm that + # preprocessors work. + result = validateCSS css,rules + expect(result.messages.length).toBe 0, "#{ util.inspect result.messages }" + jasmine.asyncSpecDone() + + + + + + + diff --git a/node_modules/piler/spec/asseturlparser.spec.coffee b/node_modules/piler/spec/asseturlparser.spec.coffee new file mode 100644 index 0000000..2586ec2 --- /dev/null +++ b/node_modules/piler/spec/asseturlparser.spec.coffee @@ -0,0 +1,92 @@ + +assetUrlParse = require "../lib/asseturlparse" + +describe "parses url production url", -> + for url in [ "/pile/min/cachekey/my.js?v=43234", "/pile/min/my.js"] + urlOb = assetUrlParse url + + it "is minified", -> + expect(urlOb.min).toBeDefined() + + it "name is my", -> + expect(urlOb.name).toBe "my" + + it "has extension js", -> + expect(urlOb.ext).toBe "js" + +describe "can find global", -> + urlOb = assetUrlParse "/pile/min/cachekey/global.js?v=67cc16bec85749bfe34592397e4a31b0f47d4c59" + + it "has the default global", -> + + expect(urlOb.min).toBeDefined() + expect(urlOb.dev).toBeUndefined() + expect(urlOb.name).toBe "global" + + it "has extension js", -> + expect(urlOb.ext).toBe "js" + + + +describe "parses url development url", -> + for url in [ "/pile/dev/cachekey/my.exec-123.js?v=43234", "/pile/dev/cachekey/my.exec-123.js"] + urlOb = assetUrlParse url + + it "name is my", -> + expect(urlOb.name).toBe "my" + + it "is dev", -> + expect(urlOb.dev).toBeDefined() + + it "has uid 123", -> + expect(urlOb.dev.uid).toBe "123" + + it "has type exec", -> + expect(urlOb.dev.type).toBe "exec" + + it "has ext js", -> + expect(urlOb.ext).toBe "js" + + +describe "parses css urls too", -> + for url in [ "/pile/dev/cachekey/my.file-321.css?v=43234", "/pile/dev/cachekey/my.file-321.css"] + urlOb = assetUrlParse url + + it "is css", -> + expect(urlOb.ext).toBe "css" + + it "is dev", -> + expect(urlOb.dev).toBeDefined() + + it "is has name my", -> + expect(urlOb.name).toBe "my" + + +describe "longer custom url root works too", -> + urlOb = assetUrlParse "/node-pile/pile/min/cachekey/global.js?v=67cc16bec85749bfe34592397e4a31b0f47d4c59" + + it "is min", -> + expect(urlOb.min).toBeDefined() + + it "is not development", -> + expect(urlOb.dev).toBeUndefined() + + it "it is the global pile", -> + expect(urlOb.name).toBe "global" + + +describe "longer custom url root works too and in development", -> + urlOb = assetUrlParse "/node-pile/pile/dev/cachekey/my.file-321.css?v=43234" + + it "is min", -> + expect(urlOb.min).toBeUndefined() + + it "is not development", -> + expect(urlOb.dev).toBeDefined() + + it "it is the global pile", -> + expect(urlOb.name).toBe "my" + + it "has id 321", -> + expect(urlOb.dev.uid).toBe "321" + diff --git a/node_modules/piler/spec/basepile.spec.coffee b/node_modules/piler/spec/basepile.spec.coffee new file mode 100644 index 0000000..fbaa3c9 --- /dev/null +++ b/node_modules/piler/spec/basepile.spec.coffee @@ -0,0 +1,33 @@ + +{JSPile, CSSPile, JSManager, CSSManager} = require "../lib/piler" + +for Pile in [JSPile, CSSPile] then do (Pile) -> + + describe "addFile works as expected in #{ Pile.name }", -> + dummyPath = "/foo/bar" + + it "Pile addFile adds up to one file", -> + js = new Pile + js.addFile dummyPath + expect(js.code.length).toBe 1 + + it "Pile addFile cannot make duplicates", -> + js = new Pile + js.addFile dummyPath + js.addFile dummyPath + expect(js.code.length).toBe 1 + + + describe "addUrl works as expected in #{ Pile.name }", -> + dummyUrl = "http://example.com/test.js" + + it "Pile addUrl adds up to one url", -> + js = new Pile + js.addUrl dummyUrl + expect(js.urls.length).toBe 1 + + it "Pile addUrl cannot make duplicates", -> + js = new Pile + js.addUrl dummyUrl + js.addUrl dummyUrl + expect(js.urls.length).toBe 1 diff --git a/node_modules/piler/spec/hrefupdater.spec.coffee b/node_modules/piler/spec/hrefupdater.spec.coffee new file mode 100644 index 0000000..2294956 --- /dev/null +++ b/node_modules/piler/spec/hrefupdater.spec.coffee @@ -0,0 +1,13 @@ + +{incUrlSeq} = require "../lib/livecss" + + +describe "incUrlSeq increases the id in the url", -> + url = "/foo/bar.js?v=123" + + it "adds id in to url", -> + expect(incUrlSeq url).toBe url.replace('.','--1.') + + it "increases existing id", -> + url2 = incUrlSeq url + expect(incUrlSeq url2).toBe url.replace('.','--2.') diff --git a/node_modules/piler/spec/testapp/app.coffee b/node_modules/piler/spec/testapp/app.coffee new file mode 100644 index 0000000..6770b2f --- /dev/null +++ b/node_modules/piler/spec/testapp/app.coffee @@ -0,0 +1,68 @@ +express = require "express" +pile = require("../../index") + +js = pile.createJSManager() +css = pile.createCSSManager() + + +app = express.createServer() +app.configure -> + app.use express.static __dirname + '/clientscripts' + +js.bind app +css.bind app + + +css.addFile __dirname + "/stylesheets/style.css" +css.addFile "namespaced", __dirname + "/stylesheets/namespaced.css" +css.addFile __dirname + "/stylesheets/style.styl" +css.addFile __dirname + "/stylesheets/import.styl" +css.addFile __dirname + "/stylesheets/style.less" +css.addRaw "#raw { display: none }" + + +js.addOb "addOb global": true + +js.addUrl "/remote.js" + +js.addFile __dirname + "/clientscripts/jquery.js" +js.addFile __dirname + "/clientscripts/global.js" +js.addFile __dirname + "/clientscripts/global.coffee" + +js.addRaw "window['raw js'] = true;" +js.addRaw "mynamespace", "window['raw namespace js'] = true;" +# js.addModule __dirname + "/sharedmodule.coffee" + +js.addFile "mynamespace", __dirname + "/clientscripts/namespace.js" + + +js.addExec -> + window["js exec"] = true + +js.addExec "mynamespace", -> + window["namespace js exec"] = true + + +js.addOb "namespaceob.first": true +js.addOb "namespaceob.second": true + +app.get "/namespace", (req, res) -> + res.render "namespace.jade", + layout: false + js: js.renderTags "mynamespace" + css: css.renderTags "mynamespace" + + + +app.get "/", (req, res) -> + + res.render "index.jade", + js: js.renderTags() + css: css.renderTags("namespaced") + + +port = if process.env.NODE_ENV is "production" then 7001 else 7000 + +app.listen port +console.log "server running on port #{ port }" + diff --git a/node_modules/piler/spec/testapp/clientscripts/global.coffee b/node_modules/piler/spec/testapp/clientscripts/global.coffee new file mode 100644 index 0000000..32aa31b --- /dev/null +++ b/node_modules/piler/spec/testapp/clientscripts/global.coffee @@ -0,0 +1,3 @@ + +window["coffee fs"] = true + diff --git a/node_modules/piler/spec/testapp/clientscripts/global.js b/node_modules/piler/spec/testapp/clientscripts/global.js new file mode 100644 index 0000000..1393dc2 --- /dev/null +++ b/node_modules/piler/spec/testapp/clientscripts/global.js @@ -0,0 +1,2 @@ + +window["js fs"] = true; diff --git a/node_modules/piler/spec/testapp/clientscripts/jquery.js b/node_modules/piler/spec/testapp/clientscripts/jquery.js new file mode 100644 index 0000000..f3201aa --- /dev/null +++ b/node_modules/piler/spec/testapp/clientscripts/jquery.js @@ -0,0 +1,8981 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z])/ig, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Converts a dashed string to camelCased string; + // Used by both the css and data modules + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action ]( returned ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
    a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0 + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: -1000, + top: -1000 + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? + // Check for both converted-to-camel and non-converted data property names + thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] : + thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + rinvalidChar = /\:|^on/, + formHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + + hooks = boolHook; + + // Use formHook for forms and if the name contains certain characters + } else if ( formHook && name !== "className" && + (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { + + hooks = formHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + }, + // Use the value property for back compat + // Use the formHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: {} +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + return jQuery.prop( elem, name ) ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // propFix is more comprehensive and contains all fixes + jQuery.attrFix = jQuery.propFix; + + // Use this for any attribute on a form in IE6/7 + formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + +``` + +For more thorough examples, look at the `examples/` directory. + +## Short recipes + +### Sending and receiving events. + +Socket.IO allows you to emit and receive custom events. +Besides `connect`, `message` and `disconnect`, you can emit custom events: + +```js +// note, io.listen() will create a http server for you +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + io.sockets.emit('this', { will: 'be received by everyone' }); + + socket.on('private message', function (from, msg) { + console.log('I received a private message by ', from, ' saying ', msg); + }); + + socket.on('disconnect', function () { + io.sockets.emit('user disconnected'); + }); +}); +``` + +### Storing data associated to a client + +Sometimes it's necessary to store data associated with a client that's +necessary for the duration of the session. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('set nickname', function (name) { + socket.set('nickname', name, function () { socket.emit('ready'); }); + }); + + socket.on('msg', function () { + socket.get('nickname', function (err, name) { + console.log('Chat message by ', name); + }); + }); +}); +``` + +#### Client side + +```html + +``` + +### Restricting yourself to a namespace + +If you have control over all the messages and events emitted for a particular +application, using the default `/` namespace works. + +If you want to leverage 3rd-party code, or produce code to share with others, +socket.io provides a way of namespacing a `socket`. + +This has the benefit of `multiplexing` a single connection. Instead of +socket.io using two `WebSocket` connections, it'll use one. + +The following example defines a socket that listens on '/chat' and one for +'/news': + +#### Server side + +```js +var io = require('socket.io').listen(80); + +var chat = io + .of('/chat') + .on('connection', function (socket) { + socket.emit('a message', { that: 'only', '/chat': 'will get' }); + chat.emit('a message', { everyone: 'in', '/chat': 'will get' }); + }); + +var news = io + .of('/news'); + .on('connection', function (socket) { + socket.emit('item', { news: 'item' }); + }); +``` + +#### Client side: + +```html + +``` + +### Sending volatile messages. + +Sometimes certain messages can be dropped. Let's say you have an app that +shows realtime tweets for the keyword `bieber`. + +If a certain client is not ready to receive messages (because of network slowness +or other issues, or because he's connected through long polling and is in the +middle of a request-response cycle), if he doesn't receive ALL the tweets related +to bieber your application won't suffer. + +In that case, you might want to send those messages as volatile messages. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + var tweets = setInterval(function () { + getBieberTweet(function (tweet) { + socket.volatile.emit('bieber tweet', tweet); + }); + }, 100); + + socket.on('disconnect', function () { + clearInterval(tweets); + }); +}); +``` + +#### Client side + +In the client side, messages are received the same way whether they're volatile +or not. + +### Getting acknowledgements + +Sometimes, you might want to get a callback when the client confirmed the message +reception. + +To do this, simply pass a function as the last parameter of `.send` or `.emit`. +What's more, when you use `.emit`, the acknowledgement is done by you, which +means you can also pass data along: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('ferret', function (name, fn) { + fn('woot'); + }); +}); +``` + +#### Client side + +```html + +``` + +### Broadcasting messages + +To broadcast, simply add a `broadcast` flag to `emit` and `send` method calls. +Broadcasting means sending a message to everyone else except for the socket +that starts it. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.broadcast.emit('user connected'); + socket.broadcast.json.send({ a: 'message' }); +}); +``` + +### Rooms + +Sometimes you want to put certain sockets in the same room, so that it's easy +to broadcast to all of them together. + +Think of this as built-in channels for sockets. Sockets `join` and `leave` +rooms in each socket. + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.join('justin bieber fans'); + socket.broadcast.to('justin bieber fans').emit('new fan'); + io.sockets.in('rammstein fans').emit('new non-fan'); +}); +``` + +### Using it just as a cross-browser WebSocket + +If you just want the WebSocket semantics, you can do that too. +Simply leverage `send` and listen on the `message` event: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.sockets.on('connection', function (socket) { + socket.on('message', function () { }); + socket.on('disconnect', function () { }); +}); +``` + +#### Client side + +```html + +``` + +### Changing configuration + +Configuration in socket.io is TJ-style: + +#### Server side + +```js +var io = require('socket.io').listen(80); + +io.configure(function () { + io.set('transports', ['websocket', 'flashsocket', 'xhr-polling']); +}); + +io.configure('development', function () { + io.set('transports', ['websocket', 'xhr-polling']); + io.enable('log'); +}); +``` + +## License + +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch <guillermo@learnboost.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/socket.io/benchmarks/decode.bench.js b/node_modules/socket.io/benchmarks/decode.bench.js new file mode 100644 index 0000000..4855d80 --- /dev/null +++ b/node_modules/socket.io/benchmarks/decode.bench.js @@ -0,0 +1,64 @@ + +/** + * Module dependencies. + */ + +var benchmark = require('benchmark') + , colors = require('colors') + , io = require('../') + , parser = io.parser + , suite = new benchmark.Suite('Decode packet'); + +suite.add('string', function () { + parser.decodePacket('4:::"2"'); +}); + +suite.add('event', function () { + parser.decodePacket('5:::{"name":"woot"}'); +}); + +suite.add('event+ack', function () { + parser.decodePacket('5:1+::{"name":"tobi"}'); +}); + +suite.add('event+data', function () { + parser.decodePacket('5:::{"name":"edwald","args":[{"a": "b"},2,"3"]}'); +}); + +suite.add('heartbeat', function () { + parser.decodePacket('2:::'); +}); + +suite.add('error', function () { + parser.decodePacket('7:::2+0'); +}); + +var payload = parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) +]); + +suite.add('payload', function () { + parser.decodePayload(payload); +}); + +suite.on('cycle', function (bench, details) { + console.log('\n' + suite.name.grey, details.name.white.bold); + console.log([ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/socket.io/benchmarks/encode.bench.js b/node_modules/socket.io/benchmarks/encode.bench.js new file mode 100644 index 0000000..5037702 --- /dev/null +++ b/node_modules/socket.io/benchmarks/encode.bench.js @@ -0,0 +1,90 @@ + +/** + * Module dependencies. + */ + +var benchmark = require('benchmark') + , colors = require('colors') + , io = require('../') + , parser = io.parser + , suite = new benchmark.Suite('Encode packet'); + +suite.add('string', function () { + parser.encodePacket({ + type: 'json' + , endpoint: '' + , data: '2' + }); +}); + +suite.add('event', function () { + parser.encodePacket({ + type: 'event' + , name: 'woot' + , endpoint: '' + , args: [] + }); +}); + +suite.add('event+ack', function () { + parser.encodePacket({ + type: 'json' + , id: 1 + , ack: 'data' + , endpoint: '' + , data: { a: 'b' } + }); +}); + +suite.add('event+data', function () { + parser.encodePacket({ + type: 'event' + , name: 'edwald' + , endpoint: '' + , args: [{a: 'b'}, 2, '3'] + }); +}); + +suite.add('heartbeat', function () { + parser.encodePacket({ + type: 'heartbeat' + , endpoint: '' + }) +}); + +suite.add('error', function () { + parser.encodePacket({ + type: 'error' + , reason: 'unauthorized' + , advice: 'reconnect' + , endpoint: '' + }) +}) + +suite.add('payload', function () { + parser.encodePayload([ + parser.encodePacket({ type: 'message', data: '5', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: '53d', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbazfoobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobarbaz', endpoint: '' }) + , parser.encodePacket({ type: 'message', data: 'foobar', endpoint: '' }) + ]); +}); + +suite.on('cycle', function (bench, details) { + console.log('\n' + suite.name.grey, details.name.white.bold); + console.log([ + details.hz.toFixed(2).cyan + ' ops/sec'.grey + , details.count.toString().white + ' times executed'.grey + , 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey + , + ].join(', '.grey)); +}); + +if (!module.parent) { + suite.run(); +} else { + module.exports = suite; +} diff --git a/node_modules/socket.io/benchmarks/runner.js b/node_modules/socket.io/benchmarks/runner.js new file mode 100644 index 0000000..81e55ca --- /dev/null +++ b/node_modules/socket.io/benchmarks/runner.js @@ -0,0 +1,55 @@ +/** + * Benchmark runner dependencies + */ + +var colors = require('colors') + , path = require('path'); + +/** + * Find all the benchmarks + */ + +var benchmarks_files = process.env.BENCHMARKS.split(' ') + , all = [].concat(benchmarks_files) + , first = all.shift() + , benchmarks = {}; + +// find the benchmarks and load them all in our obj +benchmarks_files.forEach(function (file) { + benchmarks[file] = require(path.join(__dirname, '..', file)); +}); + +// setup the complete listeners +benchmarks_files.forEach(function (file) { + var benchmark = benchmarks[file] + , next_file = all.shift() + , next = benchmarks[next_file]; + + /** + * Generate a oncomplete function for the tests, either we are done or we + * have more benchmarks to process. + */ + + function complete () { + if (!next) { + console.log( + '\n\nBenchmark completed in'.grey + , (Date.now() - start).toString().green + ' ms'.grey + ); + } else { + console.log('\nStarting benchmark '.grey + next_file.yellow); + next.run(); + } + } + + // attach the listener + benchmark.on('complete', complete); +}); + +/** + * Start the benchmark + */ + +var start = Date.now(); +console.log('Starting benchmark '.grey + first.yellow); +benchmarks[first].run(); diff --git a/node_modules/socket.io/index.js b/node_modules/socket.io/index.js new file mode 100644 index 0000000..cc00c10 --- /dev/null +++ b/node_modules/socket.io/index.js @@ -0,0 +1,8 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +module.exports = require('./lib/socket.io'); diff --git a/node_modules/socket.io/lib/logger.js b/node_modules/socket.io/lib/logger.js new file mode 100644 index 0000000..49d02c9 --- /dev/null +++ b/node_modules/socket.io/lib/logger.js @@ -0,0 +1,97 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var util = require('./util') + , toArray = util.toArray; + +/** + * Log levels. + */ + +var levels = [ + 'error' + , 'warn' + , 'info' + , 'debug' +]; + +/** + * Colors for log levels. + */ + +var colors = [ + 31 + , 33 + , 36 + , 90 +]; + +/** + * Pads the nice output to the longest log level. + */ + +function pad (str) { + var max = 0; + + for (var i = 0, l = levels.length; i < l; i++) + max = Math.max(max, levels[i].length); + + if (str.length < max) + return str + new Array(max - str.length + 1).join(' '); + + return str; +}; + +/** + * Logger (console). + * + * @api public + */ + +var Logger = module.exports = function (opts) { + opts = opts || {} + this.colors = false !== opts.colors; + this.level = 3; + this.enabled = true; +}; + +/** + * Log method. + * + * @api public + */ + +Logger.prototype.log = function (type) { + var index = levels.indexOf(type); + + if (index > this.level || !this.enabled) + return this; + + console.log.apply( + console + , [this.colors + ? ' \033[' + colors[index] + 'm' + pad(type) + ' -\033[39m' + : type + ':' + ].concat(toArray(arguments).slice(1)) + ); + + return this; +}; + +/** + * Generate methods. + */ + +levels.forEach(function (name) { + Logger.prototype[name] = function () { + this.log.apply(this, [name].concat(toArray(arguments))); + }; +}); diff --git a/node_modules/socket.io/lib/manager.js b/node_modules/socket.io/lib/manager.js new file mode 100644 index 0000000..8393785 --- /dev/null +++ b/node_modules/socket.io/lib/manager.js @@ -0,0 +1,1027 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , url = require('url') + , tty = require('tty') + , crypto = require('crypto') + , util = require('./util') + , store = require('./store') + , client = require('socket.io-client') + , transports = require('./transports') + , Logger = require('./logger') + , Socket = require('./socket') + , MemoryStore = require('./stores/memory') + , SocketNamespace = require('./namespace') + , Static = require('./static') + , EventEmitter = process.EventEmitter; + +/** + * Export the constructor. + */ + +exports = module.exports = Manager; + +/** + * Default transports. + */ + +var defaultTransports = exports.defaultTransports = [ + 'websocket' + , 'htmlfile' + , 'xhr-polling' + , 'jsonp-polling' +]; + +/** + * Inherited defaults. + */ + +var parent = module.parent.exports + , protocol = parent.protocol + , jsonpolling_re = /^\d+$/; + +/** + * Manager constructor. + * + * @param {HTTPServer} server + * @param {Object} options, optional + * @api public + */ + +function Manager (server, options) { + this.server = server; + this.namespaces = {}; + this.sockets = this.of(''); + this.settings = { + origins: '*:*' + , log: true + , store: new MemoryStore + , logger: new Logger + , static: new Static(this) + , heartbeats: true + , resource: '/socket.io' + , transports: defaultTransports + , authorization: false + , blacklist: ['disconnect'] + , 'log level': 3 + , 'log colors': tty.isatty(process.stdout.fd) + , 'close timeout': 60 + , 'heartbeat interval': 25 + , 'heartbeat timeout': 60 + , 'polling duration': 20 + , 'flash policy server': true + , 'flash policy port': 10843 + , 'destroy upgrade': true + , 'destroy buffer size': 10E7 + , 'browser client': true + , 'browser client cache': true + , 'browser client minification': false + , 'browser client etag': false + , 'browser client expires': 315360000 + , 'browser client gzip': false + , 'browser client handler': false + , 'client store expiration': 15 + , 'match origin protocol': false + }; + + for (var i in options) { + if (options.hasOwnProperty(i)) { + this.settings[i] = options[i]; + } + } + + var self = this; + + // default error handler + server.on('error', function(err) { + self.log.warn('error raised: ' + err); + }); + + this.initStore(); + + this.on('set:store', function() { + self.initStore(); + }); + + // reset listeners + this.oldListeners = server.listeners('request').splice(0); + server.removeAllListeners('request'); + + server.on('request', function (req, res) { + self.handleRequest(req, res); + }); + + server.on('upgrade', function (req, socket, head) { + self.handleUpgrade(req, socket, head); + }); + + server.on('close', function () { + clearInterval(self.gc); + }); + + server.once('listening', function () { + self.gc = setInterval(self.garbageCollection.bind(self), 10000); + }); + + for (var i in transports) { + if (transports.hasOwnProperty(i)) { + if (transports[i].init) { + transports[i].init(this); + } + } + } + + // forward-compatibility with 1.0 + var self = this; + this.sockets.on('connection', function (conn) { + self.emit('connection', conn); + }); + + this.sequenceNumber = Date.now() | 0; + + this.log.info('socket.io started'); +}; + +Manager.prototype.__proto__ = EventEmitter.prototype + +/** + * Store accessor shortcut. + * + * @api public + */ + +Manager.prototype.__defineGetter__('store', function () { + var store = this.get('store'); + store.manager = this; + return store; +}); + +/** + * Logger accessor. + * + * @api public + */ + +Manager.prototype.__defineGetter__('log', function () { + var logger = this.get('logger'); + + logger.level = this.get('log level') || -1; + logger.colors = this.get('log colors'); + logger.enabled = this.enabled('log'); + + return logger; +}); + +/** + * Static accessor. + * + * @api public + */ + +Manager.prototype.__defineGetter__('static', function () { + return this.get('static'); +}); + +/** + * Get settings. + * + * @api public + */ + +Manager.prototype.get = function (key) { + return this.settings[key]; +}; + +/** + * Set settings + * + * @api public + */ + +Manager.prototype.set = function (key, value) { + if (arguments.length == 1) return this.get(key); + this.settings[key] = value; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Enable a setting + * + * @api public + */ + +Manager.prototype.enable = function (key) { + this.settings[key] = true; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Disable a setting + * + * @api public + */ + +Manager.prototype.disable = function (key) { + this.settings[key] = false; + this.emit('set:' + key, this.settings[key], key); + return this; +}; + +/** + * Checks if a setting is enabled + * + * @api public + */ + +Manager.prototype.enabled = function (key) { + return !!this.settings[key]; +}; + +/** + * Checks if a setting is disabled + * + * @api public + */ + +Manager.prototype.disabled = function (key) { + return !this.settings[key]; +}; + +/** + * Configure callbacks. + * + * @api public + */ + +Manager.prototype.configure = function (env, fn) { + if ('function' == typeof env) { + env.call(this); + } else if (env == (process.env.NODE_ENV || 'development')) { + fn.call(this); + } + + return this; +}; + +/** + * Initializes everything related to the message dispatcher. + * + * @api private + */ + +Manager.prototype.initStore = function () { + this.handshaken = {}; + this.connected = {}; + this.open = {}; + this.closed = {}; + this.rooms = {}; + this.roomClients = {}; + + var self = this; + + this.store.subscribe('handshake', function (id, data) { + self.onHandshake(id, data); + }); + + this.store.subscribe('connect', function (id) { + self.onConnect(id); + }); + + this.store.subscribe('open', function (id) { + self.onOpen(id); + }); + + this.store.subscribe('join', function (id, room) { + self.onJoin(id, room); + }); + + this.store.subscribe('leave', function (id, room) { + self.onLeave(id, room); + }); + + this.store.subscribe('close', function (id) { + self.onClose(id); + }); + + this.store.subscribe('dispatch', function (room, packet, volatile, exceptions) { + self.onDispatch(room, packet, volatile, exceptions); + }); + + this.store.subscribe('disconnect', function (id) { + self.onDisconnect(id); + }); +}; + +/** + * Called when a client handshakes. + * + * @param text + */ + +Manager.prototype.onHandshake = function (id, data) { + this.handshaken[id] = data; +}; + +/** + * Called when a client connects (ie: transport first opens) + * + * @api private + */ + +Manager.prototype.onConnect = function (id) { + this.connected[id] = true; +}; + +/** + * Called when a client opens a request in a different node. + * + * @api private + */ + +Manager.prototype.onOpen = function (id) { + this.open[id] = true; + + if (this.closed[id]) { + var self = this; + + this.store.unsubscribe('dispatch:' + id, function () { + var transport = self.transports[id]; + if (self.closed[id] && self.closed[id].length && transport) { + + // if we have buffered messages that accumulate between calling + // onOpen an this async callback, send them if the transport is + // still open, otherwise leave them buffered + if (transport.open) { + transport.payload(self.closed[id]); + self.closed[id] = []; + } + } + }); + } + + // clear the current transport + if (this.transports[id]) { + this.transports[id].discard(); + this.transports[id] = null; + } +}; + +/** + * Called when a message is sent to a namespace and/or room. + * + * @api private + */ + +Manager.prototype.onDispatch = function (room, packet, volatile, exceptions) { + if (this.rooms[room]) { + for (var i = 0, l = this.rooms[room].length; i < l; i++) { + var id = this.rooms[room][i]; + + if (!~exceptions.indexOf(id)) { + if (this.transports[id] && this.transports[id].open) { + this.transports[id].onDispatch(packet, volatile); + } else if (!volatile) { + this.onClientDispatch(id, packet); + } + } + } + } +}; + +/** + * Called when a client joins a nsp / room. + * + * @api private + */ + +Manager.prototype.onJoin = function (id, name) { + if (!this.roomClients[id]) { + this.roomClients[id] = {}; + } + + if (!this.rooms[name]) { + this.rooms[name] = []; + } + + if (!~this.rooms[name].indexOf(id)) { + this.rooms[name].push(id); + this.roomClients[id][name] = true; + } +}; + +/** + * Called when a client leaves a nsp / room. + * + * @param private + */ + +Manager.prototype.onLeave = function (id, room) { + if (this.rooms[room]) { + var index = this.rooms[room].indexOf(id); + + if (index >= 0) { + this.rooms[room].splice(index, 1); + } + + if (!this.rooms[room].length) { + delete this.rooms[room]; + } + + if (this.roomClients[id]) { + delete this.roomClients[id][room]; + } + } +}; + +/** + * Called when a client closes a request in different node. + * + * @api private + */ + +Manager.prototype.onClose = function (id) { + if (this.open[id]) { + delete this.open[id]; + } + + this.closed[id] = []; + + var self = this; + + this.store.subscribe('dispatch:' + id, function (packet, volatile) { + if (!volatile) { + self.onClientDispatch(id, packet); + } + }); +}; + +/** + * Dispatches a message for a closed client. + * + * @api private + */ + +Manager.prototype.onClientDispatch = function (id, packet) { + if (this.closed[id]) { + this.closed[id].push(packet); + } +}; + +/** + * Receives a message for a client. + * + * @api private + */ + +Manager.prototype.onClientMessage = function (id, packet) { + if (this.namespaces[packet.endpoint]) { + this.namespaces[packet.endpoint].handlePacket(id, packet); + } +}; + +/** + * Fired when a client disconnects (not triggered). + * + * @api private + */ + +Manager.prototype.onClientDisconnect = function (id, reason) { + for (var name in this.namespaces) { + if (this.namespaces.hasOwnProperty(name)) { + this.namespaces[name].handleDisconnect(id, reason, typeof this.roomClients[id] !== 'undefined' && + typeof this.roomClients[id][name] !== 'undefined'); + } + } + + this.onDisconnect(id); +}; + +/** + * Called when a client disconnects. + * + * @param text + */ + +Manager.prototype.onDisconnect = function (id, local) { + delete this.handshaken[id]; + + if (this.open[id]) { + delete this.open[id]; + } + + if (this.connected[id]) { + delete this.connected[id]; + } + + if (this.transports[id]) { + this.transports[id].discard(); + delete this.transports[id]; + } + + if (this.closed[id]) { + delete this.closed[id]; + } + + if (this.roomClients[id]) { + for (var room in this.roomClients[id]) { + if (this.roomClients[id].hasOwnProperty(room)) { + this.onLeave(id, room); + } + } + delete this.roomClients[id] + } + + this.store.destroyClient(id, this.get('client store expiration')); + + this.store.unsubscribe('dispatch:' + id); + + if (local) { + this.store.unsubscribe('message:' + id); + this.store.unsubscribe('disconnect:' + id); + } +}; + +/** + * Handles an HTTP request. + * + * @api private + */ + +Manager.prototype.handleRequest = function (req, res) { + var data = this.checkRequest(req); + + if (!data) { + for (var i = 0, l = this.oldListeners.length; i < l; i++) { + this.oldListeners[i].call(this.server, req, res); + } + + return; + } + + if (data.static || !data.transport && !data.protocol) { + if (data.static && this.enabled('browser client')) { + this.static.write(data.path, req, res); + } else { + res.writeHead(200); + res.end('Welcome to socket.io.'); + + this.log.info('unhandled socket.io url'); + } + + return; + } + + if (data.protocol != protocol) { + res.writeHead(500); + res.end('Protocol version not supported.'); + + this.log.info('client protocol version unsupported'); + } else { + if (data.id) { + this.handleHTTPRequest(data, req, res); + } else { + this.handleHandshake(data, req, res); + } + } +}; + +/** + * Handles an HTTP Upgrade. + * + * @api private + */ + +Manager.prototype.handleUpgrade = function (req, socket, head) { + var data = this.checkRequest(req) + , self = this; + + if (!data) { + if (this.enabled('destroy upgrade')) { + socket.end(); + this.log.debug('destroying non-socket.io upgrade'); + } + + return; + } + + req.head = head; + this.handleClient(data, req); + req.head = null; +}; + +/** + * Handles a normal handshaken HTTP request (eg: long-polling) + * + * @api private + */ + +Manager.prototype.handleHTTPRequest = function (data, req, res) { + req.res = res; + this.handleClient(data, req); +}; + +/** + * Intantiantes a new client. + * + * @api private + */ + +Manager.prototype.handleClient = function (data, req) { + var socket = req.socket + , store = this.store + , self = this; + + // handle sync disconnect xhrs + if (undefined != data.query.disconnect) { + if (this.transports[data.id] && this.transports[data.id].open) { + this.transports[data.id].onForcedDisconnect(); + } else { + this.store.publish('disconnect-force:' + data.id); + } + req.res.writeHead(200); + req.res.end(); + return; + } + + if (!~this.get('transports').indexOf(data.transport)) { + this.log.warn('unknown transport: "' + data.transport + '"'); + req.connection.end(); + return; + } + + var transport = new transports[data.transport](this, data, req) + , handshaken = this.handshaken[data.id]; + + if (transport.disconnected) { + // failed during transport setup + req.connection.end(); + return; + } + if (handshaken) { + if (transport.open) { + if (this.closed[data.id] && this.closed[data.id].length) { + transport.payload(this.closed[data.id]); + this.closed[data.id] = []; + } + + this.onOpen(data.id); + this.store.publish('open', data.id); + this.transports[data.id] = transport; + } + + if (!this.connected[data.id]) { + this.onConnect(data.id); + this.store.publish('connect', data.id); + + // flag as used + delete handshaken.issued; + this.onHandshake(data.id, handshaken); + this.store.publish('handshake', data.id, handshaken); + + // initialize the socket for all namespaces + for (var i in this.namespaces) { + if (this.namespaces.hasOwnProperty(i)) { + var socket = this.namespaces[i].socket(data.id, true); + + // echo back connect packet and fire connection event + if (i === '') { + this.namespaces[i].handlePacket(data.id, { type: 'connect' }); + } + } + } + + this.store.subscribe('message:' + data.id, function (packet) { + self.onClientMessage(data.id, packet); + }); + + this.store.subscribe('disconnect:' + data.id, function (reason) { + self.onClientDisconnect(data.id, reason); + }); + } + } else { + if (transport.open) { + transport.error('client not handshaken', 'reconnect'); + } + + transport.discard(); + } +}; + +/** + * Generates a session id. + * + * @api private + */ + +Manager.prototype.generateId = function () { + var rand = new Buffer(15); // multiple of 3 for base64 + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = (this.sequenceNumber + 1) | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + crypto.randomBytes(12).copy(rand); + } else { + // not secure for node 0.4 + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); +}; + +/** + * Handles a handshake request. + * + * @api private + */ + +Manager.prototype.handleHandshake = function (data, req, res) { + var self = this + , origin = req.headers.origin + , headers = { + 'Content-Type': 'text/plain' + }; + + function writeErr (status, message) { + if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) { + res.writeHead(200, { 'Content-Type': 'application/javascript' }); + res.end('io.j[' + data.query.jsonp + '](new Error("' + message + '"));'); + } else { + res.writeHead(status, headers); + res.end(message); + } + }; + + function error (err) { + writeErr(500, 'handshake error'); + self.log.warn('handshake error ' + err); + }; + + if (!this.verifyOrigin(req)) { + writeErr(403, 'handshake bad origin'); + return; + } + + var handshakeData = this.handshakeData(data); + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + + this.authorize(handshakeData, function (err, authorized, newData) { + if (err) return error(err); + + if (authorized) { + var id = self.generateId() + , hs = [ + id + , self.enabled('heartbeats') ? self.get('heartbeat timeout') || '' : '' + , self.get('close timeout') || '' + , self.transports(data).join(',') + ].join(':'); + + if (data.query.jsonp && jsonpolling_re.test(data.query.jsonp)) { + hs = 'io.j[' + data.query.jsonp + '](' + JSON.stringify(hs) + ');'; + res.writeHead(200, { 'Content-Type': 'application/javascript' }); + } else { + res.writeHead(200, headers); + } + + res.end(hs); + + self.onHandshake(id, newData || handshakeData); + self.store.publish('handshake', id, newData || handshakeData); + + self.log.info('handshake authorized', id); + } else { + writeErr(403, 'handshake unauthorized'); + self.log.info('handshake unauthorized'); + } + }) +}; + +/** + * Gets normalized handshake data + * + * @api private + */ + +Manager.prototype.handshakeData = function (data) { + var connection = data.request.connection + , connectionAddress + , date = new Date; + + if (connection.remoteAddress) { + connectionAddress = { + address: connection.remoteAddress + , port: connection.remotePort + }; + } else if (connection.socket && connection.socket.remoteAddress) { + connectionAddress = { + address: connection.socket.remoteAddress + , port: connection.socket.remotePort + }; + } + + return { + headers: data.headers + , address: connectionAddress + , time: date.toString() + , query: data.query + , url: data.request.url + , xdomain: !!data.request.headers.origin + , secure: data.request.connection.secure + , issued: +date + }; +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +Manager.prototype.verifyOrigin = function (request) { + var origin = request.headers.origin || request.headers.referer + , origins = this.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from handshake, yet required by config'); + } + return false; +}; + +/** + * Handles an incoming packet. + * + * @api private + */ + +Manager.prototype.handlePacket = function (sessid, packet) { + this.of(packet.endpoint || '').handlePacket(sessid, packet); +}; + +/** + * Performs authentication. + * + * @param Object client request data + * @api private + */ + +Manager.prototype.authorize = function (data, fn) { + if (this.get('authorization')) { + var self = this; + + this.get('authorization').call(this, data, function (err, authorized) { + self.log.debug('client ' + authorized ? 'authorized' : 'unauthorized'); + fn(err, authorized); + }); + } else { + this.log.debug('client authorized'); + fn(null, true); + } + + return this; +}; + +/** + * Retrieves the transports adviced to the user. + * + * @api private + */ + +Manager.prototype.transports = function (data) { + var transp = this.get('transports') + , ret = []; + + for (var i = 0, l = transp.length; i < l; i++) { + var transport = transp[i]; + + if (transport) { + if (!transport.checkClient || transport.checkClient(data)) { + ret.push(transport); + } + } + } + + return ret; +}; + +/** + * Checks whether a request is a socket.io one. + * + * @return {Object} a client request data object or `false` + * @api private + */ + +var regexp = /^\/([^\/]+)\/?([^\/]+)?\/?([^\/]+)?\/?$/ + +Manager.prototype.checkRequest = function (req) { + var resource = this.get('resource'); + + var match; + if (typeof resource === 'string') { + match = req.url.substr(0, resource.length); + if (match !== resource) match = null; + } else { + match = resource.exec(req.url); + if (match) match = match[0]; + } + + if (match) { + var uri = url.parse(req.url.substr(match.length), true) + , path = uri.pathname || '' + , pieces = path.match(regexp); + + // client request data + var data = { + query: uri.query || {} + , headers: req.headers + , request: req + , path: path + }; + + if (pieces) { + data.protocol = Number(pieces[1]); + data.transport = pieces[2]; + data.id = pieces[3]; + data.static = !!this.static.has(path); + }; + + return data; + } + + return false; +}; + +/** + * Declares a socket namespace + * + * @api public + */ + +Manager.prototype.of = function (nsp) { + if (this.namespaces[nsp]) { + return this.namespaces[nsp]; + } + + return this.namespaces[nsp] = new SocketNamespace(this, nsp); +}; + +/** + * Perform garbage collection on long living objects and properties that cannot + * be removed automatically. + * + * @api private + */ + +Manager.prototype.garbageCollection = function () { + // clean up unused handshakes + var ids = Object.keys(this.handshaken) + , i = ids.length + , now = Date.now() + , handshake; + + while (i--) { + handshake = this.handshaken[ids[i]]; + + if ('issued' in handshake && (now - handshake.issued) >= 3E4) { + this.onDisconnect(ids[i]); + } + } +}; diff --git a/node_modules/socket.io/lib/namespace.js b/node_modules/socket.io/lib/namespace.js new file mode 100644 index 0000000..6e1e1c9 --- /dev/null +++ b/node_modules/socket.io/lib/namespace.js @@ -0,0 +1,355 @@ +/** + * Module dependencies. + */ + +var Socket = require('./socket') + , EventEmitter = process.EventEmitter + , parser = require('./parser') + , util = require('./util'); + +/** + * Exports the constructor. + */ + +exports = module.exports = SocketNamespace; + +/** + * Constructor. + * + * @api public. + */ + +function SocketNamespace (mgr, name) { + this.manager = mgr; + this.name = name || ''; + this.sockets = {}; + this.auth = false; + this.setFlags(); +}; + +/** + * Inherits from EventEmitter. + */ + +SocketNamespace.prototype.__proto__ = EventEmitter.prototype; + +/** + * Copies emit since we override it. + * + * @api private + */ + +SocketNamespace.prototype.$emit = EventEmitter.prototype.emit; + +/** + * Retrieves all clients as Socket instances as an array. + * + * @api public + */ + +SocketNamespace.prototype.clients = function (room) { + var room = this.name + (room !== undefined ? + '/' + room : ''); + + if (!this.manager.rooms[room]) { + return []; + } + + return this.manager.rooms[room].map(function (id) { + return this.socket(id); + }, this); +}; + +/** + * Access logger interface. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * Access store. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('store', function () { + return this.manager.store; +}); + +/** + * JSON message flag. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('json', function () { + this.flags.json = true; + return this; +}); + +/** + * Volatile message flag. + * + * @api public + */ + +SocketNamespace.prototype.__defineGetter__('volatile', function () { + this.flags.volatile = true; + return this; +}); + +/** + * Overrides the room to relay messages to (flag). + * + * @api public + */ + +SocketNamespace.prototype.in = SocketNamespace.prototype.to = function (room) { + this.flags.endpoint = this.name + (room ? '/' + room : ''); + return this; +}; + +/** + * Adds a session id we should prevent relaying messages to (flag). + * + * @api public + */ + +SocketNamespace.prototype.except = function (id) { + this.flags.exceptions.push(id); + return this; +}; + +/** + * Sets the default flags. + * + * @api private + */ + +SocketNamespace.prototype.setFlags = function () { + this.flags = { + endpoint: this.name + , exceptions: [] + }; + return this; +}; + +/** + * Sends out a packet. + * + * @api private + */ + +SocketNamespace.prototype.packet = function (packet) { + packet.endpoint = this.name; + + var store = this.store + , log = this.log + , volatile = this.flags.volatile + , exceptions = this.flags.exceptions + , packet = parser.encodePacket(packet); + + this.manager.onDispatch(this.flags.endpoint, packet, volatile, exceptions); + this.store.publish('dispatch', this.flags.endpoint, packet, volatile, exceptions); + + this.setFlags(); + + return this; +}; + +/** + * Sends to everyone. + * + * @api public + */ + +SocketNamespace.prototype.send = function (data) { + return this.packet({ + type: this.flags.json ? 'json' : 'message' + , data: data + }); +}; + +/** + * Emits to everyone (override). + * + * @api public + */ + +SocketNamespace.prototype.emit = function (name) { + if (name == 'newListener') { + return this.$emit.apply(this, arguments); + } + + return this.packet({ + type: 'event' + , name: name + , args: util.toArray(arguments).slice(1) + }); +}; + +/** + * Retrieves or creates a write-only socket for a client, unless specified. + * + * @param {Boolean} whether the socket will be readable when initialized + * @api public + */ + +SocketNamespace.prototype.socket = function (sid, readable) { + if (!this.sockets[sid]) { + this.sockets[sid] = new Socket(this.manager, sid, this, readable); + } + + return this.sockets[sid]; +}; + +/** + * Sets authorization for this namespace. + * + * @api public + */ + +SocketNamespace.prototype.authorization = function (fn) { + this.auth = fn; + return this; +}; + +/** + * Called when a socket disconnects entirely. + * + * @api private + */ + +SocketNamespace.prototype.handleDisconnect = function (sid, reason, raiseOnDisconnect) { + if (this.sockets[sid] && this.sockets[sid].readable) { + if (raiseOnDisconnect) this.sockets[sid].onDisconnect(reason); + delete this.sockets[sid]; + } +}; + +/** + * Performs authentication. + * + * @param Object client request data + * @api private + */ + +SocketNamespace.prototype.authorize = function (data, fn) { + if (this.auth) { + var self = this; + + this.auth.call(this, data, function (err, authorized) { + self.log.debug('client ' + + (authorized ? '' : 'un') + 'authorized for ' + self.name); + fn(err, authorized); + }); + } else { + this.log.debug('client authorized for ' + this.name); + fn(null, true); + } + + return this; +}; + +/** + * Handles a packet. + * + * @api private + */ + +SocketNamespace.prototype.handlePacket = function (sessid, packet) { + var socket = this.socket(sessid) + , dataAck = packet.ack == 'data' + , manager = this.manager + , self = this; + + function ack () { + self.log.debug('sending data ack packet'); + socket.packet({ + type: 'ack' + , args: util.toArray(arguments) + , ackId: packet.id + }); + }; + + function error (err) { + self.log.warn('handshake error ' + err + ' for ' + self.name); + socket.packet({ type: 'error', reason: err }); + }; + + function connect () { + self.manager.onJoin(sessid, self.name); + self.store.publish('join', sessid, self.name); + + // packet echo + socket.packet({ type: 'connect' }); + + // emit connection event + self.$emit('connection', socket); + }; + + switch (packet.type) { + case 'connect': + if (packet.endpoint == '') { + connect(); + } else { + var handshakeData = manager.handshaken[sessid]; + + this.authorize(handshakeData, function (err, authorized, newData) { + if (err) return error(err); + + if (authorized) { + manager.onHandshake(sessid, newData || handshakeData); + self.store.publish('handshake', sessid, newData || handshakeData); + connect(); + } else { + error('unauthorized'); + } + }); + } + break; + + case 'ack': + if (socket.acks[packet.ackId]) { + socket.acks[packet.ackId].apply(socket, packet.args); + } else { + this.log.info('unknown ack packet'); + } + break; + + case 'event': + // check if the emitted event is not blacklisted + if (-~manager.get('blacklist').indexOf(packet.name)) { + this.log.debug('ignoring blacklisted event `' + packet.name + '`'); + } else { + var params = [packet.name].concat(packet.args); + + if (dataAck) { + params.push(ack); + } + + socket.$emit.apply(socket, params); + } + break; + + case 'disconnect': + this.manager.onLeave(sessid, this.name); + this.store.publish('leave', sessid, this.name); + + socket.$emit('disconnect', packet.reason || 'packet'); + break; + + case 'json': + case 'message': + var params = ['message', packet.data]; + + if (dataAck) + params.push(ack); + + socket.$emit.apply(socket, params); + }; +}; diff --git a/node_modules/socket.io/lib/parser.js b/node_modules/socket.io/lib/parser.js new file mode 100644 index 0000000..d56b550 --- /dev/null +++ b/node_modules/socket.io/lib/parser.js @@ -0,0 +1,249 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +/** + * Packet types. + */ + +var packets = exports.packets = { + 'disconnect': 0 + , 'connect': 1 + , 'heartbeat': 2 + , 'message': 3 + , 'json': 4 + , 'event': 5 + , 'ack': 6 + , 'error': 7 + , 'noop': 8 + } + , packetslist = Object.keys(packets); + +/** + * Errors reasons. + */ + +var reasons = exports.reasons = { + 'transport not supported': 0 + , 'client not handshaken': 1 + , 'unauthorized': 2 + } + , reasonslist = Object.keys(reasons); + +/** + * Errors advice. + */ + +var advice = exports.advice = { + 'reconnect': 0 + } + , advicelist = Object.keys(advice); + +/** + * Encodes a packet. + * + * @api private + */ + +exports.encodePacket = function (packet) { + var type = packets[packet.type] + , id = packet.id || '' + , endpoint = packet.endpoint || '' + , ack = packet.ack + , data = null; + + switch (packet.type) { + case 'message': + if (packet.data !== '') + data = packet.data; + break; + + case 'event': + var ev = { name: packet.name }; + + if (packet.args && packet.args.length) { + ev.args = packet.args; + } + + data = JSON.stringify(ev); + break; + + case 'json': + data = JSON.stringify(packet.data); + break; + + case 'ack': + data = packet.ackId + + (packet.args && packet.args.length + ? '+' + JSON.stringify(packet.args) : ''); + break; + + case 'connect': + if (packet.qs) + data = packet.qs; + break; + + case 'error': + var reason = packet.reason ? reasons[packet.reason] : '' + , adv = packet.advice ? advice[packet.advice] : '' + + if (reason !== '' || adv !== '') + data = reason + (adv !== '' ? ('+' + adv) : '') + + break; + } + + // construct packet with required fragments + var encoded = type + ':' + id + (ack == 'data' ? '+' : '') + ':' + endpoint; + + // data fragment is optional + if (data !== null && data !== undefined) + encoded += ':' + data; + + return encoded; +}; + +/** + * Encodes multiple messages (payload). + * + * @param {Array} messages + * @api private + */ + +exports.encodePayload = function (packets) { + var decoded = ''; + + if (packets.length == 1) + return packets[0]; + + for (var i = 0, l = packets.length; i < l; i++) { + var packet = packets[i]; + decoded += '\ufffd' + packet.length + '\ufffd' + packets[i] + } + + return decoded; +}; + +/** + * Decodes a packet + * + * @api private + */ + +var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/; + +/** + * Wrap the JSON.parse in a seperate function the crankshaft optimizer will + * only punish this function for the usage for try catch + * + * @api private + */ + +function parse (data) { + try { return JSON.parse(data) } + catch (e) { return false } +} + +exports.decodePacket = function (data) { + var pieces = data.match(regexp); + + if (!pieces) return {}; + + var id = pieces[2] || '' + , data = pieces[5] || '' + , packet = { + type: packetslist[pieces[1]] + , endpoint: pieces[4] || '' + }; + + // whether we need to acknowledge the packet + if (id) { + packet.id = id; + if (pieces[3]) + packet.ack = 'data'; + else + packet.ack = true; + } + + // handle different packet types + switch (packet.type) { + case 'message': + packet.data = data || ''; + break; + + case 'event': + pieces = parse(data); + if (pieces) { + packet.name = pieces.name; + packet.args = pieces.args; + } + + packet.args = packet.args || []; + break; + + case 'json': + packet.data = parse(data); + break; + + case 'connect': + packet.qs = data || ''; + break; + + case 'ack': + pieces = data.match(/^([0-9]+)(\+)?(.*)/); + if (pieces) { + packet.ackId = pieces[1]; + packet.args = []; + + if (pieces[3]) { + packet.args = parse(pieces[3]) || []; + } + } + break; + + case 'error': + pieces = data.split('+'); + packet.reason = reasonslist[pieces[0]] || ''; + packet.advice = advicelist[pieces[1]] || ''; + } + + return packet; +}; + +/** + * Decodes data payload. Detects multiple messages + * + * @return {Array} messages + * @api public + */ + +exports.decodePayload = function (data) { + if (undefined == data || null == data) { + return []; + } + + if (data[0] == '\ufffd') { + var ret = []; + + for (var i = 1, length = ''; i < data.length; i++) { + if (data[i] == '\ufffd') { + ret.push(exports.decodePacket(data.substr(i + 1, length))); + i += Number(length) + 1; + length = ''; + } else { + length += data[i]; + } + } + + return ret; + } else { + return [exports.decodePacket(data)]; + } +}; diff --git a/node_modules/socket.io/lib/socket.io.js b/node_modules/socket.io/lib/socket.io.js new file mode 100644 index 0000000..d9d1c1f --- /dev/null +++ b/node_modules/socket.io/lib/socket.io.js @@ -0,0 +1,143 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var client = require('socket.io-client'); + +/** + * Version. + */ + +exports.version = '0.9.16'; + +/** + * Supported protocol version. + */ + +exports.protocol = 1; + +/** + * Client that we serve. + */ + +exports.clientVersion = client.version; + +/** + * Attaches a manager + * + * @param {HTTPServer/Number} a HTTP/S server or a port number to listen on. + * @param {Object} opts to be passed to Manager and/or http server + * @param {Function} callback if a port is supplied + * @api public + */ + +exports.listen = function (server, options, fn) { + if ('function' == typeof server) { + console.warn('Socket.IO\'s `listen()` method expects an `http.Server` instance\n' + + 'as its first parameter. Are you migrating from Express 2.x to 3.x?\n' + + 'If so, check out the "Socket.IO compatibility" section at:\n' + + 'https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x'); + } + + if ('function' == typeof options) { + fn = options; + options = {}; + } + + if ('undefined' == typeof server) { + // create a server that listens on port 80 + server = 80; + } + + if ('number' == typeof server) { + // if a port number is passed + var port = server; + + if (options && options.key) + server = require('https').createServer(options); + else + server = require('http').createServer(); + + // default response + server.on('request', function (req, res) { + res.writeHead(200); + res.end('Welcome to socket.io.'); + }); + + server.listen(port, fn); + } + + // otherwise assume a http/s server + return new exports.Manager(server, options); +}; + +/** + * Manager constructor. + * + * @api public + */ + +exports.Manager = require('./manager'); + +/** + * Transport constructor. + * + * @api public + */ + +exports.Transport = require('./transport'); + +/** + * Socket constructor. + * + * @api public + */ + +exports.Socket = require('./socket'); + +/** + * Static constructor. + * + * @api public + */ + +exports.Static = require('./static'); + +/** + * Store constructor. + * + * @api public + */ + +exports.Store = require('./store'); + +/** + * Memory Store constructor. + * + * @api public + */ + +exports.MemoryStore = require('./stores/memory'); + +/** + * Redis Store constructor. + * + * @api public + */ + +exports.RedisStore = require('./stores/redis'); + +/** + * Parser. + * + * @api public + */ + +exports.parser = require('./parser'); diff --git a/node_modules/socket.io/lib/socket.js b/node_modules/socket.io/lib/socket.js new file mode 100644 index 0000000..d9807f6 --- /dev/null +++ b/node_modules/socket.io/lib/socket.js @@ -0,0 +1,369 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var parser = require('./parser') + , util = require('./util') + , EventEmitter = process.EventEmitter + +/** + * Export the constructor. + */ + +exports = module.exports = Socket; + +/** + * Default error event listener to prevent uncaught exceptions. + */ + +var defaultError = function () {}; + +/** + * Socket constructor. + * + * @param {Manager} manager instance + * @param {String} session id + * @param {Namespace} namespace the socket belongs to + * @param {Boolean} whether the + * @api public + */ + +function Socket (manager, id, nsp, readable) { + this.id = id; + this.namespace = nsp; + this.manager = manager; + this.disconnected = false; + this.ackPackets = 0; + this.acks = {}; + this.setFlags(); + this.readable = readable; + this.store = this.manager.store.client(this.id); + this.on('error', defaultError); +}; + +/** + * Inherits from EventEmitter. + */ + +Socket.prototype.__proto__ = EventEmitter.prototype; + +/** + * Accessor shortcut for the handshake data + * + * @api private + */ + +Socket.prototype.__defineGetter__('handshake', function () { + return this.manager.handshaken[this.id]; +}); + +/** + * Accessor shortcut for the transport type + * + * @api private + */ + +Socket.prototype.__defineGetter__('transport', function () { + return this.manager.transports[this.id].name; +}); + +/** + * Accessor shortcut for the logger. + * + * @api private + */ + +Socket.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * JSON message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('json', function () { + this.flags.json = true; + return this; +}); + +/** + * Volatile message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('volatile', function () { + this.flags.volatile = true; + return this; +}); + +/** + * Broadcast message flag. + * + * @api public + */ + +Socket.prototype.__defineGetter__('broadcast', function () { + this.flags.broadcast = true; + return this; +}); + +/** + * Overrides the room to broadcast messages to (flag) + * + * @api public + */ + +Socket.prototype.to = Socket.prototype.in = function (room) { + this.flags.room = room; + return this; +}; + +/** + * Resets flags + * + * @api private + */ + +Socket.prototype.setFlags = function () { + this.flags = { + endpoint: this.namespace.name + , room: '' + }; + return this; +}; + +/** + * Triggered on disconnect + * + * @api private + */ + +Socket.prototype.onDisconnect = function (reason) { + if (!this.disconnected) { + this.$emit('disconnect', reason); + this.disconnected = true; + } +}; + +/** + * Joins a user to a room. + * + * @api public + */ + +Socket.prototype.join = function (name, fn) { + var nsp = this.namespace.name + , name = (nsp + '/') + name; + + this.manager.onJoin(this.id, name); + this.manager.store.publish('join', this.id, name); + + if (fn) { + this.log.warn('Client#join callback is deprecated'); + fn(); + } + + return this; +}; + +/** + * Un-joins a user from a room. + * + * @api public + */ + +Socket.prototype.leave = function (name, fn) { + var nsp = this.namespace.name + , name = (nsp + '/') + name; + + this.manager.onLeave(this.id, name); + this.manager.store.publish('leave', this.id, name); + + if (fn) { + this.log.warn('Client#leave callback is deprecated'); + fn(); + } + + return this; +}; + +/** + * Transmits a packet. + * + * @api private + */ + +Socket.prototype.packet = function (packet) { + if (this.flags.broadcast) { + this.log.debug('broadcasting packet'); + this.namespace.in(this.flags.room).except(this.id).packet(packet); + } else { + packet.endpoint = this.flags.endpoint; + packet = parser.encodePacket(packet); + + this.dispatch(packet, this.flags.volatile); + } + + this.setFlags(); + + return this; +}; + +/** + * Dispatches a packet + * + * @api private + */ + +Socket.prototype.dispatch = function (packet, volatile) { + if (this.manager.transports[this.id] && this.manager.transports[this.id].open) { + this.manager.transports[this.id].onDispatch(packet, volatile); + } else { + if (!volatile) { + this.manager.onClientDispatch(this.id, packet, volatile); + } + + this.manager.store.publish('dispatch:' + this.id, packet, volatile); + } +}; + +/** + * Stores data for the client. + * + * @api public + */ + +Socket.prototype.set = function (key, value, fn) { + this.store.set(key, value, fn); + return this; +}; + +/** + * Retrieves data for the client + * + * @api public + */ + +Socket.prototype.get = function (key, fn) { + this.store.get(key, fn); + return this; +}; + +/** + * Checks data for the client + * + * @api public + */ + +Socket.prototype.has = function (key, fn) { + this.store.has(key, fn); + return this; +}; + +/** + * Deletes data for the client + * + * @api public + */ + +Socket.prototype.del = function (key, fn) { + this.store.del(key, fn); + return this; +}; + +/** + * Kicks client + * + * @api public + */ + +Socket.prototype.disconnect = function () { + if (!this.disconnected) { + this.log.info('booting client'); + + if ('' === this.namespace.name) { + if (this.manager.transports[this.id] && this.manager.transports[this.id].open) { + this.manager.transports[this.id].onForcedDisconnect(); + } else { + this.manager.onClientDisconnect(this.id); + this.manager.store.publish('disconnect:' + this.id); + } + } else { + this.packet({type: 'disconnect'}); + this.manager.onLeave(this.id, this.namespace.name); + this.$emit('disconnect', 'booted'); + } + + } + + return this; +}; + +/** + * Send a message. + * + * @api public + */ + +Socket.prototype.send = function (data, fn) { + var packet = { + type: this.flags.json ? 'json' : 'message' + , data: data + }; + + if (fn) { + packet.id = ++this.ackPackets; + packet.ack = true; + this.acks[packet.id] = fn; + } + + return this.packet(packet); +}; + +/** + * Original emit function. + * + * @api private + */ + +Socket.prototype.$emit = EventEmitter.prototype.emit; + +/** + * Emit override for custom events. + * + * @api public + */ + +Socket.prototype.emit = function (ev) { + if (ev == 'newListener') { + return this.$emit.apply(this, arguments); + } + + var args = util.toArray(arguments).slice(1) + , lastArg = args[args.length - 1] + , packet = { + type: 'event' + , name: ev + }; + + if ('function' == typeof lastArg) { + packet.id = ++this.ackPackets; + packet.ack = lastArg.length ? 'data' : true; + this.acks[packet.id] = lastArg; + args = args.slice(0, args.length - 1); + } + + packet.args = args; + + return this.packet(packet); +}; diff --git a/node_modules/socket.io/lib/static.js b/node_modules/socket.io/lib/static.js new file mode 100644 index 0000000..fe50593 --- /dev/null +++ b/node_modules/socket.io/lib/static.js @@ -0,0 +1,395 @@ + +/*! +* socket.io-node +* Copyright(c) 2011 LearnBoost +* MIT Licensed +*/ + +/** + * Module dependencies. + */ + +var client = require('socket.io-client') + , cp = require('child_process') + , fs = require('fs') + , util = require('./util'); + +/** + * File type details. + * + * @api private + */ + +var mime = { + js: { + type: 'application/javascript' + , encoding: 'utf8' + , gzip: true + } + , swf: { + type: 'application/x-shockwave-flash' + , encoding: 'binary' + , gzip: false + } +}; + +/** + * Regexp for matching custom transport patterns. Users can configure their own + * socket.io bundle based on the url structure. Different transport names are + * concatinated using the `+` char. /socket.io/socket.io+websocket.js should + * create a bundle that only contains support for the websocket. + * + * @api private + */ + +var bundle = /\+((?:\+)?[\w\-]+)*(?:\.v\d+\.\d+\.\d+)?(?:\.js)$/ + , versioning = /\.v\d+\.\d+\.\d+(?:\.js)$/; + +/** + * Export the constructor + */ + +exports = module.exports = Static; + +/** + * Static constructor + * + * @api public + */ + +function Static (manager) { + this.manager = manager; + this.cache = {}; + this.paths = {}; + + this.init(); +} + +/** + * Initialize the Static by adding default file paths. + * + * @api public + */ + +Static.prototype.init = function () { + /** + * Generates a unique id based the supplied transports array + * + * @param {Array} transports The array with transport types + * @api private + */ + function id (transports) { + var id = transports.join('').split('').map(function (char) { + return ('' + char.charCodeAt(0)).split('').pop(); + }).reduce(function (char, id) { + return char +id; + }); + + return client.version + ':' + id; + } + + /** + * Generates a socket.io-client file based on the supplied transports. + * + * @param {Array} transports The array with transport types + * @param {Function} callback Callback for the static.write + * @api private + */ + + function build (transports, callback) { + client.builder(transports, { + minify: self.manager.enabled('browser client minification') + }, function (err, content) { + callback(err, content ? new Buffer(content) : null, id(transports)); + } + ); + } + + var self = this; + + // add our default static files + this.add('/static/flashsocket/WebSocketMain.swf', { + file: client.dist + '/WebSocketMain.swf' + }); + + this.add('/static/flashsocket/WebSocketMainInsecure.swf', { + file: client.dist + '/WebSocketMainInsecure.swf' + }); + + // generates dedicated build based on the available transports + this.add('/socket.io.js', function (path, callback) { + build(self.manager.get('transports'), callback); + }); + + this.add('/socket.io.v', { mime: mime.js }, function (path, callback) { + build(self.manager.get('transports'), callback); + }); + + // allow custom builds based on url paths + this.add('/socket.io+', { mime: mime.js }, function (path, callback) { + var available = self.manager.get('transports') + , matches = path.match(bundle) + , transports = []; + + if (!matches) return callback('No valid transports'); + + // make sure they valid transports + matches[0].split('.')[0].split('+').slice(1).forEach(function (transport) { + if (!!~available.indexOf(transport)) { + transports.push(transport); + } + }); + + if (!transports.length) return callback('No valid transports'); + build(transports, callback); + }); + + // clear cache when transports change + this.manager.on('set:transports', function (key, value) { + delete self.cache['/socket.io.js']; + Object.keys(self.cache).forEach(function (key) { + if (bundle.test(key)) { + delete self.cache[key]; + } + }); + }); +}; + +/** + * Gzip compress buffers. + * + * @param {Buffer} data The buffer that needs gzip compression + * @param {Function} callback + * @api public + */ + +Static.prototype.gzip = function (data, callback) { + var gzip = cp.spawn('gzip', ['-9', '-c', '-f', '-n']) + , encoding = Buffer.isBuffer(data) ? 'binary' : 'utf8' + , buffer = [] + , err; + + gzip.stdout.on('data', function (data) { + buffer.push(data); + }); + + gzip.stderr.on('data', function (data) { + err = data +''; + buffer.length = 0; + }); + + gzip.on('close', function () { + if (err) return callback(err); + + var size = 0 + , index = 0 + , i = buffer.length + , content; + + while (i--) { + size += buffer[i].length; + } + + content = new Buffer(size); + i = buffer.length; + + buffer.forEach(function (buffer) { + var length = buffer.length; + + buffer.copy(content, index, 0, length); + index += length; + }); + + buffer.length = 0; + callback(null, content); + }); + + gzip.stdin.end(data, encoding); +}; + +/** + * Is the path a static file? + * + * @param {String} path The path that needs to be checked + * @api public + */ + +Static.prototype.has = function (path) { + // fast case + if (this.paths[path]) return this.paths[path]; + + var keys = Object.keys(this.paths) + , i = keys.length; + + while (i--) { + if (-~path.indexOf(keys[i])) return this.paths[keys[i]]; + } + + return false; +}; + +/** + * Add new paths new paths that can be served using the static provider. + * + * @param {String} path The path to respond to + * @param {Options} options Options for writing out the response + * @param {Function} [callback] Optional callback if no options.file is + * supplied this would be called instead. + * @api public + */ + +Static.prototype.add = function (path, options, callback) { + var extension = /(?:\.(\w{1,4}))$/.exec(path); + + if (!callback && typeof options == 'function') { + callback = options; + options = {}; + } + + options.mime = options.mime || (extension ? mime[extension[1]] : false); + + if (callback) options.callback = callback; + if (!(options.file || options.callback) || !options.mime) return false; + + this.paths[path] = options; + + return true; +}; + +/** + * Writes a static response. + * + * @param {String} path The path for the static content + * @param {HTTPRequest} req The request object + * @param {HTTPResponse} res The response object + * @api public + */ + +Static.prototype.write = function (path, req, res) { + /** + * Write a response without throwing errors because can throw error if the + * response is no longer writable etc. + * + * @api private + */ + + function write (status, headers, content, encoding) { + try { + res.writeHead(status, headers || undefined); + + // only write content if it's not a HEAD request and we actually have + // some content to write (304's doesn't have content). + res.end( + req.method !== 'HEAD' && content ? content : '' + , encoding || undefined + ); + } catch (e) {} + } + + /** + * Answers requests depending on the request properties and the reply object. + * + * @param {Object} reply The details and content to reply the response with + * @api private + */ + + function answer (reply) { + var cached = req.headers['if-none-match'] === reply.etag; + if (cached && self.manager.enabled('browser client etag')) { + return write(304); + } + + var accept = req.headers['accept-encoding'] || '' + , gzip = !!~accept.toLowerCase().indexOf('gzip') + , mime = reply.mime + , versioned = reply.versioned + , headers = { + 'Content-Type': mime.type + }; + + // check if we can add a etag + if (self.manager.enabled('browser client etag') && reply.etag && !versioned) { + headers['Etag'] = reply.etag; + } + + // see if we need to set Expire headers because the path is versioned + if (versioned) { + var expires = self.manager.get('browser client expires'); + headers['Cache-Control'] = 'private, x-gzip-ok="", max-age=' + expires; + headers['Date'] = new Date().toUTCString(); + headers['Expires'] = new Date(Date.now() + (expires * 1000)).toUTCString(); + } + + if (gzip && reply.gzip) { + headers['Content-Length'] = reply.gzip.length; + headers['Content-Encoding'] = 'gzip'; + headers['Vary'] = 'Accept-Encoding'; + write(200, headers, reply.gzip.content, mime.encoding); + } else { + headers['Content-Length'] = reply.length; + write(200, headers, reply.content, mime.encoding); + } + + self.manager.log.debug('served static content ' + path); + } + + var self = this + , details; + + // most common case first + if (this.manager.enabled('browser client cache') && this.cache[path]) { + return answer(this.cache[path]); + } else if (this.manager.get('browser client handler')) { + return this.manager.get('browser client handler').call(this, req, res); + } else if ((details = this.has(path))) { + /** + * A small helper function that will let us deal with fs and dynamic files + * + * @param {Object} err Optional error + * @param {Buffer} content The data + * @api private + */ + + function ready (err, content, etag) { + if (err) { + self.manager.log.warn('Unable to serve file. ' + (err.message || err)); + return write(500, null, 'Error serving static ' + path); + } + + // store the result in the cache + var reply = self.cache[path] = { + content: content + , length: content.length + , mime: details.mime + , etag: etag || client.version + , versioned: versioning.test(path) + }; + + // check if gzip is enabled + if (details.mime.gzip && self.manager.enabled('browser client gzip')) { + self.gzip(content, function (err, content) { + if (!err) { + reply.gzip = { + content: content + , length: content.length + } + } + + answer(reply); + }); + } else { + answer(reply); + } + } + + if (details.file) { + fs.readFile(details.file, ready); + } else if(details.callback) { + details.callback.call(this, path, ready); + } else { + write(404, null, 'File handle not found'); + } + } else { + write(404, null, 'File not found'); + } +}; diff --git a/node_modules/socket.io/lib/store.js b/node_modules/socket.io/lib/store.js new file mode 100644 index 0000000..06c0389 --- /dev/null +++ b/node_modules/socket.io/lib/store.js @@ -0,0 +1,98 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Expose the constructor. + */ + +exports = module.exports = Store; + +/** + * Module dependencies. + */ + +var EventEmitter = process.EventEmitter; + +/** + * Store interface + * + * @api public + */ + +function Store (options) { + this.options = options; + this.clients = {}; +}; + +/** + * Inherit from EventEmitter. + */ + +Store.prototype.__proto__ = EventEmitter.prototype; + +/** + * Initializes a client store + * + * @param {String} id + * @api public + */ + +Store.prototype.client = function (id) { + if (!this.clients[id]) { + this.clients[id] = new (this.constructor.Client)(this, id); + } + + return this.clients[id]; +}; + +/** + * Destroys a client + * + * @api {String} sid + * @param {Number} number of seconds to expire client data + * @api private + */ + +Store.prototype.destroyClient = function (id, expiration) { + if (this.clients[id]) { + this.clients[id].destroy(expiration); + delete this.clients[id]; + } + + return this; +}; + +/** + * Destroys the store + * + * @param {Number} number of seconds to expire client data + * @api private + */ + +Store.prototype.destroy = function (clientExpiration) { + var keys = Object.keys(this.clients) + , count = keys.length; + + for (var i = 0, l = count; i < l; i++) { + this.destroyClient(keys[i], clientExpiration); + } + + this.clients = {}; + + return this; +}; + +/** + * Client. + * + * @api public + */ + +Store.Client = function (store, id) { + this.store = store; + this.id = id; +}; diff --git a/node_modules/socket.io/lib/stores/memory.js b/node_modules/socket.io/lib/stores/memory.js new file mode 100644 index 0000000..8b731a7 --- /dev/null +++ b/node_modules/socket.io/lib/stores/memory.js @@ -0,0 +1,143 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , Store = require('../store'); + +/** + * Exports the constructor. + */ + +exports = module.exports = Memory; +Memory.Client = Client; + +/** + * Memory store + * + * @api public + */ + +function Memory (opts) { + Store.call(this, opts); +}; + +/** + * Inherits from Store. + */ + +Memory.prototype.__proto__ = Store.prototype; + +/** + * Publishes a message. + * + * @api private + */ + +Memory.prototype.publish = function () { }; + +/** + * Subscribes to a channel + * + * @api private + */ + +Memory.prototype.subscribe = function () { }; + +/** + * Unsubscribes + * + * @api private + */ + +Memory.prototype.unsubscribe = function () { }; + +/** + * Client constructor + * + * @api private + */ + +function Client () { + Store.Client.apply(this, arguments); + this.data = {}; +}; + +/** + * Inherits from Store.Client + */ + +Client.prototype.__proto__ = Store.Client; + +/** + * Gets a key + * + * @api public + */ + +Client.prototype.get = function (key, fn) { + fn(null, this.data[key] === undefined ? null : this.data[key]); + return this; +}; + +/** + * Sets a key + * + * @api public + */ + +Client.prototype.set = function (key, value, fn) { + this.data[key] = value; + fn && fn(null); + return this; +}; + +/** + * Has a key + * + * @api public + */ + +Client.prototype.has = function (key, fn) { + fn(null, key in this.data); +}; + +/** + * Deletes a key + * + * @api public + */ + +Client.prototype.del = function (key, fn) { + delete this.data[key]; + fn && fn(null); + return this; +}; + +/** + * Destroys the client. + * + * @param {Number} number of seconds to expire data + * @api private + */ + +Client.prototype.destroy = function (expiration) { + if ('number' != typeof expiration) { + this.data = {}; + } else { + var self = this; + + setTimeout(function () { + self.data = {}; + }, expiration * 1000); + } + + return this; +}; diff --git a/node_modules/socket.io/lib/stores/redis.js b/node_modules/socket.io/lib/stores/redis.js new file mode 100644 index 0000000..8fea235 --- /dev/null +++ b/node_modules/socket.io/lib/stores/redis.js @@ -0,0 +1,269 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , Store = require('../store') + , assert = require('assert'); + +/** + * Exports the constructor. + */ + +exports = module.exports = Redis; +Redis.Client = Client; + +/** + * Redis store. + * Options: + * - nodeId (fn) gets an id that uniquely identifies this node + * - redis (fn) redis constructor, defaults to redis + * - redisPub (object) options to pass to the pub redis client + * - redisSub (object) options to pass to the sub redis client + * - redisClient (object) options to pass to the general redis client + * - pack (fn) custom packing, defaults to JSON or msgpack if installed + * - unpack (fn) custom packing, defaults to JSON or msgpack if installed + * + * @api public + */ + +function Redis (opts) { + opts = opts || {}; + + // node id to uniquely identify this node + var nodeId = opts.nodeId || function () { + // by default, we generate a random id + return Math.abs(Math.random() * Math.random() * Date.now() | 0); + }; + + this.nodeId = nodeId(); + + // packing / unpacking mechanism + if (opts.pack) { + this.pack = opts.pack; + this.unpack = opts.unpack; + } else { + try { + var msgpack = require('msgpack'); + this.pack = msgpack.pack; + this.unpack = msgpack.unpack; + } catch (e) { + this.pack = JSON.stringify; + this.unpack = JSON.parse; + } + } + + var redis = opts.redis || require('redis') + , RedisClient = redis.RedisClient; + + // initialize a pubsub client and a regular client + if (opts.redisPub instanceof RedisClient) { + this.pub = opts.redisPub; + } else { + opts.redisPub || (opts.redisPub = {}); + this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub); + } + if (opts.redisSub instanceof RedisClient) { + this.sub = opts.redisSub; + } else { + opts.redisSub || (opts.redisSub = {}); + this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub); + } + if (opts.redisClient instanceof RedisClient) { + this.cmd = opts.redisClient; + } else { + opts.redisClient || (opts.redisClient = {}); + this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient); + } + + Store.call(this, opts); + + this.sub.setMaxListeners(0); + this.setMaxListeners(0); +}; + +/** + * Inherits from Store. + */ + +Redis.prototype.__proto__ = Store.prototype; + +/** + * Publishes a message. + * + * @api private + */ + +Redis.prototype.publish = function (name) { + var args = Array.prototype.slice.call(arguments, 1); + this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args })); + this.emit.apply(this, ['publish', name].concat(args)); +}; + +/** + * Subscribes to a channel + * + * @api private + */ + +Redis.prototype.subscribe = function (name, consumer, fn) { + this.sub.subscribe(name); + + if (consumer || fn) { + var self = this; + + self.sub.on('subscribe', function subscribe (ch) { + if (name == ch) { + function message (ch, msg) { + if (name == ch) { + msg = self.unpack(msg); + + // we check that the message consumed wasnt emitted by this node + if (self.nodeId != msg.nodeId) { + consumer.apply(null, msg.args); + } + } + }; + + self.sub.on('message', message); + + self.on('unsubscribe', function unsubscribe (ch) { + if (name == ch) { + self.sub.removeListener('message', message); + self.removeListener('unsubscribe', unsubscribe); + } + }); + + self.sub.removeListener('subscribe', subscribe); + + fn && fn(); + } + }); + } + + this.emit('subscribe', name, consumer, fn); +}; + +/** + * Unsubscribes + * + * @api private + */ + +Redis.prototype.unsubscribe = function (name, fn) { + this.sub.unsubscribe(name); + + if (fn) { + var client = this.sub; + + client.on('unsubscribe', function unsubscribe (ch) { + if (name == ch) { + fn(); + client.removeListener('unsubscribe', unsubscribe); + } + }); + } + + this.emit('unsubscribe', name, fn); +}; + +/** + * Destroys the store + * + * @api public + */ + +Redis.prototype.destroy = function () { + Store.prototype.destroy.call(this); + + this.pub.end(); + this.sub.end(); + this.cmd.end(); +}; + +/** + * Client constructor + * + * @api private + */ + +function Client (store, id) { + Store.Client.call(this, store, id); +}; + +/** + * Inherits from Store.Client + */ + +Client.prototype.__proto__ = Store.Client; + +/** + * Redis hash get + * + * @api private + */ + +Client.prototype.get = function (key, fn) { + this.store.cmd.hget(this.id, key, fn); + return this; +}; + +/** + * Redis hash set + * + * @api private + */ + +Client.prototype.set = function (key, value, fn) { + this.store.cmd.hset(this.id, key, value, fn); + return this; +}; + +/** + * Redis hash del + * + * @api private + */ + +Client.prototype.del = function (key, fn) { + this.store.cmd.hdel(this.id, key, fn); + return this; +}; + +/** + * Redis hash has + * + * @api private + */ + +Client.prototype.has = function (key, fn) { + this.store.cmd.hexists(this.id, key, function (err, has) { + if (err) return fn(err); + fn(null, !!has); + }); + return this; +}; + +/** + * Destroys client + * + * @param {Number} number of seconds to expire data + * @api private + */ + +Client.prototype.destroy = function (expiration) { + if ('number' != typeof expiration) { + this.store.cmd.del(this.id); + } else { + this.store.cmd.expire(this.id, expiration); + } + + return this; +}; diff --git a/node_modules/socket.io/lib/transport.js b/node_modules/socket.io/lib/transport.js new file mode 100644 index 0000000..2e4c08b --- /dev/null +++ b/node_modules/socket.io/lib/transport.js @@ -0,0 +1,534 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var parser = require('./parser'); + +/** + * Expose the constructor. + */ + +exports = module.exports = Transport; + +/** + * Transport constructor. + * + * @api public + */ + +function Transport (mng, data, req) { + this.manager = mng; + this.id = data.id; + this.disconnected = false; + this.drained = true; + this.handleRequest(req); +}; + +/** + * Access the logger. + * + * @api public + */ + +Transport.prototype.__defineGetter__('log', function () { + return this.manager.log; +}); + +/** + * Access the store. + * + * @api public + */ + +Transport.prototype.__defineGetter__('store', function () { + return this.manager.store; +}); + +/** + * Handles a request when it's set. + * + * @api private + */ + +Transport.prototype.handleRequest = function (req) { + this.log.debug('setting request', req.method, req.url); + this.req = req; + + if (req.method == 'GET') { + this.socket = req.socket; + this.open = true; + this.drained = true; + this.setHeartbeatInterval(); + + this.setHandlers(); + this.onSocketConnect(); + } +}; + +/** + * Called when a connection is first set. + * + * @api private + */ + +Transport.prototype.onSocketConnect = function () { }; + +/** + * Sets transport handlers + * + * @api private + */ + +Transport.prototype.setHandlers = function () { + var self = this; + + // we need to do this in a pub/sub way since the client can POST the message + // over a different socket (ie: different Transport instance) + this.store.subscribe('heartbeat-clear:' + this.id, function () { + self.onHeartbeatClear(); + }); + + this.store.subscribe('disconnect-force:' + this.id, function () { + self.onForcedDisconnect(); + }); + + this.store.subscribe('dispatch:' + this.id, function (packet, volatile) { + self.onDispatch(packet, volatile); + }); + + this.bound = { + end: this.onSocketEnd.bind(this) + , close: this.onSocketClose.bind(this) + , error: this.onSocketError.bind(this) + , drain: this.onSocketDrain.bind(this) + }; + + this.socket.on('end', this.bound.end); + this.socket.on('close', this.bound.close); + this.socket.on('error', this.bound.error); + this.socket.on('drain', this.bound.drain); + + this.handlersSet = true; +}; + +/** + * Removes transport handlers + * + * @api private + */ + +Transport.prototype.clearHandlers = function () { + if (this.handlersSet) { + this.store.unsubscribe('disconnect-force:' + this.id); + this.store.unsubscribe('heartbeat-clear:' + this.id); + this.store.unsubscribe('dispatch:' + this.id); + + this.socket.removeListener('end', this.bound.end); + this.socket.removeListener('close', this.bound.close); + this.socket.removeListener('error', this.bound.error); + this.socket.removeListener('drain', this.bound.drain); + } +}; + +/** + * Called when the connection dies + * + * @api private + */ + +Transport.prototype.onSocketEnd = function () { + this.end('socket end'); +}; + +/** + * Called when the connection dies + * + * @api private + */ + +Transport.prototype.onSocketClose = function (error) { + this.end(error ? 'socket error' : 'socket close'); +}; + +/** + * Called when the connection has an error. + * + * @api private + */ + +Transport.prototype.onSocketError = function (err) { + if (this.open) { + this.socket.destroy(); + this.onClose(); + } + + this.log.info('socket error ' + err.stack); +}; + +/** + * Called when the connection is drained. + * + * @api private + */ + +Transport.prototype.onSocketDrain = function () { + this.drained = true; +}; + +/** + * Called upon receiving a heartbeat packet. + * + * @api private + */ + +Transport.prototype.onHeartbeatClear = function () { + this.clearHeartbeatTimeout(); + this.setHeartbeatInterval(); +}; + +/** + * Called upon a forced disconnection. + * + * @api private + */ + +Transport.prototype.onForcedDisconnect = function () { + if (!this.disconnected) { + this.log.info('transport end by forced client disconnection'); + if (this.open) { + this.packet({ type: 'disconnect' }); + } + this.end('booted'); + } +}; + +/** + * Dispatches a packet. + * + * @api private + */ + +Transport.prototype.onDispatch = function (packet, volatile) { + if (volatile) { + this.writeVolatile(packet); + } else { + this.write(packet); + } +}; + +/** + * Sets the close timeout. + */ + +Transport.prototype.setCloseTimeout = function () { + if (!this.closeTimeout) { + var self = this; + + this.closeTimeout = setTimeout(function () { + self.log.debug('fired close timeout for client', self.id); + self.closeTimeout = null; + self.end('close timeout'); + }, this.manager.get('close timeout') * 1000); + + this.log.debug('set close timeout for client', this.id); + } +}; + +/** + * Clears the close timeout. + */ + +Transport.prototype.clearCloseTimeout = function () { + if (this.closeTimeout) { + clearTimeout(this.closeTimeout); + this.closeTimeout = null; + + this.log.debug('cleared close timeout for client', this.id); + } +}; + +/** + * Sets the heartbeat timeout + */ + +Transport.prototype.setHeartbeatTimeout = function () { + if (!this.heartbeatTimeout && this.manager.enabled('heartbeats')) { + var self = this; + + this.heartbeatTimeout = setTimeout(function () { + self.log.debug('fired heartbeat timeout for client', self.id); + self.heartbeatTimeout = null; + self.end('heartbeat timeout'); + }, this.manager.get('heartbeat timeout') * 1000); + + this.log.debug('set heartbeat timeout for client', this.id); + } +}; + +/** + * Clears the heartbeat timeout + * + * @param text + */ + +Transport.prototype.clearHeartbeatTimeout = function () { + if (this.heartbeatTimeout && this.manager.enabled('heartbeats')) { + clearTimeout(this.heartbeatTimeout); + this.heartbeatTimeout = null; + this.log.debug('cleared heartbeat timeout for client', this.id); + } +}; + +/** + * Sets the heartbeat interval. To be called when a connection opens and when + * a heartbeat is received. + * + * @api private + */ + +Transport.prototype.setHeartbeatInterval = function () { + if (!this.heartbeatInterval && this.manager.enabled('heartbeats')) { + var self = this; + + this.heartbeatInterval = setTimeout(function () { + self.heartbeat(); + self.heartbeatInterval = null; + }, this.manager.get('heartbeat interval') * 1000); + + this.log.debug('set heartbeat interval for client', this.id); + } +}; + +/** + * Clears all timeouts. + * + * @api private + */ + +Transport.prototype.clearTimeouts = function () { + this.clearCloseTimeout(); + this.clearHeartbeatTimeout(); + this.clearHeartbeatInterval(); +}; + +/** + * Sends a heartbeat + * + * @api private + */ + +Transport.prototype.heartbeat = function () { + if (this.open) { + this.log.debug('emitting heartbeat for client', this.id); + this.packet({ type: 'heartbeat' }); + this.setHeartbeatTimeout(); + } + + return this; +}; + +/** + * Handles a message. + * + * @param {Object} packet object + * @api private + */ + +Transport.prototype.onMessage = function (packet) { + var current = this.manager.transports[this.id]; + + if ('heartbeat' == packet.type) { + this.log.debug('got heartbeat packet'); + + if (current && current.open) { + current.onHeartbeatClear(); + } else { + this.store.publish('heartbeat-clear:' + this.id); + } + } else { + if ('disconnect' == packet.type && packet.endpoint == '') { + this.log.debug('got disconnection packet'); + + if (current) { + current.onForcedDisconnect(); + } else { + this.store.publish('disconnect-force:' + this.id); + } + + return; + } + + if (packet.id && packet.ack != 'data') { + this.log.debug('acknowledging packet automatically'); + + var ack = parser.encodePacket({ + type: 'ack' + , ackId: packet.id + , endpoint: packet.endpoint || '' + }); + + if (current && current.open) { + current.onDispatch(ack); + } else { + this.manager.onClientDispatch(this.id, ack); + this.store.publish('dispatch:' + this.id, ack); + } + } + + // handle packet locally or publish it + if (current) { + this.manager.onClientMessage(this.id, packet); + } else { + this.store.publish('message:' + this.id, packet); + } + } +}; + +/** + * Clears the heartbeat interval + * + * @api private + */ + +Transport.prototype.clearHeartbeatInterval = function () { + if (this.heartbeatInterval && this.manager.enabled('heartbeats')) { + clearTimeout(this.heartbeatInterval); + this.heartbeatInterval = null; + this.log.debug('cleared heartbeat interval for client', this.id); + } +}; + +/** + * Finishes the connection and makes sure client doesn't reopen + * + * @api private + */ + +Transport.prototype.disconnect = function (reason) { + this.packet({ type: 'disconnect' }); + this.end(reason); + + return this; +}; + +/** + * Closes the connection. + * + * @api private + */ + +Transport.prototype.close = function () { + if (this.open) { + this.doClose(); + this.onClose(); + } +}; + +/** + * Called upon a connection close. + * + * @api private + */ + +Transport.prototype.onClose = function () { + if (this.open) { + this.setCloseTimeout(); + this.clearHandlers(); + this.open = false; + this.manager.onClose(this.id); + this.store.publish('close', this.id); + } +}; + +/** + * Cleans up the connection, considers the client disconnected. + * + * @api private + */ + +Transport.prototype.end = function (reason) { + if (!this.disconnected) { + this.log.info('transport end (' + reason + ')'); + + var local = this.manager.transports[this.id]; + + this.close(); + this.clearTimeouts(); + this.disconnected = true; + + if (local) { + this.manager.onClientDisconnect(this.id, reason, true); + } else { + this.store.publish('disconnect:' + this.id, reason); + } + } +}; + +/** + * Signals that the transport should pause and buffer data. + * + * @api public + */ + +Transport.prototype.discard = function () { + this.log.debug('discarding transport'); + this.discarded = true; + this.clearTimeouts(); + this.clearHandlers(); + + return this; +}; + +/** + * Writes an error packet with the specified reason and advice. + * + * @param {Number} advice + * @param {Number} reason + * @api public + */ + +Transport.prototype.error = function (reason, advice) { + this.packet({ + type: 'error' + , reason: reason + , advice: advice + }); + + this.log.warn(reason, advice ? ('client should ' + advice) : ''); + this.end('error'); +}; + +/** + * Write a packet. + * + * @api public + */ + +Transport.prototype.packet = function (obj) { + return this.write(parser.encodePacket(obj)); +}; + +/** + * Writes a volatile message. + * + * @api private + */ + +Transport.prototype.writeVolatile = function (msg) { + if (this.open) { + if (this.drained) { + this.write(msg); + } else { + this.log.debug('ignoring volatile packet, buffer not drained'); + } + } else { + this.log.debug('ignoring volatile packet, transport not open'); + } +}; diff --git a/node_modules/socket.io/lib/transports/flashsocket.js b/node_modules/socket.io/lib/transports/flashsocket.js new file mode 100644 index 0000000..dc2d78b --- /dev/null +++ b/node_modules/socket.io/lib/transports/flashsocket.js @@ -0,0 +1,129 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ +var WebSocket = require('./websocket'); + +/** + * Export the constructor. + */ + +exports = module.exports = FlashSocket; + +/** + * The FlashSocket transport is just a proxy + * for WebSocket connections. + * + * @api public + */ + +function FlashSocket (mng, data, req) { + return WebSocket.call(this, mng, data, req); +} + +/** + * Inherits from WebSocket. + */ + +FlashSocket.prototype.__proto__ = WebSocket.prototype; + +/** + * Transport name + * + * @api public + */ + +FlashSocket.prototype.name = 'flashsocket'; + +/** + * Listens for new configuration changes of the Manager + * this way we can enable and disable the flash server. + * + * @param {Manager} Manager instance. + * @api private + */ + + +FlashSocket.init = function (manager) { + var server; + function create () { + + // Drop out immediately if the user has + // disabled the flash policy server + if (!manager.get('flash policy server')) { + return; + } + + server = require('policyfile').createServer({ + log: function(msg){ + manager.log.info(msg); + } + }, manager.get('origins')); + + server.on('close', function (e) { + server = null; + }); + + server.listen(manager.get('flash policy port'), manager.server); + + manager.flashPolicyServer = server; + } + + // listen for origin changes, so we can update the server + manager.on('set:origins', function (value, key) { + if (!server) return; + + // update the origins and compile a new response buffer + server.origins = Array.isArray(value) ? value : [value]; + server.compile(); + }); + + // destory the server and create a new server + manager.on('set:flash policy port', function (value, key) { + var transports = manager.get('transports'); + if (~transports.indexOf('flashsocket')) { + if (server) { + if (server.port === value) return; + // destroy the server and rebuild it on a new port + try { + server.close(); + } + catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ } + } + create(); + } + }); + + // create or destroy the server + manager.on('set:flash policy server', function (value, key) { + var transports = manager.get('transports'); + if (~transports.indexOf('flashsocket')) { + if (server && !value) { + // destroy the server + try { + server.close(); + } + catch (e) { /* ignore exception. could e.g. be that the server isn't started yet */ } + } + } else if (!server && value) { + // create the server + create(); + } + }); + + // only start the server + manager.on('set:transports', function (value, key){ + if (!server && ~manager.get('transports').indexOf('flashsocket')) { + create(); + } + }); + // check if we need to initialize at start + if (~manager.get('transports').indexOf('flashsocket')){ + create(); + } +}; diff --git a/node_modules/socket.io/lib/transports/htmlfile.js b/node_modules/socket.io/lib/transports/htmlfile.js new file mode 100644 index 0000000..fce0c0e --- /dev/null +++ b/node_modules/socket.io/lib/transports/htmlfile.js @@ -0,0 +1,83 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPTransport = require('./http'); + +/** + * Export the constructor. + */ + +exports = module.exports = HTMLFile; + +/** + * HTMLFile transport constructor. + * + * @api public + */ + +function HTMLFile (mng, data, req) { + HTTPTransport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +HTMLFile.prototype.__proto__ = HTTPTransport.prototype; + +/** + * Transport name + * + * @api public + */ + +HTMLFile.prototype.name = 'htmlfile'; + +/** + * Handles the request. + * + * @api private + */ + +HTMLFile.prototype.handleRequest = function (req) { + HTTPTransport.prototype.handleRequest.call(this, req); + + if (req.method == 'GET') { + req.res.writeHead(200, { + 'Content-Type': 'text/html; charset=UTF-8' + , 'Connection': 'keep-alive' + , 'Transfer-Encoding': 'chunked' + }); + + req.res.write( + '' + + '' + + new Array(174).join(' ') + ); + } +}; + +/** + * Performs the write. + * + * @api private + */ + +HTMLFile.prototype.write = function (data) { + // escape all forward slashes. see GH-1251 + data = ''; + + if (this.response.write(data)) { + this.drained = true; + } + + this.log.debug(this.name + ' writing', data); +}; diff --git a/node_modules/socket.io/lib/transports/http-polling.js b/node_modules/socket.io/lib/transports/http-polling.js new file mode 100644 index 0000000..89b7e04 --- /dev/null +++ b/node_modules/socket.io/lib/transports/http-polling.js @@ -0,0 +1,147 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPTransport = require('./http'); + +/** + * Exports the constructor. + */ + +exports = module.exports = HTTPPolling; + +/** + * HTTP polling constructor. + * + * @api public. + */ + +function HTTPPolling (mng, data, req) { + HTTPTransport.call(this, mng, data, req); +}; + +/** + * Inherits from HTTPTransport. + * + * @api public. + */ + +HTTPPolling.prototype.__proto__ = HTTPTransport.prototype; + +/** + * Transport name + * + * @api public + */ + +HTTPPolling.prototype.name = 'httppolling'; + +/** + * Override setHandlers + * + * @api private + */ + +HTTPPolling.prototype.setHandlers = function () { + HTTPTransport.prototype.setHandlers.call(this); + this.socket.removeListener('end', this.bound.end); + this.socket.removeListener('close', this.bound.close); +}; + +/** + * Removes heartbeat timeouts for polling. + */ + +HTTPPolling.prototype.setHeartbeatInterval = function () { + return this; +}; + +/** + * Handles a request + * + * @api private + */ + +HTTPPolling.prototype.handleRequest = function (req) { + HTTPTransport.prototype.handleRequest.call(this, req); + + if (req.method == 'GET') { + var self = this; + + this.pollTimeout = setTimeout(function () { + self.packet({ type: 'noop' }); + self.log.debug(self.name + ' closed due to exceeded duration'); + }, this.manager.get('polling duration') * 1000); + + this.log.debug('setting poll timeout'); + } +}; + +/** + * Clears polling timeout + * + * @api private + */ + +HTTPPolling.prototype.clearPollTimeout = function () { + if (this.pollTimeout) { + clearTimeout(this.pollTimeout); + this.pollTimeout = null; + this.log.debug('clearing poll timeout'); + } + + return this; +}; + +/** + * Override clear timeouts to clear the poll timeout + * + * @api private + */ + +HTTPPolling.prototype.clearTimeouts = function () { + HTTPTransport.prototype.clearTimeouts.call(this); + + this.clearPollTimeout(); +}; + +/** + * doWrite to clear poll timeout + * + * @api private + */ + +HTTPPolling.prototype.doWrite = function () { + this.clearPollTimeout(); +}; + +/** + * Performs a write. + * + * @api private. + */ + +HTTPPolling.prototype.write = function (data, close) { + this.doWrite(data); + this.response.end(); + this.onClose(); +}; + +/** + * Override end. + * + * @api private + */ + +HTTPPolling.prototype.end = function (reason) { + this.clearPollTimeout(); + return HTTPTransport.prototype.end.call(this, reason); +}; + diff --git a/node_modules/socket.io/lib/transports/http.js b/node_modules/socket.io/lib/transports/http.js new file mode 100644 index 0000000..28db794 --- /dev/null +++ b/node_modules/socket.io/lib/transports/http.js @@ -0,0 +1,121 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../transport') + , parser = require('../parser') + , qs = require('querystring'); + +/** + * Export the constructor. + */ + +exports = module.exports = HTTPTransport; + +/** + * HTTP interface constructor. For all non-websocket transports. + * + * @api public + */ + +function HTTPTransport (mng, data, req) { + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +HTTPTransport.prototype.__proto__ = Transport.prototype; + +/** + * Handles a request. + * + * @api private + */ + +HTTPTransport.prototype.handleRequest = function (req) { + + // Always set the response in case an error is returned to the client + this.response = req.res; + + if (req.method == 'POST') { + var buffer = '' + , res = req.res + , origin = req.headers.origin + , headers = { 'Content-Length': 1, 'Content-Type': 'text/plain; charset=UTF-8' } + , self = this; + + req.on('data', function (data) { + buffer += data; + + if (Buffer.byteLength(buffer) >= self.manager.get('destroy buffer size')) { + buffer = ''; + req.connection.destroy(); + } + }); + + req.on('end', function () { + res.writeHead(200, headers); + res.end('1'); + + self.onData(self.postEncoded ? qs.parse(buffer).d : buffer); + }); + + // prevent memory leaks for uncompleted requests + req.on('close', function () { + buffer = ''; + self.onClose(); + }); + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + } else { + Transport.prototype.handleRequest.call(this, req); + } +}; + +/** + * Handles data payload. + * + * @api private + */ + +HTTPTransport.prototype.onData = function (data) { + var messages = parser.decodePayload(data); + this.log.debug(this.name + ' received data packet', data); + + for (var i = 0, l = messages.length; i < l; i++) { + this.onMessage(messages[i]); + } +}; + +/** + * Closes the request-response cycle + * + * @api private + */ + +HTTPTransport.prototype.doClose = function () { + this.response.end(); +}; + +/** + * Writes a payload of messages + * + * @api private + */ + +HTTPTransport.prototype.payload = function (msgs) { + this.write(parser.encodePayload(msgs)); +}; diff --git a/node_modules/socket.io/lib/transports/index.js b/node_modules/socket.io/lib/transports/index.js new file mode 100644 index 0000000..b865559 --- /dev/null +++ b/node_modules/socket.io/lib/transports/index.js @@ -0,0 +1,12 @@ + +/** + * Export transports. + */ + +module.exports = { + websocket: require('./websocket') + , flashsocket: require('./flashsocket') + , htmlfile: require('./htmlfile') + , 'xhr-polling': require('./xhr-polling') + , 'jsonp-polling': require('./jsonp-polling') +}; diff --git a/node_modules/socket.io/lib/transports/jsonp-polling.js b/node_modules/socket.io/lib/transports/jsonp-polling.js new file mode 100644 index 0000000..ad7d5af --- /dev/null +++ b/node_modules/socket.io/lib/transports/jsonp-polling.js @@ -0,0 +1,97 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPPolling = require('./http-polling'); +var jsonpolling_re = /^\d+$/ + +/** + * Export the constructor. + */ + +exports = module.exports = JSONPPolling; + +/** + * JSON-P polling transport. + * + * @api public + */ + +function JSONPPolling (mng, data, req) { + HTTPPolling.call(this, mng, data, req); + + this.head = 'io.j[0]('; + this.foot = ');'; + + if (data.query.i && jsonpolling_re.test(data.query.i)) { + this.head = 'io.j[' + data.query.i + ']('; + } +}; + +/** + * Inherits from Transport. + */ + +JSONPPolling.prototype.__proto__ = HTTPPolling.prototype; + +/** + * Transport name + * + * @api public + */ + +JSONPPolling.prototype.name = 'jsonppolling'; + +/** + * Make sure POST are decoded. + */ + +JSONPPolling.prototype.postEncoded = true; + +/** + * Handles incoming data. + * Due to a bug in \n handling by browsers, we expect a JSONified string. + * + * @api private + */ + +JSONPPolling.prototype.onData = function (data) { + try { + data = JSON.parse(data); + } catch (e) { + this.error('parse', 'reconnect'); + return; + } + + HTTPPolling.prototype.onData.call(this, data); +}; + +/** + * Performs the write. + * + * @api private + */ + +JSONPPolling.prototype.doWrite = function (data) { + HTTPPolling.prototype.doWrite.call(this); + + var data = data === undefined + ? '' : this.head + JSON.stringify(data) + this.foot; + + this.response.writeHead(200, { + 'Content-Type': 'text/javascript; charset=UTF-8' + , 'Content-Length': Buffer.byteLength(data) + , 'Connection': 'Keep-Alive' + , 'X-XSS-Protection': '0' + }); + + this.response.write(data); + this.log.debug(this.name + ' writing', data); +}; diff --git a/node_modules/socket.io/lib/transports/websocket.js b/node_modules/socket.io/lib/transports/websocket.js new file mode 100644 index 0000000..78a4304 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket.js @@ -0,0 +1,36 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var protocolVersions = require('./websocket/'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + var transport + , version = req.headers['sec-websocket-version']; + if (typeof version !== 'undefined' && typeof protocolVersions[version] !== 'undefined') { + transport = new protocolVersions[version](mng, data, req); + } + else transport = new protocolVersions['default'](mng, data, req); + if (typeof this.name !== 'undefined') transport.name = this.name; + return transport; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/default.js b/node_modules/socket.io/lib/transports/websocket/default.js new file mode 100644 index 0000000..091fdd4 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/default.js @@ -0,0 +1,362 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , parser = require('../../parser'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.log.debug(self.name + ' received data packet', packet); + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function () { + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = 'hixie-76'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + this.socket.setNoDelay(true); + + this.buffer = true; + this.buffered = []; + + if (this.req.headers.upgrade !== 'WebSocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['origin'] + , waitingForNonce = false; + if(this.manager.settings['match origin protocol']){ + location = (origin.indexOf('https')>-1 ? 'wss' : 'ws') + '://' + this.req.headers.host + this.req.url; + }else if(this.socket.encrypted){ + location = 'wss://' + this.req.headers.host + this.req.url; + }else{ + location = 'ws://' + this.req.headers.host + this.req.url; + } + + if (this.req.headers['sec-websocket-key1']) { + // If we don't have the nonce yet, wait for it (HAProxy compatibility). + if (! (this.req.head && this.req.head.length >= 8)) { + waitingForNonce = true; + } + + var headers = [ + 'HTTP/1.1 101 WebSocket Protocol Handshake' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Origin: ' + origin + , 'Sec-WebSocket-Location: ' + location + ]; + + if (this.req.headers['sec-websocket-protocol']){ + headers.push('Sec-WebSocket-Protocol: ' + + this.req.headers['sec-websocket-protocol']); + } + } else { + var headers = [ + 'HTTP/1.1 101 Web Socket Protocol Handshake' + , 'Upgrade: WebSocket' + , 'Connection: Upgrade' + , 'WebSocket-Origin: ' + origin + , 'WebSocket-Location: ' + location + ]; + } + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + this.socket.setEncoding('utf8'); + } catch (e) { + this.end(); + return; + } + + if (waitingForNonce) { + this.socket.setEncoding('binary'); + } else if (this.proveReception(headers)) { + self.flush(); + } + + var headBuffer = ''; + + this.socket.on('data', function (data) { + if (waitingForNonce) { + headBuffer += data; + + if (headBuffer.length < 8) { + return; + } + + // Restore the connection to utf8 encoding after receiving the nonce + self.socket.setEncoding('utf8'); + waitingForNonce = false; + + // Stuff the nonce into the location where it's expected to be + self.req.head = headBuffer.substr(0, 8); + headBuffer = ''; + + if (self.proveReception(headers)) { + self.flush(); + } + + return; + } + + self.parser.add(data); + }); +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + this.drained = false; + + if (this.buffer) { + this.buffered.push(data); + return this; + } + + var length = Buffer.byteLength(data) + , buffer = new Buffer(2 + length); + + buffer.write('\x00', 'binary'); + buffer.write(data, 1, 'utf8'); + buffer.write('\xff', 1 + length, 'binary'); + + try { + if (this.socket.write(buffer)) { + this.drained = true; + } + } catch (e) { + this.end(); + } + + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Flushes the internal buffer + * + * @api private + */ + +WebSocket.prototype.flush = function () { + this.buffer = false; + + for (var i = 0, l = this.buffered.length; i < l; i++) { + this.write(this.buffered.splice(0, 1)[0]); + } +}; + +/** + * Finishes the handshake. + * + * @api private + */ + +WebSocket.prototype.proveReception = function (headers) { + var self = this + , k1 = this.req.headers['sec-websocket-key1'] + , k2 = this.req.headers['sec-websocket-key2']; + + if (k1 && k2){ + var md5 = crypto.createHash('md5'); + + [k1, k2].forEach(function (k) { + var n = parseInt(k.replace(/[^\d]/g, '')) + , spaces = k.replace(/[^ ]/g, '').length; + + if (spaces === 0 || n % spaces !== 0){ + self.log.warn('Invalid ' + self.name + ' key: "' + k + '".'); + self.end(); + return false; + } + + n /= spaces; + + md5.update(String.fromCharCode( + n >> 24 & 0xFF, + n >> 16 & 0xFF, + n >> 8 & 0xFF, + n & 0xFF)); + }); + + md5.update(this.req.head.toString('binary')); + + try { + this.socket.write(md5.digest('binary'), 'binary'); + } catch (e) { + this.end(); + } + } + + return true; +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.buffer = ''; + this.i = 0; +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Adds data to the buffer. + * + * @api public + */ + +Parser.prototype.add = function (data) { + this.buffer += data; + this.parse(); +}; + +/** + * Parses the buffer. + * + * @api private + */ + +Parser.prototype.parse = function () { + for (var i = this.i, chr, l = this.buffer.length; i < l; i++){ + chr = this.buffer[i]; + + if (this.buffer.length == 2 && this.buffer[1] == '\u0000') { + this.emit('close'); + this.buffer = ''; + this.i = 0; + return; + } + + if (i === 0){ + if (chr != '\u0000') + this.error('Bad framing. Expected null byte as first frame'); + else + continue; + } + + if (chr == '\ufffd'){ + this.emit('data', this.buffer.substr(1, i - 1)); + this.buffer = this.buffer.substr(i + 1); + this.i = 0; + return this.parse(); + } + } +}; + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.buffer = ''; + this.i = 0; + this.emit('error', reason); + return this; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js b/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js new file mode 100644 index 0000000..44f666a --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/hybi-07-12.js @@ -0,0 +1,622 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , url = require('url') + , parser = require('../../parser') + , util = require('../../util'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; +exports.Parser = Parser; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.manager = mng; + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('ping', function () { + // version 8 ping => pong + try { + self.socket.write('\u008a\u0000'); + } + catch (e) { + self.end(); + return; + } + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function (reason) { + self.log.warn(self.name + ' parser error: ' + reason); + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = '07-12'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + if (typeof this.req.headers.upgrade === 'undefined' || + this.req.headers.upgrade.toLowerCase() !== 'websocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['sec-websocket-origin'] + , location = ((this.manager.settings['match origin protocol'] ? + origin.match(/^https/) : this.socket.encrypted) ? + 'wss' : 'ws') + + '://' + this.req.headers.host + this.req.url; + + if (!this.verifyOrigin(origin)) { + this.log.warn(this.name + ' connection invalid: origin mismatch'); + this.end(); + return; + } + + if (!this.req.headers['sec-websocket-key']) { + this.log.warn(this.name + ' connection invalid: received no key'); + this.end(); + return; + } + + // calc key + var key = this.req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + } catch (e) { + this.end(); + return; + } + + this.socket.on('data', function (data) { + self.parser.add(data); + }); +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +WebSocket.prototype.verifyOrigin = function (origin) { + var origins = this.manager.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from websocket call, yet required by config'); + } + return false; +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + var buf = this.frame(0x81, data); + try { + this.socket.write(buf, 'binary'); + } + catch (e) { + this.end(); + return; + } + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Frame server-to-client output as a text packet. + * + * @api private + */ + +WebSocket.prototype.frame = function (opcode, str) { + var dataBuffer = new Buffer(str) + , dataLength = dataBuffer.length + , startOffset = 2 + , secondByte = dataLength; + if (dataLength > 65536) { + startOffset = 10; + secondByte = 127; + } + else if (dataLength > 125) { + startOffset = 4; + secondByte = 126; + } + var outputBuffer = new Buffer(dataLength + startOffset); + outputBuffer[0] = opcode; + outputBuffer[1] = secondByte; + dataBuffer.copy(outputBuffer, startOffset); + switch (secondByte) { + case 126: + outputBuffer[2] = dataLength >>> 8; + outputBuffer[3] = dataLength % 256; + break; + case 127: + var l = dataLength; + for (var i = 1; i <= 8; ++i) { + outputBuffer[startOffset - i] = l & 0xff; + l >>>= 8; + } + } + return outputBuffer; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.overflow = null; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = ''; + + var self = this; + this.opcodeHandlers = { + // text + '1': function(data) { + var finish = function(mask, data) { + self.currentMessage += self.unmask(mask, data); + if (self.state.lastFragment) { + self.emit('data', self.currentMessage); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // binary + '2': function(data) { + var finish = function(mask, data) { + if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list + self.currentMessage.push(self.unmask(mask, data, true)); + if (self.state.lastFragment) { + self.emit('binary', self.concatBuffers(self.currentMessage)); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // close + '8': function(data) { + self.emit('close'); + self.reset(); + }, + // ping + '9': function(data) { + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported'); + return; + } + + var finish = function(mask, data) { + self.emit('ping', self.unmask(mask, data)); + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength == 0) { + finish(null, null); + } + else if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + expectData(util.unpack(data)); + }); + } + } + } + + this.expect('Opcode', 2, this.processPacket); +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add new data to the parser. + * + * @api public + */ + +Parser.prototype.add = function(data) { + if (this.expectBuffer == null) { + this.addToOverflow(data); + return; + } + var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset); + data.copy(this.expectBuffer, this.expectOffset, 0, toRead); + this.expectOffset += toRead; + if (toRead < data.length) { + // at this point the overflow buffer shouldn't at all exist + this.overflow = new Buffer(data.length - toRead); + data.copy(this.overflow, 0, toRead, toRead + this.overflow.length); + } + if (this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Adds a piece of data to the overflow. + * + * @api private + */ + +Parser.prototype.addToOverflow = function(data) { + if (this.overflow == null) this.overflow = data; + else { + var prevOverflow = this.overflow; + this.overflow = new Buffer(this.overflow.length + data.length); + prevOverflow.copy(this.overflow, 0); + data.copy(this.overflow, prevOverflow.length); + } +} + +/** + * Waits for a certain amount of bytes to be available, then fires a callback. + * + * @api private + */ + +Parser.prototype.expect = function(what, length, handler) { + this.expectBuffer = new Buffer(length); + this.expectOffset = 0; + this.expectHandler = handler; + if (this.overflow != null) { + var toOverflow = this.overflow; + this.overflow = null; + this.add(toOverflow); + } +} + +/** + * Start processing a new packet. + * + * @api private + */ + +Parser.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty'); + } + this.state.lastFragment = (data[0] & 0x80) == 0x80; + this.state.masked = (data[1] & 0x80) == 0x80; + var opcode = data[0] & 0xf; + if (opcode == 0) { + // continuation frame + this.state.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode') + return; + } + } + else { + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.activeFragmentedOperation = opcode; + } + } + var handler = this.opcodeHandlers[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode); + else handler(data); +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Parser.prototype.endPacket = function() { + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) { + // end current fragmented operation + this.state.activeFragmentedOperation = null; + } + this.state.lastFragment = false; + this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0; + this.state.masked = false; + this.expect('Opcode', 2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Parser.prototype.reset = function() { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = null; + this.currentMessage = ''; +} + +/** + * Unmask received data. + * + * @api private + */ + +Parser.prototype.unmask = function (mask, buf, binary) { + if (mask != null) { + for (var i = 0, ll = buf.length; i < ll; i++) { + buf[i] ^= mask[i % 4]; + } + } + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Parser.prototype.concatBuffers = function(buffers) { + var length = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + length += buffers[i].length; + } + var mergedBuffer = new Buffer(length); + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + buffers[i].copy(mergedBuffer, offset); + offset += buffers[i].length; + } + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.reset(); + this.emit('error', reason); + return this; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/hybi-16.js b/node_modules/socket.io/lib/transports/websocket/hybi-16.js new file mode 100644 index 0000000..69967da --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/hybi-16.js @@ -0,0 +1,622 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var Transport = require('../../transport') + , EventEmitter = process.EventEmitter + , crypto = require('crypto') + , url = require('url') + , parser = require('../../parser') + , util = require('../../util'); + +/** + * Export the constructor. + */ + +exports = module.exports = WebSocket; +exports.Parser = Parser; + +/** + * HTTP interface constructor. Interface compatible with all transports that + * depend on request-response cycles. + * + * @api public + */ + +function WebSocket (mng, data, req) { + // parser + var self = this; + + this.manager = mng; + this.parser = new Parser(); + this.parser.on('data', function (packet) { + self.onMessage(parser.decodePacket(packet)); + }); + this.parser.on('ping', function () { + // version 8 ping => pong + try { + self.socket.write('\u008a\u0000'); + } + catch (e) { + self.end(); + return; + } + }); + this.parser.on('close', function () { + self.end(); + }); + this.parser.on('error', function (reason) { + self.log.warn(self.name + ' parser error: ' + reason); + self.end(); + }); + + Transport.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +WebSocket.prototype.__proto__ = Transport.prototype; + +/** + * Transport name + * + * @api public + */ + +WebSocket.prototype.name = 'websocket'; + +/** + * Websocket draft version + * + * @api public + */ + +WebSocket.prototype.protocolVersion = '16'; + +/** + * Called when the socket connects. + * + * @api private + */ + +WebSocket.prototype.onSocketConnect = function () { + var self = this; + + if (typeof this.req.headers.upgrade === 'undefined' || + this.req.headers.upgrade.toLowerCase() !== 'websocket') { + this.log.warn(this.name + ' connection invalid'); + this.end(); + return; + } + + var origin = this.req.headers['origin'] || '' + , location = ((this.manager.settings['match origin protocol'] ? + origin.match(/^https/) : this.socket.encrypted) ? + 'wss' : 'ws') + + '://' + this.req.headers.host + this.req.url; + + if (!this.verifyOrigin(origin)) { + this.log.warn(this.name + ' connection invalid: origin mismatch'); + this.end(); + return; + } + + if (!this.req.headers['sec-websocket-key']) { + this.log.warn(this.name + ' connection invalid: received no key'); + this.end(); + return; + } + + // calc key + var key = this.req.headers['sec-websocket-key']; + var shasum = crypto.createHash('sha1'); + shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + key = shasum.digest('base64'); + + var headers = [ + 'HTTP/1.1 101 Switching Protocols' + , 'Upgrade: websocket' + , 'Connection: Upgrade' + , 'Sec-WebSocket-Accept: ' + key + ]; + + try { + this.socket.write(headers.concat('', '').join('\r\n')); + this.socket.setTimeout(0); + this.socket.setNoDelay(true); + } catch (e) { + this.end(); + return; + } + + this.socket.on('data', function (data) { + self.parser.add(data); + }); +}; + +/** + * Verifies the origin of a request. + * + * @api private + */ + +WebSocket.prototype.verifyOrigin = function (origin) { + var origins = this.manager.get('origins'); + + if (origin === 'null') origin = '*'; + + if (origins.indexOf('*:*') !== -1) { + return true; + } + + if (origin) { + try { + var parts = url.parse(origin); + parts.port = parts.port || 80; + var ok = + ~origins.indexOf(parts.hostname + ':' + parts.port) || + ~origins.indexOf(parts.hostname + ':*') || + ~origins.indexOf('*:' + parts.port); + if (!ok) this.log.warn('illegal origin: ' + origin); + return ok; + } catch (ex) { + this.log.warn('error parsing origin'); + } + } + else { + this.log.warn('origin missing from websocket call, yet required by config'); + } + return false; +}; + +/** + * Writes to the socket. + * + * @api private + */ + +WebSocket.prototype.write = function (data) { + if (this.open) { + var buf = this.frame(0x81, data); + try { + this.socket.write(buf, 'binary'); + } + catch (e) { + this.end(); + return; + } + this.log.debug(this.name + ' writing', data); + } +}; + +/** + * Writes a payload. + * + * @api private + */ + +WebSocket.prototype.payload = function (msgs) { + for (var i = 0, l = msgs.length; i < l; i++) { + this.write(msgs[i]); + } + + return this; +}; + +/** + * Frame server-to-client output as a text packet. + * + * @api private + */ + +WebSocket.prototype.frame = function (opcode, str) { + var dataBuffer = new Buffer(str) + , dataLength = dataBuffer.length + , startOffset = 2 + , secondByte = dataLength; + if (dataLength > 65536) { + startOffset = 10; + secondByte = 127; + } + else if (dataLength > 125) { + startOffset = 4; + secondByte = 126; + } + var outputBuffer = new Buffer(dataLength + startOffset); + outputBuffer[0] = opcode; + outputBuffer[1] = secondByte; + dataBuffer.copy(outputBuffer, startOffset); + switch (secondByte) { + case 126: + outputBuffer[2] = dataLength >>> 8; + outputBuffer[3] = dataLength % 256; + break; + case 127: + var l = dataLength; + for (var i = 1; i <= 8; ++i) { + outputBuffer[startOffset - i] = l & 0xff; + l >>>= 8; + } + } + return outputBuffer; +}; + +/** + * Closes the connection. + * + * @api private + */ + +WebSocket.prototype.doClose = function () { + this.socket.end(); +}; + +/** + * WebSocket parser + * + * @api public + */ + +function Parser () { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.overflow = null; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.currentMessage = ''; + + var self = this; + this.opcodeHandlers = { + // text + '1': function(data) { + var finish = function(mask, data) { + self.currentMessage += self.unmask(mask, data); + if (self.state.lastFragment) { + self.emit('data', self.currentMessage); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // binary + '2': function(data) { + var finish = function(mask, data) { + if (typeof self.currentMessage == 'string') self.currentMessage = []; // build a buffer list + self.currentMessage.push(self.unmask(mask, data, true)); + if (self.state.lastFragment) { + self.emit('binary', self.concatBuffers(self.currentMessage)); + self.currentMessage = ''; + } + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + if (util.unpack(data.slice(0, 4)) != 0) { + self.error('packets with length spanning more than 32 bit is currently not supported'); + return; + } + var lengthBytes = data.slice(4); // note: cap to 32 bit length + expectData(util.unpack(data)); + }); + } + }, + // close + '8': function(data) { + self.emit('close'); + self.reset(); + }, + // ping + '9': function(data) { + if (self.state.lastFragment == false) { + self.error('fragmented ping is not supported'); + return; + } + + var finish = function(mask, data) { + self.emit('ping', self.unmask(mask, data)); + self.endPacket(); + } + + var expectData = function(length) { + if (self.state.masked) { + self.expect('Mask', 4, function(data) { + var mask = data; + self.expect('Data', length, function(data) { + finish(mask, data); + }); + }); + } + else { + self.expect('Data', length, function(data) { + finish(null, data); + }); + } + } + + // decode length + var firstLength = data[1] & 0x7f; + if (firstLength == 0) { + finish(null, null); + } + else if (firstLength < 126) { + expectData(firstLength); + } + else if (firstLength == 126) { + self.expect('Length', 2, function(data) { + expectData(util.unpack(data)); + }); + } + else if (firstLength == 127) { + self.expect('Length', 8, function(data) { + expectData(util.unpack(data)); + }); + } + } + } + + this.expect('Opcode', 2, this.processPacket); +}; + +/** + * Inherits from EventEmitter. + */ + +Parser.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add new data to the parser. + * + * @api public + */ + +Parser.prototype.add = function(data) { + if (this.expectBuffer == null) { + this.addToOverflow(data); + return; + } + var toRead = Math.min(data.length, this.expectBuffer.length - this.expectOffset); + data.copy(this.expectBuffer, this.expectOffset, 0, toRead); + this.expectOffset += toRead; + if (toRead < data.length) { + // at this point the overflow buffer shouldn't at all exist + this.overflow = new Buffer(data.length - toRead); + data.copy(this.overflow, 0, toRead, toRead + this.overflow.length); + } + if (this.expectOffset == this.expectBuffer.length) { + var bufferForHandler = this.expectBuffer; + this.expectBuffer = null; + this.expectOffset = 0; + this.expectHandler.call(this, bufferForHandler); + } +} + +/** + * Adds a piece of data to the overflow. + * + * @api private + */ + +Parser.prototype.addToOverflow = function(data) { + if (this.overflow == null) this.overflow = data; + else { + var prevOverflow = this.overflow; + this.overflow = new Buffer(this.overflow.length + data.length); + prevOverflow.copy(this.overflow, 0); + data.copy(this.overflow, prevOverflow.length); + } +} + +/** + * Waits for a certain amount of bytes to be available, then fires a callback. + * + * @api private + */ + +Parser.prototype.expect = function(what, length, handler) { + this.expectBuffer = new Buffer(length); + this.expectOffset = 0; + this.expectHandler = handler; + if (this.overflow != null) { + var toOverflow = this.overflow; + this.overflow = null; + this.add(toOverflow); + } +} + +/** + * Start processing a new packet. + * + * @api private + */ + +Parser.prototype.processPacket = function (data) { + if ((data[0] & 0x70) != 0) { + this.error('reserved fields must be empty'); + return; + } + this.state.lastFragment = (data[0] & 0x80) == 0x80; + this.state.masked = (data[1] & 0x80) == 0x80; + var opcode = data[0] & 0xf; + if (opcode == 0) { + // continuation frame + this.state.opcode = this.state.activeFragmentedOperation; + if (!(this.state.opcode == 1 || this.state.opcode == 2)) { + this.error('continuation frame cannot follow current opcode') + return; + } + } + else { + this.state.opcode = opcode; + if (this.state.lastFragment === false) { + this.state.activeFragmentedOperation = opcode; + } + } + var handler = this.opcodeHandlers[this.state.opcode]; + if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode); + else handler(data); +} + +/** + * Endprocessing a packet. + * + * @api private + */ + +Parser.prototype.endPacket = function() { + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + if (this.state.lastFragment && this.state.opcode == this.state.activeFragmentedOperation) { + // end current fragmented operation + this.state.activeFragmentedOperation = null; + } + this.state.lastFragment = false; + this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0; + this.state.masked = false; + this.expect('Opcode', 2, this.processPacket); +} + +/** + * Reset the parser state. + * + * @api private + */ + +Parser.prototype.reset = function() { + this.state = { + activeFragmentedOperation: null, + lastFragment: false, + masked: false, + opcode: 0 + }; + this.expectOffset = 0; + this.expectBuffer = null; + this.expectHandler = null; + this.overflow = null; + this.currentMessage = ''; +} + +/** + * Unmask received data. + * + * @api private + */ + +Parser.prototype.unmask = function (mask, buf, binary) { + if (mask != null) { + for (var i = 0, ll = buf.length; i < ll; i++) { + buf[i] ^= mask[i % 4]; + } + } + if (binary) return buf; + return buf != null ? buf.toString('utf8') : ''; +} + +/** + * Concatenates a list of buffers. + * + * @api private + */ + +Parser.prototype.concatBuffers = function(buffers) { + var length = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + length += buffers[i].length; + } + var mergedBuffer = new Buffer(length); + var offset = 0; + for (var i = 0, l = buffers.length; i < l; ++i) { + buffers[i].copy(mergedBuffer, offset); + offset += buffers[i].length; + } + return mergedBuffer; +} + +/** + * Handles an error + * + * @api private + */ + +Parser.prototype.error = function (reason) { + this.reset(); + this.emit('error', reason); + return this; +}; diff --git a/node_modules/socket.io/lib/transports/websocket/index.js b/node_modules/socket.io/lib/transports/websocket/index.js new file mode 100644 index 0000000..3a952b7 --- /dev/null +++ b/node_modules/socket.io/lib/transports/websocket/index.js @@ -0,0 +1,11 @@ + +/** + * Export websocket versions. + */ + +module.exports = { + 7: require('./hybi-07-12'), + 8: require('./hybi-07-12'), + 13: require('./hybi-16'), + default: require('./default') +}; diff --git a/node_modules/socket.io/lib/transports/xhr-polling.js b/node_modules/socket.io/lib/transports/xhr-polling.js new file mode 100644 index 0000000..1db5aee --- /dev/null +++ b/node_modules/socket.io/lib/transports/xhr-polling.js @@ -0,0 +1,69 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module requirements. + */ + +var HTTPPolling = require('./http-polling'); + +/** + * Export the constructor. + */ + +exports = module.exports = XHRPolling; + +/** + * Ajax polling transport. + * + * @api public + */ + +function XHRPolling (mng, data, req) { + HTTPPolling.call(this, mng, data, req); +}; + +/** + * Inherits from Transport. + */ + +XHRPolling.prototype.__proto__ = HTTPPolling.prototype; + +/** + * Transport name + * + * @api public + */ + +XHRPolling.prototype.name = 'xhr-polling'; + +/** + * Frames data prior to write. + * + * @api private + */ + +XHRPolling.prototype.doWrite = function (data) { + HTTPPolling.prototype.doWrite.call(this); + + var origin = this.req.headers.origin + , headers = { + 'Content-Type': 'text/plain; charset=UTF-8' + , 'Content-Length': data === undefined ? 0 : Buffer.byteLength(data) + , 'Connection': 'Keep-Alive' + }; + + if (origin) { + // https://developer.mozilla.org/En/HTTP_Access_Control + headers['Access-Control-Allow-Origin'] = origin; + headers['Access-Control-Allow-Credentials'] = 'true'; + } + + this.response.writeHead(200, headers); + this.response.write(data); + this.log.debug(this.name + ' writing', data); +}; diff --git a/node_modules/socket.io/lib/util.js b/node_modules/socket.io/lib/util.js new file mode 100644 index 0000000..f7d9f2b --- /dev/null +++ b/node_modules/socket.io/lib/util.js @@ -0,0 +1,50 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +/** + * Converts an enumerable to an array. + * + * @api public + */ + +exports.toArray = function (enu) { + var arr = []; + + for (var i = 0, l = enu.length; i < l; i++) + arr.push(enu[i]); + + return arr; +}; + +/** + * Unpacks a buffer to a number. + * + * @api public + */ + +exports.unpack = function (buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Left pads a string. + * + * @api public + */ + +exports.padl = function (s,n,c) { + return new Array(1 + n - s.length).join(c) + s; +} + diff --git a/node_modules/socket.io/node_modules/base64id/.npmignore b/node_modules/socket.io/node_modules/base64id/.npmignore new file mode 100644 index 0000000..39e9864 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/.npmignore @@ -0,0 +1,3 @@ +support +test +examples diff --git a/node_modules/socket.io/node_modules/base64id/README.md b/node_modules/socket.io/node_modules/base64id/README.md new file mode 100644 index 0000000..b4361c1 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/README.md @@ -0,0 +1,18 @@ +base64id +======== + +Node.js module that generates a base64 id. + +Uses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4. + +To increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes. + +## Installation + + $ npm install mongoose + +## Usage + + var base64id = require('base64id'); + + var id = base64id.generateId(); diff --git a/node_modules/socket.io/node_modules/base64id/lib/base64id.js b/node_modules/socket.io/node_modules/base64id/lib/base64id.js new file mode 100644 index 0000000..f688159 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/lib/base64id.js @@ -0,0 +1,103 @@ +/*! + * base64id v0.1.0 + */ + +/** + * Module dependencies + */ + +var crypto = require('crypto'); + +/** + * Constructor + */ + +var Base64Id = function() { }; + +/** + * Get random bytes + * + * Uses a buffer if available, falls back to crypto.randomBytes + */ + +Base64Id.prototype.getRandomBytes = function(bytes) { + + var BUFFER_SIZE = 4096 + var self = this; + + bytes = bytes || 12; + + if (bytes > BUFFER_SIZE) { + return crypto.randomBytes(bytes); + } + + var bytesInBuffer = parseInt(BUFFER_SIZE/bytes); + var threshold = parseInt(bytesInBuffer*0.85); + + if (!threshold) { + return crypto.randomBytes(bytes); + } + + if (this.bytesBufferIndex == null) { + this.bytesBufferIndex = -1; + } + + if (this.bytesBufferIndex == bytesInBuffer) { + this.bytesBuffer = null; + this.bytesBufferIndex = -1; + } + + // No buffered bytes available or index above threshold + if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { + + if (!this.isGeneratingBytes) { + this.isGeneratingBytes = true; + crypto.randomBytes(BUFFER_SIZE, function(err, bytes) { + self.bytesBuffer = bytes; + self.bytesBufferIndex = 0; + self.isGeneratingBytes = false; + }); + } + + // Fall back to sync call when no buffered bytes are available + if (this.bytesBufferIndex == -1) { + return crypto.randomBytes(bytes); + } + } + + var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1)); + this.bytesBufferIndex++; + + return result; +} + +/** + * Generates a base64 id + * + * (Original version from socket.io ) + */ + +Base64Id.prototype.generateId = function () { + var rand = new Buffer(15); // multiple of 3 for base64 + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = (this.sequenceNumber + 1) | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + this.getRandomBytes(12).copy(rand); + } else { + // not secure for node 0.4 + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); +}; + +/** + * Export + */ + +exports = module.exports = new Base64Id(); diff --git a/node_modules/socket.io/node_modules/base64id/package.json b/node_modules/socket.io/node_modules/base64id/package.json new file mode 100644 index 0000000..a29ba06 --- /dev/null +++ b/node_modules/socket.io/node_modules/base64id/package.json @@ -0,0 +1,25 @@ +{ + "name": "base64id", + "version": "0.1.0", + "description": "Generates a base64 id", + "author": { + "name": "Kristian Faeldt", + "email": "faeldt_kristian@cyberagent.co.jp" + }, + "repository": { + "type": "git", + "url": "https://github.com/faeldt/base64id.git" + }, + "main": "./lib/base64id.js", + "engines": { + "node": ">= 0.4.0" + }, + "readme": "base64id\n========\n\nNode.js module that generates a base64 id.\n\nUses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4.\n\nTo increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes.\n\n## Installation\n\n $ npm install mongoose\n\n## Usage\n\n var base64id = require('base64id');\n\n var id = base64id.generateId();\n", + "readmeFilename": "README.md", + "_id": "base64id@0.1.0", + "dist": { + "shasum": "acf6dca85d7e2b263ff911c389e848bb1d2fef8b" + }, + "_from": "base64id@0.1.0", + "_resolved": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz" +} diff --git a/node_modules/socket.io/node_modules/policyfile/.npmignore b/node_modules/socket.io/node_modules/policyfile/.npmignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/LICENSE b/node_modules/socket.io/node_modules/policyfile/LICENSE new file mode 100644 index 0000000..bdb8f61 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Arnout Kazemier,3rd-Eden + +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. \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/Makefile b/node_modules/socket.io/node_modules/policyfile/Makefile new file mode 100644 index 0000000..1362d66 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/Makefile @@ -0,0 +1,7 @@ +doc: + dox --title "FlashPolicyFileServer" lib/* > doc/index.html + +test: + expresso -I lib $(TESTFLAGS) tests/*.test.js + +.PHONY: test doc \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/README.md b/node_modules/socket.io/node_modules/policyfile/README.md new file mode 100644 index 0000000..527921e --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/README.md @@ -0,0 +1,98 @@ +## LOL, WUT? +It basically allows you to allow or disallow Flash Player sockets from accessing your site. + +## Installation + +```bash +npm install policyfile +``` +## Usage + +The server is based on the regular and know `net` and `http` server patterns. So it you can just listen +for all the events that a `net` based server emits etc. But there is one extra event, the `connect_failed` +event. This event is triggered when we are unable to listen on the supplied port number. + +### createServer +Creates a new server instance and accepts 2 optional arguments: + +- `options` **Object** Options to configure the server instance + - `log` **Boolean** Enable logging to STDOUT and STDERR (defaults to true) +- `origins` **Array** An Array of origins that are allowed by the server (defaults to *:*) + +```js +var pf = require('policyfile'); +pf.createServer(); +pf.listen(); +``` + +#### server.listen +Start listening on the server and it takes 3 optional arguments + +- `port` **Number** On which port number should we listen? (defaults to 843, which is the first port number the FlashPlayer checks) +- `server` **Server** A http server, if we are unable to accept requests or run the server we can also answer the policy requests inline over the supplied HTTP server. +- `callback` **Function** A callback function that is called when listening to the server was successful. + +```js +var pf = require('policyfile'); +pf.createServer(); +pf.listen(1337, function(){ + console.log(':3 yay') +}); +``` + +Changing port numbers can be handy if you do not want to run your server as root and have port 843 forward to a non root port number (aka a number above 1024). + +```js +var pf = require('policyfile') + , http = require('http'); + +server = http.createServer(function(q,r){r.writeHead(200);r.end('hello world')}); +server.listen(80); + +pf.createServer(); +pf.listen(1337, server, function(){ + console.log(':3 yay') +}); +``` + +Support for serving inline requests over a existing HTTP connection as the FlashPlayer will first check port 843, but if it's unable to get a response there it will send a policy file request over port 80, which is usually your http server. + +#### server.add +Adds more origins to the policy file you can add as many arguments as you like. + +```js +var pf = require('policyfile'); +pf.createServer(['google.com:80']); +pf.listen(); +pf.add('blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080'); // now has 3 origins +``` + +#### server.add +Adds more origins to the policy file you can add as many arguments as you like. + +```js +var pf = require('policyfile'); +pf.createServer(['blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080']); +pf.listen(); +pf.remove('blog.3rd-Eden.com:8080'); // only contains the :80 version now +``` + +#### server.close +Shuts down the server + +```js +var pf = require('policyfile'); +pf.createServer(); +pf.listen(); +pf.close(); // OH NVM. +``` + +## API +http://3rd-eden.com/FlashPolicyFileServer/ + +## Examples +See https://github.com/3rd-Eden/FlashPolicyFileServer/tree/master/examples for examples + +## Licence + +MIT see LICENSE file in the repository \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/doc/index.html b/node_modules/socket.io/node_modules/policyfile/doc/index.html new file mode 100644 index 0000000..743fcda --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/doc/index.html @@ -0,0 +1,375 @@ + + + FlashPolicyFileServer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    FlashPolicyFileServer

    server

    lib/server.js
    +

    Module dependencies and cached references. +

    +
    +
    var slice = Array.prototype.slice
    +  , net = require('net');
    +
    +

    The server that does the Policy File severing

    + +

    Options

    + +
    • log false or a function that can output log information, defaults to console.log?
    + +

    + +
    • param: Object options Options to customize the servers functionality.

    • param: Array origins The origins that are allowed on this server, defaults to *:*.

    • api: public

    +
    +
    function Server(options, origins){
    +  var me = this;
    +  
    +  this.origins = origins || ['*:*'];
    +  this.port = 843;
    +  this.log = console.log;
    +  
    +  // merge `this` with the options
    +  Object.keys(options).forEach(function(key){
    +    me[key] &amp;&amp; (me[key] = options[key])
    +  });
    +  
    +  // create the net server
    +  this.socket = net.createServer(function createServer(socket){
    +    socket.on('error', function socketError(){ me.responder.call(me, socket) });
    +    me.responder.call(me, socket);
    +  });
    +  
    +  // Listen for errors as the port might be blocked because we do not have root priv.
    +  this.socket.on('error', function serverError(err){
    +    // Special and common case error handling
    +    if (err.errno == 13){
    +      me.log &amp;&amp; me.log(
    +        'Unable to listen to port `' + me.port + '` as your Node.js instance does not have root privileges. ' +
    +        (
    +          me.server
    +          ? 'The Flash Policy file will now be served inline over the supplied HTTP server, Flash Policy files request will suffer.'
    +          : 'No fallback server supplied.'
    +        )
    +      );
    +      
    +      me.socket.removeAllListeners();
    +      delete me.socket;
    +
    +      me.emit('connect_failed', err);
    +    } else {
    +      me.log &amp;&amp; me.log('FlashPolicyFileServer received a error event:\n' + (err.message ? err.message : err));
    +    }
    +  });
    +  
    +  this.socket.on('timeout', function serverTimeout(){});
    +  this.socket.on('close', function serverClosed(err){
    +    err &amp;&amp; me.log &amp;&amp; me.log('Server closing due to an error: \n' + (err.message ? err.message : err));
    +    
    +    if (me.server){
    +      // not online anymore
    +      delete me.server.online;
    +      
    +      // Remove the inline policy listener if we close down
    +      // but only when the server was `online` (see listen prototype)
    +      if( me.server['@'] &amp;&amp; me.server.online){
    +        me.server.removeListener('connection', me.server['@']);
    +      }
    +    }
    +    me.log &amp;&amp; me.log('Shutting down FlashPolicyFileServer');
    +  });
    +  
    +  // Compile the initial `buffer`
    +  this.compile();
    +}
    +
    +

    Start listening for requests

    + +

    + +
    • param: Number port The port number it should be listening to.

    • param: Server server A HTTP server instance, this will be used to listen for inline requests

    • param: Function cb The callback needs to be called once server is ready

    • api: public

    +
    +
    Server.prototype.listen = function listen(port, server, cb){
    +  var me = this
    +    , args = slice.call(arguments, 0)
    +    , callback;
    +  
    +  // assign the correct vars, for flexible arguments
    +  args.forEach(function args(arg){
    +    var type = typeof arg;
    +    
    +    if (type === 'number') me.port = arg;
    +    if (type === 'function') callback = arg;
    +    if (type === 'object') me.server = arg;
    +  });
    +  
    +  if (this.server){
    +    
    +    // no one in their right mind would ever create a `@` prototype, so Im just gonna store
    +    // my function on the server, so I can remove it later again once the server(s) closes
    +    this.server['@'] = function connection(socket){
    +      socket.once('data', function requestData(data){
    +        // if it's a Flash policy request, and we can write to the 
    +        if (
    +             data
    +          &amp;&amp; data[0] === 60
    +          &amp;&amp; data.toString() === '<policy-file-request/>\0'
    +          &amp;&amp; socket
    +          &amp;&amp; (socket.readyState === 'open' || socket.readyState === 'writeOnly')
    +        ){
    +          // send the buffer
    +          socket.end(me.buffer);
    +        }
    +      });
    +    };
    +    // attach it
    +    this.server.on('connection', this.server['@']);
    +  }
    +  
    +  // We add a callback method, so we can set a flag for when the server is `enabled` or `online`.
    +  // this flag is needed because if a error occurs and the we cannot boot up the server the
    +  // fallback functionality should not be removed during the `close` event
    +  this.socket.listen(this.port, function serverListening(){
    +   me.socket.online = true;
    +   
    +   if (callback) callback(), callback = undefined;
    +   
    +  });
    +  
    +  return this;
    +};
    +
    +

    Adds a new origin to the Flash Policy File.

    + +

    + +
    • param: Arguments The origins that need to be added.

    • api: public

    +
    +
    Server.prototype.add = function add(){
    +  var args = slice.call(arguments, 0)
    +    , i = args.length;
    +  
    +  // flag duplicates
    +  while (i--){
    +    if (this.origins.indexOf(args[i]) &gt;= 0){
    +      args[i] = null;
    +    }
    +  }
    +  
    +  // Add all the arguments to the array
    +  // but first we want to remove all `falsy` values from the args
    +  Array.prototype.push.apply(
    +    this.origins
    +  , args.filter(function(value){ return !!value })
    +  );
    +  
    +  this.compile();
    +  return this;
    +};
    +
    +

    Removes a origin from the Flash Policy File.

    + +

    + +
    • param: String origin The origin that needs to be removed from the server

    • api: public

    +
    +
    Server.prototype.remove = function remove(origin){
    +  var position = this.origins.indexOf(origin);
    +  
    +  // only remove and recompile if we have a match
    +  if (position &gt; 0){
    +    this.origins.splice(position,1);
    +    this.compile();
    +  }
    +  
    +  return this;
    +};
    +
    +

    Closes and cleans up the server

    + +
    • api: public

    +
    +
    Server.prototype.close = function close(){
    +  this.socket.removeAllListeners();
    +  this.socket.close();
    +  
    +  return this;
    +};
    +
    +

    Proxy the event listener requests to the created Net server +

    +
    +
    Object.keys(process.EventEmitter.prototype).forEach(function proxy(key){
    +  Server.prototype[key] = Server.prototype[key] || function (){
    +    if (this.socket) this.socket[key].apply(this.socket, arguments);
    +    return this;
    +  };
    +});
    +
    +

    Creates a new server instance.

    + +

    + +
    • param: Object options A options object to override the default config

    • param: Array origins The origins that should be allowed by the server

    • api: public

    +
    +
    exports.createServer = function createServer(options, origins){
    +  origins = Array.isArray(origins) ? origins : (Array.isArray(options) ? options : false);
    +  options = !Array.isArray(options) &amp;&amp; options ? options : {};
    +  
    +  return new Server(options, origins);
    +};
    +
    +

    Provide a hook to the original server, so it can be extended if needed. +

    +
    +
    exports.Server = Server;
    +
    +

    Module version +

    +
    +
    exports.version = '0.0.2';
    +
    +
    \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js b/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js new file mode 100644 index 0000000..b439449 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/examples/basic.fallback.js @@ -0,0 +1,8 @@ +var http = require('http') + , fspfs = require('../'); + +var server = http.createServer(function(q,r){ r.writeHead(200); r.end(':3') }) + , flash = fspfs.createServer(); + +server.listen(8080); +flash.listen(8081,server); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/examples/basic.js b/node_modules/socket.io/node_modules/policyfile/examples/basic.js new file mode 100644 index 0000000..5e2290f --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/examples/basic.js @@ -0,0 +1,5 @@ +var http = require('http') + , fspfs = require('../'); + +var flash = fspfs.createServer(); +flash.listen(); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/index.js b/node_modules/socket.io/node_modules/policyfile/index.js new file mode 100644 index 0000000..60cf298 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/server.js'); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/policyfile/lib/server.js b/node_modules/socket.io/node_modules/policyfile/lib/server.js new file mode 100644 index 0000000..a525772 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/lib/server.js @@ -0,0 +1,289 @@ +/** + * Module dependencies and cached references. + */ + +var slice = Array.prototype.slice + , net = require('net'); + +/** + * The server that does the Policy File severing + * + * Options: + * - `log` false or a function that can output log information, defaults to console.log? + * + * @param {Object} options Options to customize the servers functionality. + * @param {Array} origins The origins that are allowed on this server, defaults to `*:*`. + * @api public + */ + +function Server (options, origins) { + var me = this; + + this.origins = origins || ['*:*']; + this.port = 843; + this.log = console.log; + + // merge `this` with the options + Object.keys(options).forEach(function (key) { + me[key] && (me[key] = options[key]) + }); + + // create the net server + this.socket = net.createServer(function createServer (socket) { + socket.on('error', function socketError () { + me.responder.call(me, socket); + }); + + me.responder.call(me, socket); + }); + + // Listen for errors as the port might be blocked because we do not have root priv. + this.socket.on('error', function serverError (err) { + // Special and common case error handling + if (err.errno == 13) { + me.log && me.log( + 'Unable to listen to port `' + me.port + '` as your Node.js instance does not have root privileges. ' + + ( + me.server + ? 'The Flash Policy File requests will only be served inline over the supplied HTTP server. Inline serving is slower than a dedicated server instance.' + : 'No fallback server supplied, we will be unable to answer Flash Policy File requests.' + ) + ); + + me.emit('connect_failed', err); + me.socket.removeAllListeners(); + delete me.socket; + } else { + me.log && me.log('FlashPolicyFileServer received an error event:\n' + (err.message ? err.message : err)); + } + }); + + this.socket.on('timeout', function serverTimeout () {}); + this.socket.on('close', function serverClosed (err) { + err && me.log && me.log('Server closing due to an error: \n' + (err.message ? err.message : err)); + + if (me.server) { + // Remove the inline policy listener if we close down + // but only when the server was `online` (see listen prototype) + if (me.server['@'] && me.server.online) { + me.server.removeListener('connection', me.server['@']); + } + + // not online anymore + delete me.server.online; + } + }); + + // Compile the initial `buffer` + this.compile(); +} + +/** + * Start listening for requests + * + * @param {Number} port The port number it should be listening to. + * @param {Server} server A HTTP server instance, this will be used to listen for inline requests + * @param {Function} cb The callback needs to be called once server is ready + * @api public + */ + +Server.prototype.listen = function listen (port, server, cb){ + var me = this + , args = slice.call(arguments, 0) + , callback; + + // assign the correct vars, for flexible arguments + args.forEach(function args (arg){ + var type = typeof arg; + + if (type === 'number') me.port = arg; + if (type === 'function') callback = arg; + if (type === 'object') me.server = arg; + }); + + if (this.server) { + + // no one in their right mind would ever create a `@` prototype, so Im just gonna store + // my function on the server, so I can remove it later again once the server(s) closes + this.server['@'] = function connection (socket) { + socket.once('data', function requestData (data) { + // if it's a Flash policy request, and we can write to the + if ( + data + && data[0] === 60 + && data.toString() === '\0' + && socket + && (socket.readyState === 'open' || socket.readyState === 'writeOnly') + ){ + // send the buffer + try { + socket.end(me.buffer); + } catch (e) {} + } + }); + }; + + // attach it + this.server.on('connection', this.server['@']); + } + + // We add a callback method, so we can set a flag for when the server is `enabled` or `online`. + // this flag is needed because if a error occurs and the we cannot boot up the server the + // fallback functionality should not be removed during the `close` event + this.port >= 0 && this.socket.listen(this.port, function serverListening () { + me.socket.online = true; + if (callback) { + callback.call(me); + callback = undefined; + } + }); + + return this; +}; + +/** + * Responds to socket connects and writes the compile policy file. + * + * @param {net.Socket} socket The socket that needs to receive the message + * @api private + */ + +Server.prototype.responder = function responder (socket){ + if (socket && socket.readyState == 'open' && socket.end) { + try { + socket.end(this.buffer); + } catch (e) {} + } +}; + +/** + * Compiles the supplied origins to a Flash Policy File format and stores it in a Node.js Buffer + * this way it can be send over the wire without any performance loss. + * + * @api private + */ + +Server.prototype.compile = function compile (){ + var xml = [ + '' + , '' + , '' + ]; + + // add the allow access element + this.origins.forEach(function origin (origin){ + var parts = origin.split(':'); + xml.push(''); + }); + + xml.push(''); + + // store the result in a buffer so we don't have to re-generate it all the time + this.buffer = new Buffer(xml.join(''), 'utf8'); + + return this; +}; + +/** + * Adds a new origin to the Flash Policy File. + * + * @param {Arguments} The origins that need to be added. + * @api public + */ + +Server.prototype.add = function add(){ + var args = slice.call(arguments, 0) + , i = args.length; + + // flag duplicates + while (i--) { + if (this.origins.indexOf(args[i]) >= 0){ + args[i] = null; + } + } + + // Add all the arguments to the array + // but first we want to remove all `falsy` values from the args + Array.prototype.push.apply( + this.origins + , args.filter(function filter (value) { + return !!value; + }) + ); + + this.compile(); + return this; +}; + +/** + * Removes a origin from the Flash Policy File. + * + * @param {String} origin The origin that needs to be removed from the server + * @api public + */ + +Server.prototype.remove = function remove (origin){ + var position = this.origins.indexOf(origin); + + // only remove and recompile if we have a match + if (position > 0) { + this.origins.splice(position,1); + this.compile(); + } + + return this; +}; + +/** + * Closes and cleans up the server + * + * @api public + */ + +Server.prototype.close = function close () { + this.socket.removeAllListeners(); + this.socket.close(); + + return this; +}; + +/** + * Proxy the event listener requests to the created Net server + */ + +Object.keys(process.EventEmitter.prototype).forEach(function proxy (key){ + Server.prototype[key] = Server.prototype[key] || function () { + if (this.socket) { + this.socket[key].apply(this.socket, arguments); + } + + return this; + }; +}); + +/** + * Creates a new server instance. + * + * @param {Object} options A options object to override the default config + * @param {Array} origins The origins that should be allowed by the server + * @api public + */ + +exports.createServer = function createServer(options, origins){ + origins = Array.isArray(origins) ? origins : (Array.isArray(options) ? options : false); + options = !Array.isArray(options) && options ? options : {}; + + return new Server(options, origins); +}; + +/** + * Provide a hook to the original server, so it can be extended if needed. + */ + +exports.Server = Server; + +/** + * Module version + */ + +exports.version = '0.0.4'; diff --git a/node_modules/socket.io/node_modules/policyfile/package.json b/node_modules/socket.io/node_modules/policyfile/package.json new file mode 100644 index 0000000..c3f8fae --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/package.json @@ -0,0 +1,48 @@ +{ + "name": "policyfile", + "version": "0.0.4", + "author": { + "name": "Arnout Kazemier" + }, + "description": "Flash Socket Policy File Server. A server to respond to Flash Socket Policy requests, both inline and through a dedicated server instance.", + "main": "index", + "keywords": [ + "flash", + "socket", + "policy", + "file", + "server", + "Flash Socket Policy File Server", + "cross domain" + ], + "directories": { + "lib": "./lib" + }, + "maintainers": [ + { + "name": "Arnout Kazemier", + "email": "info@3rd-Eden.com", + "url": "http://blog.3rd-Eden.com" + } + ], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/3rd-Eden/FlashPolicyFileServer/blob/master/LICENSE" + } + ], + "repositories": [ + { + "type": "git", + "url": "https://github.com/3rd-Eden/FlashPolicyFileServer.git" + } + ], + "readme": "## LOL, WUT?\nIt basically allows you to allow or disallow Flash Player sockets from accessing your site.\n\n## Installation\n\n```bash\nnpm install policyfile\n```\n## Usage\n\nThe server is based on the regular and know `net` and `http` server patterns. So it you can just listen\nfor all the events that a `net` based server emits etc. But there is one extra event, the `connect_failed`\nevent. This event is triggered when we are unable to listen on the supplied port number.\n\n### createServer\nCreates a new server instance and accepts 2 optional arguments:\n\n- `options` **Object** Options to configure the server instance\n - `log` **Boolean** Enable logging to STDOUT and STDERR (defaults to true)\n- `origins` **Array** An Array of origins that are allowed by the server (defaults to *:*)\n\n```js\nvar pf = require('policyfile');\npf.createServer();\npf.listen();\n```\n\n#### server.listen\nStart listening on the server and it takes 3 optional arguments\n\n- `port` **Number** On which port number should we listen? (defaults to 843, which is the first port number the FlashPlayer checks)\n- `server` **Server** A http server, if we are unable to accept requests or run the server we can also answer the policy requests inline over the supplied HTTP server.\n- `callback` **Function** A callback function that is called when listening to the server was successful.\n\n```js\nvar pf = require('policyfile');\npf.createServer();\npf.listen(1337, function(){\n console.log(':3 yay')\n});\n```\n\nChanging port numbers can be handy if you do not want to run your server as root and have port 843 forward to a non root port number (aka a number above 1024).\n\n```js\nvar pf = require('policyfile')\n , http = require('http');\n\nserver = http.createServer(function(q,r){r.writeHead(200);r.end('hello world')});\nserver.listen(80);\n\npf.createServer();\npf.listen(1337, server, function(){\n console.log(':3 yay')\n});\n```\n\nSupport for serving inline requests over a existing HTTP connection as the FlashPlayer will first check port 843, but if it's unable to get a response there it will send a policy file request over port 80, which is usually your http server.\n\n#### server.add\nAdds more origins to the policy file you can add as many arguments as you like.\n\n```js\nvar pf = require('policyfile');\npf.createServer(['google.com:80']);\npf.listen();\npf.add('blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080'); // now has 3 origins\n```\n\n#### server.add\nAdds more origins to the policy file you can add as many arguments as you like.\n\n```js\nvar pf = require('policyfile');\npf.createServer(['blog.3rd-Eden.com:80', 'blog.3rd-Eden.com:8080']);\npf.listen();\npf.remove('blog.3rd-Eden.com:8080'); // only contains the :80 version now\n```\n\n#### server.close\nShuts down the server\n\n```js\nvar pf = require('policyfile');\npf.createServer();\npf.listen();\npf.close(); // OH NVM.\n```\n\n## API\nhttp://3rd-eden.com/FlashPolicyFileServer/\n\n## Examples\nSee https://github.com/3rd-Eden/FlashPolicyFileServer/tree/master/examples for examples\n\n## Licence\n\nMIT see LICENSE file in the repository", + "readmeFilename": "README.md", + "_id": "policyfile@0.0.4", + "dist": { + "shasum": "996f9eff351fd93db482bd1f5411149b75537447" + }, + "_from": "policyfile@0.0.4", + "_resolved": "https://registry.npmjs.org/policyfile/-/policyfile-0.0.4.tgz" +} diff --git a/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt new file mode 100644 index 0000000..5883cd4 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAMUSOvlaeyQHMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTAxMTE2MDkzMjQ5WhcNMTMxMTE1MDkzMjQ5WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEVwfPQQp4X +wtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+1FAE0c5o +exPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404WthquTqg +S7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy25IyBK3QJ +c+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWAQsqW+COL +0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABo1AwTjAdBgNVHQ4EFgQUDnV4d6mD +tOnluLoCjkUHTX/n4agwHwYDVR0jBBgwFoAUDnV4d6mDtOnluLoCjkUHTX/n4agw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAFwV4MQfTo+qMv9JMiyno +IEiqfOz4RgtmBqRnXUffcjS2dhc7/z+FPZnM79Kej8eLHoVfxCyWRHFlzm93vEdv +wxOCrD13EDOi08OOZfxWyIlCa6Bg8cMAKqQzd2OvQOWqlRWBTThBJIhWflU33izX +Qn5GdmYqhfpc+9ZHHGhvXNydtRQkdxVK2dZNzLBvBlLlRmtoClU7xm3A+/5dddeP +AQHEPtyFlUw49VYtZ3ru6KqPms7MKvcRhYLsy9rwSfuuniMlx4d0bDR7TOkw0QQS +A0N8MGQRQpzl4mw4jLzyM5d5QtuGBh2P6hPGa0YQxtI3RPT/p6ENzzBiAKXiSfzo +xw== +-----END CERTIFICATE----- diff --git a/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key new file mode 100644 index 0000000..f31ff3d --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/tests/ssl/ssl.private.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAz+LXZOjcQCJq3+ZKUFabj71oo/ex/XsBcFqtBThjjTw9CVEV +wfPQQp4XwtPiB204vnYXwQ1/R2NdTQqCZu47l79LssL/u2a5Y9+0NEU3nQA5qdt+ +1FAE0c5oexPimXOrR3GWfKz7PmZ2O0117IeCUUXPG5U8umhDe/4mDF4ZNJiKc404 +WthquTqgS7rLQZHhZ6D0EnGnOkzlmxJMYPNHSOY1/6ivdNUUcC87awNEA3lgfhy2 +5IyBK3QJc+aYKNTbt70Lery3bu2wWLFGtmNiGlQTS4JsxImRsECTI727ObS7/FWA +QsqW+COL0Sa5BuMFrFIpjPrEe0ih7vRRbdmXRwIDAQABAoIBAGe4+9VqZfJN+dsq +8Osyuz01uQ8OmC0sAWTIqUlQgENIyf9rCJsUBlYmwR5BT6Z69XP6QhHdpSK+TiAR +XUz0EqG9HYzcxHIBaACP7j6iRoQ8R4kbbiWKo0z3WqQGIOqFjvD/mKEuQdE5mEYw +eOUCG6BnX1WY2Yr8WKd2AA/tp0/Y4d8z04u9eodMpSTbHTzYMJb5SbBN1vo6FY7q +8zSuO0BMzXlAxUsCwHsk1GQHFr8Oh3zIR7bQGtMBouI+6Lhh7sjFYsfxJboqMTBV +IKaA216M6ggHG7MU1/jeKcMGDmEfqQLQoyWp29rMK6TklUgipME2L3UD7vTyAVzz +xbVOpZkCgYEA8CXW4sZBBrSSrLR5SB+Ubu9qNTggLowOsC/kVKB2WJ4+xooc5HQo +mFhq1v/WxPQoWIxdYsfg2odlL+JclK5Qcy6vXmRSdAQ5lK9gBDKxZSYc3NwAw2HA +zyHCTK+I0n8PBYQ+yGcrxu0WqTGnlLW+Otk4CejO34WlgHwbH9bbY5UCgYEA3ZvT +C4+OoMHXlmICSt29zUrYiL33IWsR3/MaONxTEDuvgkOSXXQOl/8Ebd6Nu+3WbsSN +bjiPC/JyL1YCVmijdvFpl4gjtgvfJifs4G+QHvO6YfsYoVANk4u6g6rUuBIOwNK4 +RwYxwDc0oysp+g7tPxoSgDHReEVKJNzGBe9NGGsCgYEA4O4QP4gCEA3B9BF2J5+s +n9uPVxmiyvZUK6Iv8zP4pThTBBMIzNIf09G9AHPQ7djikU2nioY8jXKTzC3xGTHM +GJZ5m6fLsu7iH+nDvSreDSeNkTBfZqGAvoGYQ8uGE+L+ZuRfCcXYsxIOT5s6o4c3 +Dle2rVFpsuKzCY00urW796ECgYBn3go75+xEwrYGQSer6WR1nTgCV29GVYXKPooy +zmmMOT1Yw80NSkEw0pFD4cTyqVYREsTrPU0mn1sPfrOXxnGfZSVFpcR/Je9QVfQ7 +eW7GYxwfom335aqHVj10SxRqteP+UoWWnHujCPz94VRKZMakBddYCIGSan+G6YdS +7sdmwwKBgBc2qj0wvGXDF2kCLwSGfWoMf8CS1+5fIiUIdT1e/+7MfDdbmLMIFVjF +QKS3zVViXCbrG5SY6wS9hxoc57f6E2A8vcaX6zy2xkZlGHQCpWRtEM5R01OWJQaH +HsHMmQZGUQVoDm1oRkDhrTFK4K3ukc3rAxzeTZ96utOQN8/KJsTv +-----END RSA PRIVATE KEY----- diff --git a/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js b/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js new file mode 100644 index 0000000..932b3c1 --- /dev/null +++ b/node_modules/socket.io/node_modules/policyfile/tests/unit.test.js @@ -0,0 +1,231 @@ +var fspfs = require('../') + , fs = require('fs') + , http = require('http') + , https = require('https') + , net = require('net') + , should = require('should') + , assert = require('assert'); + +module.exports = { + // Library version should be Semver compatible + 'Library version': function(){ + fspfs.version.should.match(/^\d+\.\d+\.\d+$/); + } + + // Creating a server instace should not cause any problems + // either using the new Server or createServer method. +, 'Create Server instance': function(){ + var server = fspfs.createServer() + , server2 = new fspfs.Server({log:false}, ['blog.3rd-Eden.com:1337']); + + // server 2 options test + server2.log.should.be.false; + server2.origins.length.should.equal(1); + server2.origins[0].should.equal('blog.3rd-Eden.com:1337'); + + // server defaults + (typeof server.log).should.be.equal('function'); + server.origins.length.should.equal(1); + server.origins[0].should.equal('*:*'); + + // instance checking, sanity check + assert.ok(server instanceof fspfs.Server); + assert.ok(!!server.buffer); + + // more options testing + server = fspfs.createServer(['blog.3rd-Eden.com:80']); + server.origins.length.should.equal(1); + server.origins[0].should.equal('blog.3rd-Eden.com:80'); + + server = fspfs.createServer({log:false},['blog.3rd-Eden.com:80']); + server.log.should.be.false; + server.origins.length.should.equal(1); + server.origins[0].should.equal('blog.3rd-Eden.com:80'); + + } + +, 'Add origin': function(){ + var server = fspfs.createServer(); + server.add('google.com:80', 'blog.3rd-Eden.com:1337'); + + server.origins.length.should.equal(3); + server.origins.indexOf('google.com:80').should.be.above(0); + + // don't allow duplicates + server.add('google.com:80', 'google.com:80'); + + var i = server.origins.length + , count = 0; + + while(i--){ + if (server.origins[i] === 'google.com:80'){ + count++; + } + } + + count.should.equal(1); + } + +, 'Remove origin': function(){ + var server = fspfs.createServer(); + server.add('google.com:80', 'blog.3rd-Eden.com:1337'); + server.origins.length.should.equal(3); + + server.remove('google.com:80'); + server.origins.length.should.equal(2); + server.origins.indexOf('google.com:80').should.equal(-1); + } + +, 'Buffer': function(){ + var server = fspfs.createServer(); + + Buffer.isBuffer(server.buffer).should.be.true; + server.buffer.toString().indexOf('to-ports="*"').should.be.above(0); + server.buffer.toString().indexOf('domain="*"').should.be.above(0); + server.buffer.toString().indexOf('domain="google.com"').should.equal(-1); + + // The buffers should be rebuild when new origins are added + server.add('google.com:80'); + server.buffer.toString().indexOf('to-ports="80"').should.be.above(0); + server.buffer.toString().indexOf('domain="google.com"').should.be.above(0); + + server.remove('google.com:80'); + server.buffer.toString().indexOf('to-ports="80"').should.equal(-1); + server.buffer.toString().indexOf('domain="google.com"').should.equal(-1); + } + +, 'Responder': function(){ + var server = fspfs.createServer() + , calls = 0 + // dummy socket to emulate a `real` socket + , dummySocket = { + readyState: 'open' + , end: function(buffer){ + calls++; + Buffer.isBuffer(buffer).should.be.true; + buffer.toString().should.equal(server.buffer.toString()); + } + }; + + server.responder(dummySocket); + calls.should.equal(1); + } + +, 'Event proxy': function(){ + var server = fspfs.createServer() + , calls = 0; + + Object.keys(process.EventEmitter.prototype).forEach(function proxy(key){ + assert.ok(!!server[key] && typeof server[key] === 'function'); + }); + + // test if it works by calling a none default event + server.on('pew', function(){ + calls++; + }); + + server.emit('pew'); + calls.should.equal(1); + } + +, 'inline response http': function(){ + var port = 1335 + , httpserver = http.createServer(function(q,r){r.writeHead(200);r.end(':3')}) + , server = fspfs.createServer(); + + httpserver.listen(port, function(){ + server.listen(port + 1, httpserver, function(){ + var client = net.createConnection(port); + client.write('\0'); + client.on('error', function(err){ + assert.ok(!err, err) + }); + client.on('data', function(data){ + + var response = data.toString(); + console.log(response); + + response.indexOf('to-ports="*"').should.be.above(0); + response.indexOf('domain="*"').should.be.above(0); + response.indexOf('domain="google.com"').should.equal(-1); + + // clean up + client.destroy(); + server.close(); + httpserver.close(); + }); + }); + }); + } + +, 'server response': function(){ + var port = 1340 + , server = fspfs.createServer(); + + server.listen(port, function(){ + var client = net.createConnection(port); + client.write('\0'); + client.on('error', function(err){ + assert.ok(!err, err) + }); + client.on('data', function(data){ + + var response = data.toString(); + + response.indexOf('to-ports="*"').should.be.above(0); + response.indexOf('domain="*"').should.be.above(0); + response.indexOf('domain="google.com"').should.equal(-1); + + // clean up + client.destroy(); + server.close(); + }); + }); + } + +, 'inline response https': function(){ + var port = 1345 + , ssl = { + key: fs.readFileSync(__dirname + '/ssl/ssl.private.key').toString() + , cert: fs.readFileSync(__dirname + '/ssl/ssl.crt').toString() + } + , httpserver = https.createServer(ssl, function(q,r){r.writeHead(200);r.end(':3')}) + , server = fspfs.createServer(); + + httpserver.listen(port, function(){ + server.listen(port + 1, httpserver, function(){ + var client = net.createConnection(port); + client.write('\0'); + client.on('error', function(err){ + assert.ok(!err, err) + }); + client.on('data', function(data){ + + var response = data.toString(); + + response.indexOf('to-ports="*"').should.be.above(0); + response.indexOf('domain="*"').should.be.above(0); + response.indexOf('domain="google.com"').should.equal(-1); + + // clean up + client.destroy(); + server.close(); + httpserver.close(); + }); + }); + }); + } + +, 'connect_failed': function(){ + var server = fspfs.createServer(); + + server.on('connect_failed', function(){ + assert.ok(true); + }); + + server.listen(function(){ + assert.ok(false, 'Run this test without root access'); + server.close(); + }); + } +}; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/redis/.npmignore b/node_modules/socket.io/node_modules/redis/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/socket.io/node_modules/redis/README.md b/node_modules/socket.io/node_modules/redis/README.md new file mode 100644 index 0000000..46e7018 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/README.md @@ -0,0 +1,691 @@ +redis - a node.js redis client +=========================== + +This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from +experimental Redis server branches. + + +Install with: + + npm install redis + +Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do: + + npm install hiredis redis + +If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used. + +If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can +happen between node and native code modules after a node upgrade. + + +## Usage + +Simple example, included as `examples/simple.js`: + +```js + var redis = require("redis"), + client = redis.createClient(); + + // if you'd like to select database 3, instead of 0 (default), call + // client.select(3, function() { /* ... */ }); + + client.on("error", function (err) { + console.log("Error " + err); + }); + + client.set("string key", "string val", redis.print); + client.hset("hash key", "hashtest 1", "some value", redis.print); + client.hset(["hash key", "hashtest 2", "some other value"], redis.print); + client.hkeys("hash key", function (err, replies) { + console.log(replies.length + " replies:"); + replies.forEach(function (reply, i) { + console.log(" " + i + ": " + reply); + }); + client.quit(); + }); +``` + +This will display: + + mjr:~/work/node_redis (master)$ node example.js + Reply: OK + Reply: 0 + Reply: 0 + 2 replies: + 0: hashtest 1 + 1: hashtest 2 + mjr:~/work/node_redis (master)$ + + +## Performance + +Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution. +It uses 50 concurrent connections with no pipelining. + +JavaScript parser: + + PING: 20000 ops 42283.30 ops/sec 0/5/1.182 + SET: 20000 ops 32948.93 ops/sec 1/7/1.515 + GET: 20000 ops 28694.40 ops/sec 0/9/1.740 + INCR: 20000 ops 39370.08 ops/sec 0/8/1.269 + LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370 + LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048 + LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072 + +hiredis parser: + + PING: 20000 ops 46189.38 ops/sec 1/4/1.082 + SET: 20000 ops 41237.11 ops/sec 0/6/1.210 + GET: 20000 ops 39682.54 ops/sec 1/7/1.257 + INCR: 20000 ops 40080.16 ops/sec 0/8/1.242 + LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212 + LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363 + LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287 + +The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs. + + +### Sending Commands + +Each Redis command is exposed as a function on the `client` object. +All functions take either an `args` Array plus optional `callback` Function or +a variable number of individual arguments followed by an optional callback. +Here is an example of passing an array of arguments and a callback: + + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {}); + +Here is that same call in the second style: + + client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {}); + +Note that in either form the `callback` is optional: + + client.set("some key", "some val"); + client.set(["some other key", "some val"]); + +If the key is missing, reply will be null (probably): + + client.get("missingkey", function(err, reply) { + // reply is null when the key is missing + console.log(reply); + }); + +For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands) + +The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`. + +Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings, +integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a +JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys. + +# API + +## Connection Events + +`client` will emit some events about the state of the connection to the Redis server. + +### "ready" + +`client` will emit `ready` a connection is established to the Redis server and the server reports +that it is ready to receive commands. Commands issued before the `ready` event are queued, +then replayed just before this event is emitted. + +### "connect" + +`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check` +is set. If this options is set, `connect` will be emitted when the stream is connected, and then +you are free to try to send commands. + +### "error" + +`client` will emit `error` when encountering an error connecting to the Redis server. + +Note that "error" is a special event type in node. If there are no listeners for an +"error" event, node will exit. This is usually what you want, but it can lead to some +cryptic error messages like this: + + mjr:~/work/node_redis (master)$ node example.js + + node.js:50 + throw e; + ^ + Error: ECONNREFUSED, Connection refused + at IOWatcher.callback (net:870:22) + at node.js:607:9 + +Not very useful in diagnosing the problem, but if your program isn't ready to handle this, +it is probably the right thing to just exit. + +`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason. +It would be nice to distinguish these two cases. + +### "end" + +`client` will emit `end` when an established Redis server connection has closed. + +### "drain" + +`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now +writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now, +you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can +resume sending when you get `drain`. + +### "idle" + +`client` will emit `idle` when there are no outstanding commands that are awaiting a response. + +## redis.createClient(port, host, options) + +Create a new client connection. `port` defaults to `6379` and `host` defaults +to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for +port and host are probably fine. `options` in an object with the following possible properties: + +* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed. +This may also be set to `javascript`. +* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer +objects instead of JavaScript Strings. +* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects +if any of the input arguments to the original command were Buffer objects. +This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to +every command on a client. +* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the +Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the +cost of more latency. Most applications will want this set to `true`. +* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still +be loading the database from disk. While loading, the server not respond to any commands. To work around this, +`node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command +indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. +Setting `no_ready_check` to `true` will inhibit this check. +* `enable_offline_queue`: defaults to `true`. By default, if there is no active +connection to the redis server, commands are added to a queue and are executed +once the connection has been established. Setting `enable_offline_queue` to +`false` will disable this feature and the callback will be execute immediately +with an error, or an error will be thrown if no callback is specified. + +```js + var redis = require("redis"), + client = redis.createClient(null, null, {detect_buffers: true}); + + client.set("foo_rand000000000000", "OK"); + + // This will return a JavaScript String + client.get("foo_rand000000000000", function (err, reply) { + console.log(reply.toString()); // Will print `OK` + }); + + // This will return a Buffer since original key is specified as a Buffer + client.get(new Buffer("foo_rand000000000000"), function (err, reply) { + console.log(reply.toString()); // Will print `` + }); + client.end(); +``` + +`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here. + +## client.auth(password, callback) + +When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the +first command after connecting. This can be tricky to coordinate with reconnections, the ready check, +etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection, +including reconnections. `callback` is invoked only once, after the response to the very first +`AUTH` command sent. +NOTE: Your call to `client.auth()` should not be inside the ready handler. If +you are doing this wrong, `client` will emit an error that looks +something like this `Error: Ready check failed: ERR operation not permitted`. + +## client.end() + +Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed. +If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies. + +This example closes the connection to the Redis server before the replies have been read. You probably don't +want to do this: + +```js + var redis = require("redis"), + client = redis.createClient(); + + client.set("foo_rand000000000000", "some fantastic value"); + client.get("foo_rand000000000000", function (err, reply) { + console.log(reply.toString()); + }); + client.end(); +``` + +`client.end()` is useful for timeout cases where something is stuck or taking too long and you want +to start over. + +## Friendlier hash commands + +Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. +When dealing with hash values, there are a couple of useful exceptions to this. + +### client.hgetall(hash) + +The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact +with the responses using JavaScript syntax. + +Example: + + client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234"); + client.hgetall("hosts", function (err, obj) { + console.dir(obj); + }); + +Output: + + { mjr: '1', another: '23', home: '1234' } + +### client.hmset(hash, obj, [callback]) + +Multiple values in a hash can be set by supplying an object: + + client.HMSET(key2, { + "0123456789": "abcdefghij", // NOTE: the key and value must both be strings + "some manner of key": "a type of value" + }); + +The properties and values of this Object will be set as keys and values in the Redis hash. + +### client.hmset(hash, key1, val1, ... keyn, valn, [callback]) + +Multiple values may also be set by supplying a list: + + client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value"); + + +## Publish / Subscribe + +Here is a simple example of the API for publish / subscribe. This program opens two +client connections, subscribes to a channel on one of them, and publishes to that +channel on the other: + +```js + var redis = require("redis"), + client1 = redis.createClient(), client2 = redis.createClient(), + msg_count = 0; + + client1.on("subscribe", function (channel, count) { + client2.publish("a nice channel", "I am sending a message."); + client2.publish("a nice channel", "I am sending a second message."); + client2.publish("a nice channel", "I am sending my last message."); + }); + + client1.on("message", function (channel, message) { + console.log("client1 channel " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.unsubscribe(); + client1.end(); + client2.end(); + } + }); + + client1.incr("did a thing"); + client1.subscribe("a nice channel"); +``` + +When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode. +At that point, only commands that modify the subscription set are valid. When the subscription +set is empty, the connection is put back into regular mode. + +If you need to send regular commands to Redis while in pub/sub mode, just open another connection. + +## Pub / Sub Events + +If a client has subscriptions active, it may emit these events: + +### "message" (channel, message) + +Client will emit `message` for every message received that matches an active subscription. +Listeners are passed the channel name as `channel` and the message Buffer as `message`. + +### "pmessage" (pattern, channel, message) + +Client will emit `pmessage` for every message received that matches an active subscription pattern. +Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel +name as `channel`, and the message Buffer as `message`. + +### "subscribe" (channel, count) + +Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. + +### "psubscribe" (pattern, count) + +Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the +original pattern as `pattern`, and the new count of subscriptions for this client as `count`. + +### "unsubscribe" (channel, count) + +Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. When +`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted. + +### "punsubscribe" (pattern, count) + +Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the +channel name as `channel` and the new count of subscriptions for this client as `count`. When +`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted. + +## client.multi([commands]) + +`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by +Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`. + +```js + var redis = require("./index"), + client = redis.createClient(), set_size = 20; + + client.sadd("bigset", "a member"); + client.sadd("bigset", "another member"); + + while (set_size > 0) { + client.sadd("bigset", "member " + set_size); + set_size -= 1; + } + + // multi chain with an individual callback + client.multi() + .scard("bigset") + .smembers("bigset") + .keys("*", function (err, replies) { + // NOTE: code in this callback is NOT atomic + // this only happens after the the .exec call finishes. + client.mget(replies, redis.print); + }) + .dbsize() + .exec(function (err, replies) { + console.log("MULTI got " + replies.length + " replies"); + replies.forEach(function (reply, index) { + console.log("Reply " + index + ": " + reply.toString()); + }); + }); +``` + +`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the +same command methods as `client` objects do. Commands are queued up inside the `Multi` object +until `Multi.exec()` is invoked. + +You can either chain together `MULTI` commands as in the above example, or you can queue individual +commands while still sending regular client command as in this example: + +```js + var redis = require("redis"), + client = redis.createClient(), multi; + + // start a separate multi command queue + multi = client.multi(); + multi.incr("incr thing", redis.print); + multi.incr("incr other thing", redis.print); + + // runs immediately + client.mset("incr thing", 100, "incr other thing", 1, redis.print); + + // drains multi queue and runs atomically + multi.exec(function (err, replies) { + console.log(replies); // 101, 2 + }); + + // you can re-run the same transaction if you like + multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); + }); +``` + +In addition to adding commands to the `MULTI` queue individually, you can also pass an array +of commands and arguments to the constructor: + +```js + var redis = require("redis"), + client = redis.createClient(), multi; + + client.multi([ + ["mget", "multifoo", "multibar", redis.print], + ["incr", "multifoo"], + ["incr", "multibar"] + ]).exec(function (err, replies) { + console.log(replies); + }); +``` + + +## Monitor mode + +Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server +across all client connections, including from other client libraries and other computers. + +After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis` +will emit a `monitor` event for every new monitor message that comes across. The callback for the +`monitor` event takes a timestamp from the Redis server and an array of command arguments. + +Here is a simple example: + +```js + var client = require("redis").createClient(), + util = require("util"); + + client.monitor(function (err, res) { + console.log("Entering monitoring mode."); + }); + + client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); + }); +``` + +# Extras + +Some other things you might like to know about. + +## client.server_info + +After the ready probe completes, the results from the INFO command are saved in the `client.server_info` +object. + +The `versions` key contains an array of the elements of the version string for easy comparison. + + > client.server_info.redis_version + '2.3.0' + > client.server_info.versions + [ 2, 3, 0 ] + +## redis.print() + +A handy callback function for displaying return values when testing. Example: + +```js + var redis = require("redis"), + client = redis.createClient(); + + client.on("connect", function () { + client.set("foo_rand000000000000", "some fantastic value", redis.print); + client.get("foo_rand000000000000", redis.print); + }); +``` + +This will print: + + Reply: OK + Reply: some fantastic value + +Note that this program will not exit cleanly because the client is still connected. + +## redis.debug_mode + +Boolean to enable debug mode and protocol tracing. + +```js + var redis = require("redis"), + client = redis.createClient(); + + redis.debug_mode = true; + + client.on("connect", function () { + client.set("foo_rand000000000000", "some fantastic value"); + }); +``` + +This will display: + + mjr:~/work/node_redis (master)$ node ~/example.js + send command: *3 + $3 + SET + $20 + foo_rand000000000000 + $20 + some fantastic value + + on_data: +OK + +`send command` is data sent into Redis and `on_data` is data received from Redis. + +## client.send_command(command_name, args, callback) + +Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis +Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before +this library is updated, you can use `send_command()` to send arbitrary commands to Redis. + +All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted. + +## client.connected + +Boolean tracking the state of the connection to the Redis server. + +## client.command_queue.length + +The number of commands that have been sent to the Redis server but not yet replied to. You can use this to +enforce some kind of maximum queue depth for commands while connected. + +Don't mess with `client.command_queue` though unless you really know what you are doing. + +## client.offline_queue.length + +The number of commands that have been queued up for a future connection. You can use this to enforce +some kind of maximum queue depth for pre-connection commands. + +## client.retry_delay + +Current delay in milliseconds before a connection retry will be attempted. This starts at `250`. + +## client.retry_backoff + +Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries. +Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc. + +### Commands with Optional and Keyword arguments + +This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation. + +Example: +```js +var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ]; +client.zadd(args, function (err, response) { + if (err) throw err; + console.log('added '+response+' items.'); + + // -Infinity and +Infinity also work + var args1 = [ 'myzset', '+inf', '-inf' ]; + client.zrevrangebyscore(args1, function (err, response) { + if (err) throw err; + console.log('example1', response); + // write your code here + }); + + var max = 3, min = 1, offset = 1, count = 2; + var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ]; + client.zrevrangebyscore(args2, function (err, response) { + if (err) throw err; + console.log('example2', response); + // write your code here + }); +}); +``` + +## TODO + +Better tests for auth, disconnect/reconnect, and all combinations thereof. + +Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory. + +Performance can be better for very large values. + +I think there are more performance improvements left in there for smaller values, especially for large lists of small values. + +## How to Contribute +- open a pull request and then wait for feedback (if + [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days, + comment again with indignation!) + +## Contributors +Some people have have added features and fixed bugs in `node_redis` other than me. + +Ordered by date of first contribution. +[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT). + +- [Matt Ranney aka `mranney`](https://github.com/mranney) +- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart) +- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia) +- [rick aka `technoweenie`](https://github.com/technoweenie) +- [Orion Henry aka `orionz`](https://github.com/orionz) +- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas) +- [Hank Sims aka `hanksims`](https://github.com/hanksims) +- [Paul Carey aka `paulcarey`](https://github.com/paulcarey) +- [Pieter Noordhuis aka `pietern`](https://github.com/pietern) +- [nithesh aka `nithesh`](https://github.com/nithesh) +- [Andy Ray aka `andy2ray`](https://github.com/andy2ray) +- [unknown aka `unknowdna`](https://github.com/unknowdna) +- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel) +- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv) +- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique) +- [Louis-Philippe Perron aka `lp`](https://github.com/lp) +- [Mark Dawson aka `markdaws`](https://github.com/markdaws) +- [Ian Babrou aka `bobrik`](https://github.com/bobrik) +- [Felix Geisendörfer aka `felixge`](https://github.com/felixge) +- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined) +- [Maksim Lin aka `maks`](https://github.com/maks) +- [Owen Smith aka `orls`](https://github.com/orls) +- [Zachary Scott aka `zzak`](https://github.com/zzak) +- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK) +- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs) +- [David Trejo aka `DTrejo`](https://github.com/DTrejo) +- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi) +- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon) +- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2) +- [Jed Schmidt aka `jed`](https://github.com/jed) +- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3) +- [Trae Robrock aka `trobrock`](https://github.com/trobrock) +- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306) +- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio) + +Thanks. + +## LICENSE - "MIT License" + +Copyright (c) 2010 Matthew Ranney, http://ranney.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. + +![spacer](http://ranney.com/1px.gif) diff --git a/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js b/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js new file mode 100644 index 0000000..a504fbc --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/buffer_bench.js @@ -0,0 +1,89 @@ +var source = new Buffer(100), + dest = new Buffer(100), i, j, k, tmp, count = 1000000, bytes = 100; + +for (i = 99 ; i >= 0 ; i--) { + source[i] = 120; +} + +var str = "This is a nice String.", + buf = new Buffer("This is a lovely Buffer."); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (Buffer.isBuffer(str)) {} +} +var end = new Date(); +console.log("Buffer.isBuffer(str) " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (Buffer.isBuffer(buf)) {} +} +var end = new Date(); +console.log("Buffer.isBuffer(buf) " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (str instanceof Buffer) {} +} +var end = new Date(); +console.log("str instanceof Buffer " + (end - start) + " ms"); + +var start = new Date(); +for (i = count * 100; i > 0 ; i--) { + if (buf instanceof Buffer) {} +} +var end = new Date(); +console.log("buf instanceof Buffer " + (end - start) + " ms"); + +for (i = bytes ; i > 0 ; i --) { + var start = new Date(); + for (j = count ; j > 0; j--) { + tmp = source.toString("ascii", 0, bytes); + } + var end = new Date(); + console.log("toString() " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i --) { + var start = new Date(); + for (j = count ; j > 0; j--) { + tmp = ""; + for (k = 0; k <= i ; k++) { + tmp += String.fromCharCode(source[k]); + } + } + var end = new Date(); + console.log("manual string " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + for (k = i ; k > 0 ; k--) { + dest[k] = source[k]; + } + } + var end = new Date(); + console.log("Manual copy " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + for (k = i ; k > 0 ; k--) { + dest[k] = 120; + } + } + var end = new Date(); + console.log("Direct assignment " + i + " bytes " + (end - start) + " ms"); +} + +for (i = bytes ; i > 0 ; i--) { + var start = new Date(); + for (j = count ; j > 0 ; j--) { + source.copy(dest, 0, 0, i); + } + var end = new Date(); + console.log("Buffer.copy() " + i + " bytes " + (end - start) + " ms"); +} diff --git a/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js b/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js new file mode 100644 index 0000000..f1515b1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/hiredis_parser.js @@ -0,0 +1,38 @@ +var Parser = require('../lib/parser/hiredis').Parser; +var assert = require('assert'); + +/* +This test makes sure that exceptions thrown inside of "reply" event handlers +are not trapped and mistakenly emitted as parse errors. +*/ +(function testExecuteDoesNotCatchReplyCallbackExceptions() { + var parser = new Parser(); + var replies = [{}]; + + parser.reader = { + feed: function() {}, + get: function() { + return replies.shift(); + } + }; + + var emittedError = false; + var caughtException = false; + + parser + .on('error', function() { + emittedError = true; + }) + .on('reply', function() { + throw new Error('bad'); + }); + + try { + parser.execute(); + } catch (err) { + caughtException = true; + } + + assert.equal(caughtException, true); + assert.equal(emittedError, false); +})(); diff --git a/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js b/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js new file mode 100644 index 0000000..64b8f31 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/re_sub_test.js @@ -0,0 +1,14 @@ +var client = require('../index').createClient() + , client2 = require('../index').createClient() + , assert = require('assert'); + +client.once('subscribe', function (channel, count) { + client.unsubscribe('x'); + client.subscribe('x', function () { + client.quit(); + client2.quit(); + }); + client2.publish('x', 'hi'); +}); + +client.subscribe('x'); diff --git a/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js b/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js new file mode 100644 index 0000000..7abdd51 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/reconnect_test.js @@ -0,0 +1,29 @@ +var redis = require("../index").createClient(null, null, { +// max_attempts: 4 +}); + +redis.on("error", function (err) { + console.log("Redis says: " + err); +}); + +redis.on("ready", function () { + console.log("Redis ready."); +}); + +redis.on("reconnecting", function (arg) { + console.log("Redis reconnecting: " + JSON.stringify(arg)); +}); +redis.on("connect", function () { + console.log("Redis connected."); +}); + +setInterval(function () { + var now = Date.now(); + redis.set("now", now, function (err, res) { + if (err) { + console.log(now + " Redis reply error: " + err); + } else { + console.log(now + " Redis reply: " + res); + } + }); +}, 100); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/codec.js b/node_modules/socket.io/node_modules/redis/benches/stress/codec.js new file mode 100644 index 0000000..7d764f6 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/codec.js @@ -0,0 +1,16 @@ +var json = { + encode: JSON.stringify, + decode: JSON.parse +}; + +var MsgPack = require('node-msgpack'); +msgpack = { + encode: MsgPack.pack, + decode: function(str) { return MsgPack.unpack(new Buffer(str)); } +}; + +bison = require('bison'); + +module.exports = json; +//module.exports = msgpack; +//module.exports = bison; diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js new file mode 100644 index 0000000..0acde7a --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/pub.js @@ -0,0 +1,38 @@ +'use strict'; + +var freemem = require('os').freemem; +var profiler = require('v8-profiler'); +var codec = require('../codec'); + +var sent = 0; + +var pub = require('redis').createClient(null, null, { + //command_queue_high_water: 5, + //command_queue_low_water: 1 +}) +.on('ready', function() { + this.emit('drain'); +}) +.on('drain', function() { + process.nextTick(exec); +}); + +var payload = '1'; for (var i = 0; i < 12; ++i) payload += payload; +console.log('Message payload length', payload.length); + +function exec() { + pub.publish('timeline', codec.encode({ foo: payload })); + ++sent; + if (!pub.should_buffer) { + process.nextTick(exec); + } +} + +profiler.takeSnapshot('s_0'); + +exec(); + +setInterval(function() { + profiler.takeSnapshot('s_' + sent); + console.error('sent', sent, 'free', freemem(), 'cmdqlen', pub.command_queue.length, 'offqlen', pub.offline_queue.length); +}, 2000); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run new file mode 100755 index 0000000..bd9ac39 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/run @@ -0,0 +1,10 @@ +#!/bin/sh +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node server.js & +node --debug pub.js diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js new file mode 100644 index 0000000..035e6b7 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/pubsub/server.js @@ -0,0 +1,23 @@ +'use strict'; + +var freemem = require('os').freemem; +var codec = require('../codec'); + +var id = Math.random(); +var recv = 0; + +var sub = require('redis').createClient() + .on('ready', function() { + this.subscribe('timeline'); + }) + .on('message', function(channel, message) { + var self = this; + if (message) { + message = codec.decode(message); + ++recv; + } + }); + +setInterval(function() { + console.error('id', id, 'received', recv, 'free', freemem()); +}, 2000); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js new file mode 100644 index 0000000..9caf1d0 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/pub.js @@ -0,0 +1,49 @@ +'use strict'; + +var freemem = require('os').freemem; +//var profiler = require('v8-profiler'); +var codec = require('../codec'); + +var sent = 0; + +var pub = require('redis').createClient(null, null, { + //command_queue_high_water: 5, + //command_queue_low_water: 1 +}) +.on('ready', function() { + this.del('timeline'); + this.emit('drain'); +}) +.on('drain', function() { + process.nextTick(exec); +}); + +var payload = '1'; for (var i = 0; i < 12; ++i) payload += payload; +console.log('Message payload length', payload.length); + +function exec() { + pub.rpush('timeline', codec.encode({ foo: payload })); + ++sent; + if (!pub.should_buffer) { + process.nextTick(exec); + } +} + +//profiler.takeSnapshot('s_0'); + +exec(); + +setInterval(function() { + //var ss = profiler.takeSnapshot('s_' + sent); + //console.error(ss.stringify()); + pub.llen('timeline', function(err, result) { + console.error('sent', sent, 'free', freemem(), + 'cmdqlen', pub.command_queue.length, 'offqlen', pub.offline_queue.length, + 'llen', result + ); + }); +}, 2000); + +/*setTimeout(function() { + process.exit(); +}, 30000);*/ diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run new file mode 100755 index 0000000..8045ae8 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/run @@ -0,0 +1,6 @@ +#!/bin/sh +node server.js & +#node server.js & +#node server.js & +#node server.js & +node --debug pub.js diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js new file mode 100644 index 0000000..9cbcdd9 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/rpushblpop/server.js @@ -0,0 +1,30 @@ +'use strict'; + +var freemem = require('os').freemem; +var codec = require('../codec'); + +var id = Math.random(); +var recv = 0; + +var cmd = require('redis').createClient(); +var sub = require('redis').createClient() + .on('ready', function() { + this.emit('timeline'); + }) + .on('timeline', function() { + var self = this; + this.blpop('timeline', 0, function(err, result) { + var message = result[1]; + if (message) { + message = codec.decode(message); + ++recv; + } + self.emit('timeline'); + }); + }); + +setInterval(function() { + cmd.llen('timeline', function(err, result) { + console.error('id', id, 'received', recv, 'free', freemem(), 'llen', result); + }); +}, 2000); diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 b/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 new file mode 100644 index 0000000..29d7bf7 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/speed/00 @@ -0,0 +1,13 @@ +# size JSON msgpack bison +26602 2151.0170848180414 +25542 ? 2842.589272665782 +24835 ? ? 7280.4538397469805 +6104 6985.234528557929 +5045 ? 7217.461392841478 +4341 ? ? 14261.406335354604 +4180 15864.633685636572 +4143 ? 12954.806235781925 +4141 ? ? 44650.70733912719 +75 114227.07313350472 +40 ? 30162.440062810834 +39 ? ? 119815.66013519121 diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot b/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot new file mode 100755 index 0000000..2563797 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/speed/plot @@ -0,0 +1,13 @@ +#!/bin/sh + +gnuplot >size-rate.jpg << _EOF_ + +set terminal png nocrop enhanced font verdana 12 size 640,480 +set logscale x +set logscale y +set grid +set xlabel 'Serialized object size, octets' +set ylabel 'decode(encode(obj)) rate, 1/sec' +plot '00' using 1:2 title 'json' smooth bezier, '00' using 1:3 title 'msgpack' smooth bezier, '00' using 1:4 title 'bison' smooth bezier + +_EOF_ diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png b/node_modules/socket.io/node_modules/redis/benches/stress/speed/size-rate.png new file mode 100644 index 0000000000000000000000000000000000000000..c9c2bee6b076040ccf7e6bc337c307732c400463 GIT binary patch literal 6672 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 H#^C-7XAtZ( literal 0 HcmV?d00001 diff --git a/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js b/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js new file mode 100644 index 0000000..8e43cbc --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/stress/speed/speed.js @@ -0,0 +1,84 @@ +var msgpack = require('node-msgpack'); +var bison = require('bison'); +var codec = { + JSON: { + encode: JSON.stringify, + decode: JSON.parse + }, + msgpack: { + encode: msgpack.pack, + decode: msgpack.unpack + }, + bison: bison +}; + +var obj, l; + +var s = '0'; +for (var i = 0; i < 12; ++i) s += s; + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [], + a: s, + ccc: s, + b: s + s + s +}; +for (i = 0; i < 100; ++i) obj.rand.push(Math.random()); +forObj(obj); + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +for (i = 0; i < 100; ++i) obj.rand.push(Math.random()); +forObj(obj); + +obj = { + foo: s, + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +forObj(obj); + +obj = { + arrrrrr: [{a:1,b:false,c:null,d:1.0}, 1111, 2222, 33333333], + rand: [] +}; +forObj(obj); + +function run(obj, codec) { + var t1 = Date.now(); + var n = 10000; + for (var i = 0; i < n; ++i) { + codec.decode(l = codec.encode(obj)); + } + var t2 = Date.now(); + //console.log('DONE', n*1000/(t2-t1), 'codecs/sec, length=', l.length); + return [n*1000/(t2-t1), l.length]; +} + +function series(obj, cname, n) { + var rate = 0; + var len = 0; + for (var i = 0; i < n; ++i) { + var r = run(obj, codec[cname]); + rate += r[0]; + len += r[1]; + } + rate /= n; + len /= n; + console.log(cname + ' ' + rate + ' ' + len); + return [rate, len]; +} + +function forObj(obj) { + var r = { + JSON: series(obj, 'JSON', 20), + msgpack: series(obj, 'msgpack', 20), + bison: series(obj, 'bison', 20) + }; + return r; +} diff --git a/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js b/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js new file mode 100644 index 0000000..ad1f413 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/benches/sub_quit_test.js @@ -0,0 +1,18 @@ +var client = require("redis").createClient(), + client2 = require("redis").createClient(); + +client.subscribe("something"); +client.on("subscribe", function (channel, count) { + console.log("Got sub: " + channel); + client.unsubscribe("something"); +}); + +client.on("unsubscribe", function (channel, count) { + console.log("Got unsub: " + channel + ", quitting"); + client.quit(); +}); + +// exercise unsub before sub +client2.unsubscribe("something"); +client2.subscribe("another thing"); +client2.quit(); diff --git a/node_modules/socket.io/node_modules/redis/changelog.md b/node_modules/socket.io/node_modules/redis/changelog.md new file mode 100644 index 0000000..4248288 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/changelog.md @@ -0,0 +1,219 @@ +Changelog +========= + +## v0.7.2 - April 29, 2012 + +Many contributed fixes. Thank you, contributors. + +* [GH-190] - pub/sub mode fix (Brian Noguchi) +* [GH-165] - parser selection fix (TEHEK) +* numerous documentation and examples updates +* auth errors emit Errors instead of Strings (David Trejo) + +## v0.7.1 - November 15, 2011 + +Fix regression in reconnect logic. + +Very much need automated tests for reconnection and queue logic. + +## v0.7.0 - November 14, 2011 + +Many contributed fixes. Thanks everybody. + +* [GH-127] - properly re-initialize parser on reconnect +* [GH-136] - handle passing undefined as callback (Ian Babrou) +* [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer) +* [GH-141] - detect closing state on stream error (Felix Geisendörfer) +* [GH-142] - re-select database on reconnection (Jean-Hugues Pinson) +* [GH-146] - add sort example (Maksim Lin) + +Some more goodies: + +* Fix bugs with node 0.6 +* Performance improvements +* New version of `multi_bench.js` that tests more realistic scenarios +* [GH-140] - support optional callback for subscribe commands +* Properly flush and error out command queue when connection fails +* Initial work on reconnection thresholds + +## v0.6.7 - July 30, 2011 + +(accidentally skipped v0.6.6) + +Fix and test for [GH-123] + +Passing an Array as as the last argument should expand as users +expect. The old behavior was to coerce the arguments into Strings, +which did surprising things with Arrays. + +## v0.6.5 - July 6, 2011 + +Contributed changes: + +* Support SlowBuffers (Umair Siddique) +* Add Multi to exports (Louis-Philippe Perron) +* Fix for drain event calculation (Vladimir Dronnikov) + +Thanks! + +## v0.6.4 - June 30, 2011 + +Fix bug with optional callbacks for hmset. + +## v0.6.2 - June 30, 2011 + +Bugs fixed: + +* authentication retry while server is loading db (danmaz74) [GH-101] +* command arguments processing issue with arrays + +New features: + +* Auto update of new commands from redis.io (Dave Hoover) +* Performance improvements and backpressure controls. +* Commands now return the true/false value from the underlying socket write(s). +* Implement command_queue high water and low water for more better control of queueing. + +See `examples/backpressure_drain.js` for more information. + +## v0.6.1 - June 29, 2011 + +Add support and tests for Redis scripting through EXEC command. + +Bug fix for monitor mode. (forddg) + +Auto update of new commands from redis.io (Dave Hoover) + +## v0.6.0 - April 21, 2011 + +Lots of bugs fixed. + +* connection error did not properly trigger reconnection logic [GH-85] +* client.hmget(key, [val1, val2]) was not expanding properly [GH-66] +* client.quit() while in pub/sub mode would throw an error [GH-87] +* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92] +* unsubscribe before subscribe would make things very confused [GH-88] +* Add BRPOPLPUSH [GH-79] + +## v0.5.11 - April 7, 2011 + +Added DISCARD + +I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody +pointed out to me that DISCARD can be used to flush the WATCH set. + +## v0.5.10 - April 6, 2011 + +Added HVALS + +## v0.5.9 - March 14, 2011 + +Fix bug with empty Array arguments - Andy Ray + +## v0.5.8 - March 14, 2011 + +Add `MONITOR` command and special monitor command reply parsing. + +## v0.5.7 - February 27, 2011 + +Add magical auth command. + +Authentication is now remembered by the client and will be automatically sent to the server +on every connection, including any reconnections. + +## v0.5.6 - February 22, 2011 + +Fix bug in ready check with `return_buffers` set to `true`. + +Thanks to Dean Mao and Austin Chau. + +## v0.5.5 - February 16, 2011 + +Add probe for server readiness. + +When a Redis server starts up, it might take a while to load the dataset into memory. +During this time, the server will accept connections, but will return errors for all non-INFO +commands. Now node_redis will send an INFO command whenever it connects to a server. +If the info command indicates that the server is not ready, the client will keep trying until +the server is ready. Once it is ready, the client will emit a "ready" event as well as the +"connect" event. The client will queue up all commands sent before the server is ready, just +like it did before. When the server is ready, all offline/non-ready commands will be replayed. +This should be backward compatible with previous versions. + +To disable this ready check behavior, set `options.no_ready_check` when creating the client. + +As a side effect of this change, the key/val params from the info command are available as +`client.server_options`. Further, the version string is decomposed into individual elements +in `client.server_options.versions`. + +## v0.5.4 - February 11, 2011 + +Fix excess memory consumption from Queue backing store. + +Thanks to Gustaf Sjöberg. + +## v0.5.3 - February 5, 2011 + +Fix multi/exec error reply callback logic. + +Thanks to Stella Laurenzo. + +## v0.5.2 - January 18, 2011 + +Fix bug where unhandled error replies confuse the parser. + +## v0.5.1 - January 18, 2011 + +Fix bug where subscribe commands would not handle redis-server startup error properly. + +## v0.5.0 - December 29, 2010 + +Some bug fixes: + +* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after + a reconnect. +* Changed error callback argument to be an actual Error object. + +New feature: + +* Add friendly syntax for HMSET using an object. + +## v0.4.1 - December 8, 2010 + +Remove warning about missing hiredis. You probably do want it though. + +## v0.4.0 - December 5, 2010 + +Support for multiple response parsers and hiredis C library from Pieter Noordhuis. +Return Strings instead of Buffers by default. +Empty nested mb reply bug fix. + +## v0.3.9 - November 30, 2010 + +Fix parser bug on failed EXECs. + +## v0.3.8 - November 10, 2010 + +Fix for null MULTI response when WATCH condition fails. + +## v0.3.7 - November 9, 2010 + +Add "drain" and "idle" events. + +## v0.3.6 - November 3, 2010 + +Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond. + +Send a friendlier "error" event message on stream errors like connection refused / reset. + +## v0.3.5 - October 21, 2010 + +A few bug fixes. + +* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts. +* Only emit `end` once when connection goes away. +* Fixed bug in `test.js` where driver finished before all tests completed. + +## unversioned wasteland + +See the git history for what happened before. diff --git a/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js b/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js new file mode 100755 index 0000000..99fdf4d --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/diff_multi_bench_output.js @@ -0,0 +1,87 @@ +#!/usr/bin/env node + +var colors = require('colors'), + fs = require('fs'), + _ = require('underscore'), + metrics = require('metrics'), + + // `node diff_multi_bench_output.js before.txt after.txt` + before = process.argv[2], + after = process.argv[3]; + +if (!before || !after) { + console.log('Please supply two file arguments:'); + var n = __filename; + n = n.substring(n.lastIndexOf('/', n.length)); + console.log(' ./' + n + ' multiBenchBefore.txt multiBenchAfter.txt'); + console.log('To generate multiBenchBefore.txt, run'); + console.log(' node multi_bench.js > multiBenchBefore.txt'); + console.log('Thank you for benchmarking responsibly.'); + return; +} + +var before_lines = fs.readFileSync(before, 'utf8').split('\n'), + after_lines = fs.readFileSync(after, 'utf8').split('\n'); + +console.log('Comparing before,', before.green, '(', before_lines.length, + 'lines)', 'to after,', after.green, '(', after_lines.length, 'lines)'); + +var total_ops = new metrics.Histogram.createUniformHistogram(); + +before_lines.forEach(function(b, i) { + var a = after_lines[i]; + if (!a || !b || !b.trim() || !a.trim()) { + // console.log('#ignored#', '>'+a+'<', '>'+b+'<'); + return; + } + + b_words = b.split(' ').filter(is_whitespace); + a_words = a.split(' ').filter(is_whitespace); + + var ops = + [b_words, a_words] + .map(function(words) { + // console.log(words); + return parseInt10(words.slice(-2, -1)); + }).filter(function(num) { + var isNaN = !num && num !== 0; + return !isNaN; + }); + if (ops.length != 2) return + + var delta = ops[1] - ops[0]; + + total_ops.update(delta); + + delta = humanize_diff(delta); + console.log( + // name of test + command_name(a_words) == command_name(b_words) + ? command_name(a_words) + ':' + : '404:', + // results of test + ops.join(' -> '), 'ops/sec (∆', delta, ')'); +}); + +console.log('Mean difference in ops/sec:', humanize_diff(total_ops.mean())); + +function is_whitespace(s) { + return !!s.trim(); +} + +function parseInt10(s) { + return parseInt(s, 10); +} + +// green if greater than 0, red otherwise +function humanize_diff(num) { + if (num > 0) { + return ('+' + num).green; + } + return ('' + num).red; +} + +function command_name(words) { + var line = words.join(' '); + return line.substr(0, line.indexOf(',')); +} diff --git a/node_modules/socket.io/node_modules/redis/examples/auth.js b/node_modules/socket.io/node_modules/redis/examples/auth.js new file mode 100644 index 0000000..6c0a563 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/auth.js @@ -0,0 +1,5 @@ +var redis = require("redis"), + client = redis.createClient(); + +// This command is magical. Client stashes the password and will issue on every connect. +client.auth("somepass"); diff --git a/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js b/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js new file mode 100644 index 0000000..3488ef4 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/backpressure_drain.js @@ -0,0 +1,33 @@ +var redis = require("../index"), + client = redis.createClient(null, null, { + command_queue_high_water: 5, + command_queue_low_water: 1 + }), + remaining_ops = 100000, paused = false; + +function op() { + if (remaining_ops <= 0) { + console.error("Finished."); + process.exit(0); + } + + remaining_ops--; + if (client.hset("test hash", "val " + remaining_ops, remaining_ops) === false) { + console.log("Pausing at " + remaining_ops); + paused = true; + } else { + process.nextTick(op); + } +} + +client.on("drain", function () { + if (paused) { + console.log("Resuming at " + remaining_ops); + paused = false; + process.nextTick(op); + } else { + console.log("Got drain while not paused at " + remaining_ops); + } +}); + +op(); diff --git a/node_modules/socket.io/node_modules/redis/examples/eval.js b/node_modules/socket.io/node_modules/redis/examples/eval.js new file mode 100644 index 0000000..c1fbf8a --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/eval.js @@ -0,0 +1,9 @@ +var redis = require("./index"), + client = redis.createClient(); + +redis.debug_mode = true; + +client.eval("return 100.5", 0, function (err, res) { + console.dir(err); + console.dir(res); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/extend.js b/node_modules/socket.io/node_modules/redis/examples/extend.js new file mode 100644 index 0000000..488b8c2 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/extend.js @@ -0,0 +1,24 @@ +var redis = require("redis"), + client = redis.createClient(); + +// Extend the RedisClient prototype to add a custom method +// This one converts the results from "INFO" into a JavaScript Object + +redis.RedisClient.prototype.parse_info = function (callback) { + this.info(function (err, res) { + var lines = res.toString().split("\r\n").sort(); + var obj = {}; + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + obj[parts[0]] = parts[1]; + } + }); + callback(obj) + }); +}; + +client.parse_info(function (info) { + console.dir(info); + client.quit(); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/file.js b/node_modules/socket.io/node_modules/redis/examples/file.js new file mode 100644 index 0000000..4d2b5d1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/file.js @@ -0,0 +1,32 @@ +// Read a file from disk, store it in Redis, then read it back from Redis. + +var redis = require("redis"), + client = redis.createClient(), + fs = require("fs"), + filename = "kids_in_cart.jpg"; + +// Get the file I use for testing like this: +// curl http://ranney.com/kids_in_cart.jpg -o kids_in_cart.jpg +// or just use your own file. + +// Read a file from fs, store it in Redis, get it back from Redis, write it back to fs. +fs.readFile(filename, function (err, data) { + if (err) throw err + console.log("Read " + data.length + " bytes from filesystem."); + + client.set(filename, data, redis.print); // set entire file + client.get(filename, function (err, reply) { // get entire file + if (err) { + console.log("Get error: " + err); + } else { + fs.writeFile("duplicate_" + filename, reply, function (err) { + if (err) { + console.log("Error on write: " + err) + } else { + console.log("File written."); + } + client.end(); + }); + } + }); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/mget.js b/node_modules/socket.io/node_modules/redis/examples/mget.js new file mode 100644 index 0000000..936740d --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/mget.js @@ -0,0 +1,5 @@ +var client = require("redis").createClient(); + +client.mget(["sessions started", "sessions started", "foo"], function (err, res) { + console.dir(res); +}); \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/redis/examples/monitor.js b/node_modules/socket.io/node_modules/redis/examples/monitor.js new file mode 100644 index 0000000..2cb6a4e --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/monitor.js @@ -0,0 +1,10 @@ +var client = require("../index").createClient(), + util = require("util"); + +client.monitor(function (err, res) { + console.log("Entering monitoring mode."); +}); + +client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/multi.js b/node_modules/socket.io/node_modules/redis/examples/multi.js new file mode 100644 index 0000000..35c08e1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/multi.js @@ -0,0 +1,46 @@ +var redis = require("redis"), + client = redis.createClient(), set_size = 20; + +client.sadd("bigset", "a member"); +client.sadd("bigset", "another member"); + +while (set_size > 0) { + client.sadd("bigset", "member " + set_size); + set_size -= 1; +} + +// multi chain with an individual callback +client.multi() + .scard("bigset") + .smembers("bigset") + .keys("*", function (err, replies) { + client.mget(replies, redis.print); + }) + .dbsize() + .exec(function (err, replies) { + console.log("MULTI got " + replies.length + " replies"); + replies.forEach(function (reply, index) { + console.log("Reply " + index + ": " + reply.toString()); + }); + }); + +client.mset("incr thing", 100, "incr other thing", 1, redis.print); + +// start a separate multi command queue +var multi = client.multi(); +multi.incr("incr thing", redis.print); +multi.incr("incr other thing", redis.print); + +// runs immediately +client.get("incr thing", redis.print); // 100 + +// drains multi queue and runs atomically +multi.exec(function (err, replies) { + console.log(replies); // 101, 2 +}); + +// you can re-run the same transaction if you like +multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/multi2.js b/node_modules/socket.io/node_modules/redis/examples/multi2.js new file mode 100644 index 0000000..8be4d73 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/multi2.js @@ -0,0 +1,29 @@ +var redis = require("redis"), + client = redis.createClient(), multi; + +// start a separate command queue for multi +multi = client.multi(); +multi.incr("incr thing", redis.print); +multi.incr("incr other thing", redis.print); + +// runs immediately +client.mset("incr thing", 100, "incr other thing", 1, redis.print); + +// drains multi queue and runs atomically +multi.exec(function (err, replies) { + console.log(replies); // 101, 2 +}); + +// you can re-run the same transaction if you like +multi.exec(function (err, replies) { + console.log(replies); // 102, 3 + client.quit(); +}); + +client.multi([ + ["mget", "multifoo", "multibar", redis.print], + ["incr", "multifoo"], + ["incr", "multibar"] +]).exec(function (err, replies) { + console.log(replies.toString()); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/psubscribe.js b/node_modules/socket.io/node_modules/redis/examples/psubscribe.js new file mode 100644 index 0000000..c57117b --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/psubscribe.js @@ -0,0 +1,33 @@ +var redis = require("redis"), + client1 = redis.createClient(), + client2 = redis.createClient(), + client3 = redis.createClient(), + client4 = redis.createClient(), + msg_count = 0; + +redis.debug_mode = false; + +client1.on("psubscribe", function (pattern, count) { + console.log("client1 psubscribed to " + pattern + ", " + count + " total subscriptions"); + client2.publish("channeltwo", "Me!"); + client3.publish("channelthree", "Me too!"); + client4.publish("channelfour", "And me too!"); +}); + +client1.on("punsubscribe", function (pattern, count) { + console.log("client1 punsubscribed from " + pattern + ", " + count + " total subscriptions"); + client4.end(); + client3.end(); + client2.end(); + client1.end(); +}); + +client1.on("pmessage", function (pattern, channel, message) { + console.log("("+ pattern +")" + " client1 received message on " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.punsubscribe(); + } +}); + +client1.psubscribe("channel*"); diff --git a/node_modules/socket.io/node_modules/redis/examples/pub_sub.js b/node_modules/socket.io/node_modules/redis/examples/pub_sub.js new file mode 100644 index 0000000..aa508d6 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/pub_sub.js @@ -0,0 +1,41 @@ +var redis = require("redis"), + client1 = redis.createClient(), msg_count = 0, + client2 = redis.createClient(); + +redis.debug_mode = false; + +// Most clients probably don't do much on "subscribe". This example uses it to coordinate things within one program. +client1.on("subscribe", function (channel, count) { + console.log("client1 subscribed to " + channel + ", " + count + " total subscriptions"); + if (count === 2) { + client2.publish("a nice channel", "I am sending a message."); + client2.publish("another one", "I am sending a second message."); + client2.publish("a nice channel", "I am sending my last message."); + } +}); + +client1.on("unsubscribe", function (channel, count) { + console.log("client1 unsubscribed from " + channel + ", " + count + " total subscriptions"); + if (count === 0) { + client2.end(); + client1.end(); + } +}); + +client1.on("message", function (channel, message) { + console.log("client1 channel " + channel + ": " + message); + msg_count += 1; + if (msg_count === 3) { + client1.unsubscribe(); + } +}); + +client1.on("ready", function () { + // if you need auth, do it here + client1.incr("did a thing"); + client1.subscribe("a nice channel", "another one"); +}); + +client2.on("ready", function () { + // if you need auth, do it here +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/simple.js b/node_modules/socket.io/node_modules/redis/examples/simple.js new file mode 100644 index 0000000..f1f2e32 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/simple.js @@ -0,0 +1,24 @@ +var redis = require("redis"), + client = redis.createClient(); + +client.on("error", function (err) { + console.log("error event - " + client.host + ":" + client.port + " - " + err); +}); + +client.set("string key", "string val", redis.print); +client.hset("hash key", "hashtest 1", "some value", redis.print); +client.hset(["hash key", "hashtest 2", "some other value"], redis.print); +client.hkeys("hash key", function (err, replies) { + if (err) { + return console.error("error response - " + err); + } + + console.log(replies.length + " replies:"); + replies.forEach(function (reply, i) { + console.log(" " + i + ": " + reply); + }); +}); + +client.quit(function (err, res) { + console.log("Exiting from quit command."); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/sort.js b/node_modules/socket.io/node_modules/redis/examples/sort.js new file mode 100644 index 0000000..e7c6249 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/sort.js @@ -0,0 +1,17 @@ +var redis = require("redis"), + client = redis.createClient(); + +client.sadd("mylist", 1); +client.sadd("mylist", 2); +client.sadd("mylist", 3); + +client.set("weight_1", 5); +client.set("weight_2", 500); +client.set("weight_3", 1); + +client.set("object_1", "foo"); +client.set("object_2", "bar"); +client.set("object_3", "qux"); + +client.sort("mylist", "by", "weight_*", "get", "object_*", redis.print); +// Prints Reply: qux,foo,bar \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/redis/examples/subqueries.js b/node_modules/socket.io/node_modules/redis/examples/subqueries.js new file mode 100644 index 0000000..560db24 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/subqueries.js @@ -0,0 +1,15 @@ +// Sending commands in response to other commands. +// This example runs "type" against every key in the database +// +var client = require("redis").createClient(); + +client.keys("*", function (err, keys) { + keys.forEach(function (key, pos) { + client.type(key, function (err, keytype) { + console.log(key + " is " + keytype); + if (pos === (keys.length - 1)) { + client.quit(); + } + }); + }); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/subquery.js b/node_modules/socket.io/node_modules/redis/examples/subquery.js new file mode 100644 index 0000000..861657e --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/subquery.js @@ -0,0 +1,19 @@ +var client = require("redis").createClient(); + +function print_results(obj) { + console.dir(obj); +} + +// build a map of all keys and their types +client.keys("*", function (err, all_keys) { + var key_types = {}; + + all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos + client.type(key, function (err, type) { + key_types[key] = type; + if (pos === all_keys.length - 1) { // callbacks all run in order + print_results(key_types); + } + }); + }); +}); diff --git a/node_modules/socket.io/node_modules/redis/examples/unix_socket.js b/node_modules/socket.io/node_modules/redis/examples/unix_socket.js new file mode 100644 index 0000000..4a5e0bb --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/unix_socket.js @@ -0,0 +1,29 @@ +var redis = require("redis"), + client = redis.createClient("/tmp/redis.sock"), + profiler = require("v8-profiler"); + +client.on("connect", function () { + console.log("Got Unix socket connection.") +}); + +client.on("error", function (err) { + console.log(err.message); +}); + +client.set("space chars", "space value"); + +setInterval(function () { + client.get("space chars"); +}, 100); + +function done() { + client.info(function (err, reply) { + console.log(reply.toString()); + client.quit(); + }); +} + +setTimeout(function () { + console.log("Taking snapshot."); + var snap = profiler.takeSnapshot(); +}, 5000); diff --git a/node_modules/socket.io/node_modules/redis/examples/web_server.js b/node_modules/socket.io/node_modules/redis/examples/web_server.js new file mode 100644 index 0000000..9fd8592 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/examples/web_server.js @@ -0,0 +1,31 @@ +// A simple web server that generates dyanmic content based on responses from Redis + +var http = require("http"), server, + redis_client = require("redis").createClient(); + +server = http.createServer(function (request, response) { + response.writeHead(200, { + "Content-Type": "text/plain" + }); + + var redis_info, total_requests; + + redis_client.info(function (err, reply) { + redis_info = reply; // stash response in outer scope + }); + redis_client.incr("requests", function (err, reply) { + total_requests = reply; // stash response in outer scope + }); + redis_client.hincrby("ip", request.connection.remoteAddress, 1); + redis_client.hgetall("ip", function (err, reply) { + // This is the last reply, so all of the previous replies must have completed already + response.write("This page was generated after talking to redis.\n\n" + + "Redis info:\n" + redis_info + "\n" + + "Total requests: " + total_requests + "\n\n" + + "IP count: \n"); + Object.keys(reply).forEach(function (ip) { + response.write(" " + ip + ": " + reply[ip] + "\n"); + }); + response.end(); + }); +}).listen(80); diff --git a/node_modules/socket.io/node_modules/redis/generate_commands.js b/node_modules/socket.io/node_modules/redis/generate_commands.js new file mode 100644 index 0000000..e6949d3 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/generate_commands.js @@ -0,0 +1,39 @@ +var http = require("http"), + fs = require("fs"); + +function prettyCurrentTime() { + var date = new Date(); + return date.toLocaleString(); +} + +function write_file(commands, path) { + var file_contents, out_commands; + + console.log("Writing " + Object.keys(commands).length + " commands to " + path); + + file_contents = "// This file was generated by ./generate_commands.js on " + prettyCurrentTime() + "\n"; + + out_commands = Object.keys(commands).map(function (key) { + return key.toLowerCase(); + }); + + file_contents += "module.exports = " + JSON.stringify(out_commands, null, " ") + ";\n"; + + fs.writeFile(path, file_contents); +} + +http.get({host: "redis.io", path: "/commands.json"}, function (res) { + var body = ""; + + console.log("Response from redis.io/commands.json: " + res.statusCode); + + res.on('data', function (chunk) { + body += chunk; + }); + + res.on('end', function () { + write_file(JSON.parse(body), "lib/commands.js"); + }); +}).on('error', function (e) { + console.log("Error fetching command list from redis.io: " + e.message); +}); diff --git a/node_modules/socket.io/node_modules/redis/index.js b/node_modules/socket.io/node_modules/redis/index.js new file mode 100644 index 0000000..61cb4e9 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/index.js @@ -0,0 +1,1113 @@ +/*global Buffer require exports console setTimeout */ + +var net = require("net"), + util = require("./lib/util"), + Queue = require("./lib/queue"), + to_array = require("./lib/to_array"), + events = require("events"), + crypto = require("crypto"), + parsers = [], commands, + connection_id = 0, + default_port = 6379, + default_host = "127.0.0.1"; + +// can set this to true to enable for all connections +exports.debug_mode = false; + +// hiredis might not be installed +try { + require("./lib/parser/hiredis"); + parsers.push(require("./lib/parser/hiredis")); +} catch (err) { + if (exports.debug_mode) { + console.warn("hiredis parser not installed."); + } +} + +parsers.push(require("./lib/parser/javascript")); + +function RedisClient(stream, options) { + this.stream = stream; + this.options = options = options || {}; + + this.connection_id = ++connection_id; + this.connected = false; + this.ready = false; + this.connections = 0; + if (this.options.socket_nodelay === undefined) { + this.options.socket_nodelay = true; + } + this.should_buffer = false; + this.command_queue_high_water = this.options.command_queue_high_water || 1000; + this.command_queue_low_water = this.options.command_queue_low_water || 0; + this.max_attempts = null; + if (options.max_attempts && !isNaN(options.max_attempts) && options.max_attempts > 0) { + this.max_attempts = +options.max_attempts; + } + this.command_queue = new Queue(); // holds sent commands to de-pipeline them + this.offline_queue = new Queue(); // holds commands issued but not able to be sent + this.commands_sent = 0; + this.connect_timeout = false; + if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) { + this.connect_timeout = +options.connect_timeout; + } + + this.enable_offline_queue = true; + if (typeof this.options.enable_offline_queue === "boolean") { + this.enable_offline_queue = this.options.enable_offline_queue; + } + + this.initialize_retry_vars(); + this.pub_sub_mode = false; + this.subscription_set = {}; + this.monitoring = false; + this.closing = false; + this.server_info = {}; + this.auth_pass = null; + this.parser_module = null; + this.selected_db = null; // save the selected db here, used when reconnecting + + this.old_state = null; + + var self = this; + + this.stream.on("connect", function () { + self.on_connect(); + }); + + this.stream.on("data", function (buffer_from_socket) { + self.on_data(buffer_from_socket); + }); + + this.stream.on("error", function (msg) { + self.on_error(msg.message); + }); + + this.stream.on("close", function () { + self.connection_gone("close"); + }); + + this.stream.on("end", function () { + self.connection_gone("end"); + }); + + this.stream.on("drain", function () { + self.should_buffer = false; + self.emit("drain"); + }); + + events.EventEmitter.call(this); +} +util.inherits(RedisClient, events.EventEmitter); +exports.RedisClient = RedisClient; + +RedisClient.prototype.initialize_retry_vars = function () { + this.retry_timer = null; + this.retry_totaltime = 0; + this.retry_delay = 150; + this.retry_backoff = 1.7; + this.attempts = 1; +}; + +// flush offline_queue and command_queue, erroring any items with a callback first +RedisClient.prototype.flush_and_error = function (message) { + var command_obj; + while (this.offline_queue.length > 0) { + command_obj = this.offline_queue.shift(); + if (typeof command_obj.callback === "function") { + command_obj.callback(message); + } + } + this.offline_queue = new Queue(); + + while (this.command_queue.length > 0) { + command_obj = this.command_queue.shift(); + if (typeof command_obj.callback === "function") { + command_obj.callback(message); + } + } + this.command_queue = new Queue(); +}; + +RedisClient.prototype.on_error = function (msg) { + var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg, + self = this, command_obj; + + if (this.closing) { + return; + } + + if (exports.debug_mode) { + console.warn(message); + } + + this.flush_and_error(message); + + this.connected = false; + this.ready = false; + + this.emit("error", new Error(message)); + // "error" events get turned into exceptions if they aren't listened for. If the user handled this error + // then we should try to reconnect. + this.connection_gone("error"); +}; + +RedisClient.prototype.do_auth = function () { + var self = this; + + if (exports.debug_mode) { + console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id); + } + self.send_anyway = true; + self.send_command("auth", [this.auth_pass], function (err, res) { + if (err) { + if (err.toString().match("LOADING")) { + // if redis is still loading the db, it will not authenticate and everything else will fail + console.log("Redis still loading, trying to authenticate later"); + setTimeout(function () { + self.do_auth(); + }, 2000); // TODO - magic number alert + return; + } else { + return self.emit("error", new Error("Auth error: " + err.message)); + } + } + if (res.toString() !== "OK") { + return self.emit("error", new Error("Auth failed: " + res.toString())); + } + if (exports.debug_mode) { + console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id); + } + if (self.auth_callback) { + self.auth_callback(err, res); + self.auth_callback = null; + } + + // now we are really connected + self.emit("connect"); + if (self.options.no_ready_check) { + self.on_ready(); + } else { + self.ready_check(); + } + }); + self.send_anyway = false; +}; + +RedisClient.prototype.on_connect = function () { + if (exports.debug_mode) { + console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id); + } + var self = this; + + this.connected = true; + this.ready = false; + this.attempts = 0; + this.connections += 1; + this.command_queue = new Queue(); + this.emitted_end = false; + this.initialize_retry_vars(); + if (this.options.socket_nodelay) { + this.stream.setNoDelay(); + } + this.stream.setTimeout(0); + + this.init_parser(); + + if (this.auth_pass) { + this.do_auth(); + } else { + this.emit("connect"); + + if (this.options.no_ready_check) { + this.on_ready(); + } else { + this.ready_check(); + } + } +}; + +RedisClient.prototype.init_parser = function () { + var self = this; + + if (this.options.parser) { + if (! parsers.some(function (parser) { + if (parser.name === self.options.parser) { + self.parser_module = parser; + if (exports.debug_mode) { + console.log("Using parser module: " + self.parser_module.name); + } + return true; + } + })) { + throw new Error("Couldn't find named parser " + self.options.parser + " on this system"); + } + } else { + if (exports.debug_mode) { + console.log("Using default parser module: " + parsers[0].name); + } + this.parser_module = parsers[0]; + } + + this.parser_module.debug_mode = exports.debug_mode; + + // return_buffers sends back Buffers from parser to callback. detect_buffers sends back Buffers from parser, but + // converts to Strings if the input arguments are not Buffers. + this.reply_parser = new this.parser_module.Parser({ + return_buffers: self.options.return_buffers || self.options.detect_buffers || false + }); + + // "reply error" is an error sent back by Redis + this.reply_parser.on("reply error", function (reply) { + self.return_error(new Error(reply)); + }); + this.reply_parser.on("reply", function (reply) { + self.return_reply(reply); + }); + // "error" is bad. Somehow the parser got confused. It'll try to reset and continue. + this.reply_parser.on("error", function (err) { + self.emit("error", new Error("Redis reply parser error: " + err.stack)); + }); +}; + +RedisClient.prototype.on_ready = function () { + var self = this; + + this.ready = true; + + if (this.old_state !== null) { + this.monitoring = this.old_state.monitoring; + this.pub_sub_mode = this.old_state.pub_sub_mode; + this.selected_db = this.old_state.selected_db; + this.old_state = null; + } + + // magically restore any modal commands from a previous connection + if (this.selected_db !== null) { + this.send_command('select', [this.selected_db]); + } + if (this.pub_sub_mode === true) { + // only emit "ready" when all subscriptions were made again + var callback_count = 0; + var callback = function() { + callback_count--; + if (callback_count == 0) { + self.emit("ready"); + } + } + Object.keys(this.subscription_set).forEach(function (key) { + var parts = key.split(" "); + if (exports.debug_mode) { + console.warn("sending pub/sub on_ready " + parts[0] + ", " + parts[1]); + } + callback_count++; + self.send_command(parts[0] + "scribe", [parts[1]], callback); + }); + return; + } else if (this.monitoring) { + this.send_command("monitor"); + } else { + this.send_offline_queue(); + } + this.emit("ready"); +}; + +RedisClient.prototype.on_info_cmd = function (err, res) { + var self = this, obj = {}, lines, retry_time; + + if (err) { + return self.emit("error", new Error("Ready check failed: " + err.message)); + } + + lines = res.toString().split("\r\n"); + + lines.forEach(function (line) { + var parts = line.split(':'); + if (parts[1]) { + obj[parts[0]] = parts[1]; + } + }); + + obj.versions = []; + obj.redis_version.split('.').forEach(function (num) { + obj.versions.push(+num); + }); + + // expose info key/vals to users + this.server_info = obj; + + if (!obj.loading || (obj.loading && obj.loading === "0")) { + if (exports.debug_mode) { + console.log("Redis server ready."); + } + this.on_ready(); + } else { + retry_time = obj.loading_eta_seconds * 1000; + if (retry_time > 1000) { + retry_time = 1000; + } + if (exports.debug_mode) { + console.log("Redis server still loading, trying again in " + retry_time); + } + setTimeout(function () { + self.ready_check(); + }, retry_time); + } +}; + +RedisClient.prototype.ready_check = function () { + var self = this; + + if (exports.debug_mode) { + console.log("checking server ready state..."); + } + + this.send_anyway = true; // secret flag to send_command to send something even if not "ready" + this.info(function (err, res) { + self.on_info_cmd(err, res); + }); + this.send_anyway = false; +}; + +RedisClient.prototype.send_offline_queue = function () { + var command_obj, buffered_writes = 0; + + while (this.offline_queue.length > 0) { + command_obj = this.offline_queue.shift(); + if (exports.debug_mode) { + console.log("Sending offline command: " + command_obj.command); + } + buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback); + } + this.offline_queue = new Queue(); + // Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue + + if (!buffered_writes) { + this.should_buffer = false; + this.emit("drain"); + } +}; + +RedisClient.prototype.connection_gone = function (why) { + var self = this, message; + + // If a retry is already in progress, just let that happen + if (this.retry_timer) { + return; + } + + if (exports.debug_mode) { + console.warn("Redis connection is gone from " + why + " event."); + } + this.connected = false; + this.ready = false; + + if (this.old_state === null) { + var state = { + monitoring: this.monitoring, + pub_sub_mode: this.pub_sub_mode, + selected_db: this.selected_db + }; + this.old_state = state; + this.monitoring = false; + this.pub_sub_mode = false; + this.selected_db = null; + } + + // since we are collapsing end and close, users don't expect to be called twice + if (! this.emitted_end) { + this.emit("end"); + this.emitted_end = true; + } + + this.flush_and_error("Redis connection gone from " + why + " event."); + + // If this is a requested shutdown, then don't retry + if (this.closing) { + this.retry_timer = null; + if (exports.debug_mode) { + console.warn("connection ended from quit command, not retrying."); + } + return; + } + + this.retry_delay = Math.floor(this.retry_delay * this.retry_backoff); + + if (exports.debug_mode) { + console.log("Retry connection in " + this.current_retry_delay + " ms"); + } + + if (this.max_attempts && this.attempts >= this.max_attempts) { + this.retry_timer = null; + // TODO - some people need a "Redis is Broken mode" for future commands that errors immediately, and others + // want the program to exit. Right now, we just log, which doesn't really help in either case. + console.error("node_redis: Couldn't get Redis connection after " + this.max_attempts + " attempts."); + return; + } + + this.attempts += 1; + this.emit("reconnecting", { + delay: self.retry_delay, + attempt: self.attempts + }); + this.retry_timer = setTimeout(function () { + if (exports.debug_mode) { + console.log("Retrying connection..."); + } + + self.retry_totaltime += self.current_retry_delay; + + if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) { + self.retry_timer = null; + // TODO - engage Redis is Broken mode for future commands, or whatever + console.error("node_redis: Couldn't get Redis connection after " + self.retry_totaltime + "ms."); + return; + } + + self.stream.connect(self.port, self.host); + self.retry_timer = null; + }, this.retry_delay); +}; + +RedisClient.prototype.on_data = function (data) { + if (exports.debug_mode) { + console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString()); + } + + try { + this.reply_parser.execute(data); + } catch (err) { + // This is an unexpected parser problem, an exception that came from the parser code itself. + // Parser should emit "error" events if it notices things are out of whack. + // Callbacks that throw exceptions will land in return_reply(), below. + // TODO - it might be nice to have a different "error" event for different types of errors + this.emit("error", err); + } +}; + +RedisClient.prototype.return_error = function (err) { + var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength(); + + if (this.pub_sub_mode === false && queue_len === 0) { + this.emit("idle"); + this.command_queue = new Queue(); + } + if (this.should_buffer && queue_len <= this.command_queue_low_water) { + this.emit("drain"); + this.should_buffer = false; + } + + if (command_obj && typeof command_obj.callback === "function") { + try { + command_obj.callback(err); + } catch (callback_err) { + // if a callback throws an exception, re-throw it on a new stack so the parser can keep going + process.nextTick(function () { + throw callback_err; + }); + } + } else { + console.log("node_redis: no callback to send error: " + err.message); + // this will probably not make it anywhere useful, but we might as well throw + process.nextTick(function () { + throw err; + }); + } +}; + +// if a callback throws an exception, re-throw it on a new stack so the parser can keep going. +// put this try/catch in its own function because V8 doesn't optimize this well yet. +function try_callback(callback, reply) { + try { + callback(null, reply); + } catch (err) { + process.nextTick(function () { + throw err; + }); + } +} + +// hgetall converts its replies to an Object. If the reply is empty, null is returned. +function reply_to_object(reply) { + var obj = {}, j, jl, key, val; + + if (reply.length === 0) { + return null; + } + + for (j = 0, jl = reply.length; j < jl; j += 2) { + key = reply[j].toString(); + val = reply[j + 1]; + obj[key] = val; + } + + return obj; +} + +function reply_to_strings(reply) { + var i; + + if (Buffer.isBuffer(reply)) { + return reply.toString(); + } + + if (Array.isArray(reply)) { + for (i = 0; i < reply.length; i++) { + reply[i] = reply[i].toString(); + } + return reply; + } + + return reply; +} + +RedisClient.prototype.return_reply = function (reply) { + var command_obj, obj, i, len, type, timestamp, argindex, args, queue_len; + + command_obj = this.command_queue.shift(), + queue_len = this.command_queue.getLength(); + + if (this.pub_sub_mode === false && queue_len === 0) { + this.emit("idle"); + this.command_queue = new Queue(); // explicitly reclaim storage from old Queue + } + if (this.should_buffer && queue_len <= this.command_queue_low_water) { + this.emit("drain"); + this.should_buffer = false; + } + + if (command_obj && !command_obj.sub_command) { + if (typeof command_obj.callback === "function") { + if (this.options.detect_buffers && command_obj.buffer_args === false) { + // If detect_buffers option was specified, then the reply from the parser will be Buffers. + // If this command did not use Buffer arguments, then convert the reply to Strings here. + reply = reply_to_strings(reply); + } + + // TODO - confusing and error-prone that hgetall is special cased in two places + if (reply && 'hgetall' === command_obj.command.toLowerCase()) { + reply = reply_to_object(reply); + } + + try_callback(command_obj.callback, reply); + } else if (exports.debug_mode) { + console.log("no callback for reply: " + (reply && reply.toString && reply.toString())); + } + } else if (this.pub_sub_mode || (command_obj && command_obj.sub_command)) { + if (Array.isArray(reply)) { + type = reply[0].toString(); + + if (type === "message") { + this.emit("message", reply[1].toString(), reply[2]); // channel, message + } else if (type === "pmessage") { + this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message + } else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") { + if (reply[2] === 0) { + this.pub_sub_mode = false; + if (this.debug_mode) { + console.log("All subscriptions removed, exiting pub/sub mode"); + } + } else { + this.pub_sub_mode = true; + } + // subscribe commands take an optional callback and also emit an event, but only the first response is included in the callback + // TODO - document this or fix it so it works in a more obvious way + if (command_obj && typeof command_obj.callback === "function") { + try_callback(command_obj.callback, reply[1].toString()); + } + this.emit(type, reply[1].toString(), reply[2]); // channel, count + } else { + throw new Error("subscriptions are active but got unknown reply type " + type); + } + } else if (! this.closing) { + throw new Error("subscriptions are active but got an invalid reply: " + reply); + } + } else if (this.monitoring) { + len = reply.indexOf(" "); + timestamp = reply.slice(0, len); + argindex = reply.indexOf('"'); + args = reply.slice(argindex + 1, -1).split('" "').map(function (elem) { + return elem.replace(/\\"/g, '"'); + }); + this.emit("monitor", timestamp, args); + } else { + throw new Error("node_redis command queue state error. If you can reproduce this, please report it."); + } +}; + +// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using +// a named constructor helps it show up meaningfully in the V8 CPU profiler and in heap snapshots. +function Command(command, args, sub_command, buffer_args, callback) { + this.command = command; + this.args = args; + this.sub_command = sub_command; + this.buffer_args = buffer_args; + this.callback = callback; +} + +RedisClient.prototype.send_command = function (command, args, callback) { + var arg, this_args, command_obj, i, il, elem_count, buffer_args, stream = this.stream, command_str = "", buffered_writes = 0, last_arg_type; + + if (typeof command !== "string") { + throw new Error("First argument to send_command must be the command name string, not " + typeof command); + } + + if (Array.isArray(args)) { + if (typeof callback === "function") { + // probably the fastest way: + // client.command([arg1, arg2], cb); (straight passthrough) + // send_command(command, [arg1, arg2], cb); + } else if (! callback) { + // most people find this variable argument length form more convenient, but it uses arguments, which is slower + // client.command(arg1, arg2, cb); (wraps up arguments into an array) + // send_command(command, [arg1, arg2, cb]); + // client.command(arg1, arg2); (callback is optional) + // send_command(command, [arg1, arg2]); + // client.command(arg1, arg2, undefined); (callback is undefined) + // send_command(command, [arg1, arg2, undefined]); + last_arg_type = typeof args[args.length - 1]; + if (last_arg_type === "function" || last_arg_type === "undefined") { + callback = args.pop(); + } + } else { + throw new Error("send_command: last argument must be a callback or undefined"); + } + } else { + throw new Error("send_command: second argument must be an array"); + } + + // if the last argument is an array and command is sadd, expand it out: + // client.sadd(arg1, [arg2, arg3, arg4], cb); + // converts to: + // client.sadd(arg1, arg2, arg3, arg4, cb); + if ((command === 'sadd' || command === 'SADD') && args.length > 0 && Array.isArray(args[args.length - 1])) { + args = args.slice(0, -1).concat(args[args.length - 1]); + } + + buffer_args = false; + for (i = 0, il = args.length, arg; i < il; i += 1) { + if (Buffer.isBuffer(args[i])) { + buffer_args = true; + } + } + + command_obj = new Command(command, args, false, buffer_args, callback); + + if ((!this.ready && !this.send_anyway) || !stream.writable) { + if (exports.debug_mode) { + if (!stream.writable) { + console.log("send command: stream is not writeable."); + } + } + + if (this.enable_offline_queue) { + if (exports.debug_mode) { + console.log("Queueing " + command + " for next server connection."); + } + this.offline_queue.push(command_obj); + this.should_buffer = true; + } else { + var not_writeable_error = new Error('send_command: stream not writeable. enable_offline_queue is false'); + if (command_obj.callback) { + command_obj.callback(not_writeable_error); + } else { + throw not_writeable_error; + } + } + + return false; + } + + if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") { + this.pub_sub_command(command_obj); + } else if (command === "monitor") { + this.monitoring = true; + } else if (command === "quit") { + this.closing = true; + } else if (this.pub_sub_mode === true) { + throw new Error("Connection in pub/sub mode, only pub/sub commands may be used"); + } + this.command_queue.push(command_obj); + this.commands_sent += 1; + + elem_count = args.length + 1; + + // Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg. + // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer. + + command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n"; + + if (! buffer_args) { // Build up a string and send entire command in one write + for (i = 0, il = args.length, arg; i < il; i += 1) { + arg = args[i]; + if (typeof arg !== "string") { + arg = String(arg); + } + command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"; + } + if (exports.debug_mode) { + console.log("send " + this.host + ":" + this.port + " id " + this.connection_id + ": " + command_str); + } + buffered_writes += !stream.write(command_str); + } else { + if (exports.debug_mode) { + console.log("send command (" + command_str + ") has Buffer arguments"); + } + buffered_writes += !stream.write(command_str); + + for (i = 0, il = args.length, arg; i < il; i += 1) { + arg = args[i]; + if (!(Buffer.isBuffer(arg) || arg instanceof String)) { + arg = String(arg); + } + + if (Buffer.isBuffer(arg)) { + if (arg.length === 0) { + if (exports.debug_mode) { + console.log("send_command: using empty string for 0 length buffer"); + } + buffered_writes += !stream.write("$0\r\n\r\n"); + } else { + buffered_writes += !stream.write("$" + arg.length + "\r\n"); + buffered_writes += !stream.write(arg); + buffered_writes += !stream.write("\r\n"); + if (exports.debug_mode) { + console.log("send_command: buffer send " + arg.length + " bytes"); + } + } + } else { + if (exports.debug_mode) { + console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg); + } + buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n"); + } + } + } + if (exports.debug_mode) { + console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer); + } + if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) { + this.should_buffer = true; + } + return !this.should_buffer; +}; + +RedisClient.prototype.pub_sub_command = function (command_obj) { + var i, key, command, args; + + if (this.pub_sub_mode === false && exports.debug_mode) { + console.log("Entering pub/sub mode from " + command_obj.command); + } + this.pub_sub_mode = true; + command_obj.sub_command = true; + + command = command_obj.command; + args = command_obj.args; + if (command === "subscribe" || command === "psubscribe") { + if (command === "subscribe") { + key = "sub"; + } else { + key = "psub"; + } + for (i = 0; i < args.length; i++) { + this.subscription_set[key + " " + args[i]] = true; + } + } else { + if (command === "unsubscribe") { + key = "sub"; + } else { + key = "psub"; + } + for (i = 0; i < args.length; i++) { + delete this.subscription_set[key + " " + args[i]]; + } + } +}; + +RedisClient.prototype.end = function () { + this.stream._events = {}; + this.connected = false; + this.ready = false; + return this.stream.end(); +}; + +function Multi(client, args) { + this.client = client; + this.queue = [["MULTI"]]; + if (Array.isArray(args)) { + this.queue = this.queue.concat(args); + } +} + +exports.Multi = Multi; + +// take 2 arrays and return the union of their elements +function set_union(seta, setb) { + var obj = {}; + + seta.forEach(function (val) { + obj[val] = true; + }); + setb.forEach(function (val) { + obj[val] = true; + }); + return Object.keys(obj); +} + +// This static list of commands is updated from time to time. ./lib/commands.js can be updated with generate_commands.js +commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr", + "incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex", + "lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore", + "sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore", + "zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx", + "hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx", + "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave", + "bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl", + "persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster", + "restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands")); + +commands.forEach(function (command) { + RedisClient.prototype[command] = function (args, callback) { + if (Array.isArray(args) && typeof callback === "function") { + return this.send_command(command, args, callback); + } else { + return this.send_command(command, to_array(arguments)); + } + }; + RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command]; + + Multi.prototype[command] = function () { + this.queue.push([command].concat(to_array(arguments))); + return this; + }; + Multi.prototype[command.toUpperCase()] = Multi.prototype[command]; +}); + +// store db in this.select_db to restore it on reconnect +RedisClient.prototype.select = function (db, callback) { + var self = this; + + this.send_command('select', [db], function (err, res) { + if (err === null) { + self.selected_db = db; + } + if (typeof(callback) === 'function') { + callback(err, res); + } + }); +}; +RedisClient.prototype.SELECT = RedisClient.prototype.select; + +// Stash auth for connect and reconnect. Send immediately if already connected. +RedisClient.prototype.auth = function () { + var args = to_array(arguments); + this.auth_pass = args[0]; + this.auth_callback = args[1]; + if (exports.debug_mode) { + console.log("Saving auth as " + this.auth_pass); + } + + if (this.connected) { + this.send_command("auth", args); + } +}; +RedisClient.prototype.AUTH = RedisClient.prototype.auth; + +RedisClient.prototype.hmget = function (arg1, arg2, arg3) { + if (Array.isArray(arg2) && typeof arg3 === "function") { + return this.send_command("hmget", [arg1].concat(arg2), arg3); + } else if (Array.isArray(arg1) && typeof arg2 === "function") { + return this.send_command("hmget", arg1, arg2); + } else { + return this.send_command("hmget", to_array(arguments)); + } +}; +RedisClient.prototype.HMGET = RedisClient.prototype.hmget; + +RedisClient.prototype.hmset = function (args, callback) { + var tmp_args, tmp_keys, i, il, key; + + if (Array.isArray(args) && typeof callback === "function") { + return this.send_command("hmset", args, callback); + } + + args = to_array(arguments); + if (typeof args[args.length - 1] === "function") { + callback = args[args.length - 1]; + args.length -= 1; + } else { + callback = null; + } + + if (args.length === 2 && typeof args[0] === "string" && typeof args[1] === "object") { + // User does: client.hmset(key, {key1: val1, key2: val2}) + tmp_args = [ args[0] ]; + tmp_keys = Object.keys(args[1]); + for (i = 0, il = tmp_keys.length; i < il ; i++) { + key = tmp_keys[i]; + tmp_args.push(key); + if (typeof args[1][key] !== "string") { + var err = new Error("hmset expected value to be a string", key, ":", args[1][key]); + if (callback) return callback(err); + else throw err; + } + tmp_args.push(args[1][key]); + } + args = tmp_args; + } + + return this.send_command("hmset", args, callback); +}; +RedisClient.prototype.HMSET = RedisClient.prototype.hmset; + +Multi.prototype.hmset = function () { + var args = to_array(arguments), tmp_args; + if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") { + tmp_args = [ "hmset", args[0] ]; + Object.keys(args[1]).map(function (key) { + tmp_args.push(key); + tmp_args.push(args[1][key]); + }); + if (args[2]) { + tmp_args.push(args[2]); + } + args = tmp_args; + } else { + args.unshift("hmset"); + } + + this.queue.push(args); + return this; +}; +Multi.prototype.HMSET = Multi.prototype.hmset; + +Multi.prototype.exec = function (callback) { + var self = this; + + // drain queue, callback will catch "QUEUED" or error + // TODO - get rid of all of these anonymous functions which are elegant but slow + this.queue.forEach(function (args, index) { + var command = args[0], obj; + if (typeof args[args.length - 1] === "function") { + args = args.slice(1, -1); + } else { + args = args.slice(1); + } + if (args.length === 1 && Array.isArray(args[0])) { + args = args[0]; + } + if (command.toLowerCase() === 'hmset' && typeof args[1] === 'object') { + obj = args.pop(); + Object.keys(obj).forEach(function (key) { + args.push(key); + args.push(obj[key]); + }); + } + this.client.send_command(command, args, function (err, reply) { + if (err) { + var cur = self.queue[index]; + if (typeof cur[cur.length - 1] === "function") { + cur[cur.length - 1](err); + } else { + throw new Error(err); + } + self.queue.splice(index, 1); + } + }); + }, this); + + // TODO - make this callback part of Multi.prototype instead of creating it each time + return this.client.send_command("EXEC", [], function (err, replies) { + if (err) { + if (callback) { + callback(new Error(err)); + return; + } else { + throw new Error(err); + } + } + + var i, il, j, jl, reply, args; + + if (replies) { + for (i = 1, il = self.queue.length; i < il; i += 1) { + reply = replies[i - 1]; + args = self.queue[i]; + + // TODO - confusing and error-prone that hgetall is special cased in two places + if (reply && args[0].toLowerCase() === "hgetall") { + replies[i - 1] = reply = reply_to_object(reply); + } + + if (typeof args[args.length - 1] === "function") { + args[args.length - 1](null, reply); + } + } + } + + if (callback) { + callback(null, replies); + } + }); +}; +Multi.prototype.EXEC = Multi.prototype.exec; + +RedisClient.prototype.multi = function (args) { + return new Multi(this, args); +}; +RedisClient.prototype.MULTI = function (args) { + return new Multi(this, args); +}; + + +// stash original eval method +var eval = RedisClient.prototype.eval; +// hook eval with an attempt to evalsha for cached scripts +RedisClient.prototype.eval = +RedisClient.prototype.EVAL = function () { + var self = this, + args = to_array(arguments), + callback; + + if (typeof args[args.length - 1] === "function") { + callback = args.pop(); + } + + // replace script source with sha value + var source = args[0]; + args[0] = crypto.createHash("sha1").update(source).digest("hex"); + + self.evalsha(args, function (err, reply) { + if (err && /NOSCRIPT/.test(err.message)) { + args[0] = source; + eval.call(self, args, callback); + + } else if (callback) { + callback(err, reply); + } + }); +}; + + +exports.createClient = function (port_arg, host_arg, options) { + var port = port_arg || default_port, + host = host_arg || default_host, + redis_client, net_client; + + net_client = net.createConnection(port, host); + + redis_client = new RedisClient(net_client, options); + + redis_client.port = port; + redis_client.host = host; + + return redis_client; +}; + +exports.print = function (err, reply) { + if (err) { + console.log("Error: " + err); + } else { + console.log("Reply: " + reply); + } +}; diff --git a/node_modules/socket.io/node_modules/redis/lib/commands.js b/node_modules/socket.io/node_modules/redis/lib/commands.js new file mode 100644 index 0000000..f57cca9 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/commands.js @@ -0,0 +1,147 @@ +// This file was generated by ./generate_commands.js on Mon Aug 06 2012 15:04:06 GMT-0700 (PDT) +module.exports = [ + "append", + "auth", + "bgrewriteaof", + "bgsave", + "bitcount", + "bitop", + "blpop", + "brpop", + "brpoplpush", + "client kill", + "client list", + "config get", + "config set", + "config resetstat", + "dbsize", + "debug object", + "debug segfault", + "decr", + "decrby", + "del", + "discard", + "dump", + "echo", + "eval", + "evalsha", + "exec", + "exists", + "expire", + "expireat", + "flushall", + "flushdb", + "get", + "getbit", + "getrange", + "getset", + "hdel", + "hexists", + "hget", + "hgetall", + "hincrby", + "hincrbyfloat", + "hkeys", + "hlen", + "hmget", + "hmset", + "hset", + "hsetnx", + "hvals", + "incr", + "incrby", + "incrbyfloat", + "info", + "keys", + "lastsave", + "lindex", + "linsert", + "llen", + "lpop", + "lpush", + "lpushx", + "lrange", + "lrem", + "lset", + "ltrim", + "mget", + "migrate", + "monitor", + "move", + "mset", + "msetnx", + "multi", + "object", + "persist", + "pexpire", + "pexpireat", + "ping", + "psetex", + "psubscribe", + "pttl", + "publish", + "punsubscribe", + "quit", + "randomkey", + "rename", + "renamenx", + "restore", + "rpop", + "rpoplpush", + "rpush", + "rpushx", + "sadd", + "save", + "scard", + "script exists", + "script flush", + "script kill", + "script load", + "sdiff", + "sdiffstore", + "select", + "set", + "setbit", + "setex", + "setnx", + "setrange", + "shutdown", + "sinter", + "sinterstore", + "sismember", + "slaveof", + "slowlog", + "smembers", + "smove", + "sort", + "spop", + "srandmember", + "srem", + "strlen", + "subscribe", + "sunion", + "sunionstore", + "sync", + "time", + "ttl", + "type", + "unsubscribe", + "unwatch", + "watch", + "zadd", + "zcard", + "zcount", + "zincrby", + "zinterstore", + "zrange", + "zrangebyscore", + "zrank", + "zrem", + "zremrangebyrank", + "zremrangebyscore", + "zrevrange", + "zrevrangebyscore", + "zrevrank", + "zscore", + "zunionstore" +]; diff --git a/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js b/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js new file mode 100644 index 0000000..cbb15ba --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/parser/hiredis.js @@ -0,0 +1,46 @@ +/*global Buffer require exports console setTimeout */ + +var events = require("events"), + util = require("../util"), + hiredis = require("hiredis"); + +exports.debug_mode = false; +exports.name = "hiredis"; + +function HiredisReplyParser(options) { + this.name = exports.name; + this.options = options || {}; + this.reset(); + events.EventEmitter.call(this); +} + +util.inherits(HiredisReplyParser, events.EventEmitter); + +exports.Parser = HiredisReplyParser; + +HiredisReplyParser.prototype.reset = function () { + this.reader = new hiredis.Reader({ + return_buffers: this.options.return_buffers || false + }); +}; + +HiredisReplyParser.prototype.execute = function (data) { + var reply; + this.reader.feed(data); + while (true) { + try { + reply = this.reader.get(); + } catch (err) { + this.emit("error", err); + break; + } + + if (reply === undefined) break; + + if (reply && reply.constructor === Error) { + this.emit("reply error", reply); + } else { + this.emit("reply", reply); + } + } +}; diff --git a/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js b/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js new file mode 100644 index 0000000..b8f5bc6 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js @@ -0,0 +1,317 @@ +/*global Buffer require exports console setTimeout */ + +// TODO - incorporate these V8 pro tips: +// pre-allocate Arrays if length is known in advance +// do not use delete +// use numbers for parser state + +var events = require("events"), + util = require("../util"); + +exports.debug_mode = false; +exports.name = "javascript"; + +function RedisReplyParser(options) { + this.name = exports.name; + this.options = options || {}; + this.reset(); + events.EventEmitter.call(this); +} + +util.inherits(RedisReplyParser, events.EventEmitter); + +exports.Parser = RedisReplyParser; + +// Buffer.toString() is quite slow for small strings +function small_toString(buf, len) { + var tmp = "", i; + + for (i = 0; i < len; i += 1) { + tmp += String.fromCharCode(buf[i]); + } + + return tmp; +} + +// Reset parser to it's original state. +RedisReplyParser.prototype.reset = function () { + this.return_buffer = new Buffer(16384); // for holding replies, might grow + this.return_string = ""; + this.tmp_string = ""; // for holding size fields + + this.multi_bulk_length = 0; + this.multi_bulk_replies = null; + this.multi_bulk_pos = 0; + this.multi_bulk_nested_length = 0; + this.multi_bulk_nested_replies = null; + + this.states = { + TYPE: 1, + SINGLE_LINE: 2, + MULTI_BULK_COUNT: 3, + INTEGER_LINE: 4, + BULK_LENGTH: 5, + ERROR_LINE: 6, + BULK_DATA: 7, + UNKNOWN_TYPE: 8, + FINAL_CR: 9, + FINAL_LF: 10, + MULTI_BULK_COUNT_LF: 11, + BULK_LF: 12 + }; + + this.state = this.states.TYPE; +}; + +RedisReplyParser.prototype.parser_error = function (message) { + this.emit("error", message); + this.reset(); +}; + +RedisReplyParser.prototype.execute = function (incoming_buf) { + var pos = 0, bd_tmp, bd_str, i, il, states = this.states; + //, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state; + //start_switch = new Date(); + + while (pos < incoming_buf.length) { + // old_state = this.state; + // console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos])); + + switch (this.state) { + case 1: // states.TYPE + this.type = incoming_buf[pos]; + pos += 1; + + switch (this.type) { + case 43: // + + this.state = states.SINGLE_LINE; + this.return_buffer.end = 0; + this.return_string = ""; + break; + case 42: // * + this.state = states.MULTI_BULK_COUNT; + this.tmp_string = ""; + break; + case 58: // : + this.state = states.INTEGER_LINE; + this.return_buffer.end = 0; + this.return_string = ""; + break; + case 36: // $ + this.state = states.BULK_LENGTH; + this.tmp_string = ""; + break; + case 45: // - + this.state = states.ERROR_LINE; + this.return_buffer.end = 0; + this.return_string = ""; + break; + default: + this.state = states.UNKNOWN_TYPE; + } + break; + case 4: // states.INTEGER_LINE + if (incoming_buf[pos] === 13) { + this.send_reply(+small_toString(this.return_buffer, this.return_buffer.end)); + this.state = states.FINAL_LF; + } else { + this.return_buffer[this.return_buffer.end] = incoming_buf[pos]; + this.return_buffer.end += 1; + } + pos += 1; + break; + case 6: // states.ERROR_LINE + if (incoming_buf[pos] === 13) { + this.send_error(this.return_buffer.toString("ascii", 0, this.return_buffer.end)); + this.state = states.FINAL_LF; + } else { + this.return_buffer[this.return_buffer.end] = incoming_buf[pos]; + this.return_buffer.end += 1; + } + pos += 1; + break; + case 2: // states.SINGLE_LINE + if (incoming_buf[pos] === 13) { + this.send_reply(this.return_string); + this.state = states.FINAL_LF; + } else { + this.return_string += String.fromCharCode(incoming_buf[pos]); + } + pos += 1; + break; + case 3: // states.MULTI_BULK_COUNT + if (incoming_buf[pos] === 13) { // \r + this.state = states.MULTI_BULK_COUNT_LF; + } else { + this.tmp_string += String.fromCharCode(incoming_buf[pos]); + } + pos += 1; + break; + case 11: // states.MULTI_BULK_COUNT_LF + if (incoming_buf[pos] === 10) { // \n + if (this.multi_bulk_length) { // nested multi-bulk + this.multi_bulk_nested_length = this.multi_bulk_length; + this.multi_bulk_nested_replies = this.multi_bulk_replies; + this.multi_bulk_nested_pos = this.multi_bulk_pos; + } + this.multi_bulk_length = +this.tmp_string; + this.multi_bulk_pos = 0; + this.state = states.TYPE; + if (this.multi_bulk_length < 0) { + this.send_reply(null); + this.multi_bulk_length = 0; + } else if (this.multi_bulk_length === 0) { + this.multi_bulk_pos = 0; + this.multi_bulk_replies = null; + this.send_reply([]); + } else { + this.multi_bulk_replies = new Array(this.multi_bulk_length); + } + } else { + this.parser_error(new Error("didn't see LF after NL reading multi bulk count")); + return; + } + pos += 1; + break; + case 5: // states.BULK_LENGTH + if (incoming_buf[pos] === 13) { // \r + this.state = states.BULK_LF; + } else { + this.tmp_string += String.fromCharCode(incoming_buf[pos]); + } + pos += 1; + break; + case 12: // states.BULK_LF + if (incoming_buf[pos] === 10) { // \n + this.bulk_length = +this.tmp_string; + if (this.bulk_length === -1) { + this.send_reply(null); + this.state = states.TYPE; + } else if (this.bulk_length === 0) { + this.send_reply(new Buffer("")); + this.state = states.FINAL_CR; + } else { + this.state = states.BULK_DATA; + if (this.bulk_length > this.return_buffer.length) { + if (exports.debug_mode) { + console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length); + } + this.return_buffer = new Buffer(this.bulk_length); + } + this.return_buffer.end = 0; + } + } else { + this.parser_error(new Error("didn't see LF after NL while reading bulk length")); + return; + } + pos += 1; + break; + case 7: // states.BULK_DATA + this.return_buffer[this.return_buffer.end] = incoming_buf[pos]; + this.return_buffer.end += 1; + pos += 1; + if (this.return_buffer.end === this.bulk_length) { + bd_tmp = new Buffer(this.bulk_length); + // When the response is small, Buffer.copy() is a lot slower. + if (this.bulk_length > 10) { + this.return_buffer.copy(bd_tmp, 0, 0, this.bulk_length); + } else { + for (i = 0, il = this.bulk_length; i < il; i += 1) { + bd_tmp[i] = this.return_buffer[i]; + } + } + this.send_reply(bd_tmp); + this.state = states.FINAL_CR; + } + break; + case 9: // states.FINAL_CR + if (incoming_buf[pos] === 13) { // \r + this.state = states.FINAL_LF; + pos += 1; + } else { + this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR")); + return; + } + break; + case 10: // states.FINAL_LF + if (incoming_buf[pos] === 10) { // \n + this.state = states.TYPE; + pos += 1; + } else { + this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF")); + return; + } + break; + default: + this.parser_error(new Error("invalid state " + this.state)); + } + // end_switch = new Date(); + // if (state_times[old_state] === undefined) { + // state_times[old_state] = 0; + // } + // state_times[old_state] += (end_switch - start_switch); + // start_switch = end_switch; + } + // console.log("execute ran for " + (Date.now() - start_execute) + " ms, on " + incoming_buf.length + " Bytes. "); + // Object.keys(state_times).forEach(function (state) { + // console.log(" " + state + ": " + state_times[state]); + // }); +}; + +RedisReplyParser.prototype.send_error = function (reply) { + if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) { + // TODO - can this happen? Seems like maybe not. + this.add_multi_bulk_reply(reply); + } else { + this.emit("reply error", reply); + } +}; + +RedisReplyParser.prototype.send_reply = function (reply) { + if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) { + if (!this.options.return_buffers && Buffer.isBuffer(reply)) { + this.add_multi_bulk_reply(reply.toString("utf8")); + } else { + this.add_multi_bulk_reply(reply); + } + } else { + if (!this.options.return_buffers && Buffer.isBuffer(reply)) { + this.emit("reply", reply.toString("utf8")); + } else { + this.emit("reply", reply); + } + } +}; + +RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) { + if (this.multi_bulk_replies) { + this.multi_bulk_replies[this.multi_bulk_pos] = reply; + this.multi_bulk_pos += 1; + if (this.multi_bulk_pos < this.multi_bulk_length) { + return; + } + } else { + this.multi_bulk_replies = reply; + } + + if (this.multi_bulk_nested_length > 0) { + this.multi_bulk_nested_replies[this.multi_bulk_nested_pos] = this.multi_bulk_replies; + this.multi_bulk_nested_pos += 1; + + this.multi_bulk_length = 0; + this.multi_bulk_replies = null; + this.multi_bulk_pos = 0; + + if (this.multi_bulk_nested_length === this.multi_bulk_nested_pos) { + this.emit("reply", this.multi_bulk_nested_replies); + this.multi_bulk_nested_length = 0; + this.multi_bulk_nested_pos = 0; + this.multi_bulk_nested_replies = null; + } + } else { + this.emit("reply", this.multi_bulk_replies); + this.multi_bulk_length = 0; + this.multi_bulk_replies = null; + this.multi_bulk_pos = 0; + } +}; diff --git a/node_modules/socket.io/node_modules/redis/lib/queue.js b/node_modules/socket.io/node_modules/redis/lib/queue.js new file mode 100644 index 0000000..56254e1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/queue.js @@ -0,0 +1,61 @@ +var to_array = require("./to_array"); + +// Queue class adapted from Tim Caswell's pattern library +// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js + +function Queue() { + this.tail = []; + this.head = []; + this.offset = 0; +} + +Queue.prototype.shift = function () { + if (this.offset === this.head.length) { + var tmp = this.head; + tmp.length = 0; + this.head = this.tail; + this.tail = tmp; + this.offset = 0; + if (this.head.length === 0) { + return; + } + } + return this.head[this.offset++]; // sorry, JSLint +}; + +Queue.prototype.push = function (item) { + return this.tail.push(item); +}; + +Queue.prototype.forEach = function (fn, thisv) { + var array = this.head.slice(this.offset), i, il; + + array.push.apply(array, this.tail); + + if (thisv) { + for (i = 0, il = array.length; i < il; i += 1) { + fn.call(thisv, array[i], i, array); + } + } else { + for (i = 0, il = array.length; i < il; i += 1) { + fn(array[i], i, array); + } + } + + return array; +}; + +Queue.prototype.getLength = function () { + return this.head.length - this.offset + this.tail.length; +}; + +Object.defineProperty(Queue.prototype, 'length', { + get: function () { + return this.getLength(); + } +}); + + +if(typeof module !== 'undefined' && module.exports) { + module.exports = Queue; +} diff --git a/node_modules/socket.io/node_modules/redis/lib/to_array.js b/node_modules/socket.io/node_modules/redis/lib/to_array.js new file mode 100644 index 0000000..88a57e1 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/to_array.js @@ -0,0 +1,12 @@ +function to_array(args) { + var len = args.length, + arr = new Array(len), i; + + for (i = 0; i < len; i += 1) { + arr[i] = args[i]; + } + + return arr; +} + +module.exports = to_array; diff --git a/node_modules/socket.io/node_modules/redis/lib/util.js b/node_modules/socket.io/node_modules/redis/lib/util.js new file mode 100644 index 0000000..fc255ae --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/lib/util.js @@ -0,0 +1,11 @@ +// Support for very old versions of node where the module was called "sys". At some point, we should abandon this. + +var util; + +try { + util = require("util"); +} catch (err) { + util = require("sys"); +} + +module.exports = util; diff --git a/node_modules/socket.io/node_modules/redis/mem.js b/node_modules/socket.io/node_modules/redis/mem.js new file mode 100644 index 0000000..5144ab2 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/mem.js @@ -0,0 +1,11 @@ +var client = require("redis").createClient(); + +client.set("foo", "barvalskdjlksdjflkdsjflksdjdflkdsjflksdjflksdj", function (err, res) { + if (err) { + console.log("Got an error, please adapt somehow."); + } else { + console.log("Got a result: " + res); + } +}); + +client.quit(); diff --git a/node_modules/socket.io/node_modules/redis/multi_bench.js b/node_modules/socket.io/node_modules/redis/multi_bench.js new file mode 100644 index 0000000..5be2e56 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/multi_bench.js @@ -0,0 +1,225 @@ +var redis = require("./index"), + metrics = require("metrics"), + num_clients = parseInt(process.argv[2], 10) || 5, + num_requests = 20000, + tests = [], + versions_logged = false, + client_options = { + return_buffers: false + }, + small_str, large_str, small_buf, large_buf; + +redis.debug_mode = false; + +function lpad(input, len, chr) { + var str = input.toString(); + chr = chr || " "; + + while (str.length < len) { + str = chr + str; + } + return str; +} + +metrics.Histogram.prototype.print_line = function () { + var obj = this.printObj(); + + return lpad(obj.min, 4) + "/" + lpad(obj.max, 4) + "/" + lpad(obj.mean.toFixed(2), 7) + "/" + lpad(obj.p95.toFixed(2), 7); +}; + +function Test(args) { + var self = this; + + this.args = args; + + this.callback = null; + this.clients = []; + this.clients_ready = 0; + this.commands_sent = 0; + this.commands_completed = 0; + this.max_pipeline = this.args.pipeline || num_requests; + this.client_options = args.client_options || client_options; + + this.connect_latency = new metrics.Histogram(); + this.ready_latency = new metrics.Histogram(); + this.command_latency = new metrics.Histogram(); +} + +Test.prototype.run = function (callback) { + var self = this, i; + + this.callback = callback; + + for (i = 0; i < num_clients ; i++) { + this.new_client(i); + } +}; + +Test.prototype.new_client = function (id) { + var self = this, new_client; + + new_client = redis.createClient(6379, "127.0.0.1", this.client_options); + new_client.create_time = Date.now(); + + new_client.on("connect", function () { + self.connect_latency.update(Date.now() - new_client.create_time); + }); + + new_client.on("ready", function () { + if (! versions_logged) { + console.log("Client count: " + num_clients + ", node version: " + process.versions.node + ", server version: " + + new_client.server_info.redis_version + ", parser: " + new_client.reply_parser.name); + versions_logged = true; + } + self.ready_latency.update(Date.now() - new_client.create_time); + self.clients_ready++; + if (self.clients_ready === self.clients.length) { + self.on_clients_ready(); + } + }); + + self.clients[id] = new_client; +}; + +Test.prototype.on_clients_ready = function () { + process.stdout.write(lpad(this.args.descr, 13) + ", " + lpad(this.args.pipeline, 5) + "/" + this.clients_ready + " "); + this.test_start = Date.now(); + + this.fill_pipeline(); +}; + +Test.prototype.fill_pipeline = function () { + var pipeline = this.commands_sent - this.commands_completed; + + while (this.commands_sent < num_requests && pipeline < this.max_pipeline) { + this.commands_sent++; + pipeline++; + this.send_next(); + } + + if (this.commands_completed === num_requests) { + this.print_stats(); + this.stop_clients(); + } +}; + +Test.prototype.stop_clients = function () { + var self = this; + + this.clients.forEach(function (client, pos) { + if (pos === self.clients.length - 1) { + client.quit(function (err, res) { + self.callback(); + }); + } else { + client.quit(); + } + }); +}; + +Test.prototype.send_next = function () { + var self = this, + cur_client = this.commands_sent % this.clients.length, + command_num = this.commands_sent, + start = Date.now(); + + this.clients[cur_client][this.args.command](this.args.args, function (err, res) { + if (err) { + throw err; + } + self.commands_completed++; + self.command_latency.update(Date.now() - start); + self.fill_pipeline(); + }); +}; + +Test.prototype.print_stats = function () { + var duration = Date.now() - this.test_start; + + console.log("min/max/avg/p95: " + this.command_latency.print_line() + " " + lpad(duration, 6) + "ms total, " + + lpad((num_requests / (duration / 1000)).toFixed(2), 8) + " ops/sec"); +}; + +small_str = "1234"; +small_buf = new Buffer(small_str); +large_str = (new Array(4097).join("-")); +large_buf = new Buffer(large_str); + +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 1})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 50})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 200})); +tests.push(new Test({descr: "PING", command: "ping", args: [], pipeline: 20000})); + +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 1})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 50})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 200})); +tests.push(new Test({descr: "SET small str", command: "set", args: ["foo_rand000000000000", small_str], pipeline: 20000})); + +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 1})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 50})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 200})); +tests.push(new Test({descr: "SET small buf", command: "set", args: ["foo_rand000000000000", small_buf], pipeline: 20000})); + +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 1})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 50})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 200})); +tests.push(new Test({descr: "GET small str", command: "get", args: ["foo_rand000000000000"], pipeline: 20000})); + +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 1, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 50, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 200, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET small buf", command: "get", args: ["foo_rand000000000000"], pipeline: 20000, client_opts: { return_buffers: true} })); + +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 1})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 50})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 200})); +tests.push(new Test({descr: "SET large str", command: "set", args: ["foo_rand000000000001", large_str], pipeline: 20000})); + +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 1})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 50})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 200})); +tests.push(new Test({descr: "SET large buf", command: "set", args: ["foo_rand000000000001", large_buf], pipeline: 20000})); + +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 1})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 50})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 200})); +tests.push(new Test({descr: "GET large str", command: "get", args: ["foo_rand000000000001"], pipeline: 20000})); + +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 1, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 50, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 200, client_opts: { return_buffers: true} })); +tests.push(new Test({descr: "GET large buf", command: "get", args: ["foo_rand000000000001"], pipeline: 20000, client_opts: { return_buffers: true} })); + +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 1})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 50})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 200})); +tests.push(new Test({descr: "INCR", command: "incr", args: ["counter_rand000000000000"], pipeline: 20000})); + +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 1})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 50})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 200})); +tests.push(new Test({descr: "LPUSH", command: "lpush", args: ["mylist", small_str], pipeline: 20000})); + +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 1})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 50})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 200})); +tests.push(new Test({descr: "LRANGE 10", command: "lrange", args: ["mylist", "0", "9"], pipeline: 20000})); + +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 1})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 50})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 200})); +tests.push(new Test({descr: "LRANGE 100", command: "lrange", args: ["mylist", "0", "99"], pipeline: 20000})); + +function next() { + var test = tests.shift(); + if (test) { + test.run(function () { + next(); + }); + } else { + console.log("End of tests."); + process.exit(0); + } +} + +next(); diff --git a/node_modules/socket.io/node_modules/redis/package.json b/node_modules/socket.io/node_modules/redis/package.json new file mode 100644 index 0000000..6d291cf --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/package.json @@ -0,0 +1,35 @@ +{ + "name": "redis", + "version": "0.7.3", + "description": "Redis client library", + "author": { + "name": "Matt Ranney", + "email": "mjr@ranney.com" + }, + "maintainers": [ + { + "name": "David Trejo", + "email": "david.daniel.trejo@gmail.com", + "url": "http://dtrejo.com/" + } + ], + "main": "./index.js", + "scripts": { + "test": "node ./test.js" + }, + "devDependencies": { + "metrics": ">=0.1.5" + }, + "repository": { + "type": "git", + "url": "git://github.com/mranney/node_redis.git" + }, + "readme": "redis - a node.js redis client\n===========================\n\nThis is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from\nexperimental Redis server branches.\n\n\nInstall with:\n\n npm install redis\n\nPieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:\n\n npm install hiredis redis\n\nIf `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used.\n\nIf you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can\nhappen between node and native code modules after a node upgrade.\n\n\n## Usage\n\nSimple example, included as `examples/simple.js`:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n // if you'd like to select database 3, instead of 0 (default), call\n // client.select(3, function() { /* ... */ });\n\n client.on(\"error\", function (err) {\n console.log(\"Error \" + err);\n });\n\n client.set(\"string key\", \"string val\", redis.print);\n client.hset(\"hash key\", \"hashtest 1\", \"some value\", redis.print);\n client.hset([\"hash key\", \"hashtest 2\", \"some other value\"], redis.print);\n client.hkeys(\"hash key\", function (err, replies) {\n console.log(replies.length + \" replies:\");\n replies.forEach(function (reply, i) {\n console.log(\" \" + i + \": \" + reply);\n });\n client.quit();\n });\n```\n\nThis will display:\n\n mjr:~/work/node_redis (master)$ node example.js\n Reply: OK\n Reply: 0\n Reply: 0\n 2 replies:\n 0: hashtest 1\n 1: hashtest 2\n mjr:~/work/node_redis (master)$\n\n\n## Performance\n\nHere are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution.\nIt uses 50 concurrent connections with no pipelining.\n\nJavaScript parser:\n\n PING: 20000 ops 42283.30 ops/sec 0/5/1.182\n SET: 20000 ops 32948.93 ops/sec 1/7/1.515\n GET: 20000 ops 28694.40 ops/sec 0/9/1.740\n INCR: 20000 ops 39370.08 ops/sec 0/8/1.269\n LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370\n LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048\n LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072\n\nhiredis parser:\n\n PING: 20000 ops 46189.38 ops/sec 1/4/1.082\n SET: 20000 ops 41237.11 ops/sec 0/6/1.210\n GET: 20000 ops 39682.54 ops/sec 1/7/1.257\n INCR: 20000 ops 40080.16 ops/sec 0/8/1.242\n LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212\n LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363\n LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287\n\nThe performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs.\n\n\n### Sending Commands\n\nEach Redis command is exposed as a function on the `client` object.\nAll functions take either an `args` Array plus optional `callback` Function or\na variable number of individual arguments followed by an optional callback.\nHere is an example of passing an array of arguments and a callback:\n\n client.mset([\"test keys 1\", \"test val 1\", \"test keys 2\", \"test val 2\"], function (err, res) {});\n\nHere is that same call in the second style:\n\n client.mset(\"test keys 1\", \"test val 1\", \"test keys 2\", \"test val 2\", function (err, res) {});\n\nNote that in either form the `callback` is optional:\n\n client.set(\"some key\", \"some val\");\n client.set([\"some other key\", \"some val\"]);\n\nIf the key is missing, reply will be null (probably):\n\n client.get(\"missingkey\", function(err, reply) {\n // reply is null when the key is missing\n console.log(reply);\n });\n\nFor a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)\n\nThe commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.\n\nMinimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,\ninteger replies return JavaScript Numbers, \"bulk\" replies return node Buffers, and \"multi bulk\" replies return a\nJavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.\n\n# API\n\n## Connection Events\n\n`client` will emit some events about the state of the connection to the Redis server.\n\n### \"ready\"\n\n`client` will emit `ready` a connection is established to the Redis server and the server reports\nthat it is ready to receive commands. Commands issued before the `ready` event are queued,\nthen replayed just before this event is emitted.\n\n### \"connect\"\n\n`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check`\nis set. If this options is set, `connect` will be emitted when the stream is connected, and then\nyou are free to try to send commands.\n\n### \"error\"\n\n`client` will emit `error` when encountering an error connecting to the Redis server.\n\nNote that \"error\" is a special event type in node. If there are no listeners for an\n\"error\" event, node will exit. This is usually what you want, but it can lead to some\ncryptic error messages like this:\n\n mjr:~/work/node_redis (master)$ node example.js\n\n node.js:50\n throw e;\n ^\n Error: ECONNREFUSED, Connection refused\n at IOWatcher.callback (net:870:22)\n at node.js:607:9\n\nNot very useful in diagnosing the problem, but if your program isn't ready to handle this,\nit is probably the right thing to just exit.\n\n`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason.\nIt would be nice to distinguish these two cases.\n\n### \"end\"\n\n`client` will emit `end` when an established Redis server connection has closed.\n\n### \"drain\"\n\n`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now\nwritable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,\nyou need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can\nresume sending when you get `drain`.\n\n### \"idle\"\n\n`client` will emit `idle` when there are no outstanding commands that are awaiting a response.\n\n## redis.createClient(port, host, options)\n\nCreate a new client connection. `port` defaults to `6379` and `host` defaults\nto `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for\nport and host are probably fine. `options` in an object with the following possible properties:\n\n* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.\nThis may also be set to `javascript`.\n* `return_buffers`: defaults to `false`. If set to `true`, then all replies will be sent to callbacks as node Buffer\nobjects instead of JavaScript Strings.\n* `detect_buffers`: default to `false`. If set to `true`, then replies will be sent to callbacks as node Buffer objects\nif any of the input arguments to the original command were Buffer objects.\nThis option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to\nevery command on a client.\n* `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the\nNagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the\ncost of more latency. Most applications will want this set to `true`.\n* `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still\nbe loading the database from disk. While loading, the server not respond to any commands. To work around this,\n`node_redis` has a \"ready check\" which sends the `INFO` command to the server. The response from the `INFO` command\nindicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event.\nSetting `no_ready_check` to `true` will inhibit this check.\n* `enable_offline_queue`: defaults to `true`. By default, if there is no active\nconnection to the redis server, commands are added to a queue and are executed\nonce the connection has been established. Setting `enable_offline_queue` to\n`false` will disable this feature and the callback will be execute immediately\nwith an error, or an error will be thrown if no callback is specified.\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(null, null, {detect_buffers: true});\n\n client.set(\"foo_rand000000000000\", \"OK\");\n\n // This will return a JavaScript String\n client.get(\"foo_rand000000000000\", function (err, reply) {\n console.log(reply.toString()); // Will print `OK`\n });\n\n // This will return a Buffer since original key is specified as a Buffer\n client.get(new Buffer(\"foo_rand000000000000\"), function (err, reply) {\n console.log(reply.toString()); // Will print ``\n });\n client.end();\n```\n\n`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.\n\n## client.auth(password, callback)\n\nWhen connecting to Redis servers that require authentication, the `AUTH` command must be sent as the\nfirst command after connecting. This can be tricky to coordinate with reconnections, the ready check,\netc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,\nincluding reconnections. `callback` is invoked only once, after the response to the very first\n`AUTH` command sent.\nNOTE: Your call to `client.auth()` should not be inside the ready handler. If\nyou are doing this wrong, `client` will emit an error that looks\nsomething like this `Error: Ready check failed: ERR operation not permitted`.\n\n## client.end()\n\nForcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.\nIf you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.\n\nThis example closes the connection to the Redis server before the replies have been read. You probably don't\nwant to do this:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n client.set(\"foo_rand000000000000\", \"some fantastic value\");\n client.get(\"foo_rand000000000000\", function (err, reply) {\n console.log(reply.toString());\n });\n client.end();\n```\n\n`client.end()` is useful for timeout cases where something is stuck or taking too long and you want\nto start over.\n\n## Friendlier hash commands\n\nMost Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings.\nWhen dealing with hash values, there are a couple of useful exceptions to this.\n\n### client.hgetall(hash)\n\nThe reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact\nwith the responses using JavaScript syntax.\n\nExample:\n\n client.hmset(\"hosts\", \"mjr\", \"1\", \"another\", \"23\", \"home\", \"1234\");\n client.hgetall(\"hosts\", function (err, obj) {\n console.dir(obj);\n });\n\nOutput:\n\n { mjr: '1', another: '23', home: '1234' }\n\n### client.hmset(hash, obj, [callback])\n\nMultiple values in a hash can be set by supplying an object:\n\n client.HMSET(key2, {\n \"0123456789\": \"abcdefghij\", // NOTE: the key and value must both be strings\n \"some manner of key\": \"a type of value\"\n });\n\nThe properties and values of this Object will be set as keys and values in the Redis hash.\n\n### client.hmset(hash, key1, val1, ... keyn, valn, [callback])\n\nMultiple values may also be set by supplying a list:\n\n client.HMSET(key1, \"0123456789\", \"abcdefghij\", \"some manner of key\", \"a type of value\");\n\n\n## Publish / Subscribe\n\nHere is a simple example of the API for publish / subscribe. This program opens two\nclient connections, subscribes to a channel on one of them, and publishes to that\nchannel on the other:\n\n```js\n var redis = require(\"redis\"),\n client1 = redis.createClient(), client2 = redis.createClient(),\n msg_count = 0;\n\n client1.on(\"subscribe\", function (channel, count) {\n client2.publish(\"a nice channel\", \"I am sending a message.\");\n client2.publish(\"a nice channel\", \"I am sending a second message.\");\n client2.publish(\"a nice channel\", \"I am sending my last message.\");\n });\n\n client1.on(\"message\", function (channel, message) {\n console.log(\"client1 channel \" + channel + \": \" + message);\n msg_count += 1;\n if (msg_count === 3) {\n client1.unsubscribe();\n client1.end();\n client2.end();\n }\n });\n\n client1.incr(\"did a thing\");\n client1.subscribe(\"a nice channel\");\n```\n\nWhen a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into \"pub/sub\" mode.\nAt that point, only commands that modify the subscription set are valid. When the subscription\nset is empty, the connection is put back into regular mode.\n\nIf you need to send regular commands to Redis while in pub/sub mode, just open another connection.\n\n## Pub / Sub Events\n\nIf a client has subscriptions active, it may emit these events:\n\n### \"message\" (channel, message)\n\nClient will emit `message` for every message received that matches an active subscription.\nListeners are passed the channel name as `channel` and the message Buffer as `message`.\n\n### \"pmessage\" (pattern, channel, message)\n\nClient will emit `pmessage` for every message received that matches an active subscription pattern.\nListeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel\nname as `channel`, and the message Buffer as `message`.\n\n### \"subscribe\" (channel, count)\n\nClient will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`.\n\n### \"psubscribe\" (pattern, count)\n\nClient will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the\noriginal pattern as `pattern`, and the new count of subscriptions for this client as `count`.\n\n### \"unsubscribe\" (channel, count)\n\nClient will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`. When\n`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.\n\n### \"punsubscribe\" (pattern, count)\n\nClient will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the\nchannel name as `channel` and the new count of subscriptions for this client as `count`. When\n`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.\n\n## client.multi([commands])\n\n`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by\nRedis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.\n\n```js\n var redis = require(\"./index\"),\n client = redis.createClient(), set_size = 20;\n\n client.sadd(\"bigset\", \"a member\");\n client.sadd(\"bigset\", \"another member\");\n\n while (set_size > 0) {\n client.sadd(\"bigset\", \"member \" + set_size);\n set_size -= 1;\n }\n\n // multi chain with an individual callback\n client.multi()\n .scard(\"bigset\")\n .smembers(\"bigset\")\n .keys(\"*\", function (err, replies) {\n // NOTE: code in this callback is NOT atomic\n // this only happens after the the .exec call finishes.\n client.mget(replies, redis.print);\n })\n .dbsize()\n .exec(function (err, replies) {\n console.log(\"MULTI got \" + replies.length + \" replies\");\n replies.forEach(function (reply, index) {\n console.log(\"Reply \" + index + \": \" + reply.toString());\n });\n });\n```\n\n`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the\nsame command methods as `client` objects do. Commands are queued up inside the `Multi` object\nuntil `Multi.exec()` is invoked.\n\nYou can either chain together `MULTI` commands as in the above example, or you can queue individual\ncommands while still sending regular client command as in this example:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(), multi;\n\n // start a separate multi command queue\n multi = client.multi();\n multi.incr(\"incr thing\", redis.print);\n multi.incr(\"incr other thing\", redis.print);\n\n // runs immediately\n client.mset(\"incr thing\", 100, \"incr other thing\", 1, redis.print);\n\n // drains multi queue and runs atomically\n multi.exec(function (err, replies) {\n console.log(replies); // 101, 2\n });\n\n // you can re-run the same transaction if you like\n multi.exec(function (err, replies) {\n console.log(replies); // 102, 3\n client.quit();\n });\n```\n\nIn addition to adding commands to the `MULTI` queue individually, you can also pass an array\nof commands and arguments to the constructor:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient(), multi;\n\n client.multi([\n [\"mget\", \"multifoo\", \"multibar\", redis.print],\n [\"incr\", \"multifoo\"],\n [\"incr\", \"multibar\"]\n ]).exec(function (err, replies) {\n console.log(replies);\n });\n```\n\n\n## Monitor mode\n\nRedis supports the `MONITOR` command, which lets you see all commands received by the Redis server\nacross all client connections, including from other client libraries and other computers.\n\nAfter you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`\nwill emit a `monitor` event for every new monitor message that comes across. The callback for the\n`monitor` event takes a timestamp from the Redis server and an array of command arguments.\n\nHere is a simple example:\n\n```js\n var client = require(\"redis\").createClient(),\n util = require(\"util\");\n\n client.monitor(function (err, res) {\n console.log(\"Entering monitoring mode.\");\n });\n\n client.on(\"monitor\", function (time, args) {\n console.log(time + \": \" + util.inspect(args));\n });\n```\n\n# Extras\n\nSome other things you might like to know about.\n\n## client.server_info\n\nAfter the ready probe completes, the results from the INFO command are saved in the `client.server_info`\nobject.\n\nThe `versions` key contains an array of the elements of the version string for easy comparison.\n\n > client.server_info.redis_version\n '2.3.0'\n > client.server_info.versions\n [ 2, 3, 0 ]\n\n## redis.print()\n\nA handy callback function for displaying return values when testing. Example:\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n client.on(\"connect\", function () {\n client.set(\"foo_rand000000000000\", \"some fantastic value\", redis.print);\n client.get(\"foo_rand000000000000\", redis.print);\n });\n```\n\nThis will print:\n\n Reply: OK\n Reply: some fantastic value\n\nNote that this program will not exit cleanly because the client is still connected.\n\n## redis.debug_mode\n\nBoolean to enable debug mode and protocol tracing.\n\n```js\n var redis = require(\"redis\"),\n client = redis.createClient();\n\n redis.debug_mode = true;\n\n client.on(\"connect\", function () {\n client.set(\"foo_rand000000000000\", \"some fantastic value\");\n });\n```\n\nThis will display:\n\n mjr:~/work/node_redis (master)$ node ~/example.js\n send command: *3\n $3\n SET\n $20\n foo_rand000000000000\n $20\n some fantastic value\n\n on_data: +OK\n\n`send command` is data sent into Redis and `on_data` is data received from Redis.\n\n## client.send_command(command_name, args, callback)\n\nUsed internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis\nWiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before\nthis library is updated, you can use `send_command()` to send arbitrary commands to Redis.\n\nAll commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted.\n\n## client.connected\n\nBoolean tracking the state of the connection to the Redis server.\n\n## client.command_queue.length\n\nThe number of commands that have been sent to the Redis server but not yet replied to. You can use this to\nenforce some kind of maximum queue depth for commands while connected.\n\nDon't mess with `client.command_queue` though unless you really know what you are doing.\n\n## client.offline_queue.length\n\nThe number of commands that have been queued up for a future connection. You can use this to enforce\nsome kind of maximum queue depth for pre-connection commands.\n\n## client.retry_delay\n\nCurrent delay in milliseconds before a connection retry will be attempted. This starts at `250`.\n\n## client.retry_backoff\n\nMultiplier for future retry timeouts. This should be larger than 1 to add more time between retries.\nDefaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.\n\n### Commands with Optional and Keyword arguments\n\nThis applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.\n\nExample:\n```js\nvar args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];\nclient.zadd(args, function (err, response) {\n if (err) throw err;\n console.log('added '+response+' items.');\n\n // -Infinity and +Infinity also work\n var args1 = [ 'myzset', '+inf', '-inf' ];\n client.zrevrangebyscore(args1, function (err, response) {\n if (err) throw err;\n console.log('example1', response);\n // write your code here\n });\n\n var max = 3, min = 1, offset = 1, count = 2;\n var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ];\n client.zrevrangebyscore(args2, function (err, response) {\n if (err) throw err;\n console.log('example2', response);\n // write your code here\n });\n});\n```\n\n## TODO\n\nBetter tests for auth, disconnect/reconnect, and all combinations thereof.\n\nStream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory.\n\nPerformance can be better for very large values.\n\nI think there are more performance improvements left in there for smaller values, especially for large lists of small values.\n\n## How to Contribute\n- open a pull request and then wait for feedback (if\n [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days,\n comment again with indignation!)\n\n## Contributors\nSome people have have added features and fixed bugs in `node_redis` other than me.\n\nOrdered by date of first contribution.\n[Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT).\n\n- [Matt Ranney aka `mranney`](https://github.com/mranney)\n- [Tim-Smart aka `tim-smart`](https://github.com/tim-smart)\n- [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia)\n- [rick aka `technoweenie`](https://github.com/technoweenie)\n- [Orion Henry aka `orionz`](https://github.com/orionz)\n- [Aivo Paas aka `aivopaas`](https://github.com/aivopaas)\n- [Hank Sims aka `hanksims`](https://github.com/hanksims)\n- [Paul Carey aka `paulcarey`](https://github.com/paulcarey)\n- [Pieter Noordhuis aka `pietern`](https://github.com/pietern)\n- [nithesh aka `nithesh`](https://github.com/nithesh)\n- [Andy Ray aka `andy2ray`](https://github.com/andy2ray)\n- [unknown aka `unknowdna`](https://github.com/unknowdna)\n- [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel)\n- [Vladimir Dronnikov aka `dvv`](https://github.com/dvv)\n- [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique)\n- [Louis-Philippe Perron aka `lp`](https://github.com/lp)\n- [Mark Dawson aka `markdaws`](https://github.com/markdaws)\n- [Ian Babrou aka `bobrik`](https://github.com/bobrik)\n- [Felix Geisendörfer aka `felixge`](https://github.com/felixge)\n- [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined)\n- [Maksim Lin aka `maks`](https://github.com/maks)\n- [Owen Smith aka `orls`](https://github.com/orls)\n- [Zachary Scott aka `zzak`](https://github.com/zzak)\n- [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK)\n- [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs)\n- [David Trejo aka `DTrejo`](https://github.com/DTrejo)\n- [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi)\n- [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon)\n- [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2)\n- [Jed Schmidt aka `jed`](https://github.com/jed)\n- [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3)\n- [Trae Robrock aka `trobrock`](https://github.com/trobrock)\n- [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306)\n- [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio)\n\nThanks.\n\n## LICENSE - \"MIT License\"\n\nCopyright (c) 2010 Matthew Ranney, http://ranney.com/\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n![spacer](http://ranney.com/1px.gif)\n", + "readmeFilename": "README.md", + "_id": "redis@0.7.3", + "dist": { + "shasum": "a24d7b987e69a9a9d6d01e6a3ea037493bedfb02" + }, + "_from": "redis@0.7.3", + "_resolved": "https://registry.npmjs.org/redis/-/redis-0.7.3.tgz" +} diff --git a/node_modules/socket.io/node_modules/redis/test.js b/node_modules/socket.io/node_modules/redis/test.js new file mode 100644 index 0000000..0a03375 --- /dev/null +++ b/node_modules/socket.io/node_modules/redis/test.js @@ -0,0 +1,1618 @@ +/*global require console setTimeout process Buffer */ +var redis = require("./index"), + client = redis.createClient(), + client2 = redis.createClient(), + client3 = redis.createClient(), + assert = require("assert"), + crypto = require("crypto"), + util = require("./lib/util"), + test_db_num = 15, // this DB will be flushed and used for testing + tests = {}, + connected = false, + ended = false, + next, cur_start, run_next_test, all_tests, all_start, test_count; + +// Set this to truthy to see the wire protocol and other debugging info +redis.debug_mode = process.argv[2]; + +function buffers_to_strings(arr) { + return arr.map(function (val) { + return val.toString(); + }); +} + +function require_number(expected, label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected " + expected + ", got error: " + err); + assert.strictEqual(expected, results, label + " " + expected + " !== " + results); + assert.strictEqual(typeof results, "number", label); + return true; + }; +} + +function require_number_any(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected any number, got error: " + err); + assert.strictEqual(typeof results, "number", label + " " + results + " is not a number"); + return true; + }; +} + +function require_number_pos(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected positive number, got error: " + err); + assert.strictEqual(true, (results > 0), label + " " + results + " is not a positive number"); + return true; + }; +} + +function require_string(str, label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected string '" + str + "', got error: " + err); + assert.equal(str, results, label + " " + str + " does not match " + results); + return true; + }; +} + +function require_null(label) { + return function (err, results) { + assert.strictEqual(null, err, label + " expected null, got error: " + err); + assert.strictEqual(null, results, label + ": " + results + " is not null"); + return true; + }; +} + +function require_error(label) { + return function (err, results) { + assert.notEqual(err, null, label + " err is null, but an error is expected here."); + return true; + }; +} + +function is_empty_array(obj) { + return Array.isArray(obj) && obj.length === 0; +} + +function last(name, fn) { + return function (err, results) { + fn(err, results); + next(name); + }; +} + +next = function next(name) { + console.log(" \x1b[33m" + (Date.now() - cur_start) + "\x1b[0m ms"); + run_next_test(); +}; + +// Tests are run in the order they are defined. So FLUSHDB should be stay first. + +tests.FLUSHDB = function () { + var name = "FLUSHDB"; + client.select(test_db_num, require_string("OK", name)); + client2.select(test_db_num, require_string("OK", name)); + client3.select(test_db_num, require_string("OK", name)); + client.mset("flush keys 1", "flush val 1", "flush keys 2", "flush val 2", require_string("OK", name)); + client.FLUSHDB(require_string("OK", name)); + client.dbsize(last(name, require_number(0, name))); +}; + +tests.MULTI_1 = function () { + var name = "MULTI_1", multi1, multi2; + + // Provoke an error at queue time + multi1 = client.multi(); + multi1.mset("multifoo", "10", "multibar", "20", require_string("OK", name)); + multi1.set("foo2", require_error(name)); + multi1.incr("multifoo", require_number(11, name)); + multi1.incr("multibar", require_number(21, name)); + multi1.exec(); + + // Confirm that the previous command, while containing an error, still worked. + multi2 = client.multi(); + multi2.incr("multibar", require_number(22, name)); + multi2.incr("multifoo", require_number(12, name)); + multi2.exec(function (err, replies) { + assert.strictEqual(22, replies[0]); + assert.strictEqual(12, replies[1]); + next(name); + }); +}; + +tests.MULTI_2 = function () { + var name = "MULTI_2"; + + // test nested multi-bulk replies + client.multi([ + ["mget", "multifoo", "multibar", function (err, res) { + assert.strictEqual(2, res.length, name); + assert.strictEqual("12", res[0].toString(), name); + assert.strictEqual("22", res[1].toString(), name); + }], + ["set", "foo2", require_error(name)], + ["incr", "multifoo", require_number(13, name)], + ["incr", "multibar", require_number(23, name)] + ]).exec(function (err, replies) { + assert.strictEqual(2, replies[0].length, name); + assert.strictEqual("12", replies[0][0].toString(), name); + assert.strictEqual("22", replies[0][1].toString(), name); + + assert.strictEqual("13", replies[1].toString()); + assert.strictEqual("23", replies[2].toString()); + next(name); + }); +}; + +tests.MULTI_3 = function () { + var name = "MULTI_3"; + + client.sadd("some set", "mem 1"); + client.sadd("some set", "mem 2"); + client.sadd("some set", "mem 3"); + client.sadd("some set", "mem 4"); + + // make sure empty mb reply works + client.del("some missing set"); + client.smembers("some missing set", function (err, reply) { + // make sure empty mb reply works + assert.strictEqual(true, is_empty_array(reply), name); + }); + + // test nested multi-bulk replies with empty mb elements. + client.multi([ + ["smembers", "some set"], + ["del", "some set"], + ["smembers", "some set"] + ]) + .scard("some set") + .exec(function (err, replies) { + assert.strictEqual(true, is_empty_array(replies[2]), name); + next(name); + }); +}; + +tests.MULTI_4 = function () { + var name = "MULTI_4"; + + client.multi() + .mset('some', '10', 'keys', '20') + .incr('some') + .incr('keys') + .mget('some', 'keys') + .exec(function (err, replies) { + assert.strictEqual(null, err); + assert.equal('OK', replies[0]); + assert.equal(11, replies[1]); + assert.equal(21, replies[2]); + assert.equal(11, replies[3][0].toString()); + assert.equal(21, replies[3][1].toString()); + next(name); + }); +}; + +tests.MULTI_5 = function () { + var name = "MULTI_5"; + + // test nested multi-bulk replies with nulls. + client.multi([ + ["mget", ["multifoo", "some", "random value", "keys"]], + ["incr", "multifoo"] + ]) + .exec(function (err, replies) { + assert.strictEqual(replies.length, 2, name); + assert.strictEqual(replies[0].length, 4, name); + next(name); + }); +}; + +tests.MULTI_6 = function () { + var name = "MULTI_6"; + + client.multi() + .hmset("multihash", "a", "foo", "b", 1) + .hmset("multihash", { + extra: "fancy", + things: "here" + }) + .hgetall("multihash") + .exec(function (err, replies) { + assert.strictEqual(null, err); + assert.equal("OK", replies[0]); + assert.equal(Object.keys(replies[2]).length, 4); + assert.equal("foo", replies[2].a); + assert.equal("1", replies[2].b); + assert.equal("fancy", replies[2].extra); + assert.equal("here", replies[2].things); + next(name); + }); +}; + +tests.EVAL_1 = function () { + var name = "EVAL_1"; + + if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 5) { + // test {EVAL - Lua integer -> Redis protocol type conversion} + client.eval("return 100.5", 0, require_number(100, name)); + // test {EVAL - Lua string -> Redis protocol type conversion} + client.eval("return 'hello world'", 0, require_string("hello world", name)); + // test {EVAL - Lua true boolean -> Redis protocol type conversion} + client.eval("return true", 0, require_number(1, name)); + // test {EVAL - Lua false boolean -> Redis protocol type conversion} + client.eval("return false", 0, require_null(name)); + // test {EVAL - Lua status code reply -> Redis protocol type conversion} + client.eval("return {ok='fine'}", 0, require_string("fine", name)); + // test {EVAL - Lua error reply -> Redis protocol type conversion} + client.eval("return {err='this is an error'}", 0, require_error(name)); + // test {EVAL - Lua table -> Redis protocol type conversion} + client.eval("return {1,2,3,'ciao',{1,2}}", 0, function (err, res) { + assert.strictEqual(5, res.length, name); + assert.strictEqual(1, res[0], name); + assert.strictEqual(2, res[1], name); + assert.strictEqual(3, res[2], name); + assert.strictEqual("ciao", res[3], name); + assert.strictEqual(2, res[4].length, name); + assert.strictEqual(1, res[4][0], name); + assert.strictEqual(2, res[4][1], name); + }); + // test {EVAL - Are the KEYS and ARGS arrays populated correctly?} + client.eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", 2, "a", "b", "c", "d", function (err, res) { + assert.strictEqual(4, res.length, name); + assert.strictEqual("a", res[0], name); + assert.strictEqual("b", res[1], name); + assert.strictEqual("c", res[2], name); + assert.strictEqual("d", res[3], name); + }); + + // prepare sha sum for evalsha cache test + var source = "return redis.call('get', 'sha test')", + sha = crypto.createHash('sha1').update(source).digest('hex'); + + client.set("sha test", "eval get sha test", function (err, res) { + if (err) throw err; + // test {EVAL - is Lua able to call Redis API?} + client.eval(source, 0, function (err, res) { + require_string("eval get sha test", name)(err, res); + // test {EVALSHA - Can we call a SHA1 if already defined?} + client.evalsha(sha, 0, require_string("eval get sha test", name)); + // test {EVALSHA - Do we get an error on non defined SHA1?} + client.evalsha("ffffffffffffffffffffffffffffffffffffffff", 0, require_error(name)); + }); + }); + + // test {EVAL - Redis integer -> Lua type conversion} + client.set("incr key", 0, function (err, reply) { + if (err) throw err; + client.eval("local foo = redis.call('incr','incr key')\n" + "return {type(foo),foo}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("number", res[0], name); + assert.strictEqual(1, res[1], name); + }); + }); + + client.set("bulk reply key", "bulk reply value", function (err, res) { + // test {EVAL - Redis bulk -> Lua type conversion} + client.eval("local foo = redis.call('get','bulk reply key'); return {type(foo),foo}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("string", res[0], name); + assert.strictEqual("bulk reply value", res[1], name); + }); + }); + + // test {EVAL - Redis multi bulk -> Lua type conversion} + client.multi() + .del("mylist") + .rpush("mylist", "a") + .rpush("mylist", "b") + .rpush("mylist", "c") + .exec(function (err, replies) { + if (err) throw err; + client.eval("local foo = redis.call('lrange','mylist',0,-1); return {type(foo),foo[1],foo[2],foo[3],# foo}", 0, function (err, res) { + assert.strictEqual(5, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("a", res[1], name); + assert.strictEqual("b", res[2], name); + assert.strictEqual("c", res[3], name); + assert.strictEqual(3, res[4], name); + }); + }); + // test {EVAL - Redis status reply -> Lua type conversion} + client.eval("local foo = redis.call('set','mykey','myval'); return {type(foo),foo['ok']}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("OK", res[1], name); + }); + // test {EVAL - Redis error reply -> Lua type conversion} + client.set("error reply key", "error reply value", function (err, res) { + if (err) throw err; + client.eval("local foo = redis.pcall('incr','error reply key'); return {type(foo),foo['err']}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("table", res[0], name); + assert.strictEqual("ERR value is not an integer or out of range", res[1], name); + }); + }); + // test {EVAL - Redis nil bulk reply -> Lua type conversion} + client.del("nil reply key", function (err, res) { + if (err) throw err; + client.eval("local foo = redis.call('get','nil reply key'); return {type(foo),foo == false}", 0, function (err, res) { + if (err) throw err; + assert.strictEqual(2, res.length, name); + assert.strictEqual("boolean", res[0], name); + assert.strictEqual(1, res[1], name); + next(name); + }); + }); + } else { + console.log("Skipping " + name + " because server version isn't new enough."); + next(name); + } +}; + +tests.WATCH_MULTI = function () { + var name = 'WATCH_MULTI', multi; + + if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 1) { + client.watch(name); + client.incr(name); + multi = client.multi(); + multi.incr(name); + multi.exec(last(name, require_null(name))); + } else { + console.log("Skipping " + name + " because server version isn't new enough."); + next(name); + } +}; + +tests.detect_buffers = function () { + var name = "detect_buffers", detect_client = redis.createClient(null, null, {detect_buffers: true}); + + detect_client.on("ready", function () { + // single Buffer or String + detect_client.set("string key 1", "string value"); + detect_client.get("string key 1", require_string("string value", name)); + detect_client.get(new Buffer("string key 1"), function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Buffer.isBuffer(reply), name); + assert.strictEqual("", reply.inspect(), name); + }); + + detect_client.hmset("hash key 2", "key 1", "val 1", "key 2", "val 2"); + // array of Buffers or Strings + detect_client.hmget("hash key 2", "key 1", "key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Array.isArray(reply), name); + assert.strictEqual(2, reply.length, name); + assert.strictEqual("val 1", reply[0], name); + assert.strictEqual("val 2", reply[1], name); + }); + detect_client.hmget(new Buffer("hash key 2"), "key 1", "key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual(true, Array.isArray(reply)); + assert.strictEqual(2, reply.length, name); + assert.strictEqual(true, Buffer.isBuffer(reply[0])); + assert.strictEqual(true, Buffer.isBuffer(reply[1])); + assert.strictEqual("", reply[0].inspect(), name); + assert.strictEqual("", reply[1].inspect(), name); + }); + + // Object of Buffers or Strings + detect_client.hgetall("hash key 2", function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual("object", typeof reply, name); + assert.strictEqual(2, Object.keys(reply).length, name); + assert.strictEqual("val 1", reply["key 1"], name); + assert.strictEqual("val 2", reply["key 2"], name); + }); + detect_client.hgetall(new Buffer("hash key 2"), function (err, reply) { + assert.strictEqual(null, err, name); + assert.strictEqual("object", typeof reply, name); + assert.strictEqual(2, Object.keys(reply).length, name); + assert.strictEqual(true, Buffer.isBuffer(reply["key 1"])); + assert.strictEqual(true, Buffer.isBuffer(reply["key 2"])); + assert.strictEqual("", reply["key 1"].inspect(), name); + assert.strictEqual("", reply["key 2"].inspect(), name); + }); + + detect_client.quit(function (err, res) { + next(name); + }); + }); +}; + +tests.socket_nodelay = function () { + var name = "socket_nodelay", c1, c2, c3, ready_count = 0, quit_count = 0; + + c1 = redis.createClient(null, null, {socket_nodelay: true}); + c2 = redis.createClient(null, null, {socket_nodelay: false}); + c3 = redis.createClient(null, null); + + function quit_check() { + quit_count++; + + if (quit_count === 3) { + next(name); + } + } + + function run() { + assert.strictEqual(true, c1.options.socket_nodelay, name); + assert.strictEqual(false, c2.options.socket_nodelay, name); + assert.strictEqual(true, c3.options.socket_nodelay, name); + + c1.set(["set key 1", "set val"], require_string("OK", name)); + c1.set(["set key 2", "set val"], require_string("OK", name)); + c1.get(["set key 1"], require_string("set val", name)); + c1.get(["set key 2"], require_string("set val", name)); + + c2.set(["set key 3", "set val"], require_string("OK", name)); + c2.set(["set key 4", "set val"], require_string("OK", name)); + c2.get(["set key 3"], require_string("set val", name)); + c2.get(["set key 4"], require_string("set val", name)); + + c3.set(["set key 5", "set val"], require_string("OK", name)); + c3.set(["set key 6", "set val"], require_string("OK", name)); + c3.get(["set key 5"], require_string("set val", name)); + c3.get(["set key 6"], require_string("set val", name)); + + c1.quit(quit_check); + c2.quit(quit_check); + c3.quit(quit_check); + } + + function ready_check() { + ready_count++; + if (ready_count === 3) { + run(); + } + } + + c1.on("ready", ready_check); + c2.on("ready", ready_check); + c3.on("ready", ready_check); +}; + +tests.reconnect = function () { + var name = "reconnect"; + + client.set("recon 1", "one"); + client.set("recon 2", "two", function (err, res) { + // Do not do this in normal programs. This is to simulate the server closing on us. + // For orderly shutdown in normal programs, do client.quit() + client.stream.destroy(); + }); + + client.on("reconnecting", function on_recon(params) { + client.on("connect", function on_connect() { + client.select(test_db_num, require_string("OK", name)); + client.get("recon 1", require_string("one", name)); + client.get("recon 1", require_string("one", name)); + client.get("recon 2", require_string("two", name)); + client.get("recon 2", require_string("two", name)); + client.removeListener("connect", on_connect); + client.removeListener("reconnecting", on_recon); + next(name); + }); + }); +}; + +tests.idle = function () { + var name = "idle"; + + client.on("idle", function on_idle() { + client.removeListener("idle", on_idle); + next(name); + }); + + client.set("idle", "test"); +}; + +tests.HSET = function () { + var key = "test hash", + field1 = new Buffer("0123456789"), + value1 = new Buffer("abcdefghij"), + field2 = new Buffer(0), + value2 = new Buffer(0), + name = "HSET"; + + client.HSET(key, field1, value1, require_number(1, name)); + client.HGET(key, field1, require_string(value1.toString(), name)); + + // Empty value + client.HSET(key, field1, value2, require_number(0, name)); + client.HGET([key, field1], require_string("", name)); + + // Empty key, empty value + client.HSET([key, field2, value1], require_number(1, name)); + client.HSET(key, field2, value2, last(name, require_number(0, name))); +}; + +tests.HLEN = function () { + var key = "test hash", + field1 = new Buffer("0123456789"), + value1 = new Buffer("abcdefghij"), + field2 = new Buffer(0), + value2 = new Buffer(0), + name = "HSET", + timeout = 1000; + + client.HSET(key, field1, value1, function (err, results) { + client.HLEN(key, function (err, len) { + assert.ok(2 === +len); + next(name); + }); + }); +} + +tests.HMSET_BUFFER_AND_ARRAY = function () { + // Saving a buffer and an array to the same key should not error + var key = "test hash", + field1 = "buffer", + value1 = new Buffer("abcdefghij"), + field2 = "array", + value2 = ["array contents"], + name = "HSET"; + + client.HMSET(key, field1, value1, field2, value2, last(name, require_string("OK", name))); +}; + +// TODO - add test for HMSET with optional callbacks + +tests.HMGET = function () { + var key1 = "test hash 1", key2 = "test hash 2", name = "HMGET"; + + // redis-like hmset syntax + client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value", require_string("OK", name)); + + // fancy hmset syntax + client.HMSET(key2, { + "0123456789": "abcdefghij", + "some manner of key": "a type of value" + }, require_string("OK", name)); + + client.HMGET(key1, "0123456789", "some manner of key", function (err, reply) { + assert.strictEqual("abcdefghij", reply[0].toString(), name); + assert.strictEqual("a type of value", reply[1].toString(), name); + }); + + client.HMGET(key2, "0123456789", "some manner of key", function (err, reply) { + assert.strictEqual("abcdefghij", reply[0].toString(), name); + assert.strictEqual("a type of value", reply[1].toString(), name); + }); + + client.HMGET(key1, ["0123456789"], function (err, reply) { + assert.strictEqual("abcdefghij", reply[0], name); + }); + + client.HMGET(key1, ["0123456789", "some manner of key"], function (err, reply) { + assert.strictEqual("abcdefghij", reply[0], name); + assert.strictEqual("a type of value", reply[1], name); + }); + + client.HMGET(key1, "missing thing", "another missing thing", function (err, reply) { + assert.strictEqual(null, reply[0], name); + assert.strictEqual(null, reply[1], name); + next(name); + }); +}; + +tests.HINCRBY = function () { + var name = "HINCRBY"; + client.hset("hash incr", "value", 10, require_number(1, name)); + client.HINCRBY("hash incr", "value", 1, require_number(11, name)); + client.HINCRBY("hash incr", "value 2", 1, last(name, require_number(1, name))); +}; + +tests.SUBSCRIBE = function () { + var client1 = client, msg_count = 0, name = "SUBSCRIBE"; + + client1.on("subscribe", function (channel, count) { + if (channel === "chan1") { + client2.publish("chan1", "message 1", require_number(1, name)); + client2.publish("chan2", "message 2", require_number(1, name)); + client2.publish("chan1", "message 3", require_number(1, name)); + } + }); + + client1.on("unsubscribe", function (channel, count) { + if (count === 0) { + // make sure this connection can go into and out of pub/sub mode + client1.incr("did a thing", last(name, require_number(2, name))); + } + }); + + client1.on("message", function (channel, message) { + msg_count += 1; + assert.strictEqual("message " + msg_count, message.toString()); + if (msg_count === 3) { + client1.unsubscribe("chan1", "chan2"); + } + }); + + client1.set("did a thing", 1, require_string("OK", name)); + client1.subscribe("chan1", "chan2", function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual("chan1", results.toString(), name); + }); +}; + +tests.SUB_UNSUB_SUB = function () { + var name = "SUB_UNSUB_SUB"; + client3.subscribe('chan3'); + client3.unsubscribe('chan3'); + client3.subscribe('chan3', function (err, results) { + assert.strictEqual(null, err, "unexpected error: " + err); + client2.publish('chan3', 'foo'); + }); + client3.on('message', function (channel, message) { + assert.strictEqual(channel, 'chan3'); + assert.strictEqual(message, 'foo'); + next(name); + }); +}; + +tests.SUBSCRIBE_QUIT = function () { + var name = "SUBSCRIBE_QUIT"; + client3.on("end", function () { + next(name); + }); + client3.on("subscribe", function (channel, count) { + client3.quit(); + }); + client3.subscribe("chan3"); +}; + +tests.SUBSCRIBE_CLOSE_RESUBSCRIBE = function () { + var name = "SUBSCRIBE_CLOSE_RESUBSCRIBE"; + var c1 = redis.createClient(); + var c2 = redis.createClient(); + var count = 0; + + /* Create two clients. c1 subscribes to two channels, c2 will publish to them. + c2 publishes the first message. + c1 gets the message and drops its connection. It must resubscribe itself. + When it resubscribes, c2 publishes the second message, on the same channel + c1 gets the message and drops its connection. It must resubscribe itself, again. + When it resubscribes, c2 publishes the third message, on the second channel + c1 gets the message and drops its connection. When it reconnects, the test ends. + */ + + c1.on("message", function(channel, message) { + if (channel === "chan1") { + assert.strictEqual(message, "hi on channel 1"); + c1.stream.end(); + + } else if (channel === "chan2") { + assert.strictEqual(message, "hi on channel 2"); + c1.stream.end(); + + } else { + c1.quit(); + c2.quit(); + assert.fail("test failed"); + } + }) + + c1.subscribe("chan1", "chan2"); + + c2.once("ready", function() { + console.log("c2 is ready"); + c1.on("ready", function(err, results) { + console.log("c1 is ready", count); + + count++; + if (count == 1) { + c2.publish("chan1", "hi on channel 1"); + return; + + } else if (count == 2) { + c2.publish("chan2", "hi on channel 2"); + + } else { + c1.quit(function() { + c2.quit(function() { + next(name); + }); + }); + } + }); + + c2.publish("chan1", "hi on channel 1"); + + }); +}; + +tests.EXISTS = function () { + var name = "EXISTS"; + client.del("foo", "foo2", require_number_any(name)); + client.set("foo", "bar", require_string("OK", name)); + client.EXISTS("foo", require_number(1, name)); + client.EXISTS("foo2", last(name, require_number(0, name))); +}; + +tests.DEL = function () { + var name = "DEL"; + client.DEL("delkey", require_number_any(name)); + client.set("delkey", "delvalue", require_string("OK", name)); + client.DEL("delkey", require_number(1, name)); + client.exists("delkey", require_number(0, name)); + client.DEL("delkey", require_number(0, name)); + client.mset("delkey", "delvalue", "delkey2", "delvalue2", require_string("OK", name)); + client.DEL("delkey", "delkey2", last(name, require_number(2, name))); +}; + +tests.TYPE = function () { + var name = "TYPE"; + client.set(["string key", "should be a string"], require_string("OK", name)); + client.rpush(["list key", "should be a list"], require_number_pos(name)); + client.sadd(["set key", "should be a set"], require_number_any(name)); + client.zadd(["zset key", "10.0", "should be a zset"], require_number_any(name)); + client.hset(["hash key", "hashtest", "should be a hash"], require_number_any(0, name)); + + client.TYPE(["string key"], require_string("string", name)); + client.TYPE(["list key"], require_string("list", name)); + client.TYPE(["set key"], require_string("set", name)); + client.TYPE(["zset key"], require_string("zset", name)); + client.TYPE("not here yet", require_string("none", name)); + client.TYPE(["hash key"], last(name, require_string("hash", name))); +}; + +tests.KEYS = function () { + var name = "KEYS"; + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name)); + client.KEYS(["test keys*"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(2, results.length, name); + assert.strictEqual("test keys 1", results[0].toString(), name); + assert.strictEqual("test keys 2", results[1].toString(), name); + next(name); + }); +}; + +tests.MULTIBULK_ZERO_LENGTH = function () { + var name = "MULTIBULK_ZERO_LENGTH"; + client.KEYS(['users:*'], function (err, results) { + assert.strictEqual(null, err, 'error on empty multibulk reply'); + assert.strictEqual(true, is_empty_array(results), "not an empty array"); + next(name); + }); +}; + +tests.RANDOMKEY = function () { + var name = "RANDOMKEY"; + client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name)); + client.RANDOMKEY([], function (err, results) { + assert.strictEqual(null, err, name + " result sent back unexpected error: " + err); + assert.strictEqual(true, /\w+/.test(results), name); + next(name); + }); +}; + +tests.RENAME = function () { + var name = "RENAME"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.RENAME(["foo", "new foo"], require_string("OK", name)); + client.exists(["foo"], require_number(0, name)); + client.exists(["new foo"], last(name, require_number(1, name))); +}; + +tests.RENAMENX = function () { + var name = "RENAMENX"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.set(['foo2', 'bar2'], require_string("OK", name)); + client.RENAMENX(["foo", "foo2"], require_number(0, name)); + client.exists(["foo"], require_number(1, name)); + client.exists(["foo2"], require_number(1, name)); + client.del(["foo2"], require_number(1, name)); + client.RENAMENX(["foo", "foo2"], require_number(1, name)); + client.exists(["foo"], require_number(0, name)); + client.exists(["foo2"], last(name, require_number(1, name))); +}; + +tests.DBSIZE = function () { + var name = "DBSIZE"; + client.set(['foo', 'bar'], require_string("OK", name)); + client.DBSIZE([], last(name, require_number_pos("DBSIZE"))); +}; + +tests.GET = function () { + var name = "GET"; + client.set(["get key", "get val"], require_string("OK", name)); + client.GET(["get key"], last(name, require_string("get val", name))); +}; + +tests.SET = function () { + var name = "SET"; + client.SET(["set key", "set val"], require_string("OK", name)); + client.get(["set key"], last(name, require_string("set val", name))); +}; + +tests.GETSET = function () { + var name = "GETSET"; + client.set(["getset key", "getset val"], require_string("OK", name)); + client.GETSET(["getset key", "new getset val"], require_string("getset val", name)); + client.get(["getset key"], last(name, require_string("new getset val", name))); +}; + +tests.MGET = function () { + var name = "MGET"; + client.mset(["mget keys 1", "mget val 1", "mget keys 2", "mget val 2", "mget keys 3", "mget val 3"], require_string("OK", name)); + client.MGET("mget keys 1", "mget keys 2", "mget keys 3", function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(3, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual("mget val 2", results[1].toString(), name); + assert.strictEqual("mget val 3", results[2].toString(), name); + }); + client.MGET(["mget keys 1", "mget keys 2", "mget keys 3"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(3, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual("mget val 2", results[1].toString(), name); + assert.strictEqual("mget val 3", results[2].toString(), name); + }); + client.MGET(["mget keys 1", "some random shit", "mget keys 2", "mget keys 3"], function (err, results) { + assert.strictEqual(null, err, "result sent back unexpected error: " + err); + assert.strictEqual(4, results.length, name); + assert.strictEqual("mget val 1", results[0].toString(), name); + assert.strictEqual(null, results[1], name); + assert.strictEqual("mget val 2", results[2].toString(), name); + assert.strictEqual("mget val 3", results[3].toString(), name); + next(name); + }); +}; + +tests.SETNX = function () { + var name = "SETNX"; + client.set(["setnx key", "setnx value"], require_string("OK", name)); + client.SETNX(["setnx key", "new setnx value"], require_number(0, name)); + client.del(["setnx key"], require_number(1, name)); + client.exists(["setnx key"], require_number(0, name)); + client.SETNX(["setnx key", "new setnx value"], require_number(1, name)); + client.exists(["setnx key"], last(name, require_number(1, name))); +}; + +tests.SETEX = function () { + var name = "SETEX"; + client.SETEX(["setex key", "100", "setex val"], require_string("OK", name)); + client.exists(["setex key"], require_number(1, name)); + client.ttl(["setex key"], last(name, require_number_pos(name))); +}; + +tests.MSETNX = function () { + var name = "MSETNX"; + client.mset(["mset1", "val1", "mset2", "val2", "mset3", "val3"], require_string("OK", name)); + client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(0, name)); + client.del(["mset3"], require_number(1, name)); + client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(1, name)); + client.exists(["mset3"], require_number(1, name)); + client.exists(["mset4"], last(name, require_number(1, name))); +}; + +tests.HGETALL = function () { + var name = "HGETALL"; + client.hmset(["hosts", "mjr", "1", "another", "23", "home", "1234"], require_string("OK", name)); + client.HGETALL(["hosts"], function (err, obj) { + assert.strictEqual(null, err, name + " result sent back unexpected error: " + err); + assert.strictEqual(3, Object.keys(obj).length, name); + assert.strictEqual("1", obj.mjr.toString(), name); + assert.strictEqual("23", obj.another.toString(), name); + assert.strictEqual("1234", obj.home.toString(), name); + next(name); + }); +}; + +tests.HGETALL_NULL = function () { + var name = "HGETALL_NULL"; + + client.hgetall("missing", function (err, obj) { + assert.strictEqual(null, err); + assert.strictEqual(null, obj); + next(name); + }); +}; + +tests.UTF8 = function () { + var name = "UTF8", + utf8_sample = "ಠ_ಠ"; + + client.set(["utf8test", utf8_sample], require_string("OK", name)); + client.get(["utf8test"], function (err, obj) { + assert.strictEqual(null, err); + assert.strictEqual(utf8_sample, obj); + next(name); + }); +}; + +// Set tests were adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite + +tests.SADD = function () { + var name = "SADD"; + + client.del('set0'); + client.SADD('set0', 'member0', require_number(1, name)); + client.sadd('set0', 'member0', last(name, require_number(0, name))); +}; + +tests.SADD2 = function () { + var name = "SADD2"; + + client.del("set0"); + client.sadd("set0", ["member0", "member1", "member2"], require_number(3, name)); + client.smembers("set0", function (err, res) { + assert.strictEqual(res.length, 3); + assert.strictEqual(res[0], "member0"); + assert.strictEqual(res[1], "member1"); + assert.strictEqual(res[2], "member2"); + }); + client.SADD("set1", ["member0", "member1", "member2"], require_number(3, name)); + client.smembers("set1", function (err, res) { + assert.strictEqual(res.length, 3); + assert.strictEqual(res[0], "member0"); + assert.strictEqual(res[1], "member1"); + assert.strictEqual(res[2], "member2"); + next(name); + }); +}; + +tests.SISMEMBER = function () { + var name = "SISMEMBER"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.sismember('set0', 'member0', require_number(1, name)); + client.sismember('set0', 'member1', last(name, require_number(0, name))); +}; + +tests.SCARD = function () { + var name = "SCARD"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.scard('set0', require_number(1, name)); + client.sadd('set0', 'member1', require_number(1, name)); + client.scard('set0', last(name, require_number(2, name))); +}; + +tests.SREM = function () { + var name = "SREM"; + + client.del('set0'); + client.sadd('set0', 'member0', require_number(1, name)); + client.srem('set0', 'foobar', require_number(0, name)); + client.srem('set0', 'member0', require_number(1, name)); + client.scard('set0', last(name, require_number(0, name))); +}; + +tests.SPOP = function () { + var name = "SPOP"; + + client.del('zzz'); + client.sadd('zzz', 'member0', require_number(1, name)); + client.scard('zzz', require_number(1, name)); + + client.spop('zzz', function (err, value) { + if (err) { + assert.fail(err); + } + assert.equal(value, 'member0', name); + }); + + client.scard('zzz', last(name, require_number(0, name))); +}; + +tests.SDIFF = function () { + var name = "SDIFF"; + + client.del('foo'); + client.sadd('foo', 'x', require_number(1, name)); + client.sadd('foo', 'a', require_number(1, name)); + client.sadd('foo', 'b', require_number(1, name)); + client.sadd('foo', 'c', require_number(1, name)); + + client.sadd('bar', 'c', require_number(1, name)); + + client.sadd('baz', 'a', require_number(1, name)); + client.sadd('baz', 'd', require_number(1, name)); + + client.sdiff('foo', 'bar', 'baz', function (err, values) { + if (err) { + assert.fail(err, name); + } + values.sort(); + assert.equal(values.length, 2, name); + assert.equal(values[0], 'b', name); + assert.equal(values[1], 'x', name); + next(name); + }); +}; + +tests.SDIFFSTORE = function () { + var name = "SDIFFSTORE"; + + client.del('foo'); + client.del('bar'); + client.del('baz'); + client.del('quux'); + + client.sadd('foo', 'x', require_number(1, name)); + client.sadd('foo', 'a', require_number(1, name)); + client.sadd('foo', 'b', require_number(1, name)); + client.sadd('foo', 'c', require_number(1, name)); + + client.sadd('bar', 'c', require_number(1, name)); + + client.sadd('baz', 'a', require_number(1, name)); + client.sadd('baz', 'd', require_number(1, name)); + + // NB: SDIFFSTORE returns the number of elements in the dstkey + + client.sdiffstore('quux', 'foo', 'bar', 'baz', require_number(2, name)); + + client.smembers('quux', function (err, values) { + if (err) { + assert.fail(err, name); + } + var members = buffers_to_strings(values).sort(); + + assert.deepEqual(members, [ 'b', 'x' ], name); + next(name); + }); +}; + +tests.SMEMBERS = function () { + var name = "SMEMBERS"; + + client.del('foo'); + client.sadd('foo', 'x', require_number(1, name)); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(members), [ 'x' ], name); + }); + + client.sadd('foo', 'y', require_number(1, name)); + + client.smembers('foo', function (err, values) { + if (err) { + assert.fail(err, name); + } + assert.equal(values.length, 2, name); + var members = buffers_to_strings(values).sort(); + + assert.deepEqual(members, [ 'x', 'y' ], name); + next(name); + }); +}; + +tests.SMOVE = function () { + var name = "SMOVE"; + + client.del('foo'); + client.del('bar'); + + client.sadd('foo', 'x', require_number(1, name)); + client.smove('foo', 'bar', 'x', require_number(1, name)); + client.sismember('foo', 'x', require_number(0, name)); + client.sismember('bar', 'x', require_number(1, name)); + client.smove('foo', 'bar', 'x', last(name, require_number(0, name))); +}; + +tests.SINTER = function () { + var name = "SINTER"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sinter('sa', 'sb', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 2, name); + assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'b', 'c' ], name); + }); + + client.sinter('sb', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 2, name); + assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'c', 'd' ], name); + }); + + client.sinter('sa', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 1, name); + assert.equal(intersection[0], 'c', name); + }); + + // 3-way + + client.sinter('sa', 'sb', 'sc', function (err, intersection) { + if (err) { + assert.fail(err, name); + } + assert.equal(intersection.length, 1, name); + assert.equal(intersection[0], 'c', name); + next(name); + }); +}; + +tests.SINTERSTORE = function () { + var name = "SINTERSTORE"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + client.del('foo'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sinterstore('foo', 'sa', 'sb', 'sc', require_number(1, name)); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(members), [ 'c' ], name); + next(name); + }); +}; + +tests.SUNION = function () { + var name = "SUNION"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sunion('sa', 'sb', 'sc', function (err, union) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(union).sort(), ['a', 'b', 'c', 'd', 'e'], name); + next(name); + }); +}; + +tests.SUNIONSTORE = function () { + var name = "SUNIONSTORE"; + + client.del('sa'); + client.del('sb'); + client.del('sc'); + client.del('foo'); + + client.sadd('sa', 'a', require_number(1, name)); + client.sadd('sa', 'b', require_number(1, name)); + client.sadd('sa', 'c', require_number(1, name)); + + client.sadd('sb', 'b', require_number(1, name)); + client.sadd('sb', 'c', require_number(1, name)); + client.sadd('sb', 'd', require_number(1, name)); + + client.sadd('sc', 'c', require_number(1, name)); + client.sadd('sc', 'd', require_number(1, name)); + client.sadd('sc', 'e', require_number(1, name)); + + client.sunionstore('foo', 'sa', 'sb', 'sc', function (err, cardinality) { + if (err) { + assert.fail(err, name); + } + assert.equal(cardinality, 5, name); + }); + + client.smembers('foo', function (err, members) { + if (err) { + assert.fail(err, name); + } + assert.equal(members.length, 5, name); + assert.deepEqual(buffers_to_strings(members).sort(), ['a', 'b', 'c', 'd', 'e'], name); + next(name); + }); +}; + +// SORT test adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite + +tests.SORT = function () { + var name = "SORT"; + + client.del('y'); + client.del('x'); + + client.rpush('y', 'd', require_number(1, name)); + client.rpush('y', 'b', require_number(2, name)); + client.rpush('y', 'a', require_number(3, name)); + client.rpush('y', 'c', require_number(4, name)); + + client.rpush('x', '3', require_number(1, name)); + client.rpush('x', '9', require_number(2, name)); + client.rpush('x', '2', require_number(3, name)); + client.rpush('x', '4', require_number(4, name)); + + client.set('w3', '4', require_string("OK", name)); + client.set('w9', '5', require_string("OK", name)); + client.set('w2', '12', require_string("OK", name)); + client.set('w4', '6', require_string("OK", name)); + + client.set('o2', 'buz', require_string("OK", name)); + client.set('o3', 'foo', require_string("OK", name)); + client.set('o4', 'baz', require_string("OK", name)); + client.set('o9', 'bar', require_string("OK", name)); + + client.set('p2', 'qux', require_string("OK", name)); + client.set('p3', 'bux', require_string("OK", name)); + client.set('p4', 'lux', require_string("OK", name)); + client.set('p9', 'tux', require_string("OK", name)); + + // Now the data has been setup, we can test. + + // But first, test basic sorting. + + // y = [ d b a c ] + // sort y ascending = [ a b c d ] + // sort y descending = [ d c b a ] + + client.sort('y', 'asc', 'alpha', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['a', 'b', 'c', 'd'], name); + }); + + client.sort('y', 'desc', 'alpha', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['d', 'c', 'b', 'a'], name); + }); + + // Now try sorting numbers in a list. + // x = [ 3, 9, 2, 4 ] + + client.sort('x', 'asc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [2, 3, 4, 9], name); + }); + + client.sort('x', 'desc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [9, 4, 3, 2], name); + }); + + // Try sorting with a 'by' pattern. + + client.sort('x', 'by', 'w*', 'asc', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), [3, 9, 4, 2], name); + }); + + // Try sorting with a 'by' pattern and 1 'get' pattern. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bar', 'baz', 'buz'], name); + }); + + // Try sorting with a 'by' pattern and 2 'get' patterns. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', function (err, sorted) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name); + }); + + // Try sorting with a 'by' pattern and 2 'get' patterns. + // Instead of getting back the sorted set/list, store the values to a list. + // Then check that the values are there in the expected order. + + client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', 'store', 'bacon', function (err) { + if (err) { + assert.fail(err, name); + } + }); + + client.lrange('bacon', 0, -1, function (err, values) { + if (err) { + assert.fail(err, name); + } + assert.deepEqual(buffers_to_strings(values), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name); + next(name); + }); + + // TODO - sort by hash value +}; + +tests.MONITOR = function () { + var name = "MONITOR", responses = [], monitor_client; + + monitor_client = redis.createClient(); + monitor_client.monitor(function (err, res) { + client.mget("some", "keys", "foo", "bar"); + client.set("json", JSON.stringify({ + foo: "123", + bar: "sdflkdfsjk", + another: false + })); + }); + monitor_client.on("monitor", function (time, args) { + // skip monitor command for Redis <= 2.4.16 + if (args[0] === "monitor") return; + + responses.push(args); + if (responses.length === 2) { + assert.strictEqual(5, responses[0].length); + assert.strictEqual("mget", responses[0][0]); + assert.strictEqual("some", responses[0][1]); + assert.strictEqual("keys", responses[0][2]); + assert.strictEqual("foo", responses[0][3]); + assert.strictEqual("bar", responses[0][4]); + assert.strictEqual(3, responses[1].length); + assert.strictEqual("set", responses[1][0]); + assert.strictEqual("json", responses[1][1]); + assert.strictEqual('{"foo":"123","bar":"sdflkdfsjk","another":false}', responses[1][2]); + monitor_client.quit(function (err, res) { + next(name); + }); + } + }); +}; + +tests.BLPOP = function () { + var name = "BLPOP"; + + client.rpush("blocking list", "initial value", function (err, res) { + client2.BLPOP("blocking list", 0, function (err, res) { + assert.strictEqual("blocking list", res[0].toString()); + assert.strictEqual("initial value", res[1].toString()); + + client.rpush("blocking list", "wait for this value"); + }); + client2.BLPOP("blocking list", 0, function (err, res) { + assert.strictEqual("blocking list", res[0].toString()); + assert.strictEqual("wait for this value", res[1].toString()); + next(name); + }); + }); +}; + +tests.BLPOP_TIMEOUT = function () { + var name = "BLPOP_TIMEOUT"; + + // try to BLPOP the list again, which should be empty. This should timeout and return null. + client2.BLPOP("blocking list", 1, function (err, res) { + if (err) { + throw err; + } + + assert.strictEqual(res, null); + next(name); + }); +}; + +tests.EXPIRE = function () { + var name = "EXPIRE"; + client.set(['expiry key', 'bar'], require_string("OK", name)); + client.EXPIRE(["expiry key", "1"], require_number_pos(name)); + setTimeout(function () { + client.exists(["expiry key"], last(name, require_number(0, name))); + }, 2000); +}; + +tests.TTL = function () { + var name = "TTL"; + client.set(["ttl key", "ttl val"], require_string("OK", name)); + client.expire(["ttl key", "100"], require_number_pos(name)); + setTimeout(function () { + client.TTL(["ttl key"], last(name, require_number_pos(0, name))); + }, 500); +}; + +tests.OPTIONAL_CALLBACK = function () { + var name = "OPTIONAL_CALLBACK"; + client.del("op_cb1"); + client.set("op_cb1", "x"); + client.get("op_cb1", last(name, require_string("x", name))); +}; + +tests.OPTIONAL_CALLBACK_UNDEFINED = function () { + var name = "OPTIONAL_CALLBACK_UNDEFINED"; + client.del("op_cb2"); + client.set("op_cb2", "y", undefined); + client.get("op_cb2", last(name, require_string("y", name))); +}; + +tests.HMSET_THROWS_ON_NON_STRINGS = function () { + var name = "HMSET_THROWS_ON_NON_STRINGS"; + var hash = name; + var data = { "a": [ "this is not a string" ] }; + + client.hmset(hash, data, cb); + function cb(e, r) { + assert(e); // should be an error! + } + + // alternative way it throws + function thrower() { + client.hmset(hash, data); + } + assert.throws(thrower); + next(name); +}; + +tests.ENABLE_OFFLINE_QUEUE_TRUE = function () { + var name = "ENABLE_OFFLINE_QUEUE_TRUE"; + var cli = redis.createClient(9999, null, { + max_attempts: 1 + // default :) + // enable_offline_queue: true + }); + cli.on('error', function(e) { + // ignore, b/c expecting a "can't connect" error + }); + return setTimeout(function() { + cli.set(name, name, function(err, result) { + assert.ifError(err); + }); + + return setTimeout(function(){ + assert.strictEqual(cli.offline_queue.length, 1); + return next(name); + }, 25); + }, 50); +}; + +tests.ENABLE_OFFLINE_QUEUE_FALSE = function () { + var name = "ENABLE_OFFLINE_QUEUE_FALSE"; + var cli = redis.createClient(9999, null, { + max_attempts: 1, + enable_offline_queue: false + }); + cli.on('error', function() { + // ignore, see above + }); + assert.throws(function () { + cli.set(name, name) + }) + assert.doesNotThrow(function () { + cli.set(name, name, function (err) { + // should callback with an error + assert.ok(err); + setTimeout(function () { + next(name); + }, 50); + }); + }); +}; + +// TODO - need a better way to test auth, maybe auto-config a local Redis server or something. +// Yes, this is the real password. Please be nice, thanks. +tests.auth = function () { + var name = "AUTH", client4, ready_count = 0; + + client4 = redis.createClient(9006, "filefish.redistogo.com"); + client4.auth("664b1b6aaf134e1ec281945a8de702a9", function (err, res) { + assert.strictEqual(null, err, name); + assert.strictEqual("OK", res.toString(), name); + }); + + // test auth, then kill the connection so it'll auto-reconnect and auto-re-auth + client4.on("ready", function () { + ready_count++; + if (ready_count === 1) { + client4.stream.destroy(); + } else { + client4.quit(function (err, res) { + next(name); + }); + } + }); +}; + +all_tests = Object.keys(tests); +all_start = new Date(); +test_count = 0; + +run_next_test = function run_next_test() { + var test_name = all_tests.shift(); + if (typeof tests[test_name] === "function") { + util.print('- \x1b[1m' + test_name.toLowerCase() + '\x1b[0m:'); + cur_start = new Date(); + test_count += 1; + tests[test_name](); + } else { + console.log('\n completed \x1b[32m%d\x1b[0m tests in \x1b[33m%d\x1b[0m ms\n', test_count, new Date() - all_start); + client.quit(); + client2.quit(); + } +}; + +client.once("ready", function start_tests() { + console.log("Connected to " + client.host + ":" + client.port + ", Redis server version " + client.server_info.redis_version + "\n"); + console.log("Using reply parser " + client.reply_parser.name); + + run_next_test(); + + connected = true; +}); + +client.on('end', function () { + ended = true; +}); + +// Exit immediately on connection failure, which triggers "exit", below, which fails the test +client.on("error", function (err) { + console.error("client: " + err.stack); + process.exit(); +}); +client2.on("error", function (err) { + console.error("client2: " + err.stack); + process.exit(); +}); +client3.on("error", function (err) { + console.error("client3: " + err.stack); + process.exit(); +}); +client.on("reconnecting", function (params) { + console.log("reconnecting: " + util.inspect(params)); +}); + +process.on('uncaughtException', function (err) { + console.error("Uncaught exception: " + err.stack); + process.exit(1); +}); + +process.on('exit', function (code) { + assert.equal(true, connected); + assert.equal(true, ended); +}); diff --git a/node_modules/socket.io/node_modules/socket.io-client/.npmignore b/node_modules/socket.io/node_modules/socket.io-client/.npmignore new file mode 100644 index 0000000..c27cb50 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/.npmignore @@ -0,0 +1,2 @@ +test/node_modules +support diff --git a/node_modules/socket.io/node_modules/socket.io-client/History.md b/node_modules/socket.io/node_modules/socket.io-client/History.md new file mode 100644 index 0000000..0867b2f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/History.md @@ -0,0 +1,237 @@ + +0.9.16 / 2013-06-06 +=================== + + * transports: fix escaping for tests + +0.9.15 / 2013-06-06 +=================== + + * transports: added unescaping for escaped htmlfile + * skipped 12-14 to match socket.io server version + +0.9.11 / 2012-11-02 +=================== + + * Enable use of 'xhr' transport in Node.js + * Fix the problem with disconnecting xhr-polling users + * Add should to devDependencies + * Prefer XmlHttpRequest if CORS is available + * Make client compatible with AMD loaders. + +0.9.10 / 2012-08-10 +=================== + + * fix removeAllListeners to behave as expected. + * set withCredentials to true only if xdomain. + * socket: disable disconnect on unload by default. + +0.9.9 / 2012-08-01 +================== + + * socket: fixed disconnect xhr url and made it actually sync + * *: bump xmlhttprequest dep + +0.9.8 / 2012-07-24 +================== + + * Fixed build. + +0.9.7 / 2012-07-24 +================== + + * iOS websocket crash fix. + * Fixed potential `open` collision. + * Fixed disconnectSync. + +0.9.6 / 2012-04-17 +================== + + * Don't position the jsonp form off the screen (android fix). + +0.9.5 / 2012-04-05 +================== + + * Bumped version. + +0.9.4 / 2012-04-01 +================== + + * Fixes polling loop upon reconnect advice (fixes #438). + +0.9.3 / 2012-03-28 +================== + + * Fix XHR.check, which was throwing an error transparently and causing non-IE browsers to fall back to JSONP [mikito] + * Fixed forced disconnect on window close [zzzaaa] + +0.9.2 / 2012-03-13 +================== + + * Transport order set by "options" [zzzaaa] + +0.9.1-1 / 2012-03-02 +==================== + + * Fixed active-x-obfuscator NPM dependency. + +0.9.1 / 2012-03-02 +================== + + * Misc corrections. + * Added warning within Firefox about webworker test in test runner. + * Update ws dependency [einaros] + * Implemented client side heartbeat checks. [felixge] + * Improved Firewall support with ActiveX obfuscation. [felixge] + * Fixed error handling during connection process. [Outsideris] + +0.9.0 / 2012-02-26 +================== + + * Added DS_Store to gitignore. + * Updated depedencies. + * Bumped uglify + * Tweaking code so it doesn't throw an exception when used inside a WebWorker in Firefox + * Do not rely on Array.prototype.indexOf as it breaks with pages that use the Prototype.js library. + * Windows support landed + * Use @einaros ws module instead of the old crap one + * Fix for broken closeTimeout and 'IE + xhr' goes into infinite loop on disconnection + * Disabled reconnection on error if reconnect option is set to false + * Set withCredentials to true before xhr to fix authentication + * Clears the timeout from reconnection attempt when there is a successful or failed reconnection. + This fixes the issue of setTimeout's carrying over from previous reconnection + and changing (skipping) values of self.reconnectionDelay in the newer reconnection. + * Removed decoding of parameters when chunking the query string. + This was used later on to construct the url to post to the socket.io server + for connection and if we're adding custom parameters of our own to this url + (for example for OAuth authentication) they were being sent decoded, which is wrong. + +0.8.7 / 2011-11-05 +================== + + * Bumped client + +0.8.6 / 2011-10-27 +================== + + * Added WebWorker support. + * Fixed swfobject and web_socket.js to not assume window. + * Fixed CORS detection for webworker. + * Fix `defer` for webkit in a webworker. + * Fixed io.util.request to not rely on window. + * FIxed; use global instead of window and dont rely on document. + * Fixed; JSON-P handshake if CORS is not available. + * Made underlying Transport disconnection trigger immediate socket.io disconnect. + * Fixed warning when compressing with Google Closure Compiler. + * Fixed builder's uglify utf-8 support. + * Added workaround for loading indicator in FF jsonp-polling. [3rd-Eden] + * Fixed host discovery lookup. [holic] + * Fixed close timeout when disconnected/reconnecting. [jscharlach] + * Fixed jsonp-polling feature detection. + * Fixed jsonp-polling client POSTing of \n. + * Fixed test runner on IE6/7 + +0.8.5 / 2011-10-07 +================== + + * Bumped client + +0.8.4 / 2011-09-06 +================== + + * Corrected build + +0.8.3 / 2011-09-03 +================== + + * Fixed `\n` parsing for non-JSON packets. + * Fixed; make Socket.IO XHTML doctype compatible (fixes #460 from server) + * Fixed support for Node.JS running `socket.io-client`. + * Updated repository name in `package.json`. + * Added support for different policy file ports without having to port + forward 843 on the server side [3rd-Eden] + +0.8.2 / 2011-08-29 +================== + + * Fixed flashsocket detection. + +0.8.1 / 2011-08-29 +================== + + * Bump version. + +0.8.0 / 2011-08-28 +================== + + * Added MozWebSocket support (hybi-10 doesn't require API changes) [einaros]. + +0.7.11 / 2011-08-27 +=================== + + * Corrected previous release (missing build). + +0.7.10 / 2011-08-27 +=================== + + * Fix for failing fallback in websockets + +0.7.9 / 2011-08-12 +================== + + * Added check on `Socket#onConnect` to prevent double `connect` events on the main manager. + * Fixed socket namespace connect test. Remove broken alternative namespace connect test. + * Removed test handler for removed test. + * Bumped version to match `socket.io` server. + +0.7.5 / 2011-08-08 +================== + + * Added querystring support for `connect` [3rd-Eden] + * Added partial Node.JS transports support [3rd-Eden, josephg] + * Fixed builder test. + * Changed `util.inherit` to replicate Object.create / __proto__. + * Changed and cleaned up some acceptance tests. + * Fixed race condition with a test that could not be run multiple times. + * Added test for encoding a payload. + * Added the ability to override the transport to use in acceptance test [3rd-Eden] + * Fixed multiple connect packets [DanielBaulig] + * Fixed jsonp-polling over-buffering [3rd-Eden] + * Fixed ascii preservation in minified socket.io client [3rd-Eden] + * Fixed socket.io in situations where the page is not served through utf8. + * Fixed namespaces not reconnecting after disconnect [3rd-Eden] + * Fixed default port for secure connections. + +0.7.4 / 2011-07-12 +================== + + * Added `SocketNamespace#of` shortcut. [3rd-Eden] + * Fixed a IE payload decoding bug. [3rd-Eden] + * Honor document protocol, unless overriden. [dvv] + * Fixed new builder dependencies. [3rd-Eden] + +0.7.3 / 2011-06-30 +================== + + * Fixed; acks don't depend on arity. They're automatic for `.send` and + callback based for `.emit`. [dvv] + * Added support for sub-sockets authorization. [3rd-Eden] + * Added BC support for `new io.connect`. [fat] + * Fixed double `connect` events. [3rd-Eden] + * Fixed reconnection with jsonp-polling maintaining old sessionid. [franck34] + +0.7.2 / 2011-06-22 +================== + + * Added `noop` message type. + +0.7.1 / 2011-06-21 +================== + + * Bumped socket.io dependency version for acceptance tests. + +0.7.0 / 2011-06-21 +================== + + * http://socket.io/announcement.html + diff --git a/node_modules/socket.io/node_modules/socket.io-client/Makefile b/node_modules/socket.io/node_modules/socket.io-client/Makefile new file mode 100644 index 0000000..f2d2f41 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/Makefile @@ -0,0 +1,20 @@ + +ALL_TESTS = $(shell find test/ -name '*.test.js') + +run-tests: + @./node_modules/.bin/expresso \ + -I lib \ + -I support \ + --serial \ + $(TESTS) + +test: + @$(MAKE) TESTS="$(ALL_TESTS)" run-tests + +test-acceptance: + @node support/test-runner/app $(TRANSPORT) + +build: + @node ./bin/builder.js + +.PHONY: test diff --git a/node_modules/socket.io/node_modules/socket.io-client/README.md b/node_modules/socket.io/node_modules/socket.io-client/README.md new file mode 100644 index 0000000..cdb7715 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/README.md @@ -0,0 +1,246 @@ +socket.io +========= + +#### Sockets for the rest of us + +The `socket.io` client is basically a simple HTTP Socket interface implementation. +It looks similar to WebSocket while providing additional features and +leveraging other transports when WebSocket is not supported by the user's +browser. + +```js +var socket = io.connect('http://domain.com'); +socket.on('connect', function () { + // socket connected +}); +socket.on('custom event', function () { + // server emitted a custom event +}); +socket.on('disconnect', function () { + // socket disconnected +}); +socket.send('hi there'); +``` + +### Recipes + +#### Utilizing namespaces (ie: multiple sockets) + +If you want to namespace all the messages and events emitted to a particular +endpoint, simply specify it as part of the `connect` uri: + +```js +var chat = io.connect('http://localhost/chat'); +chat.on('connect', function () { + // chat socket connected +}); + +var news = io.connect('/news'); // io.connect auto-detects host +news.on('connect', function () { + // news socket connected +}); +``` + +#### Emitting custom events + +To ease with the creation of applications, you can emit custom events outside +of the global `message` event. + +```js +var socket = io.connect(); +socket.emit('server custom event', { my: 'data' }); +``` + +#### Forcing disconnection + +```js +var socket = io.connect(); +socket.on('connect', function () { + socket.disconnect(); +}); +``` + +### Documentation + +#### io#connect + +```js +io.connect(uri, [options]); +``` + +##### Options: + +- *resource* + + socket.io + + The resource is what allows the `socket.io` server to identify incoming connections by `socket.io` clients. In other words, any HTTP server can implement socket.io and still serve other normal, non-realtime HTTP requests. + +- *transports* + +```js +['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling'] +``` + + A list of the transports to attempt to utilize (in order of preference). + +- *'connect timeout'* + +```js +5000 +``` + + The amount of milliseconds a transport has to create a connection before we consider it timed out. + +- *'try multiple transports'* + +```js +true +``` + + A boolean indicating if we should try other transports when the connectTimeout occurs. + +- *reconnect* + +```js +true +``` + + A boolean indicating if we should automatically reconnect if a connection is disconnected. + +- *'reconnection delay'* + +```js +500 +``` + + The amount of milliseconds before we try to connect to the server again. We are using a exponential back off algorithm for the following reconnections, on each reconnect attempt this value will get multiplied (500 > 1000 > 2000 > 4000 > 8000). + + +- *'max reconnection attempts'* + +```js +10 +``` + + The amount of attempts should we make using the current transport to connect to the server? After this we will do one final attempt, and re-try with all enabled transport methods before we give up. + +##### Properties: + +- *options* + + The passed in options combined with the defaults. + +- *connected* + + Whether the socket is connected or not. + +- *connecting* + + Whether the socket is connecting or not. + +- *reconnecting* + + Whether we are reconnecting or not. + +- *transport* + + The transport instance. + +##### Methods: + +- *connect(λ)* + + Establishes a connection. If λ is supplied as argument, it will be called once the connection is established. + +- *send(message)* + + A string of data to send. + +- *disconnect* + + Closes the connection. + +- *on(event, λ)* + + Adds a listener for the event *event*. + +- *once(event, λ)* + + Adds a one time listener for the event *event*. The listener is removed after the first time the event is fired. + +- *removeListener(event, λ)* + + Removes the listener λ for the event *event*. + +##### Events: + +- *connect* + + Fired when the connection is established and the handshake successful. + +- *connecting(transport_type)* + + Fired when a connection is attempted, passing the transport name. + +- *connect_failed* + + Fired when the connection timeout occurs after the last connection attempt. + This only fires if the `connectTimeout` option is set. + If the `tryTransportsOnConnectTimeout` option is set, this only fires once all + possible transports have been tried. + +- *message(message)* + + Fired when a message arrives from the server + +- *close* + + Fired when the connection is closed. Be careful with using this event, as some transports will fire it even under temporary, expected disconnections (such as XHR-Polling). + +- *disconnect* + + Fired when the connection is considered disconnected. + +- *reconnect(transport_type,reconnectionAttempts)* + + Fired when the connection has been re-established. This only fires if the `reconnect` option is set. + +- *reconnecting(reconnectionDelay,reconnectionAttempts)* + + Fired when a reconnection is attempted, passing the next delay for the next reconnection. + +- *reconnect_failed* + + Fired when all reconnection attempts have failed and we where unsuccessful in reconnecting to the server. + +### Contributors + +Guillermo Rauch <guillermo@learnboost.com> + +Arnout Kazemier <info@3rd-eden.com> + +### License + +(The MIT License) + +Copyright (c) 2010 LearnBoost <dev@learnboost.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/socket.io/node_modules/socket.io-client/bin/builder.js b/node_modules/socket.io/node_modules/socket.io-client/bin/builder.js new file mode 100755 index 0000000..7383c75 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/bin/builder.js @@ -0,0 +1,303 @@ +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , socket = require('../lib/io') + , uglify = require('uglify-js') + , activeXObfuscator = require('active-x-obfuscator'); + +/** + * License headers. + * + * @api private + */ + +var template = '/*! Socket.IO.%ext% build:' + socket.version + ', %type%. Copyright(c) 2011 LearnBoost MIT Licensed */\n' + , development = template.replace('%type%', 'development').replace('%ext%', 'js') + , production = template.replace('%type%', 'production').replace('%ext%', 'min.js'); + +/** + * If statements, these allows you to create serveride & client side compatible + * code using specially designed `if` statements that remove serverside + * designed code from the source files + * + * @api private + */ + +var starttagIF = '// if node' + , endtagIF = '// end node'; + +/** + * The modules that are required to create a base build of Socket.IO. + * + * @const + * @type {Array} + * @api private + */ + +var base = [ + 'io.js' + , 'util.js' + , 'events.js' + , 'json.js' + , 'parser.js' + , 'transport.js' + , 'socket.js' + , 'namespace.js' + ]; + +/** + * The available transports for Socket.IO. These are mapped as: + * + * - `key` the name of the transport + * - `value` the dependencies for the transport + * + * @const + * @type {Object} + * @api public + */ + +var baseTransports = { + 'websocket': ['transports/websocket.js'] + , 'flashsocket': [ + 'transports/websocket.js' + , 'transports/flashsocket.js' + , 'vendor/web-socket-js/swfobject.js' + , 'vendor/web-socket-js/web_socket.js' + ] + , 'htmlfile': ['transports/xhr.js', 'transports/htmlfile.js'] + /* FIXME: re-enable me once we have multi-part support + , 'xhr-multipart': ['transports/xhr.js', 'transports/xhr-multipart.js'] */ + , 'xhr-polling': ['transports/xhr.js', 'transports/xhr-polling.js'] + , 'jsonp-polling': [ + 'transports/xhr.js' + , 'transports/xhr-polling.js' + , 'transports/jsonp-polling.js' + ] +}; + +/** + * Wrappers for client-side usage. + * This enables usage in top-level browser window, client-side CommonJS systems and AMD loaders. + * If doing a node build for server-side client, this wrapper is NOT included. + * @api private + */ +var wrapperPre = "\nvar io = ('undefined' === typeof module ? {} : module.exports);\n(function() {\n"; + +var wrapperPost = "\nif (typeof define === \"function\" && define.amd) {" + + "\n define([], function () { return io; });" + + "\n}\n})();"; + + +/** + * Builds a custom Socket.IO distribution based on the transports that you + * need. You can configure the build to create development build or production + * build (minified). + * + * @param {Array} transports The transports that needs to be bundled. + * @param {Object} [options] Options to configure the building process. + * @param {Function} callback Last argument should always be the callback + * @callback {String|Boolean} err An optional argument, if it exists than an error + * occurred during the build process. + * @callback {String} result The result of the build process. + * @api public + */ + +var builder = module.exports = function () { + var transports, options, callback, error = null + , args = Array.prototype.slice.call(arguments, 0) + , settings = { + minify: true + , node: false + , custom: [] + }; + + // Fancy pancy argument support this makes any pattern possible mainly + // because we require only one of each type + args.forEach(function (arg) { + var type = Object.prototype.toString.call(arg) + .replace(/\[object\s(\w+)\]/gi , '$1' ).toLowerCase(); + + switch (type) { + case 'array': + return transports = arg; + case 'object': + return options = arg; + case 'function': + return callback = arg; + } + }); + + // Add defaults + options = options || {}; + transports = transports || Object.keys(baseTransports); + + // Merge the data + for(var option in options) { + settings[option] = options[option]; + } + + // Start creating a dependencies chain with all the required files for the + // custom Socket.IO bundle. + var files = []; + base.forEach(function (file) { + files.push(__dirname + '/../lib/' + file); + }); + + transports.forEach(function (transport) { + var dependencies = baseTransports[transport]; + if (!dependencies) { + error = 'Unsupported transport `' + transport + '` supplied as argument.'; + return; + } + + // Add the files to the files list, but only if they are not added before + dependencies.forEach(function (file) { + var path = __dirname + '/../lib/' + file; + if (!~files.indexOf(path)) files.push(path); + }) + }); + + // check to see if the files tree compilation generated any errors. + if (error) return callback(error); + + var results = {}; + files.forEach(function (file) { + fs.readFile(file, function (err, content) { + if (err) error = err; + results[file] = content; + + // check if we are done yet, or not.. Just by checking the size of the result + // object. + if (Object.keys(results).length !== files.length) return; + + // we are done, did we error? + if (error) return callback(error); + + // start with the license header + var code = development + , ignore = 0; + + // pre-wrapper for non-server-side builds + if (!settings.node) code += wrapperPre; + + // concatenate the file contents in order + files.forEach(function (file) { + code += results[file]; + }); + + // check if we need to add custom code + if (settings.custom.length) { + settings.custom.forEach(function (content) { + code += content; + }); + } + + // post-wrapper for non-server-side builds + if (!settings.node) { + code += wrapperPost; + } + + code = activeXObfuscator(code); + + // Search for conditional code blocks that need to be removed as they + // where designed for a server side env. but only if we don't want to + // make this build node compatible. + if (!settings.node) { + code = code.split('\n').filter(function (line) { + // check if there are tags in here + var start = line.indexOf(starttagIF) >= 0 + , end = line.indexOf(endtagIF) >= 0 + , ret = ignore; + + // ignore the current line + if (start) { + ignore++; + ret = ignore; + } + + // stop ignoring the next line + if (end) { + ignore--; + } + + return ret == 0; + }).join('\n'); + } + + // check if we need to process it any further + if (settings.minify) { + var ast = uglify.parser.parse(code); + ast = uglify.uglify.ast_mangle(ast); + ast = uglify.uglify.ast_squeeze(ast); + + code = production + uglify.uglify.gen_code(ast, { ascii_only: true }); + } + + callback(error, code); + }) + }) +}; + +/** + * Builder version is also the current client version + * this way we don't have to do another include for the + * clients version number and we can just include the builder. + * + * @type {String} + * @api public + */ + +builder.version = socket.version; + +/** + * A list of all build in transport types. + * + * @type {Object} + * @api public + */ + +builder.transports = baseTransports; + +/** + * Command line support, this allows us to generate builds without having + * to load it as module. + */ + +if (!module.parent){ + // the first 2 are `node` and the path to this file, we don't need them + var args = process.argv.slice(2); + + // build a development build + builder(args.length ? args : false, { minify:false }, function (err, content) { + if (err) return console.error(err); + + fs.write( + fs.openSync(__dirname + '/../dist/socket.io.js', 'w') + , content + , 0 + , 'utf8' + ); + console.log('Successfully generated the development build: socket.io.js'); + }); + + // and build a production build + builder(args.length ? args : false, function (err, content) { + if (err) return console.error(err); + + fs.write( + fs.openSync(__dirname + '/../dist/socket.io.min.js', 'w') + , content + , 0 + , 'utf8' + ); + console.log('Successfully generated the production build: socket.io.min.js'); + }); +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json new file mode 100644 index 0000000..ebdf642 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/component.json @@ -0,0 +1,14 @@ +{ + "name": "bind", + "version": "0.0.1", + "description": "function binding utility", + "keywords": [ + "bind", + "utility" + ], + "dependencies": {}, + "scripts": [ + "index.js" + ], + "repo": "https://raw.github.com/component/bind" +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js new file mode 100644 index 0000000..9808fc0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-bind/index.js @@ -0,0 +1,24 @@ + +/** + * Slice reference. + */ + +var slice = [].slice; + +/** + * Bind `obj` to `fn`. + * + * @param {Object} obj + * @param {Function|String} fn or string + * @return {Function} + * @api public + */ + +module.exports = function(obj, fn){ + if ('string' == typeof fn) fn = obj[fn]; + if ('function' != typeof fn) throw new Error('bind() requires a function'); + var args = [].slice.call(arguments, 2); + return function(){ + return fn.apply(obj, args.concat(slice.call(arguments))); + } +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json new file mode 100644 index 0000000..0eec23b --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/component.json @@ -0,0 +1,13 @@ +{ + "name": "emitter", + "description": "Event emitter", + "keywords": [ + "emitter", + "events" + ], + "version": "0.0.6", + "scripts": [ + "index.js" + ], + "repo": "https://raw.github.com/component/emitter" +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js new file mode 100644 index 0000000..8cc74ae --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-emitter/index.js @@ -0,0 +1,147 @@ + +/** + * 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 = 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){ + var self = this; + this._callbacks = this._callbacks || {}; + + function on() { + self.off(event, on); + fn.apply(this, arguments); + } + + fn._off = on; + 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 = function(event, fn){ + this._callbacks = this._callbacks || {}; + 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 i = callbacks.indexOf(fn._off || fn); + if (~i) callbacks.splice(i, 1); + 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/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json new file mode 100644 index 0000000..6b35f45 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/component.json @@ -0,0 +1,15 @@ +{ + "name": "json-fallback", + "repo": "component/json", + "description": "JSON parser / stringifier fallback", + "version": "0.0.1", + "keywords": [ + "json", + "fallback" + ], + "dependencies": {}, + "development": {}, + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js new file mode 100644 index 0000000..5a47ca6 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json-fallback/index.js @@ -0,0 +1,486 @@ +/* + json2.js + 2011-10-19 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, regexp: true */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON = {}; + +(function () { + 'use strict'; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) + ? this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' + : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' + ? c + : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 + ? '[]' + : gap + ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' + : '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 + ? '{}' + : gap + ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' + : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' + ? walk({'': j}, '') + : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); + +module.exports = JSON \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json new file mode 100644 index 0000000..da7097c --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/component.json @@ -0,0 +1,17 @@ +{ + "name": "json", + "repo": "component/json", + "description": "JSON parser / stringifier", + "version": "0.0.1", + "keywords": [ + "json" + ], + "dependencies": {}, + "development": {}, + "optional": { + "component/json-fallback": "*" + }, + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js new file mode 100644 index 0000000..c05cc28 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/component-json/index.js @@ -0,0 +1,4 @@ + +module.exports = 'undefined' == typeof JSON + ? require('json-fallback') + : JSON; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json new file mode 100644 index 0000000..b90c1f2 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/component.json @@ -0,0 +1,24 @@ +{ + "name": "engine.io", + "version": "0.4.0", + "dependencies": { + "component/emitter": "0.0.6", + "visionmedia/debug": "*" + }, + "main": "lib/index.js", + "scripts": [ + "lib/index.js", + "lib/parser.js", + "lib/socket.js", + "lib/transport.js", + "lib/emitter.js", + "lib/util.js", + "lib/transports/index.js", + "lib/transports/polling.js", + "lib/transports/polling-xhr.js", + "lib/transports/polling-jsonp.js", + "lib/transports/websocket.js", + "lib/transports/flashsocket.js" + ], + "repo": "https://raw.github.com/learnboost/engine.io-client" +} \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js new file mode 100644 index 0000000..142a9bf --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/emitter.js @@ -0,0 +1,52 @@ + +/** + * Module dependencies. + */ + +var Emitter; + +try { + Emitter = require('emitter'); +} catch(e){ + Emitter = require('emitter-component'); +} + +/** + * Module exports. + */ + +module.exports = Emitter; + +/** + * Compatibility with `WebSocket#addEventListener`. + * + * @api public + */ + +Emitter.prototype.addEventListener = Emitter.prototype.on; + +/** + * Compatibility with `WebSocket#removeEventListener`. + * + * @api public + */ + +Emitter.prototype.removeEventListener = Emitter.prototype.off; + +/** + * Node-compatible `EventEmitter#removeListener` + * + * @api public + */ + +Emitter.prototype.removeListener = Emitter.prototype.off; + +/** + * Node-compatible `EventEmitter#removeAllListeners` + * + * @api public + */ + +Emitter.prototype.removeAllListeners = function(){ + this._callbacks = {}; +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js new file mode 100644 index 0000000..d463b3f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./socket'); diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js new file mode 100644 index 0000000..2c2928e --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/parser.js @@ -0,0 +1,163 @@ +/** + * Module dependencies. + */ + +var util = require('./util') + +/** + * Packet types. + */ + +var packets = exports.packets = { + open: 0 // non-ws + , close: 1 // non-ws + , ping: 2 + , pong: 3 + , message: 4 + , upgrade: 5 + , noop: 6 +}; + +var packetslist = util.keys(packets); + +/** + * Premade error packet. + */ + +var err = { type: 'error', data: 'parser error' } + +/** + * Encodes a packet. + * + * [ `:` ] + * + * Example: + * + * 5:hello world + * 3 + * 4 + * + * @api private + */ + +exports.encodePacket = function (packet) { + var encoded = packets[packet.type] + + // data fragment is optional + if (undefined !== packet.data) { + encoded += String(packet.data); + } + + return '' + encoded; +}; + +/** + * Decodes a packet. + * + * @return {Object} with `type` and `data` (if any) + * @api private + */ + +exports.decodePacket = function (data) { + var type = data.charAt(0); + + if (Number(type) != type || !packetslist[type]) { + return err; + } + + if (data.length > 1) { + return { type: packetslist[type], data: data.substring(1) }; + } else { + return { type: packetslist[type] }; + } +}; + +/** + * Encodes multiple messages (payload). + * + * :data + * + * Example: + * + * 11:hello world2:hi + * + * @param {Array} packets + * @api private + */ + +exports.encodePayload = function (packets) { + if (!packets.length) { + return '0:'; + } + + var encoded = '' + , message + + for (var i = 0, l = packets.length; i < l; i++) { + message = exports.encodePacket(packets[i]); + encoded += message.length + ':' + message; + } + + return encoded; +}; + +/* + * Decodes data when a payload is maybe expected. + * + * @param {String} data + * @return {Array} packets + * @api public + */ + +exports.decodePayload = function (data) { + if (data == '') { + // parser error - ignoring payload + return [err]; + } + + var packets = [] + , length = '' + , n, msg, packet + + for (var i = 0, l = data.length; i < l; i++) { + var chr = data.charAt(i) + + if (':' != chr) { + length += chr; + } else { + if ('' == length || (length != (n = Number(length)))) { + // parser error - ignoring payload + return [err]; + } + + msg = data.substr(i + 1, n); + + if (length != msg.length) { + // parser error - ignoring payload + return [err]; + } + + if (msg.length) { + packet = exports.decodePacket(msg); + + if (err.type == packet.type && err.data == packet.data) { + // parser error in individual packet - ignoring payload + return [err]; + } + + packets.push(packet); + } + + // advance cursor + i += n; + length = '' + } + } + + if (length != '') { + // parser error - ignoring payload + return [err]; + } + + return packets; +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js new file mode 100644 index 0000000..ad86283 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/socket.js @@ -0,0 +1,492 @@ +/** + * Module dependencies. + */ + +var util = require('./util') + , transports = require('./transports') + , Emitter = require('./emitter') + , debug = require('debug')('engine-client:socket'); + +/** + * Module exports. + */ + +module.exports = Socket; + +/** + * Global reference. + */ + +var global = 'undefined' != typeof window ? window : global; + +/** + * Socket constructor. + * + * @param {Object} options + * @api public + */ + +function Socket(opts){ + if (!(this instanceof Socket)) return new Socket(opts); + + if ('string' == typeof opts) { + var uri = util.parseUri(opts); + opts = arguments[1] || {}; + opts.host = uri.host; + opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; + opts.port = uri.port; + } + + opts = opts || {}; + this.secure = null != opts.secure ? opts.secure : (global.location && 'https:' == location.protocol); + this.host = opts.host || opts.hostname || (global.location ? location.hostname : 'localhost'); + this.port = opts.port || (global.location && location.port ? location.port : (this.secure ? 443 : 80)); + this.query = opts.query || {}; + this.query.uid = rnd(); + this.upgrade = false !== opts.upgrade; + this.resource = opts.resource || 'default'; + this.path = (opts.path || '/engine.io').replace(/\/$/, ''); + this.path += '/' + this.resource + '/'; + this.forceJSONP = !!opts.forceJSONP; + this.timestampParam = opts.timestampParam || 't'; + this.timestampRequests = !!opts.timestampRequests; + this.flashPath = opts.flashPath || ''; + this.transports = opts.transports || ['polling', 'websocket', 'flashsocket']; + this.readyState = ''; + this.writeBuffer = []; + this.policyPort = opts.policyPort || 843; + this.open(); + + Socket.sockets.push(this); + Socket.sockets.evs.emit('add', this); +}; + +/** + * Mix in `Emitter`. + */ + +Emitter(Socket.prototype); + +/** + * Protocol version. + * + * @api public + */ + +Socket.protocol = 1; + +/** + * Static EventEmitter. + */ + +Socket.sockets = []; +Socket.sockets.evs = new Emitter; + +/** + * Expose deps for legacy compatibility + * and standalone browser access. + */ + +Socket.Socket = Socket; +Socket.Transport = require('./transport'); +Socket.Emitter = require('./emitter'); +Socket.transports = require('./transports'); +Socket.util = require('./util'); +Socket.parser = require('./parser'); + +/** + * Creates transport of the given type. + * + * @param {String} transport name + * @return {Transport} + * @api private + */ + +Socket.prototype.createTransport = function (name) { + debug('creating transport "%s"', name); + var query = clone(this.query); + query.transport = name; + + if (this.id) { + query.sid = this.id; + } + + var transport = new transports[name]({ + host: this.host + , port: this.port + , secure: this.secure + , path: this.path + , query: query + , forceJSONP: this.forceJSONP + , timestampRequests: this.timestampRequests + , timestampParam: this.timestampParam + , flashPath: this.flashPath + , policyPort: this.policyPort + }); + + return transport; +}; + +function clone (obj) { + var o = {}; + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + o[i] = obj[i]; + } + } + return o; +} + +/** + * Initializes transport to use and starts probe. + * + * @api private + */ + +Socket.prototype.open = function () { + this.readyState = 'opening'; + var transport = this.createTransport(this.transports[0]); + transport.open(); + this.setTransport(transport); +}; + +/** + * Sets the current transport. Disables the existing one (if any). + * + * @api private + */ + +Socket.prototype.setTransport = function (transport) { + var self = this; + + if (this.transport) { + debug('clearing existing transport'); + this.transport.removeAllListeners(); + } + + // set up transport + this.transport = transport; + + // set up transport listeners + transport + .on('drain', function () { + self.flush(); + }) + .on('packet', function (packet) { + self.onPacket(packet); + }) + .on('error', function (e) { + self.onError(e); + }) + .on('close', function () { + self.onClose('transport close'); + }); +}; + +/** + * Probes a transport. + * + * @param {String} transport name + * @api private + */ + +Socket.prototype.probe = function (name) { + debug('probing transport "%s"', name); + var transport = this.createTransport(name, { probe: 1 }) + , failed = false + , self = this; + + transport.once('open', function () { + if (failed) return; + + debug('probe transport "%s" opened', name); + transport.send([{ type: 'ping', data: 'probe' }]); + transport.once('packet', function (msg) { + if (failed) return; + if ('pong' == msg.type && 'probe' == msg.data) { + debug('probe transport "%s" pong', name); + self.upgrading = true; + self.emit('upgrading', transport); + + debug('pausing current transport "%s"', self.transport.name); + self.transport.pause(function () { + if (failed) return; + if ('closed' == self.readyState || 'closing' == self.readyState) { + return; + } + debug('changing transport and sending upgrade packet'); + transport.removeListener('error', onerror); + self.emit('upgrade', transport); + self.setTransport(transport); + transport.send([{ type: 'upgrade' }]); + transport = null; + self.upgrading = false; + self.flush(); + }); + } else { + debug('probe transport "%s" failed', name); + var err = new Error('probe error'); + err.transport = transport.name; + self.emit('error', err); + } + }); + }); + + transport.once('error', onerror); + function onerror(err) { + if (failed) return; + + // Any callback called by transport should be ignored since now + failed = true; + + var error = new Error('probe error: ' + err); + error.transport = transport.name; + + transport.close(); + transport = null; + + debug('probe transport "%s" failed because of error: %s', name, err); + + self.emit('error', error); + }; + + transport.open(); + + this.once('close', function () { + if (transport) { + debug('socket closed prematurely - aborting probe'); + failed = true; + transport.close(); + transport = null; + } + }); + + this.once('upgrading', function (to) { + if (transport && to.name != transport.name) { + debug('"%s" works - aborting "%s"', to.name, transport.name); + transport.close(); + transport = null; + } + }); +}; + +/** + * Called when connection is deemed open. + * + * @api public + */ + +Socket.prototype.onOpen = function () { + debug('socket open'); + this.readyState = 'open'; + this.emit('open'); + this.onopen && this.onopen.call(this); + this.flush(); + + // we check for `readyState` in case an `open` + // listener alreay closed the socket + if ('open' == this.readyState && this.upgrade && this.transport.pause) { + debug('starting upgrade probes'); + for (var i = 0, l = this.upgrades.length; i < l; i++) { + this.probe(this.upgrades[i]); + } + } +}; + +/** + * Handles a packet. + * + * @api private + */ + +Socket.prototype.onPacket = function (packet) { + if ('opening' == this.readyState || 'open' == this.readyState) { + debug('socket receive: type "%s", data "%s"', packet.type, packet.data); + + this.emit('packet', packet); + + // Socket is live - any packet counts + this.emit('heartbeat'); + + switch (packet.type) { + case 'open': + this.onHandshake(util.parseJSON(packet.data)); + break; + + case 'pong': + this.ping(); + break; + + case 'error': + var err = new Error('server error'); + err.code = packet.data; + this.emit('error', err); + break; + + case 'message': + this.emit('message', packet.data); + var event = { data: packet.data }; + event.toString = function () { + return packet.data; + }; + this.onmessage && this.onmessage.call(this, event); + break; + } + } else { + debug('packet received with socket readyState "%s"', this.readyState); + } +}; + +/** + * Called upon handshake completion. + * + * @param {Object} handshake obj + * @api private + */ + +Socket.prototype.onHandshake = function (data) { + this.emit('handshake', data); + this.id = data.sid; + this.transport.query.sid = data.sid; + this.upgrades = data.upgrades; + this.pingInterval = data.pingInterval; + this.pingTimeout = data.pingTimeout; + this.onOpen(); + this.ping(); + + // Prolong liveness of socket on heartbeat + this.removeListener('heartbeat', this.onHeartbeat); + this.on('heartbeat', this.onHeartbeat); +}; + +/** + * Resets ping timeout. + * + * @api private + */ + +Socket.prototype.onHeartbeat = function (timeout) { + clearTimeout(this.pingTimeoutTimer); + var self = this; + self.pingTimeoutTimer = setTimeout(function () { + if ('closed' == self.readyState) return; + self.onClose('ping timeout'); + }, timeout || (self.pingInterval + self.pingTimeout)); +}; + +/** + * Pings server every `this.pingInterval` and expects response + * within `this.pingTimeout` or closes connection. + * + * @api private + */ + +Socket.prototype.ping = function () { + var self = this; + clearTimeout(self.pingIntervalTimer); + self.pingIntervalTimer = setTimeout(function () { + debug('writing ping packet - expecting pong within %sms', self.pingTimeout); + self.sendPacket('ping'); + self.onHeartbeat(self.pingTimeout); + }, self.pingInterval); +}; + +/** + * Flush write buffers. + * + * @api private + */ + +Socket.prototype.flush = function () { + if ('closed' != this.readyState && this.transport.writable && + !this.upgrading && this.writeBuffer.length) { + debug('flushing %d packets in socket', this.writeBuffer.length); + this.transport.send(this.writeBuffer); + this.writeBuffer = []; + } +}; + +/** + * Sends a message. + * + * @param {String} message. + * @return {Socket} for chaining. + * @api public + */ + +Socket.prototype.write = +Socket.prototype.send = function (msg) { + this.sendPacket('message', msg); + return this; +}; + +/** + * Sends a packet. + * + * @param {String} packet type. + * @param {String} data. + * @api private + */ + +Socket.prototype.sendPacket = function (type, data) { + var packet = { type: type, data: data }; + this.emit('packetCreate', packet); + this.writeBuffer.push(packet); + this.flush(); +}; + +/** + * Closes the connection. + * + * @api private + */ + +Socket.prototype.close = function () { + if ('opening' == this.readyState || 'open' == this.readyState) { + this.onClose('forced close'); + debug('socket closing - telling transport to close'); + this.transport.close(); + this.transport.removeAllListeners(); + } + + return this; +}; + +/** + * Called upon transport error + * + * @api private + */ + +Socket.prototype.onError = function (err) { + this.emit('error', err); + this.onClose('transport error', err); +}; + +/** + * Called upon transport close. + * + * @api private + */ + +Socket.prototype.onClose = function (reason, desc) { + if ('closed' != this.readyState) { + debug('socket close with reason: "%s"', reason); + clearTimeout(this.pingIntervalTimer); + clearTimeout(this.pingTimeoutTimer); + this.readyState = 'closed'; + this.emit('close', reason, desc); + this.onclose && this.onclose.call(this); + this.id = null; + } +}; + +/** + * Generates a random uid. + * + * @api private + */ + +function rnd () { + return String(Math.random()).substr(5) + String(Math.random()).substr(5); +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js new file mode 100644 index 0000000..5760f84 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transport.js @@ -0,0 +1,141 @@ + +/** + * Module dependencies. + */ + +var util = require('./util') + , parser = require('./parser') + , Emitter = require('./emitter'); + +/** + * Module exports. + */ + +module.exports = Transport; + +/** + * Transport abstract constructor. + * + * @param {Object} options. + * @api private + */ + +function Transport (opts) { + this.path = opts.path; + this.host = opts.host; + this.port = opts.port; + this.secure = opts.secure; + this.query = opts.query; + this.timestampParam = opts.timestampParam; + this.timestampRequests = opts.timestampRequests; + this.readyState = ''; +}; + +/** + * Mix in `Emitter`. + */ + +Emitter(Transport.prototype); + +/** + * Emits an error. + * + * @param {String} str + * @return {Transport} for chaining + * @api public + */ + +Transport.prototype.onError = function (msg, desc) { + var err = new Error(msg); + err.type = 'TransportError'; + err.description = desc; + this.emit('error', err); + return this; +}; + +/** + * Opens the transport. + * + * @api public + */ + +Transport.prototype.open = function () { + if ('closed' == this.readyState || '' == this.readyState) { + this.readyState = 'opening'; + this.doOpen(); + } + + return this; +}; + +/** + * Closes the transport. + * + * @api private + */ + +Transport.prototype.close = function () { + if ('opening' == this.readyState || 'open' == this.readyState) { + this.doClose(); + this.onClose(); + } + + return this; +}; + +/** + * Sends multiple packets. + * + * @param {Array} packets + * @api private + */ + +Transport.prototype.send = function(packets){ + if ('open' == this.readyState) { + this.write(packets); + } else { + throw new Error('Transport not open'); + } +}; + +/** + * Called upon open + * + * @api private + */ + +Transport.prototype.onOpen = function () { + this.readyState = 'open'; + this.writable = true; + this.emit('open'); +}; + +/** + * Called with data. + * + * @param {String} data + * @api private + */ + +Transport.prototype.onData = function (data) { + this.onPacket(parser.decodePacket(data)); +}; + +/** + * Called with a decoded packet. + */ + +Transport.prototype.onPacket = function (packet) { + this.emit('packet', packet); +}; + +/** + * Called upon close. + * + * @api private + */ + +Transport.prototype.onClose = function () { + this.readyState = 'closed'; + this.emit('close'); +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js new file mode 100644 index 0000000..9a5a108 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/flashsocket.js @@ -0,0 +1,254 @@ + +/** + * Module dependencies. + */ + +var WS = require('./websocket') + , util = require('../util') + , debug = require('debug')('engine.io-client:flashsocket'); + +/** + * Module exports. + */ + +module.exports = FlashWS; + +/** + * Obfuscated key for Blue Coat. + */ + +var xobject = global[['Active'].concat('Object').join('X')]; + +/** + * FlashWS constructor. + * + * @api public + */ + +function FlashWS (options) { + WS.call(this, options); + this.flashPath = options.flashPath; + this.policyPort = options.policyPort; +}; + +/** + * Inherits from WebSocket. + */ + +util.inherits(FlashWS, WS); + +/** + * Transport name. + * + * @api public + */ + +FlashWS.prototype.name = 'flashsocket'; + +/** + * Opens the transport. + * + * @api public + */ + +FlashWS.prototype.doOpen = function () { + if (!this.check()) { + // let the probe timeout + return; + } + + // instrument websocketjs logging + function log (type) { + return function(){ + var str = Array.prototype.join.call(arguments, ' '); + debug('[websocketjs %s] %s', type, str); + }; + }; + + WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') }; + WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true; + WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true; + + if ('undefined' == typeof WEB_SOCKET_SWF_LOCATION) { + WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf'; + } + + // dependencies + var deps = [this.flashPath + 'web_socket.js']; + + if ('undefined' == typeof swfobject) { + deps.unshift(this.flashPath + 'swfobject.js'); + } + + var self = this; + + load(deps, function () { + self.ready(function () { + WebSocket.__addTask(function () { + WS.prototype.doOpen.call(self); + }); + }); + }); +}; + +/** + * Override to prevent closing uninitialized flashsocket. + * + * @api private + */ + +FlashWS.prototype.doClose = function () { + if (!this.socket) return; + var self = this; + WebSocket.__addTask(function() { + WS.prototype.doClose.call(self); + }); +}; + +/** + * Writes to the Flash socket. + * + * @api private + */ + +FlashWS.prototype.write = function() { + var self = this, args = arguments; + WebSocket.__addTask(function () { + WS.prototype.write.apply(self, args); + }); +}; + +/** + * Called upon dependencies are loaded. + * + * @api private + */ + +FlashWS.prototype.ready = function (fn) { + if (typeof WebSocket == 'undefined' || + !('__initialize' in WebSocket) || !swfobject) { + return; + } + + if (swfobject.getFlashPlayerVersion().major < 10) { + return; + } + + function init () { + // Only start downloading the swf file when the checked that this browser + // actually supports it + if (!FlashWS.loaded) { + if (843 != self.policyPort) { + WebSocket.loadFlashPolicyFile('xmlsocket://' + self.host + ':' + self.policyPort); + } + + WebSocket.__initialize(); + FlashWS.loaded = true; + } + + fn.call(self); + } + + var self = this; + if (document.body) { + return init(); + } + + util.load(init); +}; + +/** + * Feature detection for flashsocket. + * + * @return {Boolean} whether this transport is available. + * @api public + */ + +FlashWS.prototype.check = function () { + if ('undefined' != typeof process) { + return false; + } + + if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) { + return false; + } + + if (xobject) { + var control = null; + try { + control = new xobject('ShockwaveFlash.ShockwaveFlash'); + } catch (e) { } + if (control) { + return true; + } + } else { + for (var i = 0, l = navigator.plugins.length; i < l; i++) { + for (var j = 0, m = navigator.plugins[i].length; j < m; j++) { + if (navigator.plugins[i][j].description == 'Shockwave Flash') { + return true; + } + } + } + } + + return false; +}; + +/** + * Lazy loading of scripts. + * Based on $script by Dustin Diaz - MIT + */ + +var scripts = {}; + +/** + * Injects a script. Keeps tracked of injected ones. + * + * @param {String} path + * @param {Function} callback + * @api private + */ + +function create (path, fn) { + if (scripts[path]) return fn(); + + var el = document.createElement('script'); + var loaded = false; + + debug('loading "%s"', path); + el.onload = el.onreadystatechange = function () { + if (loaded || scripts[path]) return; + var rs = el.readyState; + if (!rs || 'loaded' == rs || 'complete' == rs) { + debug('loaded "%s"', path); + el.onload = el.onreadystatechange = null; + loaded = true; + scripts[path] = true; + fn(); + } + }; + + el.async = 1; + el.src = path; + + var head = document.getElementsByTagName('head')[0]; + head.insertBefore(el, head.firstChild); +}; + +/** + * Loads scripts and fires a callback. + * + * @param {Array} paths + * @param {Function} callback + */ + +function load (arr, fn) { + function process (i) { + if (!arr[i]) return fn(); + create(arr[i], function () { + process(++i); + }); + }; + + process(0); +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js new file mode 100644 index 0000000..374620b --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/index.js @@ -0,0 +1,62 @@ + +/** + * Module dependencies + */ + +var XHR = require('./polling-xhr') + , JSONP = require('./polling-jsonp') + , websocket = require('./websocket') + , flashsocket = require('./flashsocket') + , util = require('../util'); + +/** + * Export transports. + */ + +exports.polling = polling; +exports.websocket = websocket; +exports.flashsocket = flashsocket; + +/** + * Global reference. + */ + +var global = 'undefined' != typeof window ? window : global; + +/** + * Polling transport polymorphic constructor. + * Decides on xhr vs jsonp based on feature detection. + * + * @api private + */ + +function polling (opts) { + var xhr + , xd = false + , isXProtocol = false; + + if (global.location) { + var isSSL = 'https:' == location.protocol; + var port = location.port; + + // some user agents have empty `location.port` + if (Number(port) != port) { + port = isSSL ? 443 : 80; + } + + xd = opts.host != location.hostname || port != opts.port; + isXProtocol = opts.secure != isSSL; + } + + xhr = util.request(xd); + /* See #7 at http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx */ + if (isXProtocol && global.XDomainRequest && xhr instanceof global.XDomainRequest) { + return new JSONP(opts); + } + + if (xhr && !opts.forceJSONP) { + return new XHR(opts); + } else { + return new JSONP(opts); + } +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js new file mode 100644 index 0000000..fde3e79 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/components/learnboost-engine.io-client/lib/transports/polling-jsonp.js @@ -0,0 +1,221 @@ + +/** + * Module requirements. + */ + +var Polling = require('./polling') + , util = require('../util'); + +/** + * Module exports. + */ + +module.exports = JSONPPolling; + +/** + * Global reference. + */ + +var global = 'undefined' != typeof window ? window : global; + +/** + * Cached regular expressions. + */ + +var rNewline = /\n/g; + +/** + * Global JSONP callbacks. + */ + +var callbacks; + +/** + * Callbacks count. + */ + +var index = 0; + +/** + * Noop. + */ + +function empty () { } + +/** + * JSONP Polling constructor. + * + * @param {Object} opts. + * @api public + */ + +function JSONPPolling (opts) { + Polling.call(this, opts); + + // define global callbacks array if not present + // we do this here (lazily) to avoid unneeded global pollution + if (!callbacks) { + // we need to consider multiple engines in the same page + if (!global.___eio) global.___eio = []; + callbacks = global.___eio; + } + + // callback identifier + this.index = callbacks.length; + + // add callback to jsonp global + var self = this; + callbacks.push(function (msg) { + self.onData(msg); + }); + + // append to query string + this.query.j = this.index; +}; + +/** + * Inherits from Polling. + */ + +util.inherits(JSONPPolling, Polling); + +/** + * Opens the socket. + * + * @api private + */ + +JSONPPolling.prototype.doOpen = function () { + var self = this; + util.defer(function () { + Polling.prototype.doOpen.call(self); + }); +}; + +/** + * Closes the socket + * + * @api private + */ + +JSONPPolling.prototype.doClose = function () { + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + if (this.form) { + this.form.parentNode.removeChild(this.form); + this.form = null; + } + + Polling.prototype.doClose.call(this); +}; + +/** + * Starts a poll cycle. + * + * @api private + */ + +JSONPPolling.prototype.doPoll = function () { + var script = document.createElement('script'); + + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + script.async = true; + script.src = this.uri(); + + var insertAt = document.getElementsByTagName('script')[0]; + insertAt.parentNode.insertBefore(script, insertAt); + this.script = script; + + if (util.ua.gecko) { + setTimeout(function () { + var iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + document.body.removeChild(iframe); + }, 100); + } +}; + +/** + * Writes with a hidden iframe. + * + * @param {String} data to send + * @param {Function} called upon flush. + * @api private + */ + +JSONPPolling.prototype.doWrite = function (data, fn) { + var self = this; + + if (!this.form) { + var form = document.createElement('form') + , area = document.createElement('textarea') + , id = this.iframeId = 'eio_iframe_' + this.index + , iframe; + + form.className = 'socketio'; + form.style.position = 'absolute'; + form.style.top = '-1000px'; + form.style.left = '-1000px'; + form.target = id; + form.method = 'POST'; + form.setAttribute('accept-charset', 'utf-8'); + area.name = 'd'; + form.appendChild(area); + document.body.appendChild(form); + + this.form = form; + this.area = area; + } + + this.form.action = this.uri(); + + function complete () { + initIframe(); + fn(); + }; + + function initIframe () { + if (self.iframe) { + self.form.removeChild(self.iframe); + } + + try { + // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) + iframe = document.createElement(''; +html += '
    '; +html += '
    '; +html += '
    Upload File
    '; +html += '
    Want to upload multiple files at once? Please upgrade to the latest Flash Player, then reload this page. For some reason our Flash based uploader did not load, so you are currently using our single file uploader.
    '; +html += spacer(1,20) + '
    '; +var url = zero_client.targetURL; +if (url.indexOf('?') > -1) url += '&'; else url += '?'; +url += 'format=jshtml&onafter=' + escape('window.parent.upload_basic_finish(response);'); +Debug.trace('upload', "Prepping basic upload: " + url); +html += '
    '; +html += '
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('page_white_get.png', 'Upload', "upload_basic_go()") + '
    '; +html += '
    '; +html += ''; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +show_popup_dialog(528, 200, html); +} +function upload_basic_go() { +$('f_upload_basic').submit(); +$('d_upload_form').hide(); +$('d_upload_progress').show(); +} +function upload_basic_finish(response) { +Debug.trace('upload', "Basic upload complete: " + dumper(response)); +setTimeout( 'upload_basic_finish_2()', 100 ); +} +function upload_basic_finish_2() { +$('i_upload_basic').src = 'blank.html'; +setTimeout( 'upload_basic_finish_3()', 100 ); +} +function upload_basic_finish_3() { +hide_popup_dialog(); +delete session.progress; +show_progress_dialog( 0, 'Finishing Upload...', true ); +fire_callback( session.upload_callback ); +} +function upload_destroy() { +if (zero_client) { +zero_client.destroy(); +delete ZeroUpload.clients[ zero_client.id ]; +zero_client = null; +} +} +function prep_upload(dom_id, url, callback, types) { +session.upload_callback = callback; +if (url) { +if (url.indexOf('?') > -1) url += '&'; else url += '?'; +url += 'session=' + session.cookie.get('effect_session_id'); +} +upload_destroy(); +zero_client = new ZeroUpload.Client(); +if (url) zero_client.setURL( url ); +zero_client.setHandCursor( true ); +if (types) zero_client.setFileTypes( types[0], types[1] ); +zero_client.addEventListener( 'queueStart', uploadQueueStart ); +zero_client.addEventListener( 'fileStart', uploadFileStart ); +zero_client.addEventListener( 'progress', uploadProgress ); +zero_client.addEventListener( 'fileComplete', uploadFileComplete ); +zero_client.addEventListener( 'queueComplete', uploadQueueComplete ); +zero_client.addEventListener( 'error', uploadError ); +zero_client.addEventListener( 'debug', function(client, eventName, args) { +Debug.trace('upload', "Caught event: " + eventName); +} ); +if (dom_id) { +Debug.trace('upload', "Gluing ZeroUpload to: " + dom_id); +zero_client.glue( dom_id ); +} +} +Class.create( 'Debug', { +__static: { +enabled: false, +categories: { all: 1 }, +buffer: [], +max_rows: 5000, +win: null, +ie: !!navigator.userAgent.match(/MSIE/), +ie6: !!navigator.userAgent.match(/MSIE\D+6/), +init: function() { +Debug.enabled = true; +Debug.trace( 'debug', 'Debug log start' ); +var html = '

    '; +if (Debug.ie) { +setTimeout( function() { +document.body.insertAdjacentHTML('beforeEnd', +'
    ' + html + '
    ' +); +}, 1000 ); +} +else { +var div = document.createElement('DIV'); +div.id = 'd_debug'; +div.setAttribute('id', 'd_debug'); +div.style.position = Debug.ie6 ? 'absolute' : 'fixed'; +div.style.zIndex = '101'; +div.style.left = '0px'; +div.style.top = '0px'; +div.style.width = '100%'; +div.innerHTML = html; +document.getElementsByTagName('body')[0].appendChild(div); +} +}, +show: function() { +if (!Debug.win || Debug.win.closed) { +Debug.trace('debug', "Opening debug window"); +Debug.win = window.open( '', 'DebugWindow', 'width=600,height=500,menubar=no,resizable=yes,scrollbars=yes,location=no,status=no,toolbar=no,directories=no' ); +if (!Debug.win) return alert("Failed to open window. Popup blocker maybe?"); +var doc = Debug.win.document; +doc.open(); +doc.writeln( 'Debug Log' ); +doc.writeln( '
    ' ); +doc.writeln( '
    ' ); +doc.writeln( '
    ' ); +doc.writeln( '' ); +doc.writeln( '' ); +doc.writeln( '
    ' ); +doc.writeln( '' ); +doc.close(); +} +Debug.win.focus(); +}, +console_execute: function() { +var cmd = Debug.win.document.getElementById('fe_command'); +if (cmd.value.length) { +Debug.trace( 'console', cmd.value ); +try { +Debug.trace( 'console', '' + eval(cmd.value) ); +} +catch (e) { +Debug.trace( 'error', 'JavaScript Interpreter Exception: ' + e.toString() ); +} +} +}, +get_time_stamp: function(now) { +var date = new Date( now * 1000 ); +var hh = date.getHours(); if (hh < 10) hh = "0" + hh; +var mi = date.getMinutes(); if (mi < 10) mi = "0" + mi; +var ss = date.getSeconds(); if (ss < 10) ss = "0" + ss; +var sss = '' + date.getMilliseconds(); while (sss.length < 3) sss = "0" + sss; +return '' + hh + ':' + mi + ':' + ss + '.' + sss; +}, +refresh_console: function() { +if (!Debug.win || Debug.win.closed) return; +var div = Debug.win.document.getElementById('d_debug_log'); +if (div) { +var row = null; +while ( row = Debug.buffer.shift() ) { +var time_stamp = Debug.get_time_stamp(row.time); +var msg = row.msg; +msg = msg.replace(/\t/g, "    "); +msg = msg.replace(//g, ">"); +msg = msg.replace(/\n/g, "
    \n"); +var html = ''; +var sty = 'float:left; font-family: Consolas, Courier, mono; font-size: 12px; cursor:default; margin-right:10px; margin-bottom:1px; padding:2px;'; +html += '
    ' + time_stamp + '
    '; +html += '
    ' + row.cat + '
    '; +html += '
    ' + msg + '
    '; +html += '
    '; +var chunk = Debug.win.document.createElement('DIV'); +chunk.style['float'] = 'none'; +chunk.innerHTML = html; +div.appendChild(chunk); +} +var cmd = Debug.win.document.getElementById('fe_command'); +cmd.focus(); +} +Debug.dirty = 0; +Debug.win.scrollTo(0, 99999); +}, +hires_time_now: function() { +var now = new Date(); +return ( now.getTime() / 1000 ); +}, +trace: function(cat, msg) { +if (arguments.length == 1) { +msg = cat; +cat = 'debug'; +} +if (Debug.categories.all || Debug.categories[cat]) { +Debug.buffer.push({ cat: cat, msg: msg, time: Debug.hires_time_now() }); +if (Debug.buffer.length > Debug.max_rows) Debug.buffer.shift(); +if (!Debug.dirty) { +Debug.dirty = 1; +setTimeout( 'Debug.refresh_console();', 1 ); +} +} +} +} +} ); +var session = { +inited: false, +api_mod_cache: {}, +query: parseQueryString( ''+location.search ), +cookie: new CookieTree({ path: '/effect/' }), +storage: {}, +storage_dirty: false, +hooks: { +keys: {} +}, +username: '', +em_width: 11, +audioResourceMatch: /\.mp3$/i, +imageResourceMatch: /\.(jpe|jpeg|jpg|png|gif)$/i, +textResourceMatch: /\.xml$/i, +movieResourceMatch: /\.(flv|mp4|mp4v|mov|3gp|3g2)$/i, +imageResourceMatchString: '\.(jpe|jpeg|jpg|png|gif)$' +}; +session.debug = session.query.debug ? true : false; +var page_manager = null; +var preload_icons = []; +var preload_images = [ +'loading.gif', +'aquaprogressbar.gif', +'aquaprogressbar_bkgnd.gif' +]; +function get_base_url() { +return protocol + '://' + location.hostname + session.config.BaseURI; +} +function effect_init() { +if (session.inited) return; +session.inited = true; +assert( window.config, "Config not loaded" ); +session.config = window.config; +Debug.trace("Starting up"); +rendering_page = false; +preload(); +window.$R = {}; +for (var key in config.RegExpShortcuts) { +$R[key] = new RegExp( config.RegExpShortcuts[key] ); +} +ww_precalc_font("body", "effect_precalc_font_finish"); +page_manager = new Effect.PageManager( config.Pages.Page ); +var session_id = session.cookie.get('effect_session_id'); +if (session_id && session_id.match(/^login/)) { +do_session_recover(); +} +else { +show_default_login_status(); +Nav.init(); +} +Blog.search({ +stag: 'sidebar_docs', +limit: 20, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_documents', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +Blog.search({ +stag: 'sidebar_tutorials', +limit: 5, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_tutorials', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +Blog.search({ +stag: 'sidebar_plugins', +limit: 5, +title_only: true, +sort_by: 'seq', +sort_dir: -1, +target: 'd_sidebar_plugins', +outer_div_class: 'sidebar_blog_row', +title_class: 'sidebar_blog_title', +after: '' +}); +$('fe_search_bar').onkeydown = delay_onChange_input_text; +user_storage_idle(); +} +function effect_precalc_font_finish(width, height) { +session.em_width = width; +} +function preload() { +for (var idx = 0, len = preload_icons.length; idx < len; idx++) { +var url = images_uri + '/icons/' + preload_icons[idx] + '.gif'; +preload_icons[idx] = new Image(); +preload_icons[idx].src = url; +} +for (var idx = 0, len = preload_images.length; idx < len; idx++) { +var url = images_uri + '/' + preload_images[idx]; +preload_images[idx] = new Image(); +preload_images[idx].src = url; +} +} +function $P(id) { +if (!id) id = page_manager.current_page_id; +var page = page_manager.find(id); +assert( !!page, "Failed to locate page: " + id ); +return page; +} +function get_pref(name) { +if (!session.user || !session.user.Preferences) return alert("ASSERT FAILURE! Tried to lookup pref " + name + " and user is not yet loaded!"); +return session.user.Preferences[name]; +} +function get_bool_pref(name) { +return (get_pref(name) == 1); +} +function set_pref(name, value) { +session.user.Preferences[name] = value; +} +function set_bool_pref(name, value) { +set_pref(name, value ? '1' : '0'); +} +function save_prefs() { +var prefs_to_save = {}; +if (arguments.length) { +for (var idx = 0, len = arguments.length; idx < len; idx++) { +var key = arguments[idx]; +prefs_to_save[key] = get_pref(key); +} +} +else prefs_to_save = session.user.Preferences; +effect_api_mod_touch('user_get'); +effect_api_send('user_update', { +Username: session.username, +Preferences: prefs_to_save +}, 'save_prefs_2'); +} +function save_prefs_2(response) { +do_message('success', 'Preferences saved.'); +} + +function get_full_name(username) { +var user = session.users[username]; +if (!user) return username; +return user.FullName; +} +function get_buddy_icon_url(username, size) { +var mod = session.api_mod_cache.get_buddy_icon || 0; +if (!size) size = 32; +var url = '/effect/api/get_buddy_icon?username='+username + '&mod=' + mod + '&size=' + size; +return url; +} +function get_buddy_icon_display(username, show_icon, show_name) { +if ((typeof(show_icon) == 'undefined') && get_bool_pref('show_user_icons')) show_icon = 1; +if ((typeof(show_name) == 'undefined') && get_bool_pref('show_user_names')) show_name = 1; +var html = ''; +if (show_icon) html += ''; +if (show_icon && show_name) html += '
    '; +if (show_name) html += username; +return html; +} +function do_session_recover() { +session.hooks.after_error = 'do_logout'; +effect_api_send('session_recover', {}, 'do_login_2', { _from_recover: 1 } ); +} +function require_login() { +if (session.user) return true; +Debug.trace('Page requires login, showing login page'); +session.nav_after_login = Nav.currentAnchor(); +setTimeout( function() { +Nav.go( 'Login' ); +}, 1 ); +return false; +} +function popup_window(url, name) { +if (!url) url = ''; +if (!name) name = ''; +var win = window.open(url, name); +if (!win) return alert('Failed to open popup window. If you have a popup blocker, please disable it for this website and try again.'); +return win; +} +function do_login_prompt() { +hide_popup_dialog(); +delete session.progress; +if (!session.temp_password) session.temp_password = ''; +if (!session.username) session.username = ''; +var temp_username = session.open_id || session.username || ''; +var html = ''; +html += '
    '; +html += '
    '; +html += '
    Effect Developer Login
    '; +html += '
    '; +html += '
    Effect Username  or  '+icon('openid', 'OpenID', 'popup_window(\'http://openid.net/\')', 'What is OpenID?')+'


    '; +html += '
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "clear_login()") + ' ' + large_icon_button('check', 'Login', 'do_login()') + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_login'; +session.hooks.keys[ESC_KEY] = 'clear_login'; +safe_focus( 'fe_username' ); +show_popup_dialog(450, 225, html); +} +function do_openid_reg(title, auto_login_button) { +hide_popup_dialog(); +delete session.progress; +if (!title) title = 'Register Account Using OpenID'; +if (typeof(auto_login_button) == 'undefined') auto_login_button = 1; +var html = ''; +html += '
    '; +html += '
    '; +html += '
    '+title+'
    '; +html += '
    '; +html += '
    '+icon('openid', 'Enter Your OpenID URL:')+'
    '; +if (auto_login_button) html += '


    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', title.match(/login/i) ? 'Login' : 'Register', 'do_openid_login()') + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_openid_login'; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_username' ); +show_popup_dialog(450, 225, html); +} +function do_login_prompt_2() { +hide_popup_dialog(); +delete session.progress; +if (!session.temp_password) session.temp_password = ''; +if (!session.username) session.username = ''; +var html = ''; +html += '
    '; +html += '"; + second_cell = ""; + row = $("").attr("id", "s" + index).attr("class", "location_row").html(first_cell + second_cell); + $locationsDiv.append(row); + } + if (index === this.numSearchToDisplay) { + $locationsDiv.append(""); + return $locationsDiv.append(""); + } + }, this); + return this.geocoder.geocode({ + address: address + }, __bind(function(result, status) { + if (status !== "OK") { + $('.error_message').html(t("Search Address Failed")).fadeIn(); + return; + } + _.each(result, showResults); + $("#search_results").html($locationsDiv); + this.locationChange("search"); + this.searchResults = result; + return this.displaySearchLoc(); + }, this)); + }; + ClientsRequestView.prototype.mouseoverLocation = function(e) { + var $el, id, marker; + $el = $(e.currentTarget); + id = $el.attr("id").substring(1); + marker = this.markers[id]; + return marker.setAnimation(google.maps.Animation.BOUNCE); + }; + ClientsRequestView.prototype.mouseoutLocation = function(e) { + var $el, id, marker; + $el = $(e.currentTarget); + id = $el.attr("id").substring(1); + marker = this.markers[id]; + return marker.setAnimation(null); + }; + ClientsRequestView.prototype.searchLocation = function(e) { + e.preventDefault(); + $("#address").val($(e.currentTarget).html()); + return this.searchAddress(); + }; + ClientsRequestView.prototype.favoriteClick = function(e) { + var index, location; + e.preventDefault(); + $(".favorites").attr("href", ""); + index = $(e.currentTarget).removeAttr("href").attr("id"); + location = new google.maps.LatLng(USER.locations[index].latitude, USER.locations[index].longitude); + return this.panToLocation(location); + }; + ClientsRequestView.prototype.clickLocation = function(e) { + var id; + id = $(e.currentTarget).attr("id").substring(1); + return this.panToLocation(this.markers[id].getPosition()); + }; + ClientsRequestView.prototype.panToLocation = function(location) { + this.map.panTo(location); + this.map.setZoom(16); + return this.pickup_icon.setPosition(location); + }; + ClientsRequestView.prototype.locationLinkHandle = function(e) { + var panelName; + e.preventDefault(); + panelName = $(e.currentTarget).attr("id"); + return this.locationChange(panelName); + }; + ClientsRequestView.prototype.locationChange = function(type) { + $(".locations_link").attr("href", "").css("font-weight", "normal"); + switch (type) { + case "favorite": + $(".search_results").attr("href", ""); + $(".locations_link#favorite").removeAttr("href").css("font-weight", "bold"); + $("#search_results").hide(); + $("#favorite_results").fadeIn(); + return this.displayFavLoc(); + case "search": + $(".favorites").attr("href", ""); + $(".locations_link#search").removeAttr("href").css("font-weight", "bold"); + $("#favorite_results").hide(); + $("#search_results").fadeIn(); + return this.displaySearchLoc(); + } + }; + ClientsRequestView.prototype.rateTrip = function(e) { + var rating; + rating = $(e.currentTarget).attr("id"); + $(".stars").attr("src", "/web/img/star_inactive.png"); + return _(rating).times(function(index) { + return $(".stars#" + (index + 1)).attr("src", "/web/img/star_active.png"); + }); + }; + ClientsRequestView.prototype.pickupHandle = function(e) { + var $el, callback, message; + e.preventDefault(); + $el = $(e.currentTarget).find("span"); + switch ($el.html()) { + case t("Request Pickup"): + _.delay(this.requestRide, 3000); + $("#status_message").html(t("Sending pickup request...")); + $el.html(t("Cancel Pickup")).parent().attr("class", "button_red"); + this.pickup_icon.setDraggable(false); + this.map.panTo(this.pickup_icon.getPosition()); + return this.map.setZoom(18); + case t("Cancel Pickup"): + if (this.status === "ready") { + $el.html(t("Request Pickup")).parent().attr("class", "button_green"); + return this.pickup_icon.setDraggable(true); + } else { + callback = __bind(function(v, m, f) { + if (v) { + this.AskDispatch("PickupCanceledClient"); + return this.setStatus("ready"); + } + }, this); + message = t("Cancel Request Prompt"); + if (this.status === "arriving") { + message = 'Cancel Request Arrived Prompt'; + } + return $.prompt(message, { + buttons: { + Ok: true, + Cancel: false + }, + callback: callback + }); + } + } + }; + ClientsRequestView.prototype.requestRide = function() { + if ($("#pickupHandle").find("span").html() === t("Cancel Pickup")) { + this.AskDispatch("Pickup"); + return this.setStatus("searching"); + } + }; + ClientsRequestView.prototype.removeCabs = function() { + _.each(this.cabs, __bind(function(point) { + return point.setMap(null); + }, this)); + return this.cabs = []; + }; + ClientsRequestView.prototype.addToFavLoc = function(e) { + var $el, lat, lng, nickname; + e.preventDefault(); + $el = $(e.currentTarget); + $el.find(".error_message").html(""); + nickname = $el.find("#favLocNickname").val().toString(); + lat = $el.find("#pickupLat").val().toString(); + lng = $el.find("#pickupLng").val().toString(); + if (nickname.length < 3) { + $el.find(".error_message").html(t("Favorite Location Nickname Length Error")); + return; + } + this.ShowSpinner("submit"); + return $.ajax({ + type: 'POST', + url: API + "/locations", + dataType: 'json', + data: { + token: USER.token, + nickname: nickname, + latitude: lat, + longitude: lng + }, + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Favorite Location Save Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.find(".error_message").html(t("Favorite Location Save Failed")); + }, this), + complete: __bind(function(data) { + return this.HideSpinner(); + }, this) + }); + }; + ClientsRequestView.prototype.showFavLoc = function(e) { + $(e.currentTarget).fadeOut(); + return $("#favLoc_form").fadeIn(); + }; + ClientsRequestView.prototype.selectInputText = function(e) { + e.currentTarget.focus(); + return e.currentTarget.select(); + }; + ClientsRequestView.prototype.displayFavLoc = function() { + var alphabet, bounds; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + this.removeMarkers(); + bounds = new google.maps.LatLngBounds(); + _.each(USER.locations, __bind(function(location, index) { + var marker; + marker = new google.maps.Marker({ + position: new google.maps.LatLng(location.latitude, location.longitude), + map: this.map, + title: t("Favorite Location Title", { + id: alphabet != null ? alphabet[index] : void 0 + }), + icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png" + }); + this.markers.push(marker); + bounds.extend(marker.getPosition()); + return google.maps.event.addListener(marker, 'click', __bind(function() { + return this.pickup_icon.setPosition(marker.getPosition()); + }, this)); + }, this)); + this.pickup_icon.setPosition(_.first(this.markers).getPosition()); + return this.map.fitBounds(bounds); + }; + ClientsRequestView.prototype.displaySearchLoc = function() { + var alphabet; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + this.removeMarkers(); + return _.each(this.searchResults, __bind(function(result, index) { + var marker; + if (index < this.numSearchToDisplay) { + marker = new google.maps.Marker({ + position: result.geometry.location, + map: this.map, + title: t("Search Location Title", { + id: alphabet != null ? alphabet[index] : void 0 + }), + icon: "https://www.google.com/mapfiles/marker" + alphabet[index] + ".png" + }); + this.markers.push(marker); + return this.panToLocation(result.geometry.location); + } + }, this)); + }; + ClientsRequestView.prototype.removeMarkers = function() { + _.each(this.markers, __bind(function(marker) { + return marker.setMap(null); + }, this)); + return this.markers = []; + }; + ClientsRequestView.prototype.AskDispatch = function(ask, options) { + var attrs, lowestETA, processData, showCab; + if (ask == null) { + ask = ""; + } + if (options == null) { + options = {}; + } + switch (ask) { + case "NearestCab": + attrs = { + latitude: this.pickup_icon.getPosition().lat(), + longitude: this.pickup_icon.getPosition().lng() + }; + lowestETA = 99999; + showCab = __bind(function(cab) { + var point; + point = new google.maps.Marker({ + position: new google.maps.LatLng(cab.latitude, cab.longitude), + map: this.map, + icon: this.cabMarker, + title: t("ETA Message", { + minutes: app.helpers.FormatSeconds(cab != null ? cab.eta : void 0, true) + }) + }); + if (cab.eta < lowestETA) { + lowestETA = cab.eta; + } + return this.cabs.push(point); + }, this); + processData = __bind(function(data, textStatus, jqXHR) { + if (this.status === "ready") { + this.removeCabs(); + if (data.sorry) { + $("#status_message").html(data.sorry).fadeIn(); + } else { + _.each(data.driverLocations, showCab); + $("#status_message").html(t("Nearest Cab Message", { + minutes: app.helpers.FormatSeconds(lowestETA, true) + })).fadeIn(); + } + if (Backbone.history.fragment === "!/request") { + return _.delay(this.showCabs, this.pollInterval); + } + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "StatusClient": + processData = __bind(function(data, textStatus, jqXHR) { + var bounds, cabLocation, locationSaved, point, userLocation; + if (data.messageType === "OK") { + switch (data.status) { + case "completed": + this.removeCabs(); + this.setStatus("rate"); + return this.fetchTripDetails(data.tripID); + case "open": + return this.setStatus("ready"); + case "begintrip": + this.setStatus("riding"); + cabLocation = new google.maps.LatLng(data.latitude, data.longitude); + this.removeCabs(); + this.pickup_icon.setMap(null); + point = new google.maps.Marker({ + position: cabLocation, + map: this.map, + icon: this.cabMarker + }); + this.cabs.push(point); + this.map.panTo(point.getPosition()); + $("#rideName").html(data.driverName); + $("#ridePhone").html(data.driverMobile); + $("#ride_address_wrapper").hide(); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + break; + case "pending": + this.setStatus("searching"); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + break; + case "accepted": + case "arrived": + if (data.status === "accepted") { + this.setStatus("waiting"); + $("#status_message").html(t("Arrival ETA Message", { + minutes: app.helpers.FormatSeconds(data.eta, true) + })); + } else { + this.setStatus("arriving"); + $("#status_message").html(t("Arriving Now Message")); + } + userLocation = new google.maps.LatLng(data.pickupLocation.latitude, data.pickupLocation.longitude); + cabLocation = new google.maps.LatLng(data.latitude, data.longitude); + this.pickup_icon.setPosition(userLocation); + this.removeCabs(); + $("#rideName").html(data.driverName); + $("#ridePhone").html(data.driverMobile); + if ($("#rideAddress").html() === "") { + locationSaved = false; + _.each(USER.locations, __bind(function(location) { + if (parseFloat(location.latitude) === parseFloat(data.pickupLocation.latitude) && parseFloat(location.longitude) === parseFloat(data.pickupLocation.longitude)) { + return locationSaved = true; + } + }, this)); + if (locationSaved) { + $("#addToFavButton").hide(); + } + $("#pickupLat").val(data.pickupLocation.latitude); + $("#pickupLng").val(data.pickupLocation.longitude); + this.geocoder.geocode({ + location: userLocation + }, __bind(function(result, status) { + $("#rideAddress").html(result[0].formatted_address); + return $("#favLocNickname").val("" + result[0].address_components[0].short_name + " " + result[0].address_components[1].short_name); + }, this)); + } + point = new google.maps.Marker({ + position: cabLocation, + map: this.map, + icon: this.cabMarker + }); + this.cabs.push(point); + bounds = bounds = new google.maps.LatLngBounds(); + bounds.extend(cabLocation); + bounds.extend(userLocation); + this.map.fitBounds(bounds); + if (Backbone.history.fragment === "!/request") { + return _.delay(this.AskDispatch, this.pollInterval, "StatusClient"); + } + } + } + }, this); + return this.AjaxCall(ask, processData); + case "Pickup": + attrs = { + latitude: this.pickup_icon.getPosition().lat(), + longitude: this.pickup_icon.getPosition().lng() + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "Error") { + return $("#status_message").html(data.description); + } else { + return this.AskDispatch("StatusClient"); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "PickupCanceledClient": + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + return this.setStatus("ready"); + } else { + return $("#status_message").html(data.description); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + case "RatingDriver": + attrs = { + rating: options.rating + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + this.setStatus("init"); + } else { + $("status_message").html(t("Rating Driver Failed")); + } + return this.HideSpinner(); + }, this); + return this.AjaxCall(ask, processData, attrs); + case "Feedback": + attrs = { + message: options.message + }; + processData = __bind(function(data, textStatus, jqXHR) { + if (data.messageType === "OK") { + return alert("rated"); + } + }, this); + return this.AjaxCall(ask, processData, attrs); + } + }; + ClientsRequestView.prototype.AjaxCall = function(type, successCallback, attrs) { + if (attrs == null) { + attrs = {}; + } + _.extend(attrs, { + token: USER.token, + messageType: type, + app: "client", + version: "1.0.60", + device: "web" + }); + return $.ajax({ + type: 'POST', + url: DISPATCH + "/", + processData: false, + data: JSON.stringify(attrs), + success: successCallback, + dataType: 'json', + error: __bind(function(jqXHR, textStatus, errorThrown) { + $("#status_message").html(errorThrown); + return this.HideSpinner(); + }, this) + }); + }; + return ClientsRequestView; + })(); +}).call(this); +}, "views/clients/settings": function(exports, require, module) {(function() { + var clientsSettingsTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsSettingsTemplate = require('templates/clients/settings'); + exports.ClientsSettingsView = (function() { + __extends(ClientsSettingsView, UberView); + function ClientsSettingsView() { + this.render = __bind(this.render, this); + this.initialize = __bind(this.initialize, this); + ClientsSettingsView.__super__.constructor.apply(this, arguments); + } + ClientsSettingsView.prototype.id = 'settings_view'; + ClientsSettingsView.prototype.className = 'view_container'; + ClientsSettingsView.prototype.events = { + 'submit #profile_pic_form': 'processPicUpload', + 'click #submit_pic': 'processPicUpload', + 'click a.setting_change': "changeTab", + 'submit #edit_info_form': "submitInfo", + 'click #change_password': 'changePass' + }; + ClientsSettingsView.prototype.divs = { + 'info_div': "Information", + 'pic_div': "Picture" + }; + ClientsSettingsView.prototype.pageTitle = t("Settings") + " | " + t("Uber"); + ClientsSettingsView.prototype.tabTitle = { + 'info_div': t("Information"), + 'pic_div': t("Picture") + }; + ClientsSettingsView.prototype.initialize = function() { + return this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm); + }; + ClientsSettingsView.prototype.render = function(type) { + if (type == null) { + type = "info"; + } + this.RefreshUserInfo(__bind(function() { + var $el, alphabet; + this.delegateEvents(); + this.HideSpinner(); + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $el = $(this.el); + $(this.el).html(clientsSettingsTemplate({ + type: type + })); + $el.find("#" + type + "_div").show(); + $el.find("a[href='" + type + "_div']").parent().addClass("active"); + return document.title = "" + this.tabTitle[type + '_div'] + " " + this.pageTitle; + }, this)); + this.delegateEvents(); + return this; + }; + ClientsSettingsView.prototype.changeTab = function(e) { + var $eTarget, $el, div, link, pageDiv, _i, _j, _len, _len2, _ref, _ref2; + e.preventDefault(); + $eTarget = $(e.currentTarget); + this.ClearGlobalStatus(); + $el = $(this.el); + _ref = $el.find(".setting_change"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + $(link).parent().removeClass("active"); + } + $eTarget.parent().addClass("active"); + _ref2 = _.keys(this.divs); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + div = _ref2[_j]; + $el.find("#" + div).hide(); + } + pageDiv = $eTarget.attr('href'); + $el.find("#" + pageDiv).show(); + Backbone.history.navigate("!/settings/" + (this.divs[pageDiv].toLowerCase().replace(" ", "-")), false); + document.title = "" + this.tabTitle[pageDiv] + " " + this.pageTitle; + if (pageDiv === "loc_div") { + try { + google.maps.event.trigger(this.map, 'resize'); + return this.map.fitBounds(this.bounds); + } catch (_e) {} + } + }; + ClientsSettingsView.prototype.submitInfo = function(e) { + var $e, attrs, client, options; + $('#global_status').find('.success_message').text(''); + $('#global_status').find('.error_message').text(''); + $('.error_message').text(''); + e.preventDefault(); + $e = $(e.currentTarget); + attrs = $e.serializeToJson(); + attrs['mobile_country_id'] = this.$('#mobile_country_id').val(); + if (attrs['password'] === '') { + delete attrs['password']; + } + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Information Update Succeeded")); + return this.RefreshUserInfo(); + }, this), + error: __bind(function(model, data) { + var errors; + if (data.status === 406) { + errors = JSON.parse(data.responseText); + return _.each(_.keys(errors), function(field) { + return $("#" + field).parent().find('span.error_message').text(errors[field]); + }); + } else { + return this.ShowError(t("Information Update Failed")); + } + }, this), + type: "PUT" + }; + client = new app.models.client({ + id: USER.id + }); + return client.save(attrs, options); + }; + ClientsSettingsView.prototype.changePass = function(e) { + e.preventDefault(); + $(e.currentTarget).hide(); + return $("#password").show(); + }; + ClientsSettingsView.prototype.processPicUpload = function(e) { + e.preventDefault(); + this.ShowSpinner("submit"); + return $.ajaxFileUpload({ + url: API + '/user_pictures', + secureuri: false, + fileElementId: 'picture', + data: { + token: USER.token + }, + dataType: 'json', + complete: __bind(function(data, status) { + this.HideSpinner(); + if (status === 'success') { + this.ShowSuccess(t("Picture Update Succeeded")); + return this.RefreshUserInfo(__bind(function() { + return $("#settingsProfPic").attr("src", USER.picture_url + ("?" + (Math.floor(Math.random() * 1000)))); + }, this)); + } else { + if (data.error) { + return this.ShowError(data.error); + } else { + return this.ShowError("Picture Update Failed"); + } + } + }, this) + }); + }; + return ClientsSettingsView; + })(); +}).call(this); +}, "views/clients/sign_up": function(exports, require, module) {(function() { + var clientsSignUpTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsSignUpTemplate = require('templates/clients/sign_up'); + exports.ClientsSignUpView = (function() { + __extends(ClientsSignUpView, UberView); + function ClientsSignUpView() { + ClientsSignUpView.__super__.constructor.apply(this, arguments); + } + ClientsSignUpView.prototype.id = 'signup_view'; + ClientsSignUpView.prototype.className = 'view_container'; + ClientsSignUpView.prototype.initialize = function() { + this.mixin(require('web-lib/mixins/i18n_phone_form').i18nPhoneForm); + return $('#location_country').live('change', function() { + if (!$('#mobile').val()) { + return $('#mobile_country').find("option[value=" + ($(this).val()) + "]").attr('selected', 'selected').end().trigger('change'); + } + }); + }; + ClientsSignUpView.prototype.events = { + 'submit form': 'signup', + 'click button': 'signup', + 'change #card_number': 'showCardType', + 'change #location_country': 'countryChange' + }; + ClientsSignUpView.prototype.render = function(invite) { + this.HideSpinner(); + $(this.el).html(clientsSignUpTemplate({ + invite: invite + })); + return this; + }; + ClientsSignUpView.prototype.signup = function(e) { + var $el, attrs, client, error_messages, options; + e.preventDefault(); + $el = $("form"); + $el.find('#terms_error').hide(); + if (!$el.find('#signup_terms input[type=checkbox]').attr('checked')) { + $('#spinner.submit').hide(); + $el.find('#terms_error').show(); + return; + } + error_messages = $el.find('.error_message').html(""); + attrs = { + first_name: $el.find('#first_name').val(), + last_name: $el.find('#last_name').val(), + email: $el.find('#email').val(), + password: $el.find('#password').val(), + location_country: $el.find('#location_country option:selected').attr('data-iso2'), + location: $el.find('#location').val(), + language: $el.find('#language').val(), + mobile_country: $el.find('#mobile_country option:selected').attr('data-iso2'), + mobile: $el.find('#mobile').val(), + card_number: $el.find('#card_number').val(), + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + card_code: $el.find('#card_code').val(), + use_case: $el.find('#use_case').val(), + promotion_code: $el.find('#promotion_code').val() + }; + options = { + statusCode: { + 200: function(response) { + $.cookie('token', response.token); + amplify.store('USERjson', response); + app.refreshMenu(); + return app.routers.clients.navigate('!/dashboard', true); + }, + 406: function(e) { + var error, errors, _i, _len, _ref, _results; + errors = JSON.parse(e.responseText); + _ref = _.keys(errors); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + error = _ref[_i]; + _results.push($('#' + error).parent().find('span').html($('#' + error).parent().find('span').html() + " " + errors[error])); + } + return _results; + } + }, + complete: __bind(function(response) { + return this.HideSpinner(); + }, this) + }; + client = new app.models.client; + $('.spinner#submit').show(); + return client.save(attrs, options); + }; + ClientsSignUpView.prototype.countryChange = function(e) { + var $e; + $e = $(e.currentTarget); + return $("#mobile_country").val($e.val()).trigger('change'); + }; + ClientsSignUpView.prototype.showCardType = function(e) { + var $el, reAmerica, reDiscover, reMaster, reVisa, validCard; + reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/; + reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/; + reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/; + reDiscover = /^3[4,7]\d{13}$/; + $el = $("#card_logos_signup"); + validCard = false; + if (e.currentTarget.value.match(reVisa)) { + $el.find("#overlay_left").css('width', "0px"); + return $el.find("#overlay_right").css('width', "75%"); + } else if (e.currentTarget.value.match(reMaster)) { + $el.find("#overlay_left").css('width', "25%"); + return $el.find("#overlay_right").css('width', "50%"); + } else if (e.currentTarget.value.match(reAmerica)) { + $el.find("#overlay_left").css('width', "75%"); + $el.find("#overlay_right").css('width', "0px"); + return console.log("amex"); + } else if (e.currentTarget.value.match(reDiscover)) { + $el.find("#overlay_left").css('width', "50%"); + return $el.find("#overlay_right").css('width', "25%"); + } else { + $el.find("#overlay_left").css('width', "0px"); + return $el.find("#overlay_right").css('width', "0px"); + } + }; + return ClientsSignUpView; + })(); +}).call(this); +}, "views/clients/trip_detail": function(exports, require, module) {(function() { + var clientsTripDetailTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsTripDetailTemplate = require('templates/clients/trip_detail'); + exports.TripDetailView = (function() { + __extends(TripDetailView, UberView); + function TripDetailView() { + this.resendReceipt = __bind(this.resendReceipt, this); + TripDetailView.__super__.constructor.apply(this, arguments); + } + TripDetailView.prototype.id = 'trip_detail_view'; + TripDetailView.prototype.className = 'view_container'; + TripDetailView.prototype.events = { + 'click a#fare_review': 'showFareReview', + 'click #fare_review_hide': 'hideFareReview', + 'submit #form_review_form': 'submitFareReview', + 'click #submit_fare_review': 'submitFareReview', + 'click .resendReceipt': 'resendReceipt' + }; + TripDetailView.prototype.render = function(id) { + if (id == null) { + id = 'invalid'; + } + this.ReadUserInfo(); + this.HideSpinner(); + this.model = new app.models.trip({ + id: id + }); + this.model.fetch({ + data: { + relationships: 'points,driver,city.country' + }, + dataType: 'json', + success: __bind(function() { + var trip; + trip = this.model; + $(this.el).html(clientsTripDetailTemplate({ + trip: trip + })); + this.RequireMaps(__bind(function() { + var bounds, endPos, map, myOptions, path, polyline, startPos; + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(this.model.get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + myOptions = { + zoom: 12, + center: path[0], + mapTypeId: google.maps.MapTypeId.ROADMAP, + zoomControl: false, + rotateControl: false, + panControl: false, + mapTypeControl: false, + scrollwheel: false + }; + map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions); + map.fitBounds(bounds); + startPos = new google.maps.Marker({ + position: _.first(path), + map: map, + title: t("Trip started here"), + icon: 'https://uber-static.s3.amazonaws.com/marker_start.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: map, + title: t("Trip ended here"), + icon: 'https://uber-static.s3.amazonaws.com/marker_end.png' + }); + startPos.setMap(map); + endPos.setMap(map); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + return polyline.setMap(map); + }, this)); + return this.HideSpinner(); + }, this) + }); + this.ShowSpinner('load'); + this.delegateEvents(); + return this; + }; + TripDetailView.prototype.showFareReview = function(e) { + e.preventDefault(); + $('#fare_review_box').slideDown(); + return $('#fare_review').hide(); + }; + TripDetailView.prototype.hideFareReview = function(e) { + e.preventDefault(); + $('#fare_review_box').slideUp(); + return $('#fare_review').show(); + }; + TripDetailView.prototype.submitFareReview = function(e) { + var attrs, errorMessage, id, options; + e.preventDefault(); + errorMessage = $(".error_message"); + errorMessage.hide(); + id = $("#tripid").val(); + this.model = new app.models.trip({ + id: id + }); + attrs = { + note: $('#form_review_message').val(), + note_type: 'client_fare_review' + }; + options = { + success: __bind(function(response) { + $(".success_message").fadeIn(); + return $("#fare_review_form_wrapper").slideUp(); + }, this), + error: __bind(function(error) { + return errorMessage.fadeIn(); + }, this) + }; + return this.model.save(attrs, options); + }; + TripDetailView.prototype.resendReceipt = function(e) { + var $e; + e.preventDefault(); + $e = $(e.currentTarget); + this.$(".resendReceiptSuccess").empty().show(); + this.$(".resentReceiptError").empty().show(); + e.preventDefault(); + $('#spinner').show(); + return $.ajax('/api/trips/func/resend_receipt', { + data: { + token: $.cookie('token'), + trip_id: this.model.id + }, + type: 'POST', + complete: __bind(function(xhr) { + var response; + response = JSON.parse(xhr.responseText); + $('#spinner').hide(); + switch (xhr.status) { + case 200: + this.$(".resendReceiptSuccess").html("Receipt has been emailed"); + return this.$(".resendReceiptSuccess").fadeOut(2000); + default: + this.$(".resendReceiptError").html("Receipt has failed to be emailed"); + return this.$(".resendReceiptError").fadeOut(2000); + } + }, this) + }); + }; + return TripDetailView; + })(); +}).call(this); +}, "views/shared/menu": function(exports, require, module) {(function() { + var menuTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + menuTemplate = require('templates/shared/menu'); + exports.SharedMenuView = (function() { + __extends(SharedMenuView, Backbone.View); + function SharedMenuView() { + SharedMenuView.__super__.constructor.apply(this, arguments); + } + SharedMenuView.prototype.id = 'menu_view'; + SharedMenuView.prototype.render = function() { + var type; + if ($.cookie('token') === null) { + type = 'guest'; + } else { + type = 'client'; + } + $(this.el).html(menuTemplate({ + type: type + })); + return this; + }; + return SharedMenuView; + })(); +}).call(this); +}, "web-lib/collections/countries": function(exports, require, module) {(function() { + var UberCollection; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberCollection = require('web-lib/uber_collection').UberCollection; + exports.CountriesCollection = (function() { + __extends(CountriesCollection, UberCollection); + function CountriesCollection() { + CountriesCollection.__super__.constructor.apply(this, arguments); + } + CountriesCollection.prototype.model = app.models.country; + CountriesCollection.prototype.url = '/countries'; + return CountriesCollection; + })(); +}).call(this); +}, "web-lib/collections/vehicle_types": function(exports, require, module) {(function() { + var UberCollection, vehicleType, _ref; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberCollection = require('web-lib/uber_collection').UberCollection; + vehicleType = (typeof app !== "undefined" && app !== null ? (_ref = app.models) != null ? _ref.vehicleType : void 0 : void 0) || require('models/vehicle_type').VehicleType; + exports.VehicleTypesCollection = (function() { + __extends(VehicleTypesCollection, UberCollection); + function VehicleTypesCollection() { + VehicleTypesCollection.__super__.constructor.apply(this, arguments); + } + VehicleTypesCollection.prototype.model = vehicleType; + VehicleTypesCollection.prototype.url = '/vehicle_types'; + VehicleTypesCollection.prototype.defaultColumns = ['id', 'created_at', 'updated_at', 'deleted_at', 'created_by_user_id', 'updated_by_user_id', 'city_id', 'type', 'make', 'model', 'capacity', 'minimum_year', 'actions']; + VehicleTypesCollection.prototype.tableColumns = function(cols) { + var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, headerRow, id, make, minimum_year, model, type, updated_at, updated_by_user_id, _i, _len; + id = { + sTitle: 'Id' + }; + created_at = { + sTitle: 'Created At (UTC)', + 'sType': 'string' + }; + updated_at = { + sTitle: 'Updated At (UTC)', + 'sType': 'string' + }; + deleted_at = { + sTitle: 'Deleted At (UTC)', + 'sType': 'string' + }; + created_by_user_id = { + sTitle: 'Created By' + }; + updated_by_user_id = { + sTitle: 'Updated By' + }; + city_id = { + sTitle: 'City' + }; + type = { + sTitle: 'Type' + }; + make = { + sTitle: 'Make' + }; + model = { + sTitle: 'Model' + }; + capacity = { + sTitle: 'Capacity' + }; + minimum_year = { + sTitle: 'Min. Year' + }; + actions = { + sTitle: 'Actions' + }; + columnValues = { + id: id, + created_at: created_at, + updated_at: updated_at, + deleted_at: deleted_at, + created_by_user_id: created_by_user_id, + updated_by_user_id: updated_by_user_id, + city_id: city_id, + type: type, + make: make, + model: model, + capacity: capacity, + minimum_year: minimum_year, + actions: actions + }; + headerRow = []; + for (_i = 0, _len = cols.length; _i < _len; _i++) { + c = cols[_i]; + if (columnValues[c]) { + headerRow.push(columnValues[c]); + } + } + return headerRow; + }; + return VehicleTypesCollection; + })(); +}).call(this); +}, "web-lib/helpers": function(exports, require, module) {(function() { + var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + exports.helpers = { + pin: function(num, color) { + if (color == null) { + color = 'FF0000'; + } + return ""; + }, + reverseGeocode: function(latitude, longitude) { + if (latitude && longitude) { + return "" + latitude + ", " + longitude + ""; + } else { + return ''; + } + }, + linkedName: function(model) { + var first_name, id, last_name, role, url; + role = model.role || model.get('role'); + id = model.id || model.get('id'); + first_name = model.first_name || model.get('first_name'); + last_name = model.last_name || model.get('last_name'); + url = "/" + role + "s/" + id; + return "" + first_name + " " + last_name + ""; + }, + linkedVehicle: function(vehicle, vehicleType) { + return " " + (vehicleType != null ? vehicleType.get('make') : void 0) + " " + (vehicleType != null ? vehicleType.get('model') : void 0) + " " + (vehicle.get('year')) + " "; + }, + linkedUserId: function(userType, userId) { + return "" + userType + " " + userId + ""; + }, + timeDelta: function(start, end) { + var delta; + if (typeof start === 'string') { + start = this.parseDate(start); + } + if (typeof end === 'string') { + end = this.parseDate(end); + } + if (end && start) { + delta = end.getTime() - start.getTime(); + return this.formatSeconds(delta / 1000); + } else { + return '00:00'; + } + }, + formatSeconds: function(s) { + var minutes, seconds; + s = Math.floor(s); + minutes = Math.floor(s / 60); + seconds = s - minutes * 60; + return "" + (this.leadingZero(minutes)) + ":" + (this.leadingZero(seconds)); + }, + formatCurrency: function(strValue, reverseSign, currency) { + var currency_locale, lc, mf; + if (reverseSign == null) { + reverseSign = false; + } + if (currency == null) { + currency = null; + } + strValue = String(strValue); + if (reverseSign) { + strValue = ~strValue.indexOf('-') ? strValue.split('-').join('') : ['-', strValue].join(''); + } + currency_locale = i18n.currencyToLocale[currency]; + try { + if (!(currency_locale != null) || currency_locale === i18n.locale) { + return i18n.jsworld.mf.format(strValue); + } else { + lc = new jsworld.Locale(POSIX_LC[currency_locale]); + mf = new jsworld.MonetaryFormatter(lc); + return mf.format(strValue); + } + } catch (error) { + i18n.log(error); + return strValue; + } + }, + formatTripFare: function(trip, type) { + var _ref, _ref2; + if (type == null) { + type = "fare"; + } + if (!trip.get('fare')) { + return 'n/a'; + } + if (((_ref = trip.get('fare_breakdown_local')) != null ? _ref.currency : void 0) != null) { + return app.helpers.formatCurrency(trip.get("" + type + "_local"), false, (_ref2 = trip.get('fare_breakdown_local')) != null ? _ref2.currency : void 0); + } else if (trip.get("" + type + "_string") != null) { + return trip.get("" + type + "_string"); + } else if (trip.get("" + type + "_local") != null) { + return trip.get("" + type + "_local"); + } else { + return 'n/a'; + } + }, + formatPhoneNumber: function(phoneNumber, countryCode) { + if (countryCode == null) { + countryCode = "+1"; + } + if (phoneNumber != null) { + phoneNumber = String(phoneNumber); + switch (countryCode) { + case '+1': + return countryCode + ' ' + phoneNumber.substring(0, 3) + '-' + phoneNumber.substring(3, 6) + '-' + phoneNumber.substring(6, 10); + case '+33': + return countryCode + ' ' + phoneNumber.substring(0, 1) + ' ' + phoneNumber.substring(1, 3) + ' ' + phoneNumber.substring(3, 5) + ' ' + phoneNumber.substring(5, 7) + ' ' + phoneNumber.substring(7, 9); + default: + countryCode + phoneNumber; + } + } + return "" + countryCode + " " + phoneNumber; + }, + parseDate: function(d, cityTime, tz) { + var city_filter, parsed, _ref; + if (cityTime == null) { + cityTime = true; + } + if (tz == null) { + tz = null; + } + if (((_ref = !d.substr(-6, 1)) === '+' || _ref === '-') || d.length === 19) { + d += '+00:00'; + } + if (/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.test(d)) { + parsed = d.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/); + d = new Date(); + d.setUTCFullYear(parsed[1]); + d.setUTCMonth(parsed[2] - 1); + d.setUTCDate(parsed[3]); + d.setUTCHours(parsed[4]); + d.setUTCMinutes(parsed[5]); + d.setUTCSeconds(parsed[6]); + } else { + d = Date.parse(d); + } + if (typeof d === 'number') { + d = new Date(d); + } + d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC'); + if (tz) { + d.convertToTimezone(tz); + } else if (cityTime) { + city_filter = $.cookie('city_filter'); + if (city_filter) { + tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone'); + if (tz) { + d.convertToTimezone(tz); + } + } + } + return d; + }, + dateToTimezone: function(d) { + var city_filter, tz; + d = new timezoneJS.Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), 'Etc/UTC'); + city_filter = $.cookie('city_filter'); + if (city_filter) { + tz = $("#city_filter option[value=" + city_filter + "]").attr('data-timezone'); + d.convertToTimezone(tz); + } + return d; + }, + fixAMPM: function(d, formatted) { + if (d.hours >= 12) { + return formatted.replace(/\b[AP]M\b/, 'PM'); + } else { + return formatted.replace(/\b[AP]M\b/, 'AM'); + } + }, + formatDate: function(d, time, timezone) { + var formatted; + if (time == null) { + time = true; + } + if (timezone == null) { + timezone = null; + } + d = this.parseDate(d, true, timezone); + formatted = time ? ("" + (i18n.jsworld.dtf.formatDate(d)) + " ") + this.formatTime(d, d.getTimezoneInfo()) : i18n.jsworld.dtf.formatDate(d); + return this.fixAMPM(d, formatted); + }, + formatDateLong: function(d, time, timezone) { + if (time == null) { + time = true; + } + if (timezone == null) { + timezone = null; + } + d = this.parseDate(d, true, timezone); + timezone = d.getTimezoneInfo().tzAbbr; + if (time) { + return (i18n.jsworld.dtf.formatDateTime(d)) + (" " + timezone); + } else { + return i18n.jsworld.dtf.formatDate(d); + } + }, + formatTimezoneJSDate: function(d) { + var day, hours, jsDate, minutes, month, year; + year = d.getFullYear(); + month = this.leadingZero(d.getMonth()); + day = this.leadingZero(d.getDate()); + hours = this.leadingZero(d.getHours()); + minutes = this.leadingZero(d.getMinutes()); + jsDate = new Date(year, month, day, hours, minutes, 0); + return jsDate.toDateString(); + }, + formatTime: function(d, timezone) { + var formatted; + if (timezone == null) { + timezone = null; + } + formatted = ("" + (i18n.jsworld.dtf.formatTime(d))) + (timezone != null ? " " + (timezone != null ? timezone.tzAbbr : void 0) : ""); + return this.fixAMPM(d, formatted); + }, + formatISODate: function(d) { + var pad; + pad = function(n) { + if (n < 10) { + return '0' + n; + } + return n; + }; + return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z'; + }, + formatExpDate: function(d) { + var month, year; + d = this.parseDate(d); + year = d.getFullYear(); + month = this.leadingZero(d.getMonth() + 1); + return "" + year + "-" + month; + }, + formatLatLng: function(lat, lng, precision) { + if (precision == null) { + precision = 8; + } + return parseFloat(lat).toFixed(precision) + ',' + parseFloat(lng).toFixed(precision); + }, + leadingZero: function(num) { + if (num < 10) { + return "0" + num; + } else { + return num; + } + }, + roundNumber: function(num, dec) { + return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec); + }, + notesToHTML: function(notes) { + var i, note, notesHTML, _i, _len; + notesHTML = ''; + i = 1; + if (notes) { + for (_i = 0, _len = notes.length; _i < _len; _i++) { + note = notes[_i]; + notesHTML += "" + note['userid'] + "     " + (this.formatDate(note['created_at'])) + "

    " + note['note'] + "

    "; + notesHTML += "
    "; + } + } + return notesHTML.replace("'", '"e'); + }, + formatPhone: function(n) { + var parts, phone, regexObj; + n = "" + n; + regexObj = /^(?:\+?1[-. ]?)?(?:\(?([0-9]{3})\)?[-. ]?)?([0-9]{3})[-. ]?([0-9]{4})$/; + if (regexObj.test(n)) { + parts = n.match(regexObj); + phone = ""; + if (parts[1]) { + phone += "(" + parts[1] + ") "; + } + phone += "" + parts[2] + "-" + parts[3]; + } else { + phone = n; + } + return phone; + }, + usStates: ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'District of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'], + onboardingPages: ['applied', 'ready_to_interview', 'pending_interview', 'interviewed', 'accepted', 'ready_to_onboard', 'pending_onboarding', 'active', 'waitlisted', 'rejected'], + driverBreadCrumb: function(loc, model) { + var onboardingPage, out, _i, _len, _ref; + out = "Drivers > "; + if (!(model != null)) { + out += ""; + } else { + out += "" + (this.onboardingUrlToName(model.get('driver_status'))) + ""; + out += " > " + (this.linkedName(model)) + " (" + (model.get('role')) + ") #" + (model.get('id')); + } + return out; + }, + onboardingUrlToName: function(url) { + return url != null ? url.replace(/_/g, " ").replace(/(^|\s)([a-z])/g, function(m, p1, p2) { + return p1 + p2.toUpperCase(); + }) : void 0; + }, + formatVehicle: function(vehicle) { + if (vehicle.get('make') && vehicle.get('model') && vehicle.get('license_plate')) { + return "" + (vehicle.get('make')) + " " + (vehicle.get('model')) + " (" + (vehicle.get('license_plate')) + ")"; + } + }, + docArbitraryFields: function(docName, cityDocs) { + var doc, field, out, _i, _j, _len, _len2, _ref; + out = ""; + for (_i = 0, _len = cityDocs.length; _i < _len; _i++) { + doc = cityDocs[_i]; + if (doc.name === docName && __indexOf.call(_.keys(doc), "metaFields") >= 0) { + _ref = doc.metaFields; + for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { + field = _ref[_j]; + out += "" + field.label + ":
    "; + } + } + } + return out; + }, + capitaliseFirstLetter: function(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + createDocUploadForm: function(docName, driverId, vehicleId, cityMeta, vehicleName, expirationRequired) { + var ddocs, expDropdowns, pdocs, vdocs; + if (driverId == null) { + driverId = "None"; + } + if (vehicleId == null) { + vehicleId = "None"; + } + if (cityMeta == null) { + cityMeta = []; + } + if (vehicleName == null) { + vehicleName = false; + } + if (expirationRequired == null) { + expirationRequired = false; + } + ddocs = cityMeta["driverRequiredDocs"] || []; + pdocs = cityMeta["partnerRequiredDocs"] || []; + vdocs = cityMeta["vehicleRequiredDocs"] || []; + expDropdowns = "Expiration Date:\n -\n"; + return " \n
    \n \n \n \n\n
    \n " + (vehicleName ? vehicleName : "") + " " + docName + "\n
    \n\n
    \n \n
    \n\n
    \n " + (expirationRequired ? expDropdowns : "") + "\n
    \n\n
    \n " + (app.helpers.docArbitraryFields(docName, _.union(ddocs, pdocs, vdocs))) + "\n
    \n\n
    \n \n
    \n\n
    \n"; + }, + countrySelector: function(name, options) { + var countries, countryCodePrefix, defaultOptions; + if (options == null) { + options = {}; + } + defaultOptions = { + selectedKey: 'telephone_code', + selectedValue: '+1', + silent: false + }; + _.extend(defaultOptions, options); + options = defaultOptions; + countries = new app.collections.countries(); + countries.fetch({ + data: { + limit: 300 + }, + success: function(countries) { + var $option, $select, country, selected, _i, _len, _ref; + selected = false; + _ref = countries.models || []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + country = _ref[_i]; + $select = $("select[name=" + name + "]"); + $option = $('').val(country.id).attr('data-iso2', country.get('iso2')).attr('data-prefix', country.get('telephone_code')).html(country.get('name')); + if (country.get(options.selectedKey) === options.selectedValue && !selected) { + selected = true; + $option.attr('selected', 'selected'); + } + $select.append($option); + } + if (selected && !options.silent) { + return $select.val(options.selected).trigger('change'); + } + } + }); + countryCodePrefix = options.countryCodePrefix ? "data-country-code-prefix='" + options.countryCodePrefix + "'" : ''; + return ""; + }, + missingDocsOnDriver: function(driver) { + var city, docsReq, documents, partnerDocs; + city = driver.get('city'); + documents = driver.get('documents'); + if ((city != null) && (documents != null)) { + docsReq = _.pluck(city != null ? city.get('meta')["driverRequiredDocs"] : void 0, "name"); + if (driver.get('role') === "partner") { + partnerDocs = _.pluck(city != null ? city.get('meta')["partnerRequiredDocs"] : void 0, "name"); + docsReq = _.union(docsReq, partnerDocs); + } + return _.reject(docsReq, __bind(function(doc) { + return __indexOf.call((documents != null ? documents.pluck("name") : void 0) || [], doc) >= 0; + }, this)); + } else { + return []; + } + } + }; +}).call(this); +}, "web-lib/i18n": function(exports, require, module) {(function() { + exports.i18n = { + defaultLocale: 'en_US', + cookieName: '_LOCALE_', + locales: { + 'en_US': "English (US)", + 'fr_FR': "Français" + }, + currencyToLocale: { + 'USD': 'en_US', + 'EUR': 'fr_FR' + }, + logglyKey: 'd2d5a9bc-7ebe-4538-a180-81e62c705b1b', + logglyHost: 'https://logs.loggly.com', + init: function() { + this.castor = new window.loggly({ + url: this.logglyHost + '/inputs/' + this.logglyKey + '?rt=1', + level: 'error' + }); + this.setLocale($.cookie(this.cookieName) || this.defaultLocale); + window.t = _.bind(this.t, this); + this.loadLocaleTranslations(this.locale); + if (!(this[this.defaultLocale] != null)) { + return this.loadLocaleTranslations(this.defaultLocale); + } + }, + loadLocaleTranslations: function(locale) { + var loadPaths, path, _i, _len, _results; + loadPaths = ['web-lib/translations/' + locale, 'web-lib/translations/' + locale.slice(0, 2), 'translations/' + locale, 'translations/' + locale.slice(0, 2)]; + _results = []; + for (_i = 0, _len = loadPaths.length; _i < _len; _i++) { + path = loadPaths[_i]; + locale = path.substring(path.lastIndexOf('/') + 1); + if (this[locale] == null) { + this[locale] = {}; + } + _results.push((function() { + try { + return _.extend(this[locale], require(path).translations); + } catch (error) { + + } + }).call(this)); + } + return _results; + }, + getLocale: function() { + return this.locale; + }, + setLocale: function(locale) { + var message, parts, _ref; + parts = locale.split('_'); + this.locale = parts[0].toLowerCase(); + if (parts.length > 1) { + this.locale += "_" + (parts[1].toUpperCase()); + } + if (this.locale) { + $.cookie(this.cookieName, this.locale, { + path: '/', + domain: '.uber.com' + }); + } + try { + ((_ref = this.jsworld) != null ? _ref : this.jsworld = {}).lc = new jsworld.Locale(POSIX_LC[this.locale]); + this.jsworld.mf = new jsworld.MonetaryFormatter(this.jsworld.lc); + this.jsworld.nf = new jsworld.NumericFormatter(this.jsworld.lc); + this.jsworld.dtf = new jsworld.DateTimeFormatter(this.jsworld.lc); + this.jsworld.np = new jsworld.NumericParser(this.jsworld.lc); + this.jsworld.mp = new jsworld.MonetaryParser(this.jsworld.lc); + return this.jsworld.dtp = new jsworld.DateTimeParser(this.jsworld.lc); + } catch (error) { + message = 'JsWorld error with locale: ' + this.locale; + return this.log({ + message: message, + error: error + }); + } + }, + getTemplate: function(id) { + var _ref, _ref2; + return ((_ref = this[this.locale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.locale.slice(0, 2)]) != null ? _ref2[id] : void 0); + }, + getTemplateDefault: function(id) { + var _ref, _ref2; + return ((_ref = this[this.defaultLocale]) != null ? _ref[id] : void 0) || ((_ref2 = this[this.defaultLocale.slice(0, 2)]) != null ? _ref2[id] : void 0); + }, + getTemplateOrDefault: function(id) { + return this.getTemplate(id) || this.getTemplateDefault(id); + }, + t: function(id, vars) { + var errStr, locale, template; + if (vars == null) { + vars = {}; + } + locale = this.getLocale(); + template = this.getTemplate(id); + if (template == null) { + if (/dev|test/.test(window.location.host)) { + template = "(?) " + id; + } else { + template = this.getTemplateDefault(id); + } + errStr = "Missing [" + locale + "] translation for [" + id + "] at [" + window.location.hash + "] - Default template is [" + template + "]"; + this.log({ + error: errStr, + locale: locale, + id: id, + defaultTemplate: template + }); + } + if (template) { + return _.template(template, vars); + } else { + return id; + } + }, + log: function(error) { + if (/dev/.test(window.location.host)) { + if ((typeof console !== "undefined" && console !== null ? console.log : void 0) != null) { + return console.log(error); + } + } else { + _.extend(error, { + host: window.location.host, + hash: window.location.hash + }); + return this.castor.error(JSON.stringify(error)); + } + } + }; +}).call(this); +}, "web-lib/mixins/i18n_phone_form": function(exports, require, module) {(function() { + exports.i18nPhoneForm = { + _events: { + 'change select[data-country-code-prefix]': 'setCountryCodePrefix' + }, + setCountryCodePrefix: function(e) { + var $el, prefix; + $el = $(e.currentTarget); + prefix = $el.find('option:selected').attr('data-prefix'); + return $("#" + ($el.attr('data-country-code-prefix'))).text(prefix); + } + }; +}).call(this); +}, "web-lib/models/country": function(exports, require, module) {(function() { + var UberModel; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberModel = require('web-lib/uber_model').UberModel; + exports.Country = (function() { + __extends(Country, UberModel); + function Country() { + Country.__super__.constructor.apply(this, arguments); + } + Country.prototype.url = function() { + if (this.id) { + return "/countries/" + this.id; + } else { + return '/countries'; + } + }; + return Country; + })(); +}).call(this); +}, "web-lib/models/vehicle_type": function(exports, require, module) {(function() { + var UberModel; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + UberModel = require('web-lib/uber_model').UberModel; + exports.VehicleType = (function() { + __extends(VehicleType, UberModel); + function VehicleType() { + this.toString = __bind(this.toString, this); + VehicleType.__super__.constructor.apply(this, arguments); + } + VehicleType.prototype.endpoint = 'vehicle_types'; + VehicleType.prototype.toTableRow = function(cols) { + var actions, c, capacity, city_id, columnValues, created_at, created_by_user_id, deleted_at, id, make, minimum_year, model, rows, type, updated_at, updated_by_user_id, _i, _len, _ref; + id = "" + (this.get('id')) + ""; + if (this.get('created_at')) { + created_at = app.helpers.formatDate(this.get('created_at')); + } + if (this.get('updated_at')) { + updated_at = app.helpers.formatDate(this.get('updated_at')); + } + if (this.get('deleted_at')) { + deleted_at = app.helpers.formatDate(this.get('deleted_at')); + } + created_by_user_id = "" + (this.get('created_by_user_id')) + ""; + updated_by_user_id = "" + (this.get('updated_by_user_id')) + ""; + city_id = (_ref = this.get('city')) != null ? _ref.get('display_name') : void 0; + type = this.get('type'); + make = this.get('make'); + model = this.get('model'); + capacity = this.get('capacity'); + minimum_year = this.get('minimum_year'); + actions = "Show"; + if (!this.get('deleted_at')) { + actions += " Edit"; + actions += " Delete"; + } + columnValues = { + id: id, + created_at: created_at, + updated_at: updated_at, + deleted_at: deleted_at, + created_by_user_id: created_by_user_id, + updated_by_user_id: updated_by_user_id, + city_id: city_id, + type: type, + make: make, + model: model, + capacity: capacity, + minimum_year: minimum_year, + actions: actions + }; + rows = []; + for (_i = 0, _len = cols.length; _i < _len; _i++) { + c = cols[_i]; + rows.push(columnValues[c] ? columnValues[c] : '-'); + } + return rows; + }; + VehicleType.prototype.toString = function() { + return this.get('make') + ' ' + this.get('model') + ' ' + this.get('type') + (" (" + (this.get('capacity')) + ")"); + }; + return VehicleType; + })(); +}).call(this); +}, "web-lib/templates/footer": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var locale, title, _ref; + __out.push('\n\n\n\n\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "web-lib/translations/en": function(exports, require, module) {(function() { + exports.translations = { + "Info": "Info", + "Learn More": "Learn More", + "Pricing": "Pricing", + "FAQ": "FAQ", + "Support": "Support", + "Support & FAQ": "Support & FAQ", + "Contact Us": "Contact Us", + "Jobs": "Jobs", + "Phones": "Phones", + "Text Message": "Text Message", + "iPhone": "iPhone", + "Android": "Android", + "Drivers": "Drivers", + "Apply": "Apply", + "Sign In": "Sign In", + "Social": "Social", + "Twitter": "Twitter", + "Facebook": "Facebook", + "Blog": "Blog", + "Legal": "Legal", + "Company_Footer": "Company", + "Privacy Policy": "Privacy Policy", + "Terms": "Terms", + "Copyright © Uber Technologies, Inc.": "Copyright © Uber Technologies, Inc.", + "Language:": "Language:", + "Apply to Drive": "Apply to Drive", + "Expiration": "Expiration", + "Fare": "Fare", + "Driver": "Driver ", + "Dashboard": "Dashboard", + "Forgot Password": "Forgot Password", + "Trip Details": "Trip Details", + "Save": "Save", + "Cancel": "Cancel", + "Edit": "Edit", + "Password": "Password", + "First Name": "First Name", + "Last Name": "Last Name", + "Email Address": "Email Address", + "Submit": "Submit", + "Mobile Number": "Mobile Number", + "Zip Code": "Zip Code", + "Sign Out": "Sign Out", + "Confirm Email Message": "Attempting to confirm email...", + "Upload": "Upload", + "Rating": "Rating", + "Pickup Time": "Pickup Time", + "2011": "2011", + "2012": "2012", + "2013": "2013", + "2014": "2014", + "2015": "2015", + "2016": "2016", + "2017": "2017", + "2018": "2018", + "2019": "2019", + "2020": "2020", + "2021": "2021", + "2022": "2022", + "01": "01", + "02": "02", + "03": "03", + "04": "04", + "05": "05", + "06": "06", + "07": "07", + "08": "08", + "09": "09", + "10": "10", + "11": "11", + "12": "12" + }; +}).call(this); +}, "web-lib/translations/fr": function(exports, require, module) {(function() { + exports.translations = { + "Info": "Info", + "Learn More": "En Savoir Plus", + "Pricing": "Calcul du Prix", + "Support & FAQ": "Aide & FAQ", + "Contact Us": "Contactez Nous", + "Jobs": "Emplois", + "Phones": "Téléphones", + "Text Message": "SMS", + "iPhone": "iPhone", + "Android": "Android", + "Apply to Drive": "Candidature Chauffeur", + "Sign In": "Connexion", + "Social": "Contact", + "Twitter": "Twitter", + "Facebook": "Facebook", + "Blog": "Blog", + "Privacy Policy": "Protection des Données Personelles", + "Terms": "Conditions Générales", + "Copyright © Uber Technologies, Inc.": "© Uber, Inc.", + "Language:": "Langue:", + "Forgot Password": "Mot de passe oublié", + "Company_Footer": "À Propos d'Uber", + "Expiration": "Expiration", + "Fare": "Tarif", + "Driver": "Chauffeur", + "Drivers": "Chauffeurs", + "Dashboard": "Tableau de bord", + "Forgot Password": "Mot de passe oublié", + "Forgot Password?": "Mot de passe oublié?", + "Trip Details": "Détails de la course", + "Save": "Enregistrer", + "Cancel": "Annuler", + "Edit": "Modifier", + "Password": "Mot de passe", + "First Name": "Prénom", + "Last Name": "Nom", + "Email Address": "E-mail", + "Submit": "Soumettre", + "Mobile Number": "Téléphone Portable", + "Zip Code": "Code Postal", + "Sign Out": "Se déconnecter", + "Confirm Email Message": "E-mail de confirmation", + "Upload": "Télécharger", + "Rating": "Notation", + "Pickup Time": "Heure de prise en charge", + "2011": "2011", + "2012": "2012", + "2013": "2013", + "2014": "2014", + "2015": "2015", + "2016": "2016", + "2017": "2017", + "2018": "2018", + "2019": "2019", + "2020": "2020", + "2021": "2021", + "2022": "2022", + "01": "01", + "02": "02", + "03": "03", + "04": "04", + "05": "05", + "06": "06", + "07": "07", + "08": "08", + "09": "09", + "10": "10", + "11": "11", + "12": "12" + }; +}).call(this); +}, "web-lib/uber_collection": function(exports, require, module) {(function() { + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberCollection = (function() { + __extends(UberCollection, Backbone.Collection); + function UberCollection() { + UberCollection.__super__.constructor.apply(this, arguments); + } + UberCollection.prototype.parse = function(data) { + var model, tmp, _i, _in, _len, _out; + _in = data.resources || data; + _out = []; + if (data.meta) { + this.meta = data.meta; + } + for (_i = 0, _len = _in.length; _i < _len; _i++) { + model = _in[_i]; + tmp = new this.model; + tmp.set(tmp.parse(model)); + _out.push(tmp); + } + return _out; + }; + UberCollection.prototype.isRenderable = function() { + if (this.models.length) { + return true; + } + }; + UberCollection.prototype.toTableRows = function(cols) { + var tableRows; + tableRows = []; + _.each(this.models, function(model) { + return tableRows.push(model.toTableRow(cols)); + }); + return tableRows; + }; + return UberCollection; + })(); +}).call(this); +}, "web-lib/uber_model": function(exports, require, module) {(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }; + exports.UberModel = (function() { + __extends(UberModel, Backbone.Model); + function UberModel() { + this.refetch = __bind(this.refetch, this); + this.fetch = __bind(this.fetch, this); + this.save = __bind(this.save, this); + this.parse = __bind(this.parse, this); + UberModel.__super__.constructor.apply(this, arguments); + } + UberModel.prototype.endpoint = 'set_api_endpoint_in_subclass'; + UberModel.prototype.refetchOptions = {}; + UberModel.prototype.url = function(type) { + var endpoint_path; + endpoint_path = "/" + this.endpoint; + if (this.get('id')) { + return endpoint_path + ("/" + (this.get('id'))); + } else { + return endpoint_path; + } + }; + UberModel.prototype.isRenderable = function() { + var i, key, value, _ref; + i = 0; + _ref = this.attributes; + for (key in _ref) { + if (!__hasProp.call(_ref, key)) continue; + value = _ref[key]; + if (this.attributes.hasOwnProperty(key)) { + i += 1; + } + if (i > 1) { + return true; + } + } + return !(i === 1); + }; + UberModel.prototype.parse = function(response) { + var attrs, key, model, models, _i, _j, _k, _len, _len2, _len3, _ref, _ref2; + if (typeof response === 'object') { + _ref = _.intersection(_.keys(app.models), _.keys(response)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + if (response[key]) { + attrs = this.parse(response[key]); + if (typeof attrs === 'object') { + response[key] = new app.models[key](attrs); + } + } + } + _ref2 = _.intersection(_.keys(app.collections), _.keys(response)); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + key = _ref2[_j]; + models = response[key]; + if (_.isArray(models)) { + response[key] = new app.collections[key]; + for (_k = 0, _len3 = models.length; _k < _len3; _k++) { + model = models[_k]; + attrs = app.collections[key].prototype.model.prototype.parse(model); + response[key].add(new response[key].model(attrs)); + } + } + } + } + return response; + }; + UberModel.prototype.save = function(attributes, options) { + var attr, _i, _j, _len, _len2, _ref, _ref2; + if (options == null) { + options = {}; + } + _ref = _.intersection(_.keys(app.models), _.keys(this.attributes)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + attr = _ref[_i]; + if (typeof this.get(attr) === "object") { + this.unset(attr, { + silent: true + }); + } + } + _ref2 = _.intersection(_.keys(app.collections), _.keys(this.attributes)); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + attr = _ref2[_j]; + if (typeof this.get(attr) === "object") { + this.unset(attr, { + silent: true + }); + } + } + if ((options != null) && options.diff && (attributes != null) && attributes !== {}) { + attributes['id'] = this.get('id'); + attributes['token'] = this.get('token'); + this.clear({ + 'silent': true + }); + this.set(attributes, { + silent: true + }); + } + if (__indexOf.call(_.keys(options), "data") < 0 && __indexOf.call(_.keys(this.refetchOptions || {}), "data") >= 0) { + options.data = this.refetchOptions.data; + } + return Backbone.Model.prototype.save.call(this, attributes, options); + }; + UberModel.prototype.fetch = function(options) { + this.refetchOptions = options; + return Backbone.Model.prototype.fetch.call(this, options); + }; + UberModel.prototype.refetch = function() { + return this.fetch(this.refetchOptions); + }; + return UberModel; + })(); +}).call(this); +}, "web-lib/uber_router": function(exports, require, module) {(function() { + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberRouter = (function() { + __extends(UberRouter, Backbone.Router); + function UberRouter() { + UberRouter.__super__.constructor.apply(this, arguments); + } + UberRouter.prototype.datePickers = function(format) { + if (format == null) { + format = "%Z-%m-%dT%H:%i:%s%:"; + } + $('.datepicker').AnyTime_noPicker(); + return $('.datepicker').AnyTime_picker({ + 'format': format, + 'formatUtcOffset': '%@' + }); + }; + UberRouter.prototype.autoGrowInput = function() { + return $('.editable input').autoGrowInput(); + }; + UberRouter.prototype.windowTitle = function(title) { + return $(document).attr('title', title); + }; + return UberRouter; + })(); +}).call(this); +}, "web-lib/uber_show_view": function(exports, require, module) {(function() { + var UberView; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + UberView = require('web-lib/uber_view').UberView; + exports.UberShowView = (function() { + __extends(UberShowView, UberView); + function UberShowView() { + UberShowView.__super__.constructor.apply(this, arguments); + } + UberShowView.prototype.view = 'show'; + UberShowView.prototype.events = { + 'click #edit': 'edit', + 'submit form': 'save', + 'click .cancel': 'cancel' + }; + UberShowView.prototype.errors = null; + UberShowView.prototype.showTemplate = null; + UberShowView.prototype.editTemplate = null; + UberShowView.prototype.initialize = function() { + if (this.init_hook) { + this.init_hook(); + } + _.bindAll(this, 'render'); + return this.model.bind('change', this.render); + }; + UberShowView.prototype.render = function() { + var $el; + $el = $(this.el); + this.selectView(); + if (this.view === 'show') { + $el.html(this.showTemplate({ + model: this.model + })); + } else if (this.view === 'edit') { + $el.html(this.editTemplate({ + model: this.model, + errors: this.errors || {}, + collections: this.collections || {} + })); + } else { + $el.html(this.newTemplate({ + model: this.model, + errors: this.errors || {}, + collections: this.collections || {} + })); + } + if (this.render_hook) { + this.render_hook(); + } + this.errors = null; + this.userIdsToLinkedNames(); + this.datePickers(); + return this.place(); + }; + UberShowView.prototype.selectView = function() { + var url; + if (this.options.urlRendering) { + url = window.location.hash; + if (url.match(/\/new/)) { + return this.view = 'new'; + } else if (url.match(/\/edit/)) { + return this.view = 'edit'; + } else { + return this.view = 'show'; + } + } + }; + UberShowView.prototype.edit = function(e) { + e.preventDefault(); + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id') + '/edit'; + } else { + this.view = 'edit'; + } + return this.model.change(); + }; + UberShowView.prototype.save = function(e) { + var attributes, ele, form_attrs, _i, _len, _ref; + e.preventDefault(); + attributes = $(e.currentTarget).serializeToJson(); + form_attrs = {}; + _ref = $('input[type="radio"]'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + ele = _ref[_i]; + if ($(ele).is(':checked')) { + form_attrs[$(ele).attr('name')] = $(ele).attr('value'); + } + } + attributes = _.extend(attributes, form_attrs); + if (this.relationships) { + attributes = _.extend(attributes, { + relationships: this.relationships + }); + } + if (this.filter_attributes != null) { + this.filter_attributes(attributes); + } + return this.model.save(attributes, { + silent: true, + success: __bind(function(model) { + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id'); + } else { + this.view = 'show'; + } + return this.flash('success', "Uber save!"); + }, this), + statusCode: { + 406: __bind(function(xhr) { + this.errors = JSON.parse(xhr.responseText); + return this.flash('error', 'That was not Uber.'); + }, this) + }, + error: __bind(function(model, xhr) { + var code, message, responseJSON, responseText; + code = xhr.status; + responseText = xhr.responseText; + if (responseText) { + responseJSON = JSON.parse(responseText); + } + if (responseJSON && (typeof responseJSON === 'object') && (responseJSON.hasOwnProperty('error'))) { + message = responseJSON.error; + } + return this.flash('error', (code || 'Unknown') + ' error' + (': ' + message || '')); + }, this), + complete: __bind(function() { + return this.model.change(); + }, this) + }); + }; + UberShowView.prototype.cancel = function(e) { + e.preventDefault(); + if (this.options.urlRendering) { + window.location.hash = '#/' + this.model.endpoint + '/' + this.model.get('id'); + } else { + this.view = 'show'; + } + return this.model.fetch({ + silent: true, + complete: __bind(function() { + return this.model.change(); + }, this) + }); + }; + return UberShowView; + })(); +}).call(this); +}, "web-lib/uber_sync": function(exports, require, module) {(function() { + var methodType; + var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; + }; + methodType = { + create: 'POST', + update: 'PUT', + "delete": 'DELETE', + read: 'GET' + }; + exports.UberSync = function(method, model, options) { + var token; + options.type = methodType[method]; + options.url = _.isString(this.url) ? '/api' + this.url : '/api' + this.url(options.type); + options.data = _.extend({}, options.data); + if (__indexOf.call(_.keys(options.data), "city_id") < 0) { + if ($.cookie('city_filter')) { + _.extend(options.data, { + city_id: $.cookie('city_filter') + }); + } + } else { + delete options.data['city_id']; + } + if (options.type === 'POST' || options.type === 'PUT') { + _.extend(options.data, model.toJSON()); + } + token = $.cookie('token') ? $.cookie('token') : typeof USER !== "undefined" && USER !== null ? USER.get('token') : ""; + _.extend(options.data, { + token: token + }); + if (method === "delete") { + options.contentType = 'application/json'; + options.data = JSON.stringify(options.data); + } + return $.ajax(options); + }; +}).call(this); +}, "web-lib/uber_view": function(exports, require, module) {(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + exports.UberView = (function() { + __extends(UberView, Backbone.View); + function UberView() { + this.processDocumentUpload = __bind(this.processDocumentUpload, this); + UberView.__super__.constructor.apply(this, arguments); + } + UberView.prototype.className = 'view_container'; + UberView.prototype.hashId = function() { + return parseInt(location.hash.split('/')[2]); + }; + UberView.prototype.place = function(content) { + var $target; + $target = this.options.scope ? this.options.scope.find(this.options.selector) : $(this.options.selector); + $target[this.options.method || 'html'](content || this.el); + this.delegateEvents(); + $('#spinner').hide(); + return this; + }; + UberView.prototype.mixin = function(m, args) { + var events, self; + if (args == null) { + args = {}; + } + self = this; + events = m._events; + _.extend(this, m); + if (m.initialize) { + m.initialize(self, args); + } + return _.each(_.keys(events), function(key) { + var event, func, selector, split; + split = key.split(' '); + event = split[0]; + selector = split[1]; + func = events[key]; + return $(self.el).find(selector).live(event, function(e) { + return self[func](e); + }); + }); + }; + UberView.prototype.datePickers = function(format) { + if (format == null) { + format = "%Z-%m-%dT%H:%i:%s%:"; + } + $('.datepicker').AnyTime_noPicker(); + return $('.datepicker').AnyTime_picker({ + 'format': format, + 'formatUtcOffset': '%@' + }); + }; + UberView.prototype.dataTable = function(collection, selector, options, params, cols) { + var defaults; + if (selector == null) { + selector = 'table'; + } + if (options == null) { + options = {}; + } + if (params == null) { + params = {}; + } + if (cols == null) { + cols = []; + } + $(selector).empty(); + if (!cols.length) { + cols = collection.defaultColumns; + } + defaults = { + aoColumns: collection.tableColumns(cols), + bDestroy: true, + bSort: false, + bProcessing: true, + bFilter: false, + bServerSide: true, + bPaginate: true, + bScrollInfinite: true, + bScrollCollapse: true, + sScrollY: '600px', + iDisplayLength: 50, + fnServerData: function(source, data, callback) { + var defaultParams; + defaultParams = { + limit: data[4].value, + offset: data[3].value + }; + return collection.fetch({ + data: _.extend(defaultParams, params), + success: function() { + return callback({ + aaData: collection.toTableRows(cols), + iTotalRecords: collection.meta.count, + iTotalDisplayRecords: collection.meta.count + }); + }, + error: function() { + return new Error({ + message: 'Loading error.' + }); + } + }); + }, + fnRowCallback: function(nRow, aData, iDisplayIndex, iDisplayIndexFull) { + $('[data-tooltip]', nRow).qtip({ + content: { + attr: 'data-tooltip' + }, + style: { + classes: "ui-tooltip-light ui-tooltip-rounded ui-tooltip-shadow" + } + }); + return nRow; + } + }; + return $(this.el).find(selector).dataTable(_.extend(defaults, options)); + }; + UberView.prototype.dataTableLocal = function(collection, selector, options, params, cols) { + var $dataTable, defaults; + if (selector == null) { + selector = 'table'; + } + if (options == null) { + options = {}; + } + if (params == null) { + params = {}; + } + if (cols == null) { + cols = []; + } + $(selector).empty(); + if (!cols.length || cols.length === 0) { + cols = collection.defaultColumns; + } + defaults = { + aaData: collection.toTableRows(cols), + aoColumns: collection.tableColumns(cols), + bDestroy: true, + bSort: false, + bProcessing: true, + bFilter: false, + bScrollInfinite: true, + bScrollCollapse: true, + sScrollY: '600px', + iDisplayLength: -1 + }; + $dataTable = $(this.el).find(selector).dataTable(_.extend(defaults, options)); + _.delay(__bind(function() { + if ($dataTable && $dataTable.length > 0) { + return $dataTable.fnAdjustColumnSizing(); + } + }, this), 1); + return $dataTable; + }; + UberView.prototype.reverseGeocode = function() { + var $el; + return ''; + $el = $(this.el); + return this.requireMaps(function() { + var geocoder; + geocoder = new google.maps.Geocoder(); + return $el.find('[data-point]').each(function() { + var $this, latLng, point; + $this = $(this); + point = JSON.parse($this.attr('data-point')); + latLng = new google.maps.LatLng(point.latitude, point.longitude); + return geocoder.geocode({ + latLng: latLng + }, function(data, status) { + if (status === google.maps.GeocoderStatus.OK) { + return $this.text(data[0].formatted_address); + } + }); + }); + }); + }; + UberView.prototype.userIdsToLinkedNames = function() { + var $el; + $el = $(this.el); + return $el.find('a[data-user-id][data-user-type]').each(function() { + var $this, user, userType; + $this = $(this); + userType = $this.attr('data-user-type') === 'user' ? 'client' : $this.attr('data-user-type'); + user = new app.models[userType]({ + id: $this.attr('data-user-id') + }); + return user.fetch({ + success: function(user) { + return $this.html(app.helpers.linkedName(user)).attr('href', "!/" + user.role + "s/" + user.id); + }, + error: function() { + if ($this.attr('data-user-type') === 'user') { + user = new app.models['driver']({ + id: $this.attr('data-user-id') + }); + return user.fetch({ + success: function(user) { + return $this.html(app.helpers.linkedName(user)).attr('href', "!/driver/" + user.id); + } + }); + } + } + }); + }); + }; + UberView.prototype.selectedCity = function() { + var $selected, city, cityFilter; + cityFilter = $.cookie('city_filter'); + $selected = $("#city_filter option[value=" + cityFilter + "]"); + if (city_filter && $selected.length) { + return city = { + lat: parseFloat($selected.attr('data-lat')), + lng: parseFloat($selected.attr('data-lng')), + timezone: $selected.attr('data-timezone') + }; + } else { + return city = { + lat: 37.775, + lng: -122.45, + timezone: 'Etc/UTC' + }; + } + }; + UberView.prototype.updateModel = function(e, success) { + var $el, attrs, model, self; + e.preventDefault(); + $el = $(e.currentTarget); + self = this; + model = new this.model.__proto__.constructor({ + id: this.model.id + }); + attrs = {}; + $el.find('[name]').each(function() { + var $this; + $this = $(this); + return attrs["" + ($this.attr('name'))] = $this.val(); + }); + self.model.set(attrs); + $el.find('span.error').text(''); + return model.save(attrs, { + complete: function(xhr) { + var response; + response = JSON.parse(xhr.responseText); + switch (xhr.status) { + case 200: + self.model = model; + $el.find('[name]').val(''); + if (success) { + return success(); + } + break; + case 406: + return _.each(response, function(error, field) { + return $el.find("[name=" + field + "]").parent().find('span.error').text(error); + }); + default: + return this.unanticipatedError(response); + } + } + }); + }; + UberView.prototype.autoUpdateModel = function(e) { + var $el, arg, model, self, val; + $el = $(e.currentTarget); + val = $el.val(); + self = this; + if (val !== this.model.get($el.attr('id'))) { + arg = {}; + arg[$el.attr('id')] = $el.is(':checkbox') ? $el.is(':checked') ? 1 : 0 : val; + $('.editable span').empty(); + this.model.set(arg); + model = new this.model.__proto__.constructor({ + id: this.model.id + }); + return model.save(arg, { + complete: function(xhr) { + var key, response, _i, _len, _ref, _results; + response = JSON.parse(xhr.responseText); + switch (xhr.status) { + case 200: + self.flash('success', 'Saved!'); + return $el.blur(); + case 406: + self.flash('error', 'That was not Uber.'); + _ref = _.keys(response); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + _results.push($el.parent().find('span').html(response[key])); + } + return _results; + break; + default: + return self.unanticipatedError; + } + } + }); + } + }; + UberView.prototype.unanticipatedError = function(response) { + return self.flash('error', response); + }; + UberView.prototype.flash = function(type, text) { + var $banner; + $banner = $("." + type); + $banner.find('p').text(text).end().css('border', '1px solid #999').animate({ + top: 0 + }, 500); + return setTimeout(function() { + return $banner.animate({ + top: -$banner.outerHeight() + }, 500); + }, 3000); + }; + UberView.prototype.requireMaps = function(callback) { + if (typeof google !== 'undefined' && google.maps) { + return callback(); + } else { + return $.getScript("https://www.google.com/jsapi?key=" + CONFIG.googleJsApiKey, function() { + return google.load('maps', 3, { + callback: callback, + other_params: 'sensor=false&language=en' + }); + }); + } + }; + UberView.prototype.select_drop_down = function(model, key) { + var value; + value = model.get(key); + if (value) { + return $("select[id='" + key + "'] option[value='" + value + "']").attr('selected', 'selected'); + } + }; + UberView.prototype.processDocumentUpload = function(e) { + var $fi, $form, arbData, curDate, data, expDate, expM, expY, expiration, fileElementId, invalid; + e.preventDefault(); + $form = $(e.currentTarget); + $fi = $("input[type=file]", $form); + $(".validationError").removeClass("validationError"); + if (!$fi.val()) { + return $fi.addClass("validationError"); + } else { + fileElementId = $fi.attr('id'); + expY = $("select[name=expiration-year]", $form).val(); + expM = $("select[name=expiration-month]", $form).val(); + invalid = false; + if (expY && expM) { + expDate = new Date(expY, expM, 28); + curDate = new Date(); + if (expDate < curDate) { + invalid = true; + $(".expiration", $form).addClass("validationError"); + } + expiration = "" + expY + "-" + expM + "-28T23:59:59Z"; + } + arbData = {}; + $(".arbitraryField", $form).each(__bind(function(i, e) { + arbData[$(e).attr('name')] = $(e).val(); + if ($(e).val() === "") { + invalid = true; + return $(e).addClass("validationError"); + } + }, this)); + if (!invalid) { + data = { + token: $.cookie('token') || USER.get('token'), + name: $("input[name=fileName]", $form).val(), + meta: escape(JSON.stringify(arbData)), + user_id: $("input[name=driver_id]", $form).val(), + vehicle_id: $("input[name=vehicle_id]", $form).val() + }; + if (expiration) { + data['expiration'] = expiration; + } + $("#spinner").show(); + return $.ajaxFileUpload({ + url: '/api/documents', + secureuri: false, + fileElementId: fileElementId, + data: data, + complete: __bind(function(resp, status) { + var key, _i, _len, _ref, _results; + $("#spinner").hide(); + if (status === "success") { + if (this.model) { + this.model.refetch(); + } else { + USER.refetch(); + } + } + if (status === "error") { + _ref = _.keys(resp); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + _results.push($("*[name=" + key + "]", $form).addClass("validationError")); + } + return _results; + } + }, this) + }); + } + } + }; + return UberView; + })(); +}).call(this); +}, "web-lib/views/footer": function(exports, require, module) {(function() { + var footerTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + footerTemplate = require('web-lib/templates/footer'); + exports.SharedFooterView = (function() { + __extends(SharedFooterView, Backbone.View); + function SharedFooterView() { + SharedFooterView.__super__.constructor.apply(this, arguments); + } + SharedFooterView.prototype.id = 'footer_view'; + SharedFooterView.prototype.events = { + 'click .language': 'intl_set_cookie_locale' + }; + SharedFooterView.prototype.render = function() { + $(this.el).html(footerTemplate()); + this.delegateEvents(); + return this; + }; + SharedFooterView.prototype.intl_set_cookie_locale = function(e) { + var _ref; + i18n.setLocale(e != null ? (_ref = e.srcElement) != null ? _ref.id : void 0 : void 0); + return location.reload(); + }; + return SharedFooterView; + })(); +}).call(this); +}}); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js new file mode 100755 index 0000000..61307ee --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/embed-tokens.js @@ -0,0 +1,15 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("embed-tokens.js", "utf8").replace(/^#.*$/mg, ""); +var ast = jsp.parse(code, null, true); + +// trololo +function fooBar() {} + +console.log(sys.inspect(ast, null, null)); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js new file mode 100644 index 0000000..945960c --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto.js @@ -0,0 +1,26 @@ +function unique(arqw) { + var a = [], i, j + outer: for (i = 0; i < arqw.length; i++) { + for (j = 0; j < a.length; j++) { + if (a[j] == arqw[i]) { + continue outer + } + } + a[a.length] = arqw[i] + } + return a +} + + +function unique(arqw) { + var crap = [], i, j + outer: for (i = 0; i < arqw.length; i++) { + for (j = 0; j < crap.length; j++) { + if (crap[j] == arqw[i]) { + continue outer + } + } + crap[crap.length] = arqw[i] + } + return crap +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js new file mode 100644 index 0000000..d13b2bc --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/goto2.js @@ -0,0 +1,8 @@ +function q(qooo) { + var a; + foo: for(;;) { + a++; + if (something) break foo; + return qooo; + } +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js new file mode 100644 index 0000000..4bf2b94 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/hoist.js @@ -0,0 +1,33 @@ +function foo(arg1, arg2, arg3, arg4, arg5, arg6) { + var a = 5; + { + var d = 10, mak = 20, buz = 30; + var q = buz * 2; + } + if (moo) { + var a, b, c; + } + for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) + console.log(arg3); + for (var i in mak) {} + for (j in d) {} + var d; + + function test() { + + }; + + //test(); + + (function moo(first, second){ + console.log(first); + })(1); + + (function moo(first, second){ + console.log(moo()); + })(1); +} + + +var foo; +var bar; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js new file mode 100644 index 0000000..c6a9d79 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument.js @@ -0,0 +1,97 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", // XXX: "block" is safer + [ [ "stat", + [ "call", [ "name", "trace" ], + [ [ "string", this[0].toString() ], + [ "num", this[0].start.line ], + [ "num", this[0].start.col ], + [ "num", this[0].end.line ], + [ "num", this[0].end.col ]]]], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + }; + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + // note however that the following is broken. I guess we + // should add the block brackets in this case... + for (var i = 0; i < 5; ++i) + console.log("foo"); +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js new file mode 100644 index 0000000..6aee5f3 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/instrument2.js @@ -0,0 +1,138 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + function trace (line, comment) { + var code = pro.gen_code(line, { beautify: true }); + var data = line[0] + + var args = [] + if (!comment) comment = "" + if (typeof data === "object") { + code = code.split(/\n/).shift() + args = [ [ "string", data.toString() ], + [ "string", code ], + [ "num", data.start.line ], + [ "num", data.start.col ], + [ "num", data.end.line ], + [ "num", data.end.col ]] + } else { + args = [ [ "string", data ], + [ "string", code ]] + + } + return [ "call", [ "name", "trace" ], args ]; + } + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", + [ [ "stat", trace(this) ], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + } + + function do_cond(c, t, f) { + return [ this[0], w.walk(c), + ["seq", trace(t), w.walk(t) ], + ["seq", trace(f), w.walk(f) ]]; + } + + function do_binary(c, l, r) { + if (c !== "&&" && c !== "||") { + return [this[0], c, w.walk(l), w.walk(r)]; + } + return [ this[0], c, + ["seq", trace(l), w.walk(l) ], + ["seq", trace(r), w.walk(r) ]]; + } + + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat, + "conditional" : do_cond, + "binary" : do_binary + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + for (var i = 0; i < 5; ++i) + console.log("foo"); + + for (var i = 0; i < 5; ++i) { + console.log("foo"); + } + + var k = plurp() ? 1 : 0; + var x = a ? doX(y) && goZoo("zoo") + : b ? blerg({ x: y }) + : null; + + var x = X || Y; +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js new file mode 100644 index 0000000..2f4b7fe --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/liftvars.js @@ -0,0 +1,8 @@ +var UNUSED_VAR1 = 19; + +function main() { + var unused_var2 = 20; + alert(100); +} + +main(); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js new file mode 100755 index 0000000..f295fba --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/test.js @@ -0,0 +1,30 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("hoist.js", "utf8"); +var ast = jsp.parse(code); + +ast = pro.ast_lift_variables(ast); + +var w = pro.ast_walker(); +ast = w.with_walkers({ + "function": function() { + var node = w.dive(this); // walk depth first + console.log(pro.gen_code(node, { beautify: true })); + return node; + }, + "name": function(name) { + return [ this[0], "X" ]; + } +}, function(){ + return w.walk(ast); +}); + +console.log(pro.gen_code(ast, { + beautify: true +})); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js new file mode 100644 index 0000000..0d5b7e0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/uglify-hangs.js @@ -0,0 +1,3930 @@ +/** + * @fileoverview + * + * JsWorld + * + *

    Javascript library for localised formatting and parsing of: + *

      + *
    • Numbers + *
    • Dates and times + *
    • Currency + *
    + * + *

    The library classes are configured with standard POSIX locale definitions + * derived from Unicode's Common Locale Data Repository (CLDR). + * + *

    Website: JsWorld + * + * @author Vladimir Dzhuvinov + * @version 2.5 (2011-12-23) + */ + + + +/** + * @namespace Namespace container for the JsWorld library objects. + */ +jsworld = {}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 date/time + * string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the + * current date/time will be used. + * @param {Boolean} [withTZ] Include timezone offset, default false. + * + * @returns {String} The date/time formatted as YYYY-MM-DD HH:MM:SS. + */ +jsworld.formatIsoDateTime = function(d, withTZ) { + + if (typeof d === "undefined") + d = new Date(); // now + + if (typeof withTZ === "undefined") + withTZ = false; + + var s = jsworld.formatIsoDate(d) + " " + jsworld.formatIsoTime(d); + + if (withTZ) { + + var diff = d.getHours() - d.getUTCHours(); + var hourDiff = Math.abs(diff); + + var minuteUTC = d.getUTCMinutes(); + var minute = d.getMinutes(); + + if (minute != minuteUTC && minuteUTC < 30 && diff < 0) + hourDiff--; + + if (minute != minuteUTC && minuteUTC > 30 && diff > 0) + hourDiff--; + + var minuteDiff; + if (minute != minuteUTC) + minuteDiff = ":30"; + else + minuteDiff = ":00"; + + var timezone; + if (hourDiff < 10) + timezone = "0" + hourDiff + minuteDiff; + + else + timezone = "" + hourDiff + minuteDiff; + + if (diff < 0) + timezone = "-" + timezone; + + else + timezone = "+" + timezone; + + s = s + timezone; + } + + return s; +}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 date string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the current + * date will be used. + * + * @returns {String} The date formatted as YYYY-MM-DD. + */ +jsworld.formatIsoDate = function(d) { + + if (typeof d === "undefined") + d = new Date(); // now + + var year = d.getFullYear(); + var month = d.getMonth() + 1; + var day = d.getDate(); + + return year + "-" + jsworld._zeroPad(month, 2) + "-" + jsworld._zeroPad(day, 2); +}; + + +/** + * @function + * + * @description Formats a JavaScript Date object as an ISO-8601 time string. + * + * @param {Date} [d] A valid JavaScript Date object. If undefined the current + * time will be used. + * + * @returns {String} The time formatted as HH:MM:SS. + */ +jsworld.formatIsoTime = function(d) { + + if (typeof d === "undefined") + d = new Date(); // now + + var hour = d.getHours(); + var minute = d.getMinutes(); + var second = d.getSeconds(); + + return jsworld._zeroPad(hour, 2) + ":" + jsworld._zeroPad(minute, 2) + ":" + jsworld._zeroPad(second, 2); +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted date/time string to a JavaScript + * Date object. + * + * @param {String} isoDateTimeVal An ISO-8601 formatted date/time string. + * + *

    Accepted formats: + * + *

      + *
    • YYYY-MM-DD HH:MM:SS + *
    • YYYYMMDD HHMMSS + *
    • YYYY-MM-DD HHMMSS + *
    • YYYYMMDD HH:MM:SS + *
    + * + * @returns {Date} The corresponding Date object. + * + * @throws Error on a badly formatted date/time string or on a invalid date. + */ +jsworld.parseIsoDateTime = function(isoDateTimeVal) { + + if (typeof isoDateTimeVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "YYYY-MM-DD HH:MM:SS" format + var matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/); + + // If unsuccessful, try to match "YYYYMMDD HHMMSS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/); + + // ... try to match "YYYY-MM-DD HHMMSS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/); + + // ... try to match "YYYYMMDD HH:MM:SS" format + if (matches === null) + matches = isoDateTimeVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date/time string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var year = parseInt(matches[1], 10); + var month = parseInt(matches[2], 10); + var day = parseInt(matches[3], 10); + + var hour = parseInt(matches[4], 10); + var mins = parseInt(matches[5], 10); + var secs = parseInt(matches[6], 10); + + // Simple value range check, leap years not checked + // Note: the originial ISO time spec for leap hours (24:00:00) and seconds (00:00:60) is not supported + if (month < 1 || month > 12 || + day < 1 || day > 31 || + hour < 0 || hour > 23 || + mins < 0 || mins > 59 || + secs < 0 || secs > 59 ) + + throw "Error: Invalid ISO-8601 date/time value"; + + var d = new Date(year, month - 1, day, hour, mins, secs); + + // Check if the input date was valid + // (JS Date does automatic forward correction) + if (d.getDate() != day || d.getMonth() +1 != month) + throw "Error: Invalid date"; + + return d; +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted date string to a JavaScript + * Date object. + * + * @param {String} isoDateVal An ISO-8601 formatted date string. + * + *

    Accepted formats: + * + *

      + *
    • YYYY-MM-DD + *
    • YYYYMMDD + *
    + * + * @returns {Date} The corresponding Date object. + * + * @throws Error on a badly formatted date string or on a invalid date. + */ +jsworld.parseIsoDate = function(isoDateVal) { + + if (typeof isoDateVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "YYYY-MM-DD" format + var matches = isoDateVal.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/); + + // If unsuccessful, try to match "YYYYMMDD" format + if (matches === null) + matches = isoDateVal.match(/^(\d\d\d\d)(\d\d)(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var year = parseInt(matches[1], 10); + var month = parseInt(matches[2], 10); + var day = parseInt(matches[3], 10); + + // Simple value range check, leap years not checked + if (month < 1 || month > 12 || + day < 1 || day > 31 ) + + throw "Error: Invalid ISO-8601 date value"; + + var d = new Date(year, month - 1, day); + + // Check if the input date was valid + // (JS Date does automatic forward correction) + if (d.getDate() != day || d.getMonth() +1 != month) + throw "Error: Invalid date"; + + return d; +}; + + +/** + * @function + * + * @description Parses an ISO-8601 formatted time string to a JavaScript + * Date object. + * + * @param {String} isoTimeVal An ISO-8601 formatted time string. + * + *

    Accepted formats: + * + *

      + *
    • HH:MM:SS + *
    • HHMMSS + *
    + * + * @returns {Date} The corresponding Date object, with year, month and day set + * to zero. + * + * @throws Error on a badly formatted time string. + */ +jsworld.parseIsoTime = function(isoTimeVal) { + + if (typeof isoTimeVal != "string") + throw "Error: The parameter must be a string"; + + // First, try to match "HH:MM:SS" format + var matches = isoTimeVal.match(/^(\d\d):(\d\d):(\d\d)/); + + // If unsuccessful, try to match "HHMMSS" format + if (matches === null) + matches = isoTimeVal.match(/^(\d\d)(\d\d)(\d\d)/); + + // Report bad date/time string + if (matches === null) + throw "Error: Invalid ISO-8601 date/time string"; + + // Force base 10 parse int as some values may have leading zeros! + // (to avoid implicit octal base conversion) + var hour = parseInt(matches[1], 10); + var mins = parseInt(matches[2], 10); + var secs = parseInt(matches[3], 10); + + // Simple value range check, leap years not checked + if (hour < 0 || hour > 23 || + mins < 0 || mins > 59 || + secs < 0 || secs > 59 ) + + throw "Error: Invalid ISO-8601 time value"; + + return new Date(0, 0, 0, hour, mins, secs); +}; + + +/** + * @private + * + * @description Trims leading and trailing whitespace from a string. + * + *

    Used non-regexp the method from http://blog.stevenlevithan.com/archives/faster-trim-javascript + * + * @param {String} str The string to trim. + * + * @returns {String} The trimmed string. + */ +jsworld._trim = function(str) { + + var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'; + + for (var i = 0; i < str.length; i++) { + + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(i); + break; + } + } + + for (i = str.length - 1; i >= 0; i--) { + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(0, i + 1); + break; + } + } + + return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''; +}; + + + +/** + * @private + * + * @description Returns true if the argument represents a decimal number. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents a decimal number, + * otherwise false. + */ +jsworld._isNumber = function(arg) { + + if (typeof arg == "number") + return true; + + if (typeof arg != "string") + return false; + + // ensure string + var s = arg + ""; + + return (/^-?(\d+|\d*\.\d+)$/).test(s); +}; + + +/** + * @private + * + * @description Returns true if the argument represents a decimal integer. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents an integer, otherwise + * false. + */ +jsworld._isInteger = function(arg) { + + if (typeof arg != "number" && typeof arg != "string") + return false; + + // convert to string + var s = arg + ""; + + return (/^-?\d+$/).test(s); +}; + + +/** + * @private + * + * @description Returns true if the argument represents a decimal float. + * + * @param {Number|String} arg The argument to test. + * + * @returns {Boolean} true if the argument represents a float, otherwise false. + */ +jsworld._isFloat = function(arg) { + + if (typeof arg != "number" && typeof arg != "string") + return false; + + // convert to string + var s = arg + ""; + + return (/^-?\.\d+?$/).test(s); +}; + + +/** + * @private + * + * @description Checks if the specified formatting option is contained + * within the options string. + * + * @param {String} option The option to search for. + * @param {String} optionsString The options string. + * + * @returns {Boolean} true if the flag is found, else false + */ +jsworld._hasOption = function(option, optionsString) { + + if (typeof option != "string" || typeof optionsString != "string") + return false; + + if (optionsString.indexOf(option) != -1) + return true; + else + return false; +}; + + +/** + * @private + * + * @description String replacement function. + * + * @param {String} s The string to work on. + * @param {String} target The string to search for. + * @param {String} replacement The replacement. + * + * @returns {String} The new string. + */ +jsworld._stringReplaceAll = function(s, target, replacement) { + + var out; + + if (target.length == 1 && replacement.length == 1) { + // simple char/char case somewhat faster + out = ""; + + for (var i = 0; i < s.length; i++) { + + if (s.charAt(i) == target.charAt(0)) + out = out + replacement.charAt(0); + else + out = out + s.charAt(i); + } + + return out; + } + else { + // longer target and replacement strings + out = s; + + var index = out.indexOf(target); + + while (index != -1) { + + out = out.replace(target, replacement); + + index = out.indexOf(target); + } + + return out; + } +}; + + +/** + * @private + * + * @description Tests if a string starts with the specified substring. + * + * @param {String} testedString The string to test. + * @param {String} sub The string to match. + * + * @returns {Boolean} true if the test succeeds. + */ +jsworld._stringStartsWith = function (testedString, sub) { + + if (testedString.length < sub.length) + return false; + + for (var i = 0; i < sub.length; i++) { + if (testedString.charAt(i) != sub.charAt(i)) + return false; + } + + return true; +}; + + +/** + * @private + * + * @description Gets the requested precision from an options string. + * + *

    Example: ".3" returns 3 decimal places precision. + * + * @param {String} optionsString The options string. + * + * @returns {integer Number} The requested precision, -1 if not specified. + */ +jsworld._getPrecision = function (optionsString) { + + if (typeof optionsString != "string") + return -1; + + var m = optionsString.match(/\.(\d)/); + if (m) + return parseInt(m[1], 10); + else + return -1; +}; + + +/** + * @private + * + * @description Takes a decimal numeric amount (optionally as string) and + * returns its integer and fractional parts packed into an object. + * + * @param {Number|String} amount The amount, e.g. "123.45" or "-56.78" + * + * @returns {object} Parsed amount object with properties: + * {String} integer : the integer part + * {String} fraction : the fraction part + */ +jsworld._splitNumber = function (amount) { + + if (typeof amount == "number") + amount = amount + ""; + + var obj = {}; + + // remove negative sign + if (amount.charAt(0) == "-") + amount = amount.substring(1); + + // split amount into integer and decimal parts + var amountParts = amount.split("."); + if (!amountParts[1]) + amountParts[1] = ""; // we need "" instead of null + + obj.integer = amountParts[0]; + obj.fraction = amountParts[1]; + + return obj; +}; + + +/** + * @private + * + * @description Formats the integer part using the specified grouping + * and thousands separator. + * + * @param {String} intPart The integer part of the amount, as string. + * @param {String} grouping The grouping definition. + * @param {String} thousandsSep The thousands separator. + * + * @returns {String} The formatted integer part. + */ +jsworld._formatIntegerPart = function (intPart, grouping, thousandsSep) { + + // empty separator string? no grouping? + // -> return immediately with no formatting! + if (thousandsSep == "" || grouping == "-1") + return intPart; + + // turn the semicolon-separated string of integers into an array + var groupSizes = grouping.split(";"); + + // the formatted output string + var out = ""; + + // the intPart string position to process next, + // start at string end, e.g. "10000000 0) { + + // get next group size (if any, otherwise keep last) + if (groupSizes.length > 0) + size = parseInt(groupSizes.shift(), 10); + + // int parse error? + if (isNaN(size)) + throw "Error: Invalid grouping"; + + // size is -1? -> no more grouping, so just copy string remainder + if (size == -1) { + out = intPart.substring(0, pos) + out; + break; + } + + pos -= size; // move to next sep. char. position + + // position underrun? -> just copy string remainder + if (pos < 1) { + out = intPart.substring(0, pos + size) + out; + break; + } + + // extract group and apply sep. char. + out = thousandsSep + intPart.substring(pos, pos + size) + out; + } + + return out; +}; + + +/** + * @private + * + * @description Formats the fractional part to the specified decimal + * precision. + * + * @param {String} fracPart The fractional part of the amount + * @param {integer Number} precision The desired decimal precision + * + * @returns {String} The formatted fractional part. + */ +jsworld._formatFractionPart = function (fracPart, precision) { + + // append zeroes up to precision if necessary + for (var i=0; fracPart.length < precision; i++) + fracPart = fracPart + "0"; + + return fracPart; +}; + + +/** + * @private + * + * @desription Converts a number to string and pad it with leading zeroes if the + * string is shorter than length. + * + * @param {integer Number} number The number value subjected to selective padding. + * @param {integer Number} length If the number has fewer digits than this length + * apply padding. + * + * @returns {String} The formatted string. + */ +jsworld._zeroPad = function(number, length) { + + // ensure string + var s = number + ""; + + while (s.length < length) + s = "0" + s; + + return s; +}; + + +/** + * @private + * @description Converts a number to string and pads it with leading spaces if + * the string is shorter than length. + * + * @param {integer Number} number The number value subjected to selective padding. + * @param {integer Number} length If the number has fewer digits than this length + * apply padding. + * + * @returns {String} The formatted string. + */ +jsworld._spacePad = function(number, length) { + + // ensure string + var s = number + ""; + + while (s.length < length) + s = " " + s; + + return s; +}; + + + +/** + * @class + * Represents a POSIX-style locale with its numeric, monetary and date/time + * properties. Also provides a set of locale helper methods. + * + *

    The locale properties follow the POSIX standards: + * + *

    + * + * @public + * @constructor + * @description Creates a new locale object (POSIX-style) with the specified + * properties. + * + * @param {object} properties An object containing the raw locale properties: + * + * @param {String} properties.decimal_point + * + * A string containing the symbol that shall be used as the decimal + * delimiter (radix character) in numeric, non-monetary formatted + * quantities. This property cannot be omitted and cannot be set to the + * empty string. + * + * + * @param {String} properties.thousands_sep + * + * A string containing the symbol that shall be used as a separator for + * groups of digits to the left of the decimal delimiter in numeric, + * non-monetary formatted monetary quantities. + * + * + * @param {String} properties.grouping + * + * Defines the size of each group of digits in formatted non-monetary + * quantities. The operand is a sequence of integers separated by + * semicolons. Each integer specifies the number of digits in each group, + * with the initial integer defining the size of the group immediately + * preceding the decimal delimiter, and the following integers defining + * the preceding groups. If the last integer is not -1, then the size of + * the previous group (if any) shall be repeatedly used for the + * remainder of the digits. If the last integer is -1, then no further + * grouping shall be performed. + * + * + * @param {String} properties.int_curr_symbol + * + * The first three letters signify the ISO-4217 currency code, + * the fourth letter is the international symbol separation character + * (normally a space). + * + * + * @param {String} properties.currency_symbol + * + * The local shorthand currency symbol, e.g. "$" for the en_US locale + * + * + * @param {String} properties.mon_decimal_point + * + * The symbol to be used as the decimal delimiter (radix character) + * + * + * @param {String} properties.mon_thousands_sep + * + * The symbol to be used as a separator for groups of digits to the + * left of the decimal delimiter. + * + * + * @param {String} properties.mon_grouping + * + * A string that defines the size of each group of digits. The + * operand is a sequence of integers separated by semicolons (";"). + * Each integer specifies the number of digits in each group, with the + * initial integer defining the size of the group preceding the + * decimal delimiter, and the following integers defining the + * preceding groups. If the last integer is not -1, then the size of + * the previous group (if any) must be repeatedly used for the + * remainder of the digits. If the last integer is -1, then no + * further grouping is to be performed. + * + * + * @param {String} properties.positive_sign + * + * The string to indicate a non-negative monetary amount. + * + * + * @param {String} properties.negative_sign + * + * The string to indicate a negative monetary amount. + * + * + * @param {integer Number} properties.frac_digits + * + * An integer representing the number of fractional digits (those to + * the right of the decimal delimiter) to be written in a formatted + * monetary quantity using currency_symbol. + * + * + * @param {integer Number} properties.int_frac_digits + * + * An integer representing the number of fractional digits (those to + * the right of the decimal delimiter) to be written in a formatted + * monetary quantity using int_curr_symbol. + * + * + * @param {integer Number} properties.p_cs_precedes + * + * An integer set to 1 if the currency_symbol precedes the value for a + * monetary quantity with a non-negative value, and set to 0 if the + * symbol succeeds the value. + * + * + * @param {integer Number} properties.n_cs_precedes + * + * An integer set to 1 if the currency_symbol precedes the value for a + * monetary quantity with a negative value, and set to 0 if the symbol + * succeeds the value. + * + * + * @param {integer Number} properties.p_sep_by_space + * + * Set to a value indicating the separation of the currency_symbol, + * the sign string, and the value for a non-negative formatted monetary + * quantity: + * + *

    0 No space separates the currency symbol and value.

    + * + *

    1 If the currency symbol and sign string are adjacent, a space + * separates them from the value; otherwise, a space separates + * the currency symbol from the value.

    + * + *

    2 If the currency symbol and sign string are adjacent, a space + * separates them; otherwise, a space separates the sign string + * from the value.

    + * + * + * @param {integer Number} properties.n_sep_by_space + * + * Set to a value indicating the separation of the currency_symbol, + * the sign string, and the value for a negative formatted monetary + * quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.p_sign_posn + * + * An integer set to a value indicating the positioning of the + * positive_sign for a monetary quantity with a non-negative value: + * + *

    0 Parentheses enclose the quantity and the currency_symbol.

    + * + *

    1 The sign string precedes the quantity and the currency_symbol.

    + * + *

    2 The sign string succeeds the quantity and the currency_symbol.

    + * + *

    3 The sign string precedes the currency_symbol.

    + * + *

    4 The sign string succeeds the currency_symbol.

    + * + * + * @param {integer Number} properties.n_sign_posn + * + * An integer set to a value indicating the positioning of the + * negative_sign for a negative formatted monetary quantity. Rules same + * as for p_sign_posn. + * + * + * @param {integer Number} properties.int_p_cs_precedes + * + * An integer set to 1 if the int_curr_symbol precedes the value for a + * monetary quantity with a non-negative value, and set to 0 if the + * symbol succeeds the value. + * + * + * @param {integer Number} properties.int_n_cs_precedes + * + * An integer set to 1 if the int_curr_symbol precedes the value for a + * monetary quantity with a negative value, and set to 0 if the symbol + * succeeds the value. + * + * + * @param {integer Number} properties.int_p_sep_by_space + * + * Set to a value indicating the separation of the int_curr_symbol, + * the sign string, and the value for a non-negative internationally + * formatted monetary quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.int_n_sep_by_space + * + * Set to a value indicating the separation of the int_curr_symbol, + * the sign string, and the value for a negative internationally + * formatted monetary quantity. Rules same as for p_sep_by_space. + * + * + * @param {integer Number} properties.int_p_sign_posn + * + * An integer set to a value indicating the positioning of the + * positive_sign for a positive monetary quantity formatted with the + * international format. Rules same as for p_sign_posn. + * + * + * @param {integer Number} properties.int_n_sign_posn + * + * An integer set to a value indicating the positioning of the + * negative_sign for a negative monetary quantity formatted with the + * international format. Rules same as for p_sign_posn. + * + * + * @param {String[] | String} properties.abday + * + * The abbreviated weekday names, corresponding to the %a conversion + * specification. The property must be either an array of 7 strings or + * a string consisting of 7 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the abbreviated name + * of the day corresponding to Sunday, the second the abbreviated name + * of the day corresponding to Monday, and so on. + * + * + * @param {String[] | String} properties.day + * + * The full weekday names, corresponding to the %A conversion + * specification. The property must be either an array of 7 strings or + * a string consisting of 7 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the full name of the + * day corresponding to Sunday, the second the full name of the day + * corresponding to Monday, and so on. + * + * + * @param {String[] | String} properties.abmon + * + * The abbreviated month names, corresponding to the %b conversion + * specification. The property must be either an array of 12 strings or + * a string consisting of 12 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the abbreviated name + * of the first month of the year (January), the second the abbreviated + * name of the second month, and so on. + * + * + * @param {String[] | String} properties.mon + * + * The full month names, corresponding to the %B conversion + * specification. The property must be either an array of 12 strings or + * a string consisting of 12 semicolon-separated substrings, each + * surrounded by double-quotes. The first must be the full name of the + * first month of the year (January), the second the full name of the second + * month, and so on. + * + * + * @param {String} properties.d_fmt + * + * The appropriate date representation. The string may contain any + * combination of characters and conversion specifications (%). + * + * + * @param {String} properties.t_fmt + * + * The appropriate time representation. The string may contain any + * combination of characters and conversion specifications (%). + * + * + * @param {String} properties.d_t_fmt + * + * The appropriate date and time representation. The string may contain + * any combination of characters and conversion specifications (%). + * + * + * @param {String[] | String} properties.am_pm + * + * The appropriate representation of the ante-meridiem and post-meridiem + * strings, corresponding to the %p conversion specification. The property + * must be either an array of 2 strings or a string consisting of 2 + * semicolon-separated substrings, each surrounded by double-quotes. + * The first string must represent the ante-meridiem designation, the + * last string the post-meridiem designation. + * + * + * @throws @throws Error on a undefined or invalid locale property. + */ +jsworld.Locale = function(properties) { + + + /** + * @private + * + * @description Identifies the class for internal library purposes. + */ + this._className = "jsworld.Locale"; + + + /** + * @private + * + * @description Parses a day or month name definition list, which + * could be a ready JS array, e.g. ["Mon", "Tue", "Wed"...] or + * it could be a string formatted according to the classic POSIX + * definition e.g. "Mon";"Tue";"Wed";... + * + * @param {String[] | String} namesAn array or string defining + * the week/month names. + * @param {integer Number} expectedItems The number of expected list + * items, e.g. 7 for weekdays, 12 for months. + * + * @returns {String[]} The parsed (and checked) items. + * + * @throws Error on missing definition, unexpected item count or + * missing double-quotes. + */ + this._parseList = function(names, expectedItems) { + + var array = []; + + if (names == null) { + throw "Names not defined"; + } + else if (typeof names == "object") { + // we got a ready array + array = names; + } + else if (typeof names == "string") { + // we got the names in the classic POSIX form, do parse + array = names.split(";", expectedItems); + + for (var i = 0; i < array.length; i++) { + // check for and strip double quotes + if (array[i][0] == "\"" && array[i][array[i].length - 1] == "\"") + array[i] = array[i].slice(1, -1); + else + throw "Missing double quotes"; + } + } + else { + throw "Names must be an array or a string"; + } + + if (array.length != expectedItems) + throw "Expected " + expectedItems + " items, got " + array.length; + + return array; + }; + + + /** + * @private + * + * @description Validates a date/time format string, such as "H:%M:%S". + * Checks that the argument is of type "string" and is not empty. + * + * @param {String} formatString The format string. + * + * @returns {String} The validated string. + * + * @throws Error on null or empty string. + */ + this._validateFormatString = function(formatString) { + + if (typeof formatString == "string" && formatString.length > 0) + return formatString; + else + throw "Empty or no string"; + }; + + + // LC_NUMERIC + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing locale properties"; + + + if (typeof properties.decimal_point != "string") + throw "Error: Invalid/missing decimal_point property"; + + this.decimal_point = properties.decimal_point; + + + if (typeof properties.thousands_sep != "string") + throw "Error: Invalid/missing thousands_sep property"; + + this.thousands_sep = properties.thousands_sep; + + + if (typeof properties.grouping != "string") + throw "Error: Invalid/missing grouping property"; + + this.grouping = properties.grouping; + + + // LC_MONETARY + + if (typeof properties.int_curr_symbol != "string") + throw "Error: Invalid/missing int_curr_symbol property"; + + if (! /[A-Za-z]{3}.?/.test(properties.int_curr_symbol)) + throw "Error: Invalid int_curr_symbol property"; + + this.int_curr_symbol = properties.int_curr_symbol; + + + if (typeof properties.currency_symbol != "string") + throw "Error: Invalid/missing currency_symbol property"; + + this.currency_symbol = properties.currency_symbol; + + + if (typeof properties.frac_digits != "number" && properties.frac_digits < 0) + throw "Error: Invalid/missing frac_digits property"; + + this.frac_digits = properties.frac_digits; + + + // may be empty string/null for currencies with no fractional part + if (properties.mon_decimal_point === null || properties.mon_decimal_point == "") { + + if (this.frac_digits > 0) + throw "Error: Undefined mon_decimal_point property"; + else + properties.mon_decimal_point = ""; + } + + if (typeof properties.mon_decimal_point != "string") + throw "Error: Invalid/missing mon_decimal_point property"; + + this.mon_decimal_point = properties.mon_decimal_point; + + + if (typeof properties.mon_thousands_sep != "string") + throw "Error: Invalid/missing mon_thousands_sep property"; + + this.mon_thousands_sep = properties.mon_thousands_sep; + + + if (typeof properties.mon_grouping != "string") + throw "Error: Invalid/missing mon_grouping property"; + + this.mon_grouping = properties.mon_grouping; + + + if (typeof properties.positive_sign != "string") + throw "Error: Invalid/missing positive_sign property"; + + this.positive_sign = properties.positive_sign; + + + if (typeof properties.negative_sign != "string") + throw "Error: Invalid/missing negative_sign property"; + + this.negative_sign = properties.negative_sign; + + + + if (properties.p_cs_precedes !== 0 && properties.p_cs_precedes !== 1) + throw "Error: Invalid/missing p_cs_precedes property, must be 0 or 1"; + + this.p_cs_precedes = properties.p_cs_precedes; + + + if (properties.n_cs_precedes !== 0 && properties.n_cs_precedes !== 1) + throw "Error: Invalid/missing n_cs_precedes, must be 0 or 1"; + + this.n_cs_precedes = properties.n_cs_precedes; + + + if (properties.p_sep_by_space !== 0 && + properties.p_sep_by_space !== 1 && + properties.p_sep_by_space !== 2) + throw "Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2"; + + this.p_sep_by_space = properties.p_sep_by_space; + + + if (properties.n_sep_by_space !== 0 && + properties.n_sep_by_space !== 1 && + properties.n_sep_by_space !== 2) + throw "Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2"; + + this.n_sep_by_space = properties.n_sep_by_space; + + + if (properties.p_sign_posn !== 0 && + properties.p_sign_posn !== 1 && + properties.p_sign_posn !== 2 && + properties.p_sign_posn !== 3 && + properties.p_sign_posn !== 4) + throw "Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.p_sign_posn = properties.p_sign_posn; + + + if (properties.n_sign_posn !== 0 && + properties.n_sign_posn !== 1 && + properties.n_sign_posn !== 2 && + properties.n_sign_posn !== 3 && + properties.n_sign_posn !== 4) + throw "Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.n_sign_posn = properties.n_sign_posn; + + + if (typeof properties.int_frac_digits != "number" && properties.int_frac_digits < 0) + throw "Error: Invalid/missing int_frac_digits property"; + + this.int_frac_digits = properties.int_frac_digits; + + + if (properties.int_p_cs_precedes !== 0 && properties.int_p_cs_precedes !== 1) + throw "Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1"; + + this.int_p_cs_precedes = properties.int_p_cs_precedes; + + + if (properties.int_n_cs_precedes !== 0 && properties.int_n_cs_precedes !== 1) + throw "Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1"; + + this.int_n_cs_precedes = properties.int_n_cs_precedes; + + + if (properties.int_p_sep_by_space !== 0 && + properties.int_p_sep_by_space !== 1 && + properties.int_p_sep_by_space !== 2) + throw "Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2"; + + this.int_p_sep_by_space = properties.int_p_sep_by_space; + + + if (properties.int_n_sep_by_space !== 0 && + properties.int_n_sep_by_space !== 1 && + properties.int_n_sep_by_space !== 2) + throw "Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2"; + + this.int_n_sep_by_space = properties.int_n_sep_by_space; + + + if (properties.int_p_sign_posn !== 0 && + properties.int_p_sign_posn !== 1 && + properties.int_p_sign_posn !== 2 && + properties.int_p_sign_posn !== 3 && + properties.int_p_sign_posn !== 4) + throw "Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_p_sign_posn = properties.int_p_sign_posn; + + + if (properties.int_n_sign_posn !== 0 && + properties.int_n_sign_posn !== 1 && + properties.int_n_sign_posn !== 2 && + properties.int_n_sign_posn !== 3 && + properties.int_n_sign_posn !== 4) + throw "Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4"; + + this.int_n_sign_posn = properties.int_n_sign_posn; + + + // LC_TIME + + if (properties == null || typeof properties != "object") + throw "Error: Invalid/missing time locale properties"; + + + // parse the supported POSIX LC_TIME properties + + // abday + try { + this.abday = this._parseList(properties.abday, 7); + } + catch (error) { + throw "Error: Invalid abday property: " + error; + } + + // day + try { + this.day = this._parseList(properties.day, 7); + } + catch (error) { + throw "Error: Invalid day property: " + error; + } + + // abmon + try { + this.abmon = this._parseList(properties.abmon, 12); + } catch (error) { + throw "Error: Invalid abmon property: " + error; + } + + // mon + try { + this.mon = this._parseList(properties.mon, 12); + } catch (error) { + throw "Error: Invalid mon property: " + error; + } + + // d_fmt + try { + this.d_fmt = this._validateFormatString(properties.d_fmt); + } catch (error) { + throw "Error: Invalid d_fmt property: " + error; + } + + // t_fmt + try { + this.t_fmt = this._validateFormatString(properties.t_fmt); + } catch (error) { + throw "Error: Invalid t_fmt property: " + error; + } + + // d_t_fmt + try { + this.d_t_fmt = this._validateFormatString(properties.d_t_fmt); + } catch (error) { + throw "Error: Invalid d_t_fmt property: " + error; + } + + // am_pm + try { + var am_pm_strings = this._parseList(properties.am_pm, 2); + this.am = am_pm_strings[0]; + this.pm = am_pm_strings[1]; + } catch (error) { + // ignore empty/null string errors + this.am = ""; + this.pm = ""; + } + + + /** + * @public + * + * @description Returns the abbreviated name of the specified weekday. + * + * @param {integer Number} [weekdayNum] An integer between 0 and 6. Zero + * corresponds to Sunday, one to Monday, etc. If omitted the + * method will return an array of all abbreviated weekday + * names. + * + * @returns {String | String[]} The abbreviated name of the specified weekday + * or an array of all abbreviated weekday names. + * + * @throws Error on invalid argument. + */ + this.getAbbreviatedWeekdayName = function(weekdayNum) { + + if (typeof weekdayNum == "undefined" || weekdayNum === null) + return this.abday; + + if (! jsworld._isInteger(weekdayNum) || weekdayNum < 0 || weekdayNum > 6) + throw "Error: Invalid weekday argument, must be an integer [0..6]"; + + return this.abday[weekdayNum]; + }; + + + /** + * @public + * + * @description Returns the name of the specified weekday. + * + * @param {integer Number} [weekdayNum] An integer between 0 and 6. Zero + * corresponds to Sunday, one to Monday, etc. If omitted the + * method will return an array of all weekday names. + * + * @returns {String | String[]} The name of the specified weekday or an + * array of all weekday names. + * + * @throws Error on invalid argument. + */ + this.getWeekdayName = function(weekdayNum) { + + if (typeof weekdayNum == "undefined" || weekdayNum === null) + return this.day; + + if (! jsworld._isInteger(weekdayNum) || weekdayNum < 0 || weekdayNum > 6) + throw "Error: Invalid weekday argument, must be an integer [0..6]"; + + return this.day[weekdayNum]; + }; + + + /** + * @public + * + * @description Returns the abbreviated name of the specified month. + * + * @param {integer Number} [monthNum] An integer between 0 and 11. Zero + * corresponds to January, one to February, etc. If omitted the + * method will return an array of all abbreviated month names. + * + * @returns {String | String[]} The abbreviated name of the specified month + * or an array of all abbreviated month names. + * + * @throws Error on invalid argument. + */ + this.getAbbreviatedMonthName = function(monthNum) { + + if (typeof monthNum == "undefined" || monthNum === null) + return this.abmon; + + if (! jsworld._isInteger(monthNum) || monthNum < 0 || monthNum > 11) + throw "Error: Invalid month argument, must be an integer [0..11]"; + + return this.abmon[monthNum]; + }; + + + /** + * @public + * + * @description Returns the name of the specified month. + * + * @param {integer Number} [monthNum] An integer between 0 and 11. Zero + * corresponds to January, one to February, etc. If omitted the + * method will return an array of all month names. + * + * @returns {String | String[]} The name of the specified month or an array + * of all month names. + * + * @throws Error on invalid argument. + */ + this.getMonthName = function(monthNum) { + + if (typeof monthNum == "undefined" || monthNum === null) + return this.mon; + + if (! jsworld._isInteger(monthNum) || monthNum < 0 || monthNum > 11) + throw "Error: Invalid month argument, must be an integer [0..11]"; + + return this.mon[monthNum]; + }; + + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) character for + * numeric quantities. + * + * @returns {String} The radix character. + */ + this.getDecimalPoint = function() { + + return this.decimal_point; + }; + + + /** + * @public + * + * @description Gets the local shorthand currency symbol. + * + * @returns {String} The currency symbol. + */ + this.getCurrencySymbol = function() { + + return this.currency_symbol; + }; + + + /** + * @public + * + * @description Gets the internaltion currency symbol (ISO-4217 code). + * + * @returns {String} The international currency symbol. + */ + this.getIntCurrencySymbol = function() { + + return this.int_curr_symbol.substring(0,3); + }; + + + /** + * @public + * + * @description Gets the position of the local (shorthand) currency + * symbol relative to the amount. Assumes a non-negative amount. + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.currencySymbolPrecedes = function() { + + if (this.p_cs_precedes == 1) + return true; + else + return false; + }; + + + /** + * @public + * + * @description Gets the position of the international (ISO-4217 code) + * currency symbol relative to the amount. Assumes a non-negative + * amount. + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.intCurrencySymbolPrecedes = function() { + + if (this.int_p_cs_precedes == 1) + return true; + else + return false; + + }; + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) for monetary + * quantities. + * + * @returns {String} The radix character. + */ + this.getMonetaryDecimalPoint = function() { + + return this.mon_decimal_point; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits for local + * (shorthand) symbol formatting. + * + * @returns {integer Number} The number of fractional digits. + */ + this.getFractionalDigits = function() { + + return this.frac_digits; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits for + * international (ISO-4217 code) formatting. + * + * @returns {integer Number} The number of fractional digits. + */ + this.getIntFractionalDigits = function() { + + return this.int_frac_digits; + }; +}; + + + +/** + * @class + * Class for localised formatting of numbers. + * + *

    See: + * POSIX LC_NUMERIC. + * + * + * @public + * @constructor + * @description Creates a new numeric formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_NUMERIC formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.NumericFormatter = function(locale) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + + /** + * @public + * + * @description Formats a decimal numeric value according to the preset + * locale. + * + * @param {Number|String} number The number to format. + * @param {String} [options] Options to modify the formatted output: + *

      + *
    • "^" suppress grouping + *
    • "+" force positive sign for positive amounts + *
    • "~" suppress positive/negative sign + *
    • ".n" specify decimal precision 'n' + *
    + * + * @returns {String} The formatted number. + * + * @throws "Error: Invalid input" on bad input. + */ + this.format = function(number, options) { + + if (typeof number == "string") + number = jsworld._trim(number); + + if (! jsworld._isNumber(number)) + throw "Error: The input is not a number"; + + var floatAmount = parseFloat(number, 10); + + // get the required precision + var reqPrecision = jsworld._getPrecision(options); + + // round to required precision + if (reqPrecision != -1) + floatAmount = Math.round(floatAmount * Math.pow(10, reqPrecision)) / Math.pow(10, reqPrecision); + + + // convert the float number to string and parse into + // object with properties integer and fraction + var parsedAmount = jsworld._splitNumber(String(floatAmount)); + + // format integer part with grouping chars + var formattedIntegerPart; + + if (floatAmount === 0) + formattedIntegerPart = "0"; + else + formattedIntegerPart = jsworld._hasOption("^", options) ? + parsedAmount.integer : + jsworld._formatIntegerPart(parsedAmount.integer, + this.lc.grouping, + this.lc.thousands_sep); + + // format the fractional part + var formattedFractionPart = + reqPrecision != -1 ? + jsworld._formatFractionPart(parsedAmount.fraction, reqPrecision) : + parsedAmount.fraction; + + + // join the integer and fraction parts using the decimal_point property + var formattedAmount = + formattedFractionPart.length ? + formattedIntegerPart + this.lc.decimal_point + formattedFractionPart : + formattedIntegerPart; + + // prepend sign? + if (jsworld._hasOption("~", options) || floatAmount === 0) { + // suppress both '+' and '-' signs, i.e. return abs value + return formattedAmount; + } + else { + if (jsworld._hasOption("+", options) || floatAmount < 0) { + if (floatAmount > 0) + // force '+' sign for positive amounts + return "+" + formattedAmount; + else if (floatAmount < 0) + // prepend '-' sign + return "-" + formattedAmount; + else + // zero case + return formattedAmount; + } + else { + // positive amount with no '+' sign + return formattedAmount; + } + } + }; +}; + + +/** + * @class + * Class for localised formatting of dates and times. + * + *

    See: + * POSIX LC_TIME. + * + * @public + * @constructor + * @description Creates a new date/time formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_TIME formatting properties. + * + * @throws Error on constructor failure. + */ +jsworld.DateTimeFormatter = function(locale) { + + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance."; + + this.lc = locale; + + + /** + * @public + * + * @description Formats a date according to the preset locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted date, e.g. "2010-31-03" + * or "2010-03-31 23:59:59". + * + * @returns {String} The formatted date + * + * @throws Error on invalid date argument + */ + this.formatDate = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 date string + try { + d = jsworld.parseIsoDate(date); + } catch (error) { + // try full ISO-8601 date/time string + d = jsworld.parseIsoDateTime(date); + } + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.d_fmt); + }; + + + /** + * @public + * + * @description Formats a time according to the preset locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted time, e.g. "23:59:59" + * or "2010-03-31 23:59:59". + * + * @returns {String} The formatted time. + * + * @throws Error on invalid date argument. + */ + this.formatTime = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 time string + try { + d = jsworld.parseIsoTime(date); + } catch (error) { + // try full ISO-8601 date/time string + d = jsworld.parseIsoDateTime(date); + } + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.t_fmt); + }; + + + /** + * @public + * + * @description Formats a date/time value according to the preset + * locale. + * + * @param {Date|String} date A valid Date object instance or a string + * containing a valid ISO-8601 formatted date/time, e.g. + * "2010-03-31 23:59:59". + * + * @returns {String} The formatted time. + * + * @throws Error on invalid argument. + */ + this.formatDateTime = function(date) { + + var d = null; + + if (typeof date == "string") { + // assume ISO-8601 format + d = jsworld.parseIsoDateTime(date); + } + else if (date !== null && typeof date == "object") { + // assume ready Date object + d = date; + } + else { + throw "Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"; + } + + return this._applyFormatting(d, this.lc.d_t_fmt); + }; + + + /** + * @private + * + * @description Apples formatting to the Date object according to the + * format string. + * + * @param {Date} d A valid Date instance. + * @param {String} s The formatting string with '%' placeholders. + * + * @returns {String} The formatted string. + */ + this._applyFormatting = function(d, s) { + + s = s.replace(/%%/g, '%'); + s = s.replace(/%a/g, this.lc.abday[d.getDay()]); + s = s.replace(/%A/g, this.lc.day[d.getDay()]); + s = s.replace(/%b/g, this.lc.abmon[d.getMonth()]); + s = s.replace(/%B/g, this.lc.mon[d.getMonth()]); + s = s.replace(/%d/g, jsworld._zeroPad(d.getDate(), 2)); + s = s.replace(/%e/g, jsworld._spacePad(d.getDate(), 2)); + s = s.replace(/%F/g, d.getFullYear() + + "-" + + jsworld._zeroPad(d.getMonth()+1, 2) + + "-" + + jsworld._zeroPad(d.getDate(), 2)); + s = s.replace(/%h/g, this.lc.abmon[d.getMonth()]); // same as %b + s = s.replace(/%H/g, jsworld._zeroPad(d.getHours(), 2)); + s = s.replace(/%I/g, jsworld._zeroPad(this._hours12(d.getHours()), 2)); + s = s.replace(/%k/g, d.getHours()); + s = s.replace(/%l/g, this._hours12(d.getHours())); + s = s.replace(/%m/g, jsworld._zeroPad(d.getMonth()+1, 2)); + s = s.replace(/%n/g, "\n"); + s = s.replace(/%M/g, jsworld._zeroPad(d.getMinutes(), 2)); + s = s.replace(/%p/g, this._getAmPm(d.getHours())); + s = s.replace(/%P/g, this._getAmPm(d.getHours()).toLocaleLowerCase()); // safe? + s = s.replace(/%R/g, jsworld._zeroPad(d.getHours(), 2) + + ":" + + jsworld._zeroPad(d.getMinutes(), 2)); + s = s.replace(/%S/g, jsworld._zeroPad(d.getSeconds(), 2)); + s = s.replace(/%T/g, jsworld._zeroPad(d.getHours(), 2) + + ":" + + jsworld._zeroPad(d.getMinutes(), 2) + + ":" + + jsworld._zeroPad(d.getSeconds(), 2)); + s = s.replace(/%w/g, this.lc.day[d.getDay()]); + s = s.replace(/%y/g, new String(d.getFullYear()).substring(2)); + s = s.replace(/%Y/g, d.getFullYear()); + + s = s.replace(/%Z/g, ""); // to do: ignored until a reliable TMZ method found + + s = s.replace(/%[a-zA-Z]/g, ""); // ignore all other % sequences + + return s; + }; + + + /** + * @private + * + * @description Does 24 to 12 hour conversion. + * + * @param {integer Number} hour24 Hour [0..23]. + * + * @returns {integer Number} Corresponding hour [1..12]. + */ + this._hours12 = function(hour24) { + + if (hour24 === 0) + return 12; // 00h is 12AM + + else if (hour24 > 12) + return hour24 - 12; // 1PM to 11PM + + else + return hour24; // 1AM to 12PM + }; + + + /** + * @private + * + * @description Gets the appropriate localised AM or PM string depending + * on the day hour. Special cases: midnight is 12AM, noon is 12PM. + * + * @param {integer Number} hour24 Hour [0..23]. + * + * @returns {String} The corresponding localised AM or PM string. + */ + this._getAmPm = function(hour24) { + + if (hour24 < 12) + return this.lc.am; + else + return this.lc.pm; + }; +}; + + + +/** + * @class Class for localised formatting of currency amounts. + * + *

    See: + * POSIX LC_MONETARY. + * + * @public + * @constructor + * @description Creates a new monetary formatter for the specified locale. + * + * @param {jsworld.Locale} locale A locale object specifying the required + * POSIX LC_MONETARY formatting properties. + * @param {String} [currencyCode] Set the currency explicitly by + * passing its international ISO-4217 code, e.g. "USD", "EUR", "GBP". + * Use this optional parameter to override the default local currency + * @param {String} [altIntSymbol] Non-local currencies are formatted + * with their international ISO-4217 code to prevent ambiguity. + * Use this optional argument to force a different symbol, such as the + * currency's shorthand sign. This is mostly useful when the shorthand + * sign is both internationally recognised and identifies the currency + * uniquely (e.g. the Euro sign). + * + * @throws Error on constructor failure. + */ +jsworld.MonetaryFormatter = function(locale, currencyCode, altIntSymbol) { + + if (typeof locale != "object" || locale._className != "jsworld.Locale") + throw "Constructor error: You must provide a valid jsworld.Locale instance"; + + this.lc = locale; + + /** + * @private + * @description Lookup table to determine the fraction digits for a + * specific currency; most currencies subdivide at 1/100 (2 fractional + * digits), so we store only those that deviate from the default. + * + *

    The data is from Unicode's CLDR version 1.7.0. The two currencies + * with non-decimal subunits (MGA and MRO) are marked as having no + * fractional digits as well as all currencies that have no subunits + * in circulation. + * + *

    It is "hard-wired" for referential convenience and is only looked + * up when an overriding currencyCode parameter is supplied. + */ + this.currencyFractionDigits = { + "AFN" : 0, "ALL" : 0, "AMD" : 0, "BHD" : 3, "BIF" : 0, + "BYR" : 0, "CLF" : 0, "CLP" : 0, "COP" : 0, "CRC" : 0, + "DJF" : 0, "GNF" : 0, "GYD" : 0, "HUF" : 0, "IDR" : 0, + "IQD" : 0, "IRR" : 0, "ISK" : 0, "JOD" : 3, "JPY" : 0, + "KMF" : 0, "KRW" : 0, "KWD" : 3, "LAK" : 0, "LBP" : 0, + "LYD" : 3, "MGA" : 0, "MMK" : 0, "MNT" : 0, "MRO" : 0, + "MUR" : 0, "OMR" : 3, "PKR" : 0, "PYG" : 0, "RSD" : 0, + "RWF" : 0, "SLL" : 0, "SOS" : 0, "STD" : 0, "SYP" : 0, + "TND" : 3, "TWD" : 0, "TZS" : 0, "UGX" : 0, "UZS" : 0, + "VND" : 0, "VUV" : 0, "XAF" : 0, "XOF" : 0, "XPF" : 0, + "YER" : 0, "ZMK" : 0 + }; + + + // optional currencyCode argument? + if (typeof currencyCode == "string") { + // user wanted to override the local currency + this.currencyCode = currencyCode.toUpperCase(); + + // must override the frac digits too, for some + // currencies have 0, 2 or 3! + var numDigits = this.currencyFractionDigits[this.currencyCode]; + if (typeof numDigits != "number") + numDigits = 2; // default for most currencies + this.lc.frac_digits = numDigits; + this.lc.int_frac_digits = numDigits; + } + else { + // use local currency + this.currencyCode = this.lc.int_curr_symbol.substring(0,3).toUpperCase(); + } + + // extract intl. currency separator + this.intSep = this.lc.int_curr_symbol.charAt(3); + + // flag local or intl. sign formatting? + if (this.currencyCode == this.lc.int_curr_symbol.substring(0,3)) { + // currency matches the local one? -> + // formatting with local symbol and parameters + this.internationalFormatting = false; + this.curSym = this.lc.currency_symbol; + } + else { + // currency doesn't match the local -> + + // do we have an overriding currency symbol? + if (typeof altIntSymbol == "string") { + // -> force formatting with local parameters, using alt symbol + this.curSym = altIntSymbol; + this.internationalFormatting = false; + } + else { + // -> force formatting with intl. sign and parameters + this.internationalFormatting = true; + } + } + + + /** + * @public + * + * @description Gets the currency symbol used in formatting. + * + * @returns {String} The currency symbol. + */ + this.getCurrencySymbol = function() { + + return this.curSym; + }; + + + /** + * @public + * + * @description Gets the position of the currency symbol relative to + * the amount. Assumes a non-negative amount and local formatting. + * + * @param {String} intFlag Optional flag to force international + * formatting by passing the string "i". + * + * @returns {Boolean} True if the symbol precedes the amount, false if + * the symbol succeeds the amount. + */ + this.currencySymbolPrecedes = function(intFlag) { + + if (typeof intFlag == "string" && intFlag == "i") { + // international formatting was forced + if (this.lc.int_p_cs_precedes == 1) + return true; + else + return false; + + } + else { + // check whether local formatting is on or off + if (this.internationalFormatting) { + if (this.lc.int_p_cs_precedes == 1) + return true; + else + return false; + } + else { + if (this.lc.p_cs_precedes == 1) + return true; + else + return false; + } + } + }; + + + /** + * @public + * + * @description Gets the decimal delimiter (radix) used in formatting. + * + * @returns {String} The radix character. + */ + this.getDecimalPoint = function() { + + return this.lc.mon_decimal_point; + }; + + + /** + * @public + * + * @description Gets the number of fractional digits. Assumes local + * formatting. + * + * @param {String} intFlag Optional flag to force international + * formatting by passing the string "i". + * + * @returns {integer Number} The number of fractional digits. + */ + this.getFractionalDigits = function(intFlag) { + + if (typeof intFlag == "string" && intFlag == "i") { + // international formatting was forced + return this.lc.int_frac_digits; + } + else { + // check whether local formatting is on or off + if (this.internationalFormatting) + return this.lc.int_frac_digits; + else + return this.lc.frac_digits; + } + }; + + + /** + * @public + * + * @description Formats a monetary amount according to the preset + * locale. + * + *

    +	 * For local currencies the native shorthand symbol will be used for
    +	 * formatting.
    +	 * Example:
    +	 *        locale is en_US
    +	 *        currency is USD
    +	 *        -> the "$" symbol will be used, e.g. $123.45
    +	 *        
    +	 * For non-local currencies the international ISO-4217 code will be
    +	 * used for formatting.
    +	 * Example:
    +	 *       locale is en_US (which has USD as currency)
    +	 *       currency is EUR
    +	 *       -> the ISO three-letter code will be used, e.g. EUR 123.45
    +	 *
    +	 * If the currency is non-local, but an alternative currency symbol was
    +	 * provided, this will be used instead.
    +	 * Example
    +	 *       locale is en_US (which has USD as currency)
    +	 *       currency is EUR
    +	 *       an alternative symbol is provided - "€"
    +	 *       -> the alternative symbol will be used, e.g. €123.45
    +	 * 
    + * + * @param {Number|String} amount The amount to format as currency. + * @param {String} [options] Options to modify the formatted output: + *
    '; +html += '
    Enter Your Password
    '; +html += '
    '; +html += '
    Password:


    '; +html += '
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "clear_login()") + ' ' + large_icon_button('check', 'Login', 'do_effect_login()') + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ENTER_KEY] = 'do_effect_login'; +session.hooks.keys[ESC_KEY] = 'clear_login'; +safe_focus( 'fe_lp_password' ); +show_popup_dialog(450, 225, html); +} +function clear_login() { +hide_popup_dialog(); +Nav.prev(); +} +function do_login() { +if ($('fe_username').value.match(/^\w+$/)) { +session.username = $('fe_username').value; +session.auto_login = $('fe_auto_login').checked; +do_login_prompt_2(); +return; +} +else { +do_openid_login(); +} +} +function do_openid_login() { +if (!$('fe_username').value) return; +session.openid_win = popup_window(''); +if (!session.openid_win) return; +session.open_id = $('fe_username').value; +session.auto_login = $('fe_auto_login') && $('fe_auto_login').checked; +hide_popup_dialog(); +show_progress_dialog(1, "Logging in..."); +session.hooks.before_error = 'close_openid_window'; +session.hooks.after_error = 'do_login_prompt'; +effect_api_send('openid_login', { +OpenID: session.open_id, +Infinite: session.auto_login ? 1 : 0 +}, 'do_openid_login_2'); +} +function close_openid_window() { +if (session.openid_win) { +session.openid_win.close(); +delete session.openid_win; +} +} +function do_openid_login_2(response) { +if (response.CheckURL) { +Debug.trace('openid', "Redirecting popup window to OpenID Check URL: " + response.CheckURL); +show_progress_dialog(1, "Waiting for popup window...", false, ['x', 'Cancel', 'do_login_prompt()']); +session.openid_win.location = response.CheckURL; +session.openid_win.focus(); +} +} +function receive_openid_response(iframe_response) { +var response = deep_copy_object(iframe_response); +Debug.trace('openid', "Received OpenID Response: " + dumper(response)); +hide_popup_dialog(); +if (response.Code) { +close_openid_window(); +return do_error( response.Description ); +} +delete session.hooks.before_error; +delete session.hooks.after_error; +if (response.SessionID) { +session.cookie.set( 'effect_session_id', response.SessionID ); +session.cookie.save(); +} +switch (response.Action) { +case 'popup': +show_progress_dialog(1, "Waiting for popup window...", false, ['x', 'Cancel', 'do_login_prompt()']); +Debug.trace('openid', "Redirecting popup window to OpenID Setup URL: " + response.SetupURL); +session.openid_win.location = response.SetupURL; +session.openid_win.focus(); +break; +case 'login': +close_openid_window(); +do_login_2(response); +break; +case 'register': +if (!response.Info) response.Info = {}; +close_openid_window(); +Debug.trace('openid', 'Original OpenID: ' + response.OpenID_Login); +Debug.trace('openid', 'Clean OpenID: ' + response.OpenID_Unique); +Debug.trace('openid', 'Registration Info: ' + dumper(response.Info)); +session.prereg = response.Info; +session.prereg.open_id_login = response.OpenID_Login; +session.prereg.open_id = response.OpenID_Unique; +if (session.user) { +if (!session.user.OpenIDs) session.user.OpenIDs = {}; +if (!session.user.OpenIDs.OpenID) session.user.OpenIDs.OpenID = []; +var dupe = find_object( session.user.OpenIDs.OpenID, { Unique: session.prereg.open_id } ); +if (dupe) return do_error("That OpenID is already registered and attached to your account. No need to add it again."); +session.user.OpenIDs.OpenID.push({ +Login: session.prereg.open_id_login, +Unique: session.prereg.open_id +}); +setTimeout( function() { +Nav.go('MyAccount', true); +do_message('success', 'Added new OpenID URL to account.'); +}, 1 ); +} +else { +setTimeout( function() { Nav.go('CreateAccount', true); }, 1 ); +} +break; +} +} +function do_effect_login() { +var password = $('fe_lp_password').value; +session.auto_login = $('fe_auto_login').checked; +hide_popup_dialog(); +show_progress_dialog(1, "Logging in..."); +session.hooks.after_error = 'do_login_prompt'; +effect_api_send('user_login', { +Username: session.username, +Password: password, +Infinite: session.auto_login ? 1 : 0 +}, 'do_login_2'); +} +function do_logout() { +effect_api_send('user_logout', {}, 'do_logout_2'); +} +function do_logout_2(response) { +hide_popup_dialog(); +show_default_login_status(); +delete session.hooks.after_error; +delete session.cookie.tree.effect_session_id; +session.cookie.save(); +session.storage = {}; +session.storage_dirty = false; +delete session.user; +delete session.first_login; +var old_username = session.username; +session.username = ''; +if (Nav.inited) { +Nav.go('Main'); +if (old_username) $GR.growl('success', "Logged out of account: " + old_username); +} +else { +Nav.init(); +} +} +function do_login_2(response, tx) { +if (response.FirstLogin) session.first_login = 1; +if (response.User.UserStorage) { +Debug.trace('Recovering site storage blob: session.storage = ' + response.User.UserStorage + ';'); +try { +eval( 'session.storage = ' + response.User.UserStorage + ';' ); +} +catch (e) { +Debug.trace("SITE STORAGE RECOVERY FAILED: " + e); +session.storage = {}; +} +delete response.User.UserStorage; +session.storage_dirty = false; +} +session.user = response.User; +session.username = session.user.Username; +hide_popup_dialog(); +delete session.hooks.after_error; +update_header(); +if (!tx || !tx._from_recover) $GR.growl('success', "Logged in as: " + session.username); +if (session.nav_after_login) { +Nav.go( session.nav_after_login ); +delete session.nav_after_login; +} +else if (Nav.currentAnchor().match(/^Login/)) { +Nav.go('Home'); +} +else { +Nav.refresh(); +} +Nav.init(); +} +function user_storage_mark() { +Debug.trace("Marking user storage as dirty"); +session.storage_dirty = true; +} +function user_storage_idle() { +if (session.storage_dirty && !session.mouseIsDown) { +user_storage_save(); +session.storage_dirty = false; +} +setTimeout( 'user_storage_idle()', 5000 ); +} +function user_storage_save() { +if (session.user) { +Debug.trace("Committing user storage blob"); +effect_api_send('update_user_storage', { Data: serialize(session.storage) }, 'user_storage_save_finish', { _silent: 1 } ); +} +} +function user_storage_save_finish(response, tx) { +} +function show_default_login_status() { +$('d_sidebar_wrapper_recent_games').hide(); +$('d_login_status').innerHTML = '
    ' + +'
    ' + +large_icon_button('key', "Login", '#Home') + '' + spacer(1,1) + '' + +'' + large_icon_button('user_add.png', "Signup", '#CreateAccount') + '
    ' + +'
    '; +$('d_tagline').innerHTML = +'Login' + ' | ' + +'Create Account'; +} +function update_header() { +var html = ''; +html += '
    '; +html += ''; +html += ''; +html += ''; +html += ''+spacer(2,2)+''; +html += session.user.FullName + '
    '; +html += spacer(1,5) + '
    '; +html += 'My Home  |  '; +html += 'Logout'; +html += '
    '; +$('d_login_status').innerHTML = html; +$('d_tagline').innerHTML = +'Welcome '+session.user.FirstName+'' + ' | ' + +'My Home' + ' | ' + +'Logout'; +effect_api_get( 'get_user_games', { limit:5, offset:0 }, 'receive_sidebar_recent_games', { } ); +} +function receive_sidebar_recent_games(response, tx) { +var html = ''; +if (response.Rows && response.Rows.Row) { +var games = always_array( response.Rows.Row ); +for (var idx = 0, len = games.length; idx < len; idx++) { +var game = games[idx]; +html += ''; +} +html += ''; +$('d_sidebar_recent_games').innerHTML = html; +$('d_sidebar_wrapper_recent_games').show(); +} +else { +$('d_sidebar_wrapper_recent_games').hide(); +} +} +function check_privilege(key) { +if (!session.user) return false; +if (session.user.Privileges.admin == 1) return true; +if (!key.toString().match(/^\//)) key = '/' + key; +var value = lookup_path(key, session.user.Privileges); +return( value && (value != 0) ); +} +function is_admin() { +return check_privilege('admin'); +} +function upgrade_flash_error() { +return alert("Sorry, file upload requires Adobe Flash Player 9 or higher."); +} +function cancel_user_image_manager() { +upload_destroy(); +hide_popup_dialog(); +delete session.hooks.keys[DELETE_KEY]; +} +function do_user_image_manager(callback) { +if (callback) session.uim_callback = callback; +else session.uim_callback = null; +session.temp_last_user_img = null; +session.temp_last_user_image_filename = ''; +var html = '
    '; +html += '
    Image Manager
    '; +html += '
    '; +html += ''; +html += '
    '; +html += '
    '; +html += ''; +html += ''; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', 'cancel_user_image_manager()') + ' ' + large_icon_button('bullet_upload.png', 'Upload Files...', 'upload_basic()', 'b_upload_user_image') + ' ' + large_icon_button('check', 'Choose', 'do_choose_user_image()', 'btn_choose_user_image', '', 'disabled') + '
    '; +html += '
    '; +session.hooks.keys[ENTER_KEY] = 'do_choose_user_image'; +session.hooks.keys[ESC_KEY] = 'cancel_user_image_manager'; +session.hooks.keys[DELETE_KEY] = 'do_delete_selected_user_image'; +show_popup_dialog(500, 300, html); +var self = this; +setTimeout( function() { +prep_upload('b_upload_user_image', '/effect/api/upload_user_image', [self, 'do_upload_user_image_2'], ['Image Files', '*.jpg;*.jpe;*.jpeg;*.gif;*.png']); +}, 1 ); +var args = { +limit: 50, +offset: 0, +random: Math.random() +}; +effect_api_get( 'user_images_get', args, 'uim_populate_images', { } ); +} +function do_upload_user_image_2() { +effect_api_mod_touch('user_images_get'); +effect_api_send('user_get', { +Username: session.username +}, [this, 'do_upload_user_image_3']); +} +function do_upload_user_image_3(response) { +if (response.User.LastUploadError) return do_error( "Failed to upload image: " + response.User.LastUploadError ); +do_user_image_manager( session.uim_callback ); +} +function uim_populate_images(response, tx) { +var html = ''; +var base_url = '/effect/api/view/users/' + session.username + '/images'; +if (response.Rows && response.Rows.Row) { +var imgs = always_array( response.Rows.Row ); +for (var idx = 0, len = imgs.length; idx < len; idx++) { +var img = imgs[idx]; +var class_name = ((img.Filename == session.temp_last_user_image_filename) ? 'choose_item_selected' : 'choose_item'); +html += ''; +} +} +else { +html = ''; +} +$('d_user_image_list').innerHTML = html; +} +function do_select_user_image(img, filename) { +if (session.temp_last_user_img) session.temp_last_user_img.className = 'choose_item'; +img.className = 'choose_item_selected'; +$('btn_choose_user_image').removeClass('disabled'); +session.temp_last_user_img = img; +session.temp_last_user_image_filename = filename; +} +function do_delete_selected_user_image() { +if (session.temp_last_user_image_filename) { +effect_api_send('user_image_delete', { Filename: session.temp_last_user_image_filename }, 'do_delete_selected_user_image_finish', {}); +} +} +function do_delete_selected_user_image_finish(response, tx) { +try { $('d_user_image_list').removeChild( session.temp_last_user_img ); } catch(e) {;} +session.temp_last_user_img = null; +session.temp_last_user_image_filename = null; +} +function do_choose_user_image() { +if (!session.temp_last_user_image_filename) return; +if (session.uim_callback) { +fire_callback( session.uim_callback, session.temp_last_user_image_filename ); +} +cancel_user_image_manager(); +} +function user_image_thumbnail(filename, width, height, attribs) { +var username = session.username; +if (filename.match(/^(\w+)\/(.+)$/)) { +username = RegExp.$1; +filename = RegExp.$2; +} +var url = '/effect/api/view/users/' + username + '/images/' + filename.replace(/\.(\w+)$/, '_thumb.jpg'); +return ''; +} +function get_user_display(username, full_name, base_url) { +if (!base_url) base_url = ''; +return icon('user', full_name || username, base_url + '#User/' + username); +} +function get_game_tab_bar(game_id, cur_page_name) { +return tab_bar([ +['#Game/' + game_id, 'Game', 'controller.png'], +['#GameDisplay/' + game_id, 'Display', 'monitor.png'], +['#GameAssets/' + game_id, 'Assets', 'folder_page_white.png'], +['#GameObjects/' + game_id, 'Objects', 'bricks.png'], +['#GameAudio/' + game_id, 'Audio', 'sound.gif'], +['#GameKeys/' + game_id, 'Keyboard', 'keyboard.png'], +['#GameLevels/' + game_id, 'Levels', 'world.png'], +['#GamePublisher/' + game_id, 'Publish', 'cd.png'] +], cur_page_name); +} +function get_user_tab_bar(cur_page_name) { +var tabs = [ +['#Home', 'My Home', 'house.png'] +]; +tabs.push( ['#MyAccount', 'Edit Account', 'user_edit.png'] ); +tabs.push( ['#ArticleEdit', 'Post Article', 'page_white_edit.png'] ); +if (config.ProEnabled) { +tabs.push( ['#UserPayments', 'Payments', 'money.png'] ); +} +tabs.push( ['#UserLog', 'Security Log', 'application_view_detail.png'] ); +return tab_bar(tabs, cur_page_name); +} +function get_admin_tab_bar(cur_page_name) { +var tabs = []; +tabs.push( ['#Admin', 'Admin', 'lock.png'] ); +tabs.push( ['#TicketSearch/bugs', 'Bug Tracker', 'bug.png'] ); +tabs.push( ['#TicketSearch/helpdesk', 'Help Desk', 'telephone.png'] ); +tabs.push( ['#AdminReport', 'Reports', 'chart_pie.png'] ); +return tab_bar(tabs, cur_page_name); +} +function get_string(path, args) { +assert(window.config, "get_string() called before config loaded"); +if (!args) args = {}; +args.config = config; +args.session = session; +args.query = session.query; +var value = lookup_path(path, config.Strings); +return (typeof(value) == 'string') ? substitute(value, args) : value; +} +function normalize_dir_path(path) { +if (!path.match(/^\//)) path = '/' + path; +if (!path.match(/\/$/)) path += '/'; +return path; +} +function textedit_window_save(storage_key, filename, content, callback) { +if (!callback) callback = null; +effect_api_mod_touch('textedit'); +if (storage_key.match(/^\/games\/([a-z0-9][a-z0-9\-]*[a-z0-9])\/assets(.+)$/)) { +var game_id = RegExp.$1; +var path = RegExp.$2; +show_progress_dialog(1, "Saving file..."); +effect_api_send('asset_save_file_contents', { +GameID: game_id, +Path: path, +Filename: filename, +Content: content +}, 'textedit_window_save_finish', { _mode: 'asset', _game_id: game_id, _filename: filename, _callback: callback } ); +} +else { +show_progress_dialog(1, "Saving data..."); +effect_api_send('admin_save_file_contents', { +Path: storage_key, +Filename: filename, +Content: content +}, 'textedit_window_save_finish', { _mode: 'admin', _storage_key: storage_key, _filename: filename, _callback: callback } ); +} +} +function textedit_window_save_finish(response, tx) { +hide_progress_dialog(); +if (tx._mode == 'asset') { +do_message('success', "Saved asset: \""+tx._filename+"\""); +show_glog_widget(); +} +else { +do_message('success', "Saved data: \""+tx._storage_key+'/'+tx._filename+"\""); +} +if (tx._callback) tx._callback(); +} +function do_buy(args) { +$P().hide(); +$('d_page_loading').show(); +effect_api_send('create_order', args, 'do_buy_redirect', { _buy_args: args } ); +} +function do_buy_redirect(response, tx) { +var args = tx._buy_args; +$('fe_gco_title').value = args.Title || ''; +$('fe_gco_desc').value = args.Desc || ''; +$('fe_gco_price').value = args.Price || ''; +$('fe_gco_after').value = args.After || ''; +$('fe_gco_unique_id').value = response.OrderID; +Debug.trace('payment', "Redirecting to Google Checkout"); +setTimeout( function() { $('BB_BuyButtonForm').submit(); }, 1 ); +} +function show_glog_widget(game_id) { +if (!game_id) game_id = session.glog_game_id; +if (!game_id) { +$('glog_widget').hide(); +return; +} +if (game_id != session.glog_game_id) { +$('glog_widget').hide(); +session.glog_game_id = game_id; +update_glog_widget(game_id); +} +else { +$('glog_widget').show(); +setTimeout( function() { update_glog_widget(game_id); }, 500 ); +} +} +function update_glog_widget(game_id) { +effect_api_get('game_get_log', { +id: game_id, +offset: 0, +limit: 1, +rand: Math.random() +}, 'receive_glog_data', { _game_id: game_id }); +} +function receive_glog_data(response, tx) { +var game_id = tx._game_id; +if (response && response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +var row = rows[0]; +var html = ''; +html += '
    '; +html += '
    Latest Game Activity
    '; +html += ''; +html += ''; +html += '
    '; +html += '
    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + get_buddy_icon_display(row.Username, 1, 0) + ''; +html += '
    ' + icon( get_icon_for_glog_type(row.Type), ''+row.Message+'' ) + '
    '; +html += '
    ' + get_relative_date(row.Date, true) + '
    '; +html += '
    '; +$('glog_widget').innerHTML = html; +$('glog_widget').show(); +} +} +function show_glog_post_dialog(game_id) { +hide_popup_dialog(); +delete session.progress; +var html = ''; +html += '
    '; +html += '\n \n \n \n'); + }; + __out.push('\n\n'); + __out.push(require('templates/clients/modules/sub_header').call(this, { + heading: t("Ride Request") + })); + __out.push('\n\n\n
    \n
    \n
    \n
    \n \n \n \n \n
    \n\n
    '; +html += '
    Post Game Log Message
    '; +html += '
    '; +html += ''; +html += '
    Enter your log message here. Plain text only please.
    '; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Message', "glog_post('"+game_id+"')") + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_glog_body' ); +show_popup_dialog(500, 175, html); +} +function glog_post(game_id) { +var msg = trim( $('fe_glog_body').value ); +if (msg) { +hide_popup_dialog(); +effect_api_send('game_post_log', { +GameID: game_id, +Message: msg +}, [this, 'glog_post_finish'], { _game_id: game_id }); +} +} +function glog_post_finish(response, tx) { +show_glog_widget( tx._game_id ); +} +function hide_glog_widget() { +$('glog_widget').hide(); +} +function get_icon_for_glog_type(type) { +var icon = 'page_white.png'; +switch (type) { +case 'asset': icon = 'folder_page_white.png'; break; +case 'game': icon = 'controller.png'; break; +case 'member': icon = 'user'; break; +case 'comment': icon = 'comment.png'; break; +case 'level': icon = 'world.png'; break; +case 'sprite': icon = 'cog.png'; break; +case 'tile': icon = 'brick.png'; break; +case 'tileset': icon = 'color_swatch.png'; break; +case 'rev': icon = 'cd.png'; break; +case 'revision': icon = 'cd.png'; break; +case 'font': icon = 'style.png'; break; +case 'key': icon = 'keyboard.png'; break; +case 'audio': icon = 'sound'; break; +case 'payment': icon = 'money.png'; break; +case 'env': icon = 'weather.png'; break; +case 'environment': icon = 'weather.png'; break; +} +return icon; +} +function effect_load_script(url) { +Debug.trace('api', 'Loading script: ' + url); +load_script(url); +} +function effect_api_get_ie(cmd, params, userData) { +if (!session.api_state_ie) session.api_state_ie = {}; +var unique_id = get_unique_id(); +session.api_state_ie[unique_id] = userData; +params.format = 'js'; +params.onafter = 'effect_api_response_ie(' + unique_id + ', response);'; +var url = '/effect/api/' + cmd + composeQueryString(params); +Debug.trace('api', "Sending MSIE HTTP GET: " + url); +load_script(url); +} +function effect_api_response_ie(unique_id, tree) { +Debug.trace('api', "Got response from MSIE HTTP GET"); +var tx = session.api_state_ie[unique_id]; +delete session.api_state_ie[unique_id]; +if (tree.Code == 'session') { +do_logout_2(); +return; +} +if (tree.Code == 'access') { +do_notice("Access Denied", tree.Description, 'do_not_pass_go'); +return; +} +if (tree.Code != 0) { +if (tx._on_error) return fire_callback( tx._on_error, tree, tx ); +return do_error( tree.Description ); +} +if (tree.SessionID) { +if (tree.SessionID == '_DELETE_') { +delete session.cookie.tree.effect_session_id; +} +else { +session.cookie.set( 'effect_session_id', tree.SessionID ); +} +session.cookie.save(); +} +if (tx._api_callback) { +fire_callback( tx._api_callback, tree, tx ); +} +} +function effect_api_get(cmd, params, callback, userData) { +if (!userData) userData = {}; +userData._api_callback = callback; +if (!session.api_mod_cache[cmd] && session.username) session.api_mod_cache[cmd] = hires_time_now(); +if (!params.mod && session.api_mod_cache[cmd]) params.mod = session.api_mod_cache[cmd]; +if (ie) return effect_api_get_ie(cmd, params, userData); +var url = '/effect/api/' + cmd + composeQueryString(params); +Debug.trace('api', "Sending HTTP GET: " + url); +ajax.get( url, 'effect_api_response', userData ); +} +function effect_api_send(cmd, xml, callback, userData) { +if (!userData) userData = {}; +userData._api_callback = callback; +var data = compose_xml('EffectRequest', xml); +Debug.trace('api', "Sending API Command: " + cmd + ": " + data); +ajax.send({ +method: 'POST', +url: '/effect/api/' + cmd, +data: data, +headers: { 'Content-Type': 'text/xml' } +}, 'effect_api_response', userData); +} +function effect_api_response(tx) { +Debug.trace('api', "HTTP " + tx.response.code + ": " + tx.response.data); +if (tx.response.code == 999) { +if (tx.request._auto_retry) { +session.net_error = false; +show_progress_dialog(1, "Trying to reestablish connection..."); +session.net_error = true; +setTimeout( function() { ajax.send(tx.request); }, 1000 ); +return; +} +else return do_error( "HTTP ERROR: " + tx.response.code + ": " + tx.response.data + ' (URL: ' + tx.request.url + ')' ); +} +if (session.net_error) { +hide_progress_dialog(); +session.net_error = false; +} +if (tx.response.code != 200) { +if (tx._silent) return; +else return do_error( "HTTP ERROR: " + tx.response.code + ": " + tx.response.data + ' (URL: ' + tx.request.url + ')' ); +} +var tree = null; +if (!tx._raw) { +var parser = new XML({ +preserveAttributes: true, +text: tx.response.data +}); +if (parser.getLastError()) return do_error("XML PARSE ERROR: " + parser.getLastError()); +tree = parser.getTree(); +if (tree.Code == 'session') { +do_logout_2(); +return; +} +if (tree.Code == 'access') { +do_notice("Access Denied", tree.Description, 'do_not_pass_go'); +return; +} +if (tree.Code != 0) { +if (tx._on_error) return fire_callback( tx._on_error, tree, tx ); +return do_error( tree.Description ); +} +if (tree.SessionID) { +if (tree.SessionID == '_DELETE_') { +delete session.cookie.tree.effect_session_id; +} +else { +session.cookie.set( 'effect_session_id', tree.SessionID ); +} +session.cookie.save(); +} +} +if (tx._api_callback) { +fire_callback( tx._api_callback, tree, tx ); +} +} +function effect_api_mod_touch() { +for (var idx = 0, len = arguments.length; idx < len; idx++) { +session.api_mod_cache[ arguments[idx] ] = hires_time_now(); +} +} +function do_not_pass_go() { +Nav.go('Main'); +} +var Nav = { +loc: '', +old_loc: '', +inited: false, +nodes: [], +init: function() { +if (!this.inited) { +this.inited = true; +this.loc = 'init'; +this.monitor(); +} +}, +monitor: function() { +var parts = window.location.href.split(/\#/); +var anchor = parts[1]; +if (!anchor) anchor = 'Main'; +var full_anchor = '' + anchor; +var sub_anchor = ''; +anchor = anchor.replace(/\%7C/, '|'); +if (anchor.match(/\|(\w+)$/)) { +sub_anchor = RegExp.$1.toLowerCase(); +anchor = anchor.replace(/\|(\w+)$/, ''); +} +if ((anchor != this.loc) && !anchor.match(/^_/)) { +Debug.trace('nav', "Caught navigation anchor: " + full_anchor); +var page_name = ''; +var page_args = null; +if (full_anchor.match(/^\w+\?.+/)) { +parts = full_anchor.split(/\?/); +page_name = parts[0]; +page_args = parseQueryString( parts[1] ); +} +else if (full_anchor.match(/^(\w+)\/(.*)$/)) { +page_name = RegExp.$1; +page_args = RegExp.$2; +} +else { +parts = full_anchor.split(/\//); +page_name = parts[0]; +page_args = parts.slice(1); +} +Debug.trace('nav', "Calling page: " + page_name + ": " + serialize(page_args)); +hide_popup_dialog(); +var result = page_manager.click( page_name, page_args ); +if (result) { +if (window.pageTracker && (this.loc != 'init')) { +setTimeout( function() { pageTracker._trackPageview('/effect/' + anchor); }, 1000 ); +} +this.old_loc = this.loc; +if (this.old_loc == 'init') this.old_loc = 'Main'; +this.loc = anchor; +} +else { +this.go( this.loc ); +} +} +else if (sub_anchor != this.sub_anchor) { +Debug.trace('nav', "Caught sub-anchor: " + sub_anchor); +$P().gosub( sub_anchor ); +} +this.sub_anchor = sub_anchor; +setTimeout( 'Nav.monitor()', 100 ); +}, +go: function(anchor, force) { +anchor = anchor.replace(/^\#/, ''); +if (force) this.loc = 'init'; +window.location.href = '#' + anchor; +}, +prev: function() { +this.go( this.old_loc || 'Main' ); +}, +refresh: function() { +this.loc = 'refresh'; +}, +bar: function() { +var nodes = arguments; +var html = ''; +for (var idx = 0, len = nodes.length; idx < len; idx++) { +var node = nodes[idx]; +if (node) this.nodes[idx] = node; +else node = this.nodes[idx]; +if (node != '_ignore_') { +html += ''; +} +} +html += '
    '; +$('d_nav_bar').innerHTML = html; +}, +title: function(name) { +if (name) document.title = name + ' | EffectGames.com'; +else document.title = 'EffectGames.com'; +}, +currentAnchor: function() { +var parts = window.location.href.split(/\#/); +var anchor = parts[1] || ''; +var sub_anchor = ''; +anchor = anchor.replace(/\%7C/, '|'); +if (anchor.match(/\|(\w+)$/)) { +sub_anchor = RegExp.$1.toLowerCase(); +anchor = anchor.replace(/\|(\w+)$/, ''); +} +return anchor; +} +}; +var Blog = { +edit_caption: '
    *Bold*  |Italic|  {monospace}  [http://link]  Formatting Guide...
    ', +search: function(args) { +if (!args.mode) args.mode = 'and'; +if (!args.offset) args.offset = 0; +if (!args.limit) args.limit = 10; +if (!args.format) args.format = 'xml'; +var query_args = copy_object( args ); +delete query_args.callback; +effect_api_get( 'article_search', query_args, [this, 'search_response'], { _search_args: args } ); +}, +get_article_preview: function(row, args) { +var html = ''; +Debug.trace('blog', 'Row: ' + dumper(row)); +html += '
    '; +var ext_article_url = 'http://' + location.hostname + '/effect/article.psp.html' + row.Path + '/' + row.ArticleID; +var article_url = '#Article' + row.Path + '/' + row.ArticleID; +html += ''; +if (!args.title_only) { +html += '
    '; +html += row.Preview; +html += '  ' + (args.link_title || 'Read Full Story...') + ''; +html += '
    '; +html += ''; +html += '
    '; +var elem_class = args.footer_element_class || 'blog_preview_footer_element'; +if ((session.username == row.Username) || is_admin()) { +html += '
    ' + +icon('page_white_edit.png', "Edit", '#ArticleEdit?path=' + row.Path + '&id=' + row.ArticleID) + '
    '; +} +html += '
    ' + get_user_display(row.Username) + '
    '; +html += '
    ' + icon('calendar', get_short_date_time(row.Published)) + '
    '; +html += '
    ' + icon('talk', row.Comments) + '
    '; +if (0 && row.Tags) html += '
    ' + icon('note.png', make_tag_links(row.Tags, 3)) + '
    '; +html += '
    ' + icon('facebook.png', 'Facebook', "window.open('http://www.facebook.com/sharer.php?u="+encodeURIComponent(ext_article_url)+'&t='+encodeURIComponent(row.Title)+"','sharer','toolbar=0,status=0,width=626,height=436')", "Share on Facebook") + '
    '; +html += '
    ' + icon('twitter.png', 'Twitter', "window.open('http://twitter.com/home?status=Reading%20" + encodeURIComponent(row.Title) + "%3A%20" + encodeURIComponent(ext_article_url)+"')", "Share on Twitter") + '
    '; +html += '
    '; +html += '
    '; +html += '
    '; +} +html += '
    '; +return html; +}, +search_response: function(response, tx) { +var args = tx._search_args; +if (args.callback) return fire_callback(args.callback, response, args); +var div = $(args.target); +assert(div, "Could not find target DIV: " + args.target); +var html = ''; +if (response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +html += this.get_article_preview( row, args ); +} +if (args.more && (rows.length == args.limit)) { +html += large_icon_button('page_white_put.png', 'More...', "Blog.more(this, "+encode_object(args)+")") + '
    '; +html += spacer(1,15) + '
    '; +} +if (args.after) html += args.after; +} +else if (response.Code != 0) { +html = 'Search Error: ' . response.Code + ': ' + response.Description; +} +else { +html = args.none_found_msg || 'No articles found.'; +} +div.innerHTML = html; +}, +more: function(div, args) { +args.offset += args.limit; +Debug.trace('blog', "More Args: " + dumper(args)); +div.innerHTML = ''; +effect_api_get( 'article_search', args, [this, 'more_response'], { _search_args: args, _div: div } ); +}, +more_response: function(response, tx) { +var args = tx._search_args; +var button = tx._div; +var html = ''; +if (response.Rows && response.Rows.Row) { +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +html += this.get_article_preview( row, args ); +} +if (args.more && (rows.length == args.limit)) { +html += large_icon_button('page_white_put.png', 'More...', "Blog.more(this, "+encode_object(args)+")") + '
    '; +html += spacer(1,15) + '
    '; +} +} +else if (response.Code != 0) { +html = 'Search Error: ' . response.Code + ': ' + response.Description; +} +else { +html = args.none_found_msg || 'No more articles found.'; +} +var div = document.createElement('div'); +div.innerHTML = html; +button.parentNode.replaceChild( div, button ); +} +}; +function make_tag_links(csv, max, base_url) { +if (!base_url) base_url = ''; +var tags = csv.split(/\,\s*/); +var append = ''; +if (max && (tags.length > max)) { +tags.length = max; +append = '...'; +} +var html = ''; +for (var idx = 0, len = tags.length; idx < len; idx++) { +html += ''+tags[idx]+''; +if (idx < len - 1) html += ', '; +} +html += append; +return html; +} +function get_url_friendly_title(title) { +title = title.toString().replace(/\W+/g, '_'); +if (title.length > 40) title = title.substring(0, 40); +title = title.replace(/^_+/, ''); +title = title.replace(/_+$/, ''); +return title; +} +function get_full_url(url) { +if (url.match(/^\#/)) { +var parts = window.location.href.split(/\#/); +url = parts[0] + url; +} +return url; +} +var Comments = { +comments_per_page: 10, +get: function(page_id) { +var html = ''; +html += '
    '; +html += '
    Comments'; +html += '
    '; +html += '
    '; +html += '
    '; +setTimeout( function() { Comments.search({ page_id: page_id }); }, 1 ); +return html; +}, +search: function(args) { +if (!args.limit) args.limit = this.comments_per_page; +if (!args.offset) args.offset = 0; +assert(args.page_id, "Comments.search: No page_id specified"); +args.format = 'xml'; +this.last_search = args; +effect_api_get( 'comments_get', args, [this, 'search_response'], { _search_args: args } ); +}, +research: function(offset) { +var args = this.last_search; +if (!args) return; +args.offset = offset; +effect_api_get( 'comments_get', args, [this, 'search_response'], { _search_args: args } ); +}, +search_response: function(response, tx) { +this.comments = []; +var args = tx._search_args; +if (args.callback) return fire_callback(args.callback, response, args); +var html = ''; +html += '
    ' + +large_icon_button( 'comment_edit.png', 'Post Comment...', "Comments.add('"+args.page_id+"')" ) + '
    '; +if (args.page_id.match(/^Article\//)) { +html += '
    ' + icon('feed.png', 'RSS', '/effect/api/comment_feed/' + args.page_id + '.rss', 'Comments RSS Feed') + '
    '; +} +if (response.Items && response.Items.Item && response.List && response.List.length) { +html += ''; +html += '
    '; +var items = this.comments = always_array( response.Items.Item ); +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var extra_classes = (args.highlight && (args.highlight == item.ID)) ? ' highlight' : ''; +html += '
    '; +html += '
    '; +if (item.Username) html += ''; +html += '' + item.Name.toString().toUpperCase() + ''; +if (item.Username) html += ''; +html += ', ' + get_short_date_time(item.Date) + '
    '; +html += '
    '; +html += this.get_comment_controls( args.page_id, item ); +html += '
    '; +html += '
    '; +html += '
    ' + item.Comment + '
    '; +html += '
    '; +html += ''; +if (item.LastReply && ((item.LastReply >= time_now() - (86400 * 7)) || (session.username && (session.username == item.Username)))) { +setTimeout( "Comments.show_replies('"+args.page_id+"','"+item.ID+"')", 1 ); +} +} +} +else { +} +$( 'd_comments_' + args.page_id ).innerHTML = html; +}, +get_control: function(icon, code, text, status_text) { +if (!icon.match(/\.\w+$/)) icon += '.gif'; +return '' + code_link(code, text, status_text) + ''; +}, +get_comment_controls: function(page_id, comment) { +var html = ''; +var spacer_txt = '  |  '; +if (session.user) { +html += this.get_control('comment', "Comments.reply('"+page_id+"','"+comment.ID+"')", 'Reply') + spacer_txt; +} +if (comment.Replies) { +if (comment._replies_visible) html += this.get_control('magnify_minus', "Comments.hide_replies('"+page_id+"','"+comment.ID+"')", 'Hide Replies'); +else html += this.get_control('magnify_plus', "Comments.show_replies('"+page_id+"','"+comment.ID+"')", 'Show Replies ('+comment.Replies+')'); +if (session.user) html += spacer_txt; +} +if (session.user) { +html += this.get_control( +'star', +"Comments.like('"+page_id+"','"+comment.ID+"')", +'Like' + (comment.Like ? (' ('+comment.Like+')') : ''), +comment.Like ? (comment.Like + ' ' + ((comment.Like == 1) ? 'person likes this' : 'people like this')) : 'I like this comment' +) + spacer_txt; +if (is_admin()) html += this.get_control('trash', "Comments._delete('"+page_id+"','"+comment.ID+"')", 'Delete') + spacer_txt; +html += this.get_control('warning', "Comments.report('"+page_id+"','"+comment.ID+"')", 'Report Abuse'); +} +return html; +}, +reply: function(page_id, comment_id) { +hide_popup_dialog(); +delete session.progress; +var comment = find_object( this.comments, { ID: comment_id } ); +var html = ''; +html += '
    '; +html += '\n \n \n \n \n \n \n \n \n \n '); + }, this); + __out.push('\n\n
    \n
    '; +html += '
    Reply to Comment by "'+comment.Name+'"
    '; +html += '
    '; +var name = this.get_name(); +html += '

    Posted by: ' + name; +if (!session.user) html += ' → Create Account'; +html += '


    '; +html += ''; +html += Blog.edit_caption; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Reply', "Comments.post_reply('"+page_id+"','"+comment_id+"')") + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_comment_body' ); +show_popup_dialog(600, 300, html); +}, +post_reply: function(page_id, comment_id) { +var value = $('fe_comment_body').value; +if (!value) return; +hide_popup_dialog(); +show_progress_dialog(1, "Posting reply..."); +var name = this.get_name(); +effect_api_mod_touch('comment_replies_get'); +effect_api_send('comment_post_reply', { +PageID: page_id, +CommentID: comment_id, +Username: session.username || '', +Name: name, +Comment: value, +PageURL: location.href +}, [this, 'post_reply_finish'], { _page_id: page_id, _comment_id: comment_id } ); +}, +post_reply_finish: function(response, tx) { +hide_popup_dialog(); +var page_id = tx._page_id; +var comment_id = tx._comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +do_message('success', "Comment reply posted successfully."); +this.show_replies(page_id, comment_id); +if (!comment.Replies) comment.Replies = 1; else comment.Replies++; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +show_replies: function(page_id, comment_id) { +var comment = find_object( this.comments, { ID: comment_id } ); +if (!comment._replies_visible) { +$('d_comment_replies_' + comment_id).show().innerHTML = ''; +} +var args = { page_id: page_id, comment_id: comment_id, offset: 0, limit: 100 }; +effect_api_get( 'comment_replies_get', args, [this, 'receive_replies_response'], { _search_args: args } ); +}, +receive_replies_response: function(response, tx) { +var page_id = tx._search_args.page_id; +var comment_id = tx._search_args.comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +var html = ''; +var replies = always_array( response.Items.Item ); +for (var idx = 0, len = replies.length; idx < len; idx++) { +var reply = replies[idx]; +html += get_chat_balloon( +(reply.Username == session.username) ? 'blue' : 'grey', +reply.Username, +reply.Comment.replace(/^]*?>(.+)<\/div>$/i, '$1') +); +} +$('d_comment_replies_' + comment_id).innerHTML = html; +if (!comment._replies_visible) { +$('d_comment_replies_' + comment_id).hide(); +animate_div_visibility( 'd_comment_replies_' + comment_id, true ); +} +comment._replies_visible = true; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +hide_replies: function(page_id, comment_id) { +var comment = find_object( this.comments, { ID: comment_id } ); +if (comment._replies_visible) { +animate_div_visibility( 'd_comment_replies_' + comment_id, false ); +comment._replies_visible = false; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +} +}, +like: function(page_id, comment_id) { +effect_api_mod_touch('comments_get'); +effect_api_send('comment_like', { +PageID: page_id, +CommentID: comment_id +}, [this, 'like_finish'], { _page_id: page_id, _comment_id: comment_id, _on_error: [this, 'like_error'] } ); +}, +like_error: function(response, tx) { +if (response.Code == 'comment_already_like') do_message('error', "You already like this comment."); +else do_error( response.Description ); +}, +like_finish: function(resopnse, tx) { +var page_id = tx._page_id; +var comment_id = tx._comment_id; +var comment = find_object( this.comments, { ID: comment_id } ); +do_message('success', "You now like this comment."); +if (!comment.Like) comment.Like = 1; else comment.Like++; +$('d_comment_controls_'+comment_id).innerHTML = this.get_comment_controls( page_id, comment ); +}, +add: function(page_id) { +hide_popup_dialog(); +delete session.progress; +var html = ''; +html += '
    '; +html += '", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "
    '; +html += '
    Post New Comment
    '; +html += '
    '; +var name = this.get_name(); +html += '

    Posted by: ' + name; +if (!session.user) html += ' → Create Account'; +html += '


    '; +html += ''; +html += Blog.edit_caption; +html += '
    '; +html += '

    '; +html += ''; +html += ''; +html += ''; +html += '
    ' + large_icon_button('x', 'Cancel', "hide_popup_dialog()") + ' ' + large_icon_button('check', 'Post Comment', "Comments.post('"+page_id+"')") + '
    '; +html += '
    '; +html += ''; +session.hooks.keys[ESC_KEY] = 'hide_popup_dialog'; +safe_focus( 'fe_comment_body' ); +show_popup_dialog(600, 300, html); +}, +report: function(page_id, comment_id) { +if (confirm('Are you sure you want to report this comment to the site administrators as abusive and/or spam?')) { +effect_api_send('comment_report_abuse', { +PageID: page_id, +CommentID: comment_id +}, [this, 'report_finish'], { _page_id: page_id, _comment_id: comment_id } ); +} +}, +report_finish: function(response, tx) { +do_message('success', 'Your abuse report has been received, and will be evaluated by the site administrators.'); +}, +_delete: function(page_id, comment_id) { +if (confirm('Are you sure you want to permanently delete this comment?')) { +effect_api_mod_touch('comments_get'); +effect_api_send('comment_delete', { +PageID: page_id, +CommentID: comment_id +}, [this, 'delete_finish'], { _page_id: page_id, _comment_id: comment_id } ); +} +}, +delete_finish: function(response, tx) { +do_message('success', 'The comment was deleted successfully.'); +var page_id = tx._page_id; +this.search({ page_id: page_id }); +}, +get_name: function() { +var name = '(Anonymous)'; +if (session.user) { +if (get_bool_pref('public_profile')) name = session.user.FullName; +else name = session.username; +} +return name; +}, +post: function(page_id) { +var value = $('fe_comment_body').value; +if (!value) return; +hide_popup_dialog(); +show_progress_dialog(1, "Posting comment..."); +var name = this.get_name(); +effect_api_mod_touch('comments_get'); +effect_api_send('comment_post', { +PageID: page_id, +Username: session.username || '', +Name: name, +Comment: value +}, [this, 'post_finish'], { _page_id: page_id } ); +}, +post_finish: function(response, tx) { +hide_popup_dialog(); +var comment_id = response.CommentID; +var page_id = tx._page_id; +this.search({ page_id: page_id, highlight: comment_id }); +} +}; +Class.create( 'Menu', { +id: '', +menu: null, +__construct: function(id) { +this.id = id; +}, +load: function() { +if (!this.menu) { +this.menu = $(this.id); +assert( !!this.menu, "Could not locate DOM element: " + this.id ); +} +}, +get_value: function() { +this.load(); +return this.menu.options[this.menu.selectedIndex].value; +}, +set_value: function(value, auto_add) { +value = str_value(value); +this.load(); +for (var idx = 0, len = this.menu.options.length; idx < len; idx++) { +if (this.menu.options[idx].value == value) { +this.menu.selectedIndex = idx; +return true; +} +} +if (auto_add) { +this.menu.options[this.menu.options.length] = new Option(value, value); +this.menu.selectedIndex = this.menu.options.length - 1; +return true; +} +return false; +}, +disable: function() { +this.load(); +this.menu.disabled = true; +this.menu.setAttribute( 'disabled', 'disabled' ); +}, +enable: function() { +this.load(); +this.menu.setAttribute( 'disabled', '' ); +this.menu.disabled = false; +}, +populate: function(items, sel_value) { +this.load(); +this.menu.options.length = 0; +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var item_name = ''; +var item_value = ''; +if (isa_hash(item)) { +item_name = item.label; +item_value = item.data; +} +else if (isa_array(item)) { +item_name = item[0]; +item_value = item[1]; +} +else { +item_name = item_value = item; +} +this.menu.options[ this.menu.options.length ] = new Option( item_name, item_value ); +if (item_value == sel_value) this.menu.selectedIndex = idx; +} +} +} ); +Class.subclass( Menu, 'MultiMenu', { +__static: { +toggle_type: function(id) { +var menu = $(id); +assert(menu, "Could not find menu in DOM: " + id); +if (menu.disabled) return; +var obj = MenuManager.find(id); +assert(obj, "Could not find menu in MenuManager: " + id); +var div = $( 'd_inner_' + id ); +var ic = $( 'ic_' + id ); +var is_multiple = (ic.src.indexOf('contract') > -1); +obj.multi = !is_multiple; +var multiple_tag = !is_multiple ? +' multiple="multiple" size=5' : ''; +var items = []; +for (var idx = 0; idx < menu.options.length; idx++) { +var option = menu.options[idx]; +array_push( items, { +value: option.value, +text: option.text, +selected: option.selected +}); +} +var html = ''; +html += ''; +div.innerHTML = html; +ic.src = images_uri + '/menu_' + (is_multiple ? 'expand' : 'contract') + '.gif'; +obj.menu = null; +} +}, +attribs: null, +multi: false, +toggle: true, +__construct: function(id, attribs) { +this.id = id; +if (attribs) this.attribs = attribs; +}, +get_html: function(items, selected_csv, attribs) { +if (!items) items = []; +if (!selected_csv) selected_csv = ''; +if (attribs) this.attribs = attribs; +var selected = csv_to_hash(selected_csv); +this.menu = null; +if (num_keys(selected) > 1) this.multi = true; +var html = '
    '; +html += ''; +html += ''; +html += ''; +if (this.toggle) html += ''; +html += '
    ' + spacer(1,1) + '
    '+spacer(1,2)+'
    '; +html += '
    '; +return html; +}, +get_value: function() { +this.load(); +var value = ''; +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +if (option.selected && option.value.length) { +if (value.length > 0) value += ','; +value += option.value; +} +} +return value; +}, +set_value: function(value, auto_add) { +value = '' + value; +this.load(); +if (!value) { +value = ''; +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +option.selected = (option.value == value); +} +return; +} +var selected = csv_to_hash(value); +if ((num_keys(selected) > 1) && !this.multi) { +MultiMenu.toggle_type(this.id); +var self = this; +setTimeout( function() { +self.set_value(value, auto_add); +}, 1 ); +return; +} +for (var idx = 0; idx < this.menu.options.length; idx++) { +var option = this.menu.options[idx]; +option.selected = selected[option.value] ? true : false; +} +}, +populate: function(items, value) { +this.load(); +this.menu.options.length = 0; +if (!value) value = ''; +var selected = csv_to_hash(value); +for (var idx = 0, len = items.length; idx < len; idx++) { +var item = items[idx]; +var item_name = ''; +var item_value = ''; +if (isa_hash(item)) { +item_name = item.label; +item_value = item.data; +} +else if (isa_array(item)) { +item_name = item[0]; +item_value = item[1]; +} +else { +item_name = item_value = item; +} +var opt = new Option( item_name, item_value ); +this.menu.options[ this.menu.options.length ] = opt; +opt.selected = selected[item_value] ? true : false; +} +}, +collapse: function() { +if (this.multi) MultiMenu.toggle_type(this.id); +}, +expand: function() { +if (!this.multi) MultiMenu.toggle_type(this.id); +} +} ); +Class.create( 'MenuManager', { +__static: { +menus: {}, +register: function(menu) { +this.menus[ menu.id ] = menu; +return menu; +}, +find: function(id) { +return this.menus[id]; +} +} +} ); +Class.create( 'GrowlManager', { +lifetime: 10, +marginRight: 0, +marginTop: 0, +__construct: function() { +this.growls = []; +}, +growl: function(type, msg) { +if (find_object(this.growls, { type: type, msg: msg })) return; +var div = $(document.createElement('div')); +div.className = 'growl_message ' + type; +div.setOpacity(0.0); +div.innerHTML = '
    ' + msg + '
    ' + spacer(1,5) + '
    '; +$('d_growl_wrapper').insertBefore( div, $('d_growl_top').nextSibling ); +var growl = { id:get_unique_id(), type: type, msg: msg, opacity:0.0, start:hires_time_now(), div:div }; +this.growls.push(growl); +this.handle_resize(); +this.animate(growl); +var self = this; +div.onclick = function() { +delete_object(self.growls, { id: growl.id }); +$('d_growl_wrapper').removeChild( div ); +}; +}, +animate: function(growl) { +if (growl.deleted) return; +var now = hires_time_now(); +var div = growl.div; +if (now - growl.start <= 0.5) { +div.setOpacity( tweenFrame(0.0, 1.0, (now - growl.start) * 2, 'EaseOut', 'Quadratic') ); +} +else if (now - growl.start <= this.lifetime) { +if (!growl._fully_opaque) { +div.setOpacity( 1.0 ); +growl._fully_opaque = true; +} +} +else if (now - growl.start <= this.lifetime + 1.0) { +div.setOpacity( tweenFrame(1.0, 0.0, (now - growl.start) - this.lifetime, 'EaseOut', 'Quadratic') ); +} +else { +delete_object(this.growls, { id: growl.id }); +$('d_growl_wrapper').removeChild( div ); +return; +} +var self = this; +setTimeout( function() { self.animate(growl); }, 33 ); +}, +handle_resize: function() { +var div = $('d_growl_wrapper'); +if (this.growls.length) { +var size = getInnerWindowSize(); +div.style.top = '' + (10 + this.marginTop) + 'px'; +div.style.left = '' + Math.floor((size.width - 310) - this.marginRight) + 'px'; +} +else { +div.style.left = '-2000px'; +} +} +} ); +window.$GR = new GrowlManager(); +if (window.addEventListener) { +window.addEventListener( "resize", function() { +$GR.handle_resize(); +}, false ); +} +else if (window.attachEvent && !ie6) { +window.attachEvent("onresize", function() { +$GR.handle_resize(); +}); +} +Class.create( 'Effect.Page', { +ID: '', +data: null, +active: false, +__construct: function(config) { +if (!config) return; +this.data = {}; +if (!config) config = {}; +for (var key in config) this[key] = config[key]; +this.div = $('page_' + this.ID); +assert(this.div, "Cannot find page div: page_" + this.ID); +}, +onInit: function() { +}, +onActivate: function() { +return true; +}, +onDeactivate: function() { +return true; +}, +show: function() { +this.div.show(); +}, +hide: function() { +this.div.hide(); +}, +gosub: function(anchor) { +} +} ); +Class.require( 'Effect.Page' ); +Class.create( 'Effect.PageManager', { +pages: null, +current_page_id: '', +on_demand: {}, +__construct: function(page_list) { +this.pages = []; +this.page_list = page_list; +for (var idx = 0, len = page_list.length; idx < len; idx++) { +Debug.trace( 'page', "Initializing page: " + page_list[idx].ID ); +if (Effect.Page[ page_list[idx].ID ]) { +var page = new Effect.Page[ page_list[idx].ID ]( page_list[idx] ); +page.onInit(); +this.pages.push(page); +} +else { +Debug.trace( 'page', 'Page ' + page_list[idx].ID + ' will be loaded on-demand' ); +} +} +}, +find: function(id) { +var page = find_object( this.pages, { ID: id } ); +if (!page) Debug.trace('PageManager', "Could not find page: " + id); +return page; +}, +notify_load: function(file, id) { +for (var idx = 0, len = this.page_list.length; idx < len; idx++) { +var page_config = this.page_list[idx]; +if (page_config.File == file) { +Debug.trace( 'page', "Initializing page on-demand: " + page_config.ID ); +var page = new Effect.Page[ page_config.ID ]( page_config ); +page.onInit(); +this.pages.push(page); +} +} +var self = this; +setTimeout( function() { +var result = self.activate(id, self.temp_args); +delete self.temp_args; +$('d_page_loading').hide(); +if (!result) { +$('page_'+id).hide(); +self.current_page_id = ''; +} +}, 1 ); +}, +activate: function(id, args) { +if (!find_object( this.pages, { ID: id } )) { +var page_config = find_object( this.page_list, { ID: id } ); +assert(!!page_config, "Page config not found: " + id ); +Debug.trace('page', "Loading file on-demand: " + page_config.File + " for page: " + id); +var url = '/effect/api/load_page/' + page_config.File + '?onafter=' + escape('page_manager.notify_load(\''+page_config.File+'\',\''+id+'\')'); +if (page_config.Requires) { +var files = page_config.Requires.split(/\,\s*/); +for (var idx = 0, len = files.length; idx < len; idx++) { +var filename = files[idx]; +if (!this.on_demand[filename]) { +Debug.trace('page', "Also loading file: " + filename); +url += '&file=' + filename; +this.on_demand[filename] = 1; +} +} +} +$('d_page_loading').show(); +this.temp_args = args; +load_script( url ); +return true; +} +$('page_'+id).show(); +var page = this.find(id); +page.active = true; +if (!args) args = []; +if (!isa_array(args)) args = [ args ]; +var result = page.onActivate.apply(page, args); +if (typeof(result) == 'boolean') return result; +else return alert("Page " + id + " onActivate did not return a boolean!"); +}, +deactivate: function(id, new_id) { +var page = this.find(id); +var result = page.onDeactivate(new_id); +if (result) { +$('page_'+id).hide(); +page.active = false; +} +return result; +}, +click: function(id, args) { +Debug.trace('page', "Switching pages to: " + id); +var old_id = this.current_page_id; +if (this.current_page_id) { +var result = this.deactivate( this.current_page_id, id ); +if (!result) return false; +} +this.current_page_id = id; +this.old_page_id = old_id; +window.scrollTo( 0, 0 ); +var result = this.activate(id, args); +if (!result) { +$('page_'+id).hide(); +this.current_page_id = ''; +} +return true; +} +} ); +Class.subclass( Effect.Page, "Effect.Page.Main", { +inited: false, +onActivate: function() { +Nav.bar( ['Main', 'EffectGames.com'] ); +Nav.title(''); +$('d_blog_news').innerHTML = loading_image(); +$('d_blog_community').innerHTML = loading_image(); +$('d_blog_featured').innerHTML = loading_image(); +Blog.search({ +stag: 'featured_game', +limit: 4, +full: 1, +callback: [this, 'receive_featured_games'] +}); +effect_api_get( 'get_site_info', { cat: 'pop_pub_games' }, [this, 'receive_pop_pub_games'], { } ); +Blog.search({ +stag: 'front_page', +limit: 5, +target: 'd_blog_news', +more: 1 +}); +Blog.search({ +path: '/community', +limit: 5, +target: 'd_blog_community', +more: 1 +}); +if (!this.inited) { +this.inited = true; +config.Strings.MainSlideshow.Slide = always_array( config.Strings.MainSlideshow.Slide ); +this.slide_idx = 0; +this.num_slides = config.Strings.MainSlideshow.Slide.length; +this.slide_div_num = 0; +this.slide_dir = 1; +this.bk_pos = -340; +this.bk_pos_target = -340; +this.slide_images = []; +for (var idx = 0, len = this.num_slides; idx < len; idx++) { +var url = images_uri + '/' + config.Strings.MainSlideshow.Slide[idx].Photo; +this.slide_images[idx] = new Image(); +this.slide_images[idx].src = png(url, true); +} +} +this.height_target = 470; +this.height_start = $('d_header').offsetHeight; +this.time_start = hires_time_now(); +this.duration = 0.75; +if (!this.timer) this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +if (session.user) $('d_blurb_main').hide(); +else { +$('d_blurb_main').innerHTML = get_string('/Main/Blurb'); +$('d_blurb_main').show(); +} +return true; +}, +receive_pop_pub_games: function(response, tx) { +var html = ''; +if (response.Data && response.Data.Games && response.Data.Games.Game) { +var games = always_array( response.Data.Games.Game ); +for (var idx = 0, len = Math.min(games.length, 16); idx < len; idx++) { +var game = games[idx]; +html += '
    ' + +(game.Logo ? +user_image_thumbnail(game.Logo, 80, 60) : +'' +) + '
    ' + ww_fit_box(game.Title, 80, 2, session.em_width, 1) + '
    '; +} +html += '
    '; +} +else { +html += 'No active public games found! Why not create a new one?'; +} +$('d_main_pop_pub_games').innerHTML = html; +}, +receive_featured_games: function(response, tx) { +var html = ''; +if (response.Rows && response.Rows.Row) { +html += ''; +var rows = always_array( response.Rows.Row ); +for (var idx = 0, len = rows.length; idx < len; idx++) { +var row = rows[idx]; +var image_url = row.Params.featured_image; +if (image_url && image_url.match(/^(\w+)\/(\w+\.\w+)$/)) { +image_url = '/effect/api/view/users/' + RegExp.$1 + '/images/' + RegExp.$2; +} +if (idx % 2 == 0) html += ''; +html += ''; +if (idx % 2 == 1) html += ''; +} +if (rows.length % 2 == 1) { +html += ''; +html += ''; +} +html += '
    '; +html += ''; +html += ''; +html += ''; +html += ''; +html += ''; +html += '
    '; +html += ''; +html += '' + spacer(10,1) + ''; +html += ''; +html += ''; +html += '' + spacer(15,1) + '
    '; +html += spacer(1,20); +html += '
    '; +} +$('d_blog_featured').innerHTML = html; +}, +animate_mhs: function() { +var now = hires_time_now(); +if (now - this.time_start >= this.duration) { +$('d_header').style.height = '' + this.height_target + 'px'; +$('d_shadow').style.height = '' + this.height_target + 'px'; +delete this.timer; +} +else { +var height = tweenFrame(this.height_start, this.height_target, (now - this.time_start) / this.duration, 'EaseOut', 'Circular'); +$('d_header').style.height = '' + height + 'px'; +$('d_shadow').style.height = '' + height + 'px'; +this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +} +}, +onDeactivate: function() { +$('d_blog_news').innerHTML = ''; +$('d_blog_community').innerHTML = ''; +this.height_target = 75; +this.height_start = $('d_header').offsetHeight; +this.time_start = hires_time_now(); +if (!this.timer) this.timer = setTimeout( '$P("Main").animate_mhs()', 33 ); +return true; +}, +draw_slide: function() { +if (this.slide_timer) return; +var slide = config.Strings.MainSlideshow.Slide[ this.slide_idx ]; +this.old_photo = $('d_header_slideshow_photo_' + this.slide_div_num); +this.old_text = $('d_header_slideshow_text_' + this.slide_div_num); +this.slide_div_num = 1 - this.slide_div_num; +this.new_photo = $('d_header_slideshow_photo_' + this.slide_div_num); +this.new_text = $('d_header_slideshow_text_' + this.slide_div_num); +this.new_photo.style.backgroundImage = 'url('+png(images_uri+'/'+slide.Photo, true)+')'; +this.new_photo.setOpacity(0.0); +var html = ''; +html += slide.Text; +this.slide_width = this.new_text.offsetWidth; +this.new_text.innerHTML = html; +if (this.slide_dir == 1) this.new_text.style.left = '' + this.slide_width + 'px'; +else this.new_text.style.left = '-' + this.slide_width + 'px'; +this.slide_time_start = hires_time_now(); +this.slide_timer = setTimeout( '$P("Main").animate_mhs_slide()', 33 ); +}, +animate_mhs_slide: function() { +var now = hires_time_now(); +if (now - this.slide_time_start >= this.duration) { +this.new_text.style.left = '0px'; +this.old_text.style.left = '-' + this.slide_width + 'px'; +this.new_photo.setOpacity( 1.0 ); +this.old_photo.setOpacity( 0.0 ); +delete this.slide_timer; +this.bk_pos = this.bk_pos_target; +} +else { +var value = tweenFrame(0.0, 1.0, (now - this.slide_time_start) / this.duration, 'EaseOut', 'Circular'); +if (this.slide_dir == 1) { +this.new_text.style.left = '' + Math.floor( this.slide_width - (this.slide_width * value) ) + 'px'; +this.old_text.style.left = '-' + Math.floor( this.slide_width * value ) + 'px'; +} +else { +this.new_text.style.left = '-' + Math.floor( this.slide_width - (this.slide_width * value) ) + 'px'; +this.old_text.style.left = '' + Math.floor( this.slide_width * value ) + 'px'; +} +this.new_photo.setOpacity( value ); +this.old_photo.setOpacity( 1.0 - value ); +var bkp = Math.floor( this.bk_pos + ((this.bk_pos_target - this.bk_pos) * value) ); +$('d_header').style.backgroundPosition = '' + bkp + 'px 0px'; +this.slide_timer = setTimeout( '$P("Main").animate_mhs_slide()', 33 ); +} +}, +prev_slide: function() { +this.bk_pos_target += 200; +this.slide_idx--; +if (this.slide_idx < 0) this.slide_idx += this.num_slides; +this.slide_dir = -1; +this.draw_slide(); +}, +next_slide: function() { +this.bk_pos_target -= 200; +this.slide_idx++; +if (this.slide_idx >= this.num_slides) this.slide_idx -= this.num_slides; +this.slide_dir = 1; +this.draw_slide(); +} +} ); +Class.subclass( Effect.Page, "Effect.Page.PublicGameList", { +onActivate: function() { +Nav.bar( +['Main', 'EffectGames.com'], +['PublicGameList', "All Public Games"] +); +Nav.title( "List of All Public Game Projects" ); +effect_api_get( 'get_site_info', { cat: 'all_pub_games' }, [this, 'receive_all_pub_games'], { } ); +this.div.innerHTML = loading_image(); +return true; +}, +onDeactivate: function() { +this.div.innerHTML = ''; +return true; +}, +receive_all_pub_games: function(response, tx) { +var html = ''; +html += '

    List of All Public Game Projects

    '; +html += '
    This is the complete list of public games currently being built by our users, presented in alphabetical order. Maybe they could use some help! Check out the game project pages and see (requires user account).
    '; +if (response.Data && response.Data.Games && response.Data.Games.Game) { +var games = always_array( response.Data.Games.Game ); +for (var idx = 0, len = games.length; idx < len; idx++) { +var game = games[idx]; +html += '
    ' + +(game.Logo ? +user_image_thumbnail(game.Logo, 80, 60) : +'' +) + '
    ' + ww_fit_box(game.Title, 80, 2, session.em_width, 1) + '
    '; +} +html += '
    '; +} +else { +html += 'No public games found! Why not create a new one?'; +} +this.div.innerHTML = html; +} +} ); +Class.subclass( Effect.Page, "Effect.Page.Search", { +onActivate: function(args) { +if (!args) args = {}; +var search_text = args.q; +var start = args.s || 0; +if (!start) start = 0; +var title = 'Search results for "'+search_text+'"'; +Nav.bar( +['Main', 'EffectGames.com'], +['Search?q=' + escape(search_text), "Search Results"] +); +Nav.title( title ); +this.last_search_text = search_text; +$('d_article_search').innerHTML = loading_image(); +load_script( 'http://www.google.com/uds/GwebSearch?callback=receive_google_search_results&context=0&lstkp=0&rsz=large&hl=en&source=gsc&gss=.com&sig=&q='+escape(search_text)+'%20site%3Ahttp%3A%2F%2Fwww.effectgames.com%2F&key=notsupplied&v=1.0&start='+start+'&nocache=' + (new Date()).getTime() ); +$('h_article_search').innerHTML = title; +return true; +}, +onDeactivate: function(new_page) { +$('fe_search_bar').value = ''; +$('d_article_search').innerHTML = ''; +return true; +} +} ); +function do_search_bar() { +var search_text = $('fe_search_bar').value; +if (search_text.length) { +Nav.go('Search?q=' + escape(search_text)); +} +} +function receive_google_search_results(context, response) { +var html = ''; +html += '
    Powered by
    '; +if (response.results.length) { +for (var idx = 0, len = response.results.length; idx < len; idx++) { +var row = response.results[idx]; +var url = row.unescapedUrl.replace(/^.+article\.psp\.html/, '#Article'); +html += '
    '; +html += ''; +html += '
    ' + row.content + '
    '; +html += '
    '; +} +} +else { +html += 'No results found.'; +} +if (response.cursor.pages) { +html += '
    Page: '; +for (var idx = 0, len = response.cursor.pages.length; idx < len; idx++) { +html += ''; +var page = response.cursor.pages[idx]; +var url = '#Search?q=' + escape($P('Search').last_search_text) + '&s=' + page.start; +if (response.cursor.currentPageIndex != idx) html += ''; +else html += ''; +html += page.label; +if (response.cursor.currentPageIndex != idx) html += ''; +else html += ''; +html += ''; +} +html += '
    '; +} +$('d_article_search').innerHTML = html; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js new file mode 100644 index 0000000..8b164a4 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/index.js @@ -0,0 +1 @@ +exports.ZeParser = require('./ZeParser').ZeParser; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json new file mode 100644 index 0000000..3119563 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/package.json @@ -0,0 +1,28 @@ +{ + "author": { + "name": "Peter van der Zee", + "url": "http://qfox.nl/" + }, + "name": "zeparser", + "description": "My JavaScript parser", + "version": "0.0.5", + "homepage": "https://github.com/qfox/ZeParser/", + "repository": { + "type": "git", + "url": "git://github.com/qfox/ZeParser.git" + }, + "main": "./index", + "engines": { + "node": "*" + }, + "dependencies": {}, + "devDependencies": {}, + "readme": "This is a JavaScript parser.\nhttp://github.com/qfox/ZeParser\n(c) Peter van der Zee\nhttp://qfox.nl\n\n\nBenchmark\nhttp://qfox.github.com/ZeParser/benchmark.html\n\nThe Tokenizer is used by the parser. The parser tells the tokenizer whether the next token may be a regular expression or not. Without the parser, the tokenizer will fail if regular expression literals are used in the input.\n\nUsage:\nZeParser.parse(input);\n\nReturns a \"parse tree\" which is a tree of an array of arrays with tokens (regular objects) as leafs. Meta information embedded as properties (of the arrays and the tokens).\n\nZeParser.createParser(input);\n\nReturns a new ZeParser instance which has already parsed the input. Amongst others, the ZeParser instance will have the properties .tree, .wtree and .btree.\n\n.tree is the parse tree mentioned above.\n.wtree (\"white\" tree) is a regular array with all the tokens encountered (including whitespace, line terminators and comments)\n.btree (\"black\" tree) is just like .wtree but without the whitespace, line terminators and comments. This is what the specification would call the \"token stream\".\n\nI'm aware that the naming convention is a bit awkward. It's a tradeoff between short and descriptive. The streams are used quite often in the analysis.\n\nTokens are regular objects with several properties. Amongst them are .tokposw and .tokposw, they correspond with their own position in the .wtree and .btree.\n\nThe parser has two modes for parsing: simple and extended. Simple mode is mainly for just parsing and returning the streams and a simple parse tree. There's not so much meta information here and this mode is mainly built for speed. The other mode has everything required for Zeon to do its job. This mode is toggled by the instance property .ast, which is true by default :)\n\nNon-factory example:\n\nvar input = \"foo\";\nvar tree = []; // this should probably be refactored away some day\nvar tokenizer = new Tokenizer(input); // dito\nvar parser = new ZeParser(input, tokenizer, tree);\nparser.parse(); // returns tree..., should never throw errors\n", + "readmeFilename": "README", + "_id": "zeparser@0.0.5", + "dist": { + "shasum": "3bc0bb87a690966b2ac7639ba2d534fcdf375aad" + }, + "_from": "zeparser@0.0.5", + "_resolved": "https://registry.npmjs.org/zeparser/-/zeparser-0.0.5.tgz" +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html new file mode 100755 index 0000000..1ff5ff4 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-parser.html @@ -0,0 +1,26 @@ + + + + Parser Test Suite Page + + + + (c) qfox.nl
    + Parser test suite
    +
    Running...
    + + + + + + + \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html new file mode 100755 index 0000000..0e0d1b1 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/test-tokenizer.html @@ -0,0 +1,23 @@ + + + + Tokenizer Test Suite Page + + + + (c) qfox.nl
    + + + + + + \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js new file mode 100644 index 0000000..8a4138b --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/node_modules/zeparser/tests.js @@ -0,0 +1,478 @@ +// tests for both the tokenizer and parser. Parser test results could be checked tighter. +// api: [input, token-output-count, ?regex-hints, desc] +// regex-hints are for tokenizer, will tell for each token whether it might parse regex or not (parser's job) +var Tests = [ + +["var abc;", 4, "Variable Declaration"], +["var abc = 5;", 8, "Variable Declaration, Assignment"], +["/* */", 1, "Block Comment"], +["/** **/", 1, "JSDoc-style Comment"], +["var f = function(){;};", 13, "Assignment, Function Expression"], +["hi; // moo", 4, "Trailing Line Comment"], +["hi; // moo\n;", 6, "Trailing Line Comment, Linefeed, `;`"], +["var varwithfunction;", 4, "Variable Declaration, Identifier Containing Reserved Words, `;`"], +["a + b;", 6, "Addition/Concatenation"], + +["'a'", 1, "Single-Quoted String"], +["'a';", 2, "Single-Quoted String, `;`"], // Taken from the parser test suite. + +["'a\\n'", 1, "Single-Quoted String With Escaped Linefeed"], +["'a\\n';", 2, "Single-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. + +["\"a\"", 1, "Double-Quoted String"], +["\"a\";", 2, "Double-Quoted String, `;`"], // Taken from the parser test suite. + +["\"a\\n\"", 1, "Double-Quoted String With Escaped Linefeed"], +["\"a\\n\";", 2, "Double-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. + +["500", 1, "Integer"], +["500;", 2, "Integer, `;`"], // Taken from the parser test suite. + +["500.", 1, "Double With Trailing Decimal Point"], +["500.;", 2, "Double With Trailing Decimal Point"], // Taken from the parser test suite. + +["500.432", 1, "Double With Decimal Component"], +["500.432;", 2, "Double With Decimal Component, `;`"], // Taken from the parser test suite. + +[".432432", 1, "Number, 0 < Double < 1"], +[".432432;", 2, "Number, 0 < Double < 1, `;`"], // Taken from the parser test suite. + +["(a,b,c)", 7, "Parentheses, Comma-separated identifiers"], +["(a,b,c);", 8, "Parentheses, Comma-separated identifiers, `;`"], // Taken from the parser test suite. + +["[1,2,abc]", 7, "Array literal"], +["[1,2,abc];", 8, "Array literal, `;`"], // Taken from the parser test suite. + +["{a:1,\"b\":2,c:c}", 13, "Object literal"], +["var o = {a:1,\"b\":2,c:c};", 20, "Assignment, Object Literal, `;`"], // Taken from the parser test suite. + +["var x;\nvar y;", 9, "2 Variable Declarations, Multiple lines"], +["var x;\nfunction n(){ }", 13, "Variable, Linefeed, Function Declaration"], +["var x;\nfunction n(abc){ }", 14, "Variable, Linefeed, Function Declaration With One Argument"], +["var x;\nfunction n(abc, def){ }", 17, "Variable, Linefeed, Function Declaration With Multiple Arguments"], +["function n(){ \"hello\"; }", 11, "Function Declaration, Body"], + +["/a/;", 2, [true, false], "RegExp Literal, `;`"], +["/a/b;", 2, [true, true], "RegExp Literal, Flags, `;`"], +["++x;", 3, "Unary Increment, Prefix, `;`"], +[" / /;", 3, [true, true, false], "RegExp, Leading Whitespace, `;`"], +["/ / / / /", 5, [true, false, false, false, true], "RegExp Containing One Space, Space, Division, Space, RegExp Containing One Space"], + +// Taken from the parser test suite. + +["\"var\";", 2, "Keyword String, `;`"], +["\"variable\";", 2, "String Beginning With Keyword, `;`"], +["\"somevariable\";", 2, "String Containing Keyword, `;`"], +["\"somevar\";", 2, "String Ending With Keyword, `;`"], + +["var varwithfunction;", 4, "Keywords should not be matched in identifiers"], + +["var o = {a:1};", 12, "Object Literal With Unquoted Property"], +["var o = {\"b\":2};", 12, "Object Literal With Quoted Property"], +["var o = {c:c};", 12, "Object Literal With Equivalent Property Name and Identifier"], + +["/a/ / /b/;", 6, [true, true, false, false, true, false], "RegExp, Division, RegExp, `;`"], +["a/b/c;", 6, "Triple Division (Identifier / Identifier / Identifier)"], + +["+function(){/regex/;};", 9, [false, false, false, false, false, true, false, false, false], "Unary `+` Operator, Function Expression Containing RegExp and Semicolon, `;`"], + +// Line Terminators. +["\r\n", 1, "CRLF Line Ending = 1 Linefeed"], +["\r", 1, "CR Line Ending = 1 Linefeed"], +["\n", 1, "LF Line Ending = 1 Linefeed"], +["\r\n\n\u2028\u2029\r", 5, "Various Line Terminators"], + +// Whitespace. +["a \t\u000b\u000c\u00a0\uFFFFb", 8, "Whitespace"], + +// Comments. +["//foo!@#^&$1234\nbar;", 4, "Line Comment, Linefeed, Identifier, `;`"], +["/* abcd!@#@$* { } && null*/;", 2, "Single-Line Block Comment, `;`"], +["/*foo\nbar*/;", 2, "Multi-Line Block Comment, `;`"], +["/*x*x*/;", 2, "Block Comment With Asterisks, `;`"], +["/**/;", 2, "Empty Comment, `;`"], + +// Identifiers. +["x;", 2, "Single-Character Identifier, `;`"], +["_x;", 2, "Identifier With Leading `_`, `;`"], +["xyz;", 2, "Identifier With Letters Only, `;`"], +["$x;", 2, "Identifier With Leading `$`, `;`"], +["x5;", 2, "Identifier With Number As Second Character, `;`"], +["x_y;", 2, "Identifier Containing `_`, `;`"], +["x+5;", 4, "Identifier, Binary `+` Operator, Identifier, `;`"], +["xyz123;", 2, "Alphanumeric Identifier, `;`"], +["x1y1z1;", 2, "Alternating Alphanumeric Identifier, `;`"], +["foo\\u00d8bar;", 2, "Identifier With Unicode Escape Sequence (`\\uXXXX`), `;`"], +["f\u00d8\u00d8bar;", 2, "Identifier With Embedded Unicode Character"], + +// Numbers. +["5;", 2, "Integer, `;`"], +["5.5;", 2, "Double, `;`"], +["0;", 2, "Integer Zero, `;`"], +["0.0;", 2, "Double Zero, `;`"], +["0.001;", 2, "0 < Decimalized Double < 1, `;`"], +["1.e2;", 2, "Integer With Decimal and Exponential Component (`e`), `;`"], +["1.e-2;", 2, "Integer With Decimal and Negative Exponential Component, `;`"], +["1.E2;", 2, "Integer With Decimal and Uppercase Exponential Component (`E`), `;`"], +["1.E-2;", 2, "Integer With Decimal and Uppercase Negative Exponential Component, `;`"], +[".5;", 2, "0 < Double < 1, `;`"], +[".5e3;", 2, "(0 < Double < 1) With Exponential Component"], +[".5e-3;", 2, "(0 < Double < 1) With Negative Exponential Component"], +["0.5e3;", 2, "(0 < Decimalized Double < 1) With Exponential Component"], +["55;", 2, "Two-Digit Integer, `;`"], +["123;", 2, "Three-Digit Integer, `;`"], +["55.55;", 2, "Two-Digit Double, `;`"], +["55.55e10;", 2, "Two-Digit Double With Exponential Component, `;`"], +["123.456;", 2, "Three-Digit Double, `;`"], +["1+e;", 4, "Additive Expression, `;`"], +["0x01;", 2, "Hexadecimal `1` With 1 Leading Zero, `;`"], +["0xcafe;", 2, "Hexadecimal `51966`, `;`"], +["0x12345678;", 2, "Hexadecimal `305419896`, `;`"], +["0x1234ABCD;", 2, "Hexadecimal `305441741` With Uppercase Letters, `;`"], +["0x0001;", 2, "Hexadecimal `1` with 3 Leading Zeros, `;`"], + +// Strings. +["\"foo\";", 2, "Multi-Character Double-Quoted String, `;`"], +["\"a\\n\";", 2, "Double-Quoted String Containing Linefeed, `;`"], +["\'foo\';", 2, "Single-Quoted String, `;`"], +["'a\\n';", 2, "Single-Quoted String Containing Linefeed, `;`"], +["\"x\";", 2, "Single-Character Double-Quoted String, `;`"], +["'';", 2, "Empty Single-Quoted String, `;`"], +["\"foo\\tbar\";", 2, "Double-Quoted String With Tab Character, `;`"], +["\"!@#$%^&*()_+{}[]\";", 2, "Double-Quoted String Containing Punctuators, `;`"], +["\"/*test*/\";", 2, "Double-Quoted String Containing Block Comment, `;`"], +["\"//test\";", 2, "Double-Quoted String Containing Line Comment, `;`"], +["\"\\\\\";", 2, "Double-Quoted String Containing Reverse Solidus, `;`"], +["\"\\u0001\";", 2, "Double-Quoted String Containing Numeric Unicode Escape Sequence, `;`"], +["\"\\uFEFF\";", 2, "Double-Quoted String Containing Alphanumeric Unicode Escape Sequence, `;`"], +["\"\\u10002\";", 2, "Double-Quoted String Containing 5-Digit Unicode Escape Sequence, `;`"], +["\"\\x55\";", 2, "Double-Quoted String Containing Hex Escape Sequence, `;`"], +["\"\\x55a\";", 2, "Double-Quoted String Containing Hex Escape Sequence and Additional Character, `;`"], +["\"a\\\\nb\";", 2, "Double-Quoted String Containing Escaped Linefeed, `;`"], +["\";\"", 1, "Double-Quoted String Containing `;`"], +["\"a\\\nb\";", 2, "Double-Quoted String Containing Reverse Solidus and Linefeed, `;`"], +["'\\\\'+ ''", 4, "Single-Quoted String Containing Reverse Solidus, `+`, Empty Single-Quoted String"], + +// `null`, `true`, and `false`. +["null;", 2, "`null`, `;`"], +["true;", 2, "`true`, `;`"], +["false;", 2, "`false`, `;`"], + +// RegExps +["/a/;", 2, [true, true], "Single-Character RegExp, `;`"], +["/abc/;", 2, [true, true], "Multi-Character RegExp, `;`"], +["/abc[a-z]*def/g;", 2, [true, true], "RegExp Containing Character Range and Quantifier, `;`"], +["/\\b/;", 2, [true, true], "RegExp Containing Control Character, `;`"], +["/[a-zA-Z]/;", 2, [true, true], "RegExp Containing Extended Character Range, `;`"], +["/foo(.*)/g;", 2, [true, false], "RegExp Containing Capturing Group and Quantifier, `;`"], + +// Array Literals. +["[];", 3, "Empty Array, `;`"], +["[\b\n\f\r\t\x20];", 9, "Array Containing Whitespace, `;`"], +["[1];", 4, "Array Containing 1 Element, `;`"], +["[1,2];", 6, "Array Containing 2 Elements, `;`"], +["[1,2,,];", 8, "Array Containing 2 Elisions, `;`"], +["[1,2,3];", 8, "Array Containing 3 Elements, `;`"], +["[1,2,3,,,];", 11, "Array Containing 3 Elisions, `;`"], + +// Object Literals. +["({x:5});", 8, "Object Literal Containing 1 Member; `;`"], +["({x:5,y:6});", 12, "Object Literal Containing 2 Members, `;`"], +["({x:5,});", 9, "Object Literal Containing 1 Member and Trailing Comma, `;`"], +["({if:5});", 8, "Object Literal Containing Reserved Word Property Name, `;`"], +["({ get x() {42;} });", 17, "Object Literal Containing Getter, `;`"], +["({ set y(a) {1;} });", 18, "Object Literal Containing Setter, `;`"], + +// Member Expressions. +["o.m;", 4, "Dot Member Accessor, `;`"], +["o['m'];", 5, "Square Bracket Member Accessor, `;`"], +["o['n']['m'];", 8, "Nested Square Bracket Member Accessor, `;`"], +["o.n.m;", 6, "Nested Dot Member Accessor, `;`"], +["o.if;", 4, "Dot Reserved Property Name Accessor, `;`"], + +// Function Calls. +["f();", 4, "Function Call Operator, `;`"], +["f(x);", 5, "Function Call Operator With 1 Argument, `;`"], +["f(x,y);", 7, "Function Call Operator With Multiple Arguments, `;`"], +["o.m();", 6, "Dot Member Accessor, Function Call, `;`"], +["o['m']();", 7, "Square Bracket Member Accessor, Function Call, `;`"], +["o.m(x);", 7, "Dot Member Accessor, Function Call With 1 Argument, `;`"], +["o['m'](x);", 8, "Square Bracket Member Accessor, Function Call With 1 Argument, `;`"], +["o.m(x,y);", 9, "Dot Member Accessor, Function Call With 2 Arguments, `;`"], +["o['m'](x,y);", 10, "Square Bracket Member Accessor, Function Call With 2 Arguments, `;`"], +["f(x)(y);", 8, "Nested Function Call With 1 Argument Each, `;`"], +["f().x;", 6, "Function Call, Dot Member Accessor, `;`"], + +// `eval` Function. +["eval('x');", 5, "`eval` Invocation With 1 Argument, `;`"], +["(eval)('x');", 7, "Direct `eval` Call Example, `;`"], +["(1,eval)('x');", 9, "Indirect `eval` Call Example, `;`"], +["eval(x,y);", 7, "`eval` Invocation With 2 Arguments, `;`"], + +// `new` Operator. +["new f();", 6, "`new` Operator, Function Call, `;`"], +["new o;", 4, "`new` Operator, Identifier, `;`"], +["new o.m;", 6, "`new` Operator, Dot Member Accessor, `;`"], +["new o.m(x);", 9, "`new` Operator, Dot Member Accessor, Function Call With 1 Argument, `;`"], +["new o.m(x,y);", 11, "``new` Operator, Dot Member Accessor, Function Call With 2 Arguments , `;`"], + +// Prefix and Postfix Increment. +["++x;", 3, "Prefix Increment, Identifier, `;`"], +["x++;", 3, "Identifier, Postfix Increment, `;`"], +["--x;", 3, "Prefix Decrement, Identifier, `;`"], +["x--;", 3, "Postfix Decrement, Identifier, `;`"], +["x ++;", 4, "Identifier, Space, Postfix Increment, `;`"], +["x /* comment */ ++;", 6, "Identifier, Block Comment, Postfix Increment, `;`"], +["++ /* comment */ x;", 6, "Prefix Increment, Block Comment, Identifier, `;`"], + +// Unary Operators. +["delete x;", 4, "`delete` Operator, Space, Identifier, `;`"], +["void x;", 4, "`void` Operator, Space, Identifier, `;`"], +["typeof x;", 4, "`typeof` Operator, Space, Identifier, `;`"], +["+x;", 3, "Unary `+` Operator, Identifier, `;`"], +["-x;", 3, "Unary Negation Operator, Identifier, `;`"], +["~x;", 3, "Bitwise NOT Operator, Identifier, `;`"], +["!x;", 3, "Logical NOT Operator, Identifier, `;`"], + +// Comma Operator. +["x, y;", 5, "Comma Operator"], + +// Miscellaneous. +["new Date++;", 5, "`new` Operator, Identifier, Postfix Increment, `;`"], +["+x++;", 4, "Unary `+`, Identifier, Postfix Increment, `;`"], + +// Expressions. +["1 * 2;", 6, "Integer, Multiplication, Integer, `;`"], +["1 / 2;", 6, "Integer, Division, Integer, `;`"], +["1 % 2;", 6, "Integer, Modulus, Integer, `;`"], +["1 + 2;", 6, "Integer, Addition, Integer, `;`"], +["1 - 2;", 6, "Integer, Subtraction, Integer, `;`"], +["1 << 2;", 6, "Integer, Bitwise Left Shift, Integer, `;`"], +["1 >>> 2;", 6, "Integer, Bitwise Zero-fill Right Shift, Integer, `;`"], +["1 >> 2;", 6, "Integer, Bitwise Sign-Propagating Right Shift, Integer, `;`"], +["1 * 2 + 3;", 10, "Order-of-Operations Expression, `;`"], +["(1+2)*3;", 8, "Parenthesized Additive Expression, Multiplication, `;`"], +["1*(2+3);", 8, "Multiplication, Parenthesized Additive Expression, `;`"], +["xy;", 4, "Greater-Than Relational Operator, `;`"], +["x<=y;", 4, "Less-Than-or-Equal-To Relational Operator, `;`"], +["x>=y;", 4, "Greater-Than-or-Equal-To Relational Operator, `;`"], +["x instanceof y;", 6, "`instanceof` Operator, `;`"], +["x in y;", 6, "`in` Operator, `;`"], +["x&y;", 4, "Bitwise AND Operator, `;`"], +["x^y;", 4, "Bitwise XOR Operator, `;`"], +["x|y;", 4, "Bitwise OR Operator, `;`"], +["x+y>>= y;", 6, "Bitwise Zero-Fill Right Shift Assignment, `;`"], +["x <<= y;", 6, "Bitwise Left Shift Assignment, `;`"], +["x += y;", 6, "Additive Assignment, `;`"], +["x -= y;", 6, "Subtractive Assignment, `;`"], +["x *= y;", 6, "Multiplicative Assignment, `;`"], +["x /= y;", 6, "Divisive Assignment, `;`"], +["x %= y;", 6, "Modulus Assignment, `;`"], +["x >>= y;", 6, "Bitwise Sign-Propagating Right Shift Assignment, `;`"], +["x &= y;", 6, "Bitwise AND Assignment, `;`"], +["x ^= y;", 6, "Bitwise XOR Assignment, `;`"], +["x |= y;", 6, "Bitwise OR Assignment, `;`"], + +// Blocks. +["{};", 3, "Empty Block, `;`"], +["{x;};", 5, "Block Containing 1 Identifier, `;`"], +["{x;y;};", 7, "Block Containing 2 Identifiers, `;`"], + +// Variable Declarations. +["var abc;", 4, "Variable Declaration"], +["var x,y;", 6, "Comma-Separated Variable Declarations, `;`"], +["var x=1,y=2;", 10, "Comma-Separated Variable Initializations, `;`"], +["var x,y=2;", 8, "Variable Declaration, Variable Initialization, `;`"], + +// Empty Statements. +[";", 1, "Empty Statement"], +["\n;", 2, "Linefeed, `;`"], + +// Expression Statements. +["x;", 2, "Identifier, `;`"], +["5;", 2, "Integer, `;`"], +["1+2;", 4, "Additive Statement, `;`"], + +// `if...else` Statements. +["if (c) x; else y;", 13, "Space-Delimited `if...else` Statement"], +["if (c) x;", 8, "Space-Delimited `if` Statement, `;`"], +["if (c) {} else {};", 14, "Empty Block-Delimited `if...else` Statement"], +["if (c1) if (c2) s1; else s2;", 19, "Nested `if...else` Statement Without Dangling `else`"], + +// `while` and `do...while` Loops. +["do s; while (e);", 11, "Space-Delimited `do...while` Loop"], +["do { s; } while (e);", 15, "Block-Delimited `do...while` Loop"], +["while (e) s;", 8, "Space-Delimited `while` Loop"], +["while (e) { s; };", 13, "Block-Delimited `while` Loop"], + +// `for` and `for...in` Loops. +["for (;;) ;", 8, "Infinite Space-Delimited `for` Loop"], +["for (;c;x++) x;", 12, "`for` Loop: Empty Initialization Condition; Space-Delimited Body"], +["for (i;i foo(new window[(['Active'].concat('Object').join('X'))])\n```\n\n## License\n\nLicensed under the MIT license.\n\n[socket.io]: http://socket.io/\n", + "readmeFilename": "Readme.md", + "_id": "active-x-obfuscator@0.0.1", + "dist": { + "shasum": "6f525524246186c0996c981abff242ee86a42931" + }, + "_from": "active-x-obfuscator@0.0.1", + "_resolved": "https://registry.npmjs.org/active-x-obfuscator/-/active-x-obfuscator-0.0.1.tgz" +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js new file mode 100644 index 0000000..e8fc807 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/active-x-obfuscator/test.js @@ -0,0 +1,53 @@ +var activeXObfuscator = require('./index'); +var assert = require('assert'); + +var OBFUSCATED_ACTIVE_X_OBJECT = activeXObfuscator.OBFUSCATED_ACTIVE_X_OBJECT; +var OBFUSCATED_ACTIVE_X = activeXObfuscator.OBFUSCATED_ACTIVE_X; + +var input = + "foo(new ActiveXObject('Microsoft.XMLHTTP'))"; +var expected = + "foo(new window[" + OBFUSCATED_ACTIVE_X_OBJECT + "]('Microsoft.XMLHTTP'))"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveXObject';"; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X_OBJECT + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = "ActiveXObject";'; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X_OBJECT + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = o.ActiveXObject;'; +var expected = + "var foo = o[" + OBFUSCATED_ACTIVE_X_OBJECT + "];"; +assert.equal(activeXObfuscator(input), expected); + +var input = + 'var foo = "ActiveX";'; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveX';"; +var expected = + "var foo = " + OBFUSCATED_ACTIVE_X + ";"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo; // ActiveX is cool"; +var expected = + "var foo; // Ac...eX is cool"; +assert.equal(activeXObfuscator(input), expected); + +var input = + "var foo = 'ActiveX is cool';"; +assert.throws(function() { + activeXObfuscator(input); +}, /Unknown ActiveX occurence/); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..d97eaa0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html new file mode 100644 index 0000000..5f37ac0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.html @@ -0,0 +1,981 @@ + + + + +UglifyJS – a JavaScript parser/compressor/beautifier + + + + + + + + + + + + + +
    + +
    + +
    +

    UglifyJS – a JavaScript parser/compressor/beautifier

    + + + + +
    +

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    +
    + + +

    +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

    +

    +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

    +

    +( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

    +

    +The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

    +
      +
    • ability to re-generate JavaScript code from the AST. Optionally + indented—you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +
    • +
    • shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with eval() calls or with{} statements. In short, if eval() or + with{} are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +
    • +
    • various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + +
        +
      • foo["bar"] ==> foo.bar + +
      • +
      • remove block brackets {} + +
      • +
      • join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + +
      • +
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + +
      • +
      • consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + +
      • +
      • various optimizations for IF statements: + +
          +
        • if (foo) bar(); else baz(); ==> foo?bar():baz(); +
        • +
        • if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
        • +
        • if (foo) bar(); ==> foo&&bar(); +
        • +
        • if (!foo) bar(); ==> foo||bar(); +
        • +
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
        • +
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
        • +
        + +
      • +
      • remove some unreachable code and warn about it (code that follows a + return, throw, break or continue statement, except + function/variable declarations). + +
      • +
      • act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. +
      • +
      + +
    • +
    + + + +
    + +
    +

    1.1 Unsafe transformations

    +
    + + +

    +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

    + +
    + +
    +

    1.1.1 Calls involving the global Array constructor

    +
    + + +

    +The following transformations occur: +

    + + + +
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    +Array(a, b, c)         => [a,b,c]
    +new Array(5)           => Array(5)
    +new Array(a)           => Array(a)
    +
    + + +

    +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

    +

    +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

    + + + +
    // case 1.  globally declared variable
    +  var Array;
    +  new Array(1, 2, 3);
    +  Array(a, b);
    +
    +  // or (can be declared later)
    +  new Array(1, 2, 3);
    +  var Array;
    +
    +  // or (can be a function)
    +  new Array(1, 2, 3);
    +  function Array() { ... }
    +
    +// case 2.  declared in a function
    +  (function(){
    +    a = new Array(1, 2, 3);
    +    b = Array(5, 6);
    +    var Array;
    +  })();
    +
    +  // or
    +  (function(Array){
    +    return Array(5, 6, 7);
    +  })();
    +
    +  // or
    +  (function(){
    +    return new Array(1, 2, 3, 4);
    +    function Array() { ... }
    +  })();
    +
    +  // etc.
    +
    + + +
    + +
    + +
    +

    1.1.2 obj.toString() ==> obj+“”

    +
    + + +
    +
    + +
    + +
    +

    1.2 Install (NPM)

    +
    + + +

    +UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

    +
    + +
    + +
    +

    1.3 Install latest code from GitHub

    +
    + + + + + +
    ## clone the repository
    +mkdir -p /where/you/wanna/put/it
    +cd /where/you/wanna/put/it
    +git clone git://github.com/mishoo/UglifyJS.git
    +
    +## make the module available to Node
    +mkdir -p ~/.node_libraries/
    +cd ~/.node_libraries/
    +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
    +
    +## and if you want the CLI script too:
    +mkdir -p ~/bin
    +cd ~/bin
    +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
    +  # (then add ~/bin to your $PATH if it's not there already)
    +
    + + +
    + +
    + +
    +

    1.4 Usage

    +
    + + +

    +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

    + + + +
    uglifyjs [ options... ] [ filename ]
    +
    + + +

    +filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

    +

    +Supported options: +

    +
      +
    • -b or --beautify — output indented code; when passed, additional + options control the beautifier: + +
        +
      • -i N or --indent N — indentation level (number of spaces) + +
      • +
      • -q or --quote-keys — quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +
      • +
      + +
    • +
    • --ascii — pass this argument to encode non-ASCII characters as + \uXXXX sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +
    • +
    • -nm or --no-mangle — don't mangle names. + +
    • +
    • -nmf or --no-mangle-functions – in case you want to mangle variable + names, but not touch function names. + +
    • +
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various + optimizations that result in smaller, less readable code). + +
    • +
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too + (by default we don't do this). + +
    • +
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass + --no-squeeze) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass --no-seqs to disable it. + +
    • +
    • --no-dead-code — by default, UglifyJS will remove code that is + obviously unreachable (code that follows a return, throw, break or + continue statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +
    • +
    • -nc or --no-copyright — by default, uglifyjs will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +
    • +
    • -o filename or --output filename — put the result in filename. If + this isn't given, the result goes to standard output (or see next one). + +
    • +
    • --overwrite — if the code is read from a file (not from STDIN) and you + pass --overwrite then the output will be written in the same file. + +
    • +
    • --ast — pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +
    • +
    • -v or --verbose — output some notes on STDERR (for now just how long + each operation takes). + +
    • +
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value true, or you can specify a numeric value (such as + 1024), a quoted string value (such as ="object"= or + ='https://github.com'), or the name of another symbol or keyword (such as =null or document). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of conditional compilation + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + --define-from-module more suitable for use. + +
    • +
    • -define-from-module SOMEMODULE — will load the named module (as + per the NodeJS require() function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the --define option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of --define + options. + +
    • +
    • --unsafe — enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + +
        +
      • foo.toString() ==> foo+"" +
      • +
      • new Array(x,…) ==> [x,…] +
      • +
      • new Array(x) ==> Array(x) + +
      • +
      + +
    • +
    • --max-line-len (default 32K characters) — add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass –max-line-len 0 to disable this + safety feature. + +
    • +
    • --reserved-names — some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names require and $super + intact you'd specify –reserved-names "require,$super". + +
    • +
    • --inline-script – when you want to include the output literally in an + HTML <script> tag you can use this option to prevent </script from + showing up in the output. + +
    • +
    • --lift-vars – when you pass this, UglifyJS will apply the following + transformations (see the notes in API, ast_lift_variables): + +
        +
      • put all var declarations at the start of the scope +
      • +
      • make sure a variable is declared only once +
      • +
      • discard unused function arguments +
      • +
      • discard unused inner (named) functions +
      • +
      • finally, try to merge assignments into that one var declaration, if + possible. +
      • +
      + +
    • +
    + + + +
    + +
    +

    1.4.1 API

    +
    + + +

    +To use the library from JavaScript, you'd do the following (example for +NodeJS): +

    + + + +
    var jsp = require("uglify-js").parser;
    +var pro = require("uglify-js").uglify;
    +
    +var orig_code = "... JS code here";
    +var ast = jsp.parse(orig_code); // parse code and get the initial AST
    +ast = pro.ast_mangle(ast); // get a new AST with mangled names
    +ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
    +var final_code = pro.gen_code(ast); // compressed code here
    +
    + + +

    +The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

    +

    +Some of these functions take optional arguments. Here's a description: +

    +
      +
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. + strict_semicolons is optional and defaults to false. If you pass + true then the parser will throw an error when it expects a semicolon and + it doesn't find it. For most JS code you don't want that, but it's useful + if you want to strictly sanitize your code. + +
    • +
    • pro.ast_lift_variables(ast) – merge and move var declarations to the + scop of the scope; discard unused function arguments or variables; discard + unused (named) inner functions. It also tries to merge assignments + following the var declaration into it. + +

      + If your code is very hand-optimized concerning var declarations, this + lifting variable declarations might actually increase size. For me it + helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also + note that (since it's not enabled by default) this operation isn't yet + heavily tested (please report if you find issues!). +

      +

      + Note that although it might increase the image size (on jQuery it gains + 865 bytes, 243 after gzip) it's technically more correct: in certain + situations, dead code removal might drop variable declarations, which + would not happen if the variables are lifted in advance. +

      +

      + Here's an example of what it does: +

    • +
    + + + + + +
    function f(a, b, c, d, e) {
    +    var q;
    +    var w;
    +    w = 10;
    +    q = 20;
    +    for (var i = 1; i < 10; ++i) {
    +        var boo = foo(a);
    +    }
    +    for (var i = 0; i < 1; ++i) {
    +        var boo = bar(c);
    +    }
    +    function foo(){ ... }
    +    function bar(){ ... }
    +    function baz(){ ... }
    +}
    +
    +// transforms into ==>
    +
    +function f(a, b, c) {
    +    var i, boo, w = 10, q = 20;
    +    for (i = 1; i < 10; ++i) {
    +        boo = foo(a);
    +    }
    +    for (i = 0; i < 1; ++i) {
    +        boo = bar(c);
    +    }
    +    function foo() { ... }
    +    function bar() { ... }
    +}
    +
    + + +
      +
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled + (compressed) variable and function names. It supports the following + options: + +
        +
      • toplevel – mangle toplevel names (by default we don't touch them). +
      • +
      • except – an array of names to exclude from compression. +
      • +
      • defines – an object with properties named after symbols to + replace (see the --define option for the script) and the values + representing the AST replacement value. + +
      • +
      + +
    • +
    • pro.ast_squeeze(ast, options) – employs further optimizations designed + to reduce the size of the code that gen_code would generate from the + AST. Returns a new AST. options can be a hash; the supported options + are: + +
        +
      • make_seqs (default true) which will cause consecutive statements in a + block to be merged using the "sequence" (comma) operator + +
      • +
      • dead_code (default true) which will remove unreachable code. + +
      • +
      + +
    • +
    • pro.gen_code(ast, options) – generates JS code from the AST. By + default it's minified, but using the options argument you can get nicely + formatted output. options is, well, optional :-) and if you pass it it + must be an object and supports the following properties (below you can see + the default values): + +
        +
      • beautify: false – pass true if you want indented output +
      • +
      • indent_start: 0 (only applies when beautify is true) – initial + indentation in spaces +
      • +
      • indent_level: 4 (only applies when beautify is true) -- + indentation level, in spaces (pass an even number) +
      • +
      • quote_keys: false – if you pass true it will quote all keys in + literal objects +
      • +
      • space_colon: false (only applies when beautify is true) – wether + to put a space before the colon in object literals +
      • +
      • ascii_only: false – pass true if you want to encode non-ASCII + characters as \uXXXX. +
      • +
      • inline_script: false – pass true to escape occurrences of + </script in strings +
      • +
      + +
    • +
    + + +
    + +
    + +
    +

    1.4.2 Beautifier shortcoming – no more comments

    +
    + + +

    +The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

    +

    +In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

    +
    + +
    + +
    +

    1.4.3 Use as a code pre-processor

    +
    + + +

    +The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

    +

    +The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

    + + + +
    CLAUSE1: if (typeof DEVMODE === 'undefined') {
    +    DEVMODE = true;
    +}
    +
    +CLAUSE2: function init() {
    +    if (DEVMODE) {
    +        console.log("init() called");
    +    }
    +    ....
    +    DEVMODE &amp;&amp; console.log("init() complete");
    +}
    +
    +CLAUSE3: function reportDeviceStatus(device) {
    +    var DEVMODE = device.mode, DEVNAME = device.name;
    +    if (DEVMODE === 'open') {
    +        ....
    +    }
    +}
    +
    + + +

    +When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

    +

    +If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

    +

    +And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

    +

    +In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

    +

    +It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

    +
    +
    + +
    + +
    +

    1.5 Compression – how good is it?

    +
    + + +

    +Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

    +

    +We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

    + + ++ + + + + + + + + + +
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    + + +
    + +
    + +
    +

    1.6 Bugs?

    +
    + + +

    +Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

    +

    +DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20”, though the more readable version would clearly be to use +“if/else”. +

    +

    +Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

    +
    + +
    + +
    +

    1.7 Links

    +
    + + + + + +
    + +
    + +
    +

    1.8 License

    +
    + + +

    +UglifyJS is released under the BSD license: +

    + + + +
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
    +Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions
    +are met:
    +
    +    * Redistributions of source code must retain the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer.
    +
    +    * Redistributions in binary form must reproduce the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer in the documentation and/or other materials
    +      provided with the distribution.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
    +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +SUCH DAMAGE.
    +
    + + +
    +

    Footnotes:

    +
    +

    1 I even reported a few bugs and suggested some fixes in the original + parse-js library, and Marijn pushed fixes literally in minutes. +

    +
    +
    + +
    +
    +
    + +
    +

    Date: 2011-12-09 14:59:08 EET

    +

    Author: Mihai Bazon

    +

    Org version 7.7 with Emacs version 23

    +Validate XHTML 1.0 + +
    + + diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org new file mode 100644 index 0000000..4d01fdf --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/README.org @@ -0,0 +1,574 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle names. + +- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable + names, but not touch function names. + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML =\n\n\n\n\n
    \n\n
    \n\n
    \n

    UglifyJS – a JavaScript parser/compressor/beautifier

    \n\n\n\n\n
    \n

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    \n
    \n\n\n

    \nThis package implements a general-purpose JavaScript\nparser/compressor/beautifier toolkit. It is developed on NodeJS, but it\nshould work on any JavaScript platform supporting the CommonJS module system\n(and if your platform of choice doesn't support CommonJS, you can easily\nimplement it, or discard the exports.* lines from UglifyJS sources).\n

    \n

    \nThe tokenizer/parser generates an abstract syntax tree from JS code. You\ncan then traverse the AST to learn more about the code, or do various\nmanipulations on it. This part is implemented in parse-js.js and it's a\nport to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke.\n

    \n

    \n( See cl-uglify-js if you're looking for the Common Lisp version of\nUglifyJS. )\n

    \n

    \nThe second part of this package, implemented in process.js, inspects and\nmanipulates the AST generated by the parser to provide the following:\n

    \n
      \n
    • ability to re-generate JavaScript code from the AST. Optionally\n indented—you can use this if you want to “beautify” a program that has\n been compressed, so that you can inspect the source. But you can also run\n our code generator to print out an AST without any whitespace, so you\n achieve compression as well.\n\n
    • \n
    • shorten variable names (usually to single characters). Our mangler will\n analyze the code and generate proper variable names, depending on scope\n and usage, and is smart enough to deal with globals defined elsewhere, or\n with eval() calls or with{} statements. In short, if eval() or\n with{} are used in some scope, then all variables in that scope and any\n variables in the parent scopes will remain unmangled, and any references\n to such variables remain unmangled as well.\n\n
    • \n
    • various small optimizations that may lead to faster code but certainly\n lead to smaller code. Where possible, we do the following:\n\n
        \n
      • foo[\"bar\"] ==> foo.bar\n\n
      • \n
      • remove block brackets {}\n\n
      • \n
      • join consecutive var declarations:\n var a = 10; var b = 20; ==> var a=10,b=20;\n\n
      • \n
      • resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the\n replacement if the result occupies less bytes; for example 1/3 would\n translate to 0.333333333333, so in this case we don't replace it.\n\n
      • \n
      • consecutive statements in blocks are merged into a sequence; in many\n cases, this leaves blocks with a single statement, so then we can remove\n the block brackets.\n\n
      • \n
      • various optimizations for IF statements:\n\n
          \n
        • if (foo) bar(); else baz(); ==> foo?bar():baz();\n
        • \n
        • if (!foo) bar(); else baz(); ==> foo?baz():bar();\n
        • \n
        • if (foo) bar(); ==> foo&&bar();\n
        • \n
        • if (!foo) bar(); ==> foo||bar();\n
        • \n
        • if (foo) return bar(); else return baz(); ==> return foo?bar():baz();\n
        • \n
        • if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n\n
        • \n
        \n\n
      • \n
      • remove some unreachable code and warn about it (code that follows a\n return, throw, break or continue statement, except\n function/variable declarations).\n\n
      • \n
      • act a limited version of a pre-processor (c.f. the pre-processor of\n C/C++) to allow you to safely replace selected global symbols with\n specified values. When combined with the optimisations above this can\n make UglifyJS operate slightly more like a compilation process, in\n that when certain symbols are replaced by constant values, entire code\n blocks may be optimised away as unreachable.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.1 Unsafe transformations

    \n
    \n\n\n

    \nThe following transformations can in theory break code, although they're\nprobably safe in most practical cases. To enable them you need to pass the\n--unsafe flag.\n

    \n\n
    \n\n
    \n

    1.1.1 Calls involving the global Array constructor

    \n
    \n\n\n

    \nThe following transformations occur:\n

    \n\n\n\n
    new Array(1, 2, 3, 4)  => [1,2,3,4]\nArray(a, b, c)         => [a,b,c]\nnew Array(5)           => Array(5)\nnew Array(a)           => Array(a)\n
    \n\n\n

    \nThese are all safe if the Array name isn't redefined. JavaScript does allow\none to globally redefine Array (and pretty much everything, in fact) but I\npersonally don't see why would anyone do that.\n

    \n

    \nUglifyJS does handle the case where Array is redefined locally, or even\nglobally but with a function or var declaration. Therefore, in the\nfollowing cases UglifyJS doesn't touch calls or instantiations of Array:\n

    \n\n\n\n
    // case 1.  globally declared variable\n  var Array;\n  new Array(1, 2, 3);\n  Array(a, b);\n\n  // or (can be declared later)\n  new Array(1, 2, 3);\n  var Array;\n\n  // or (can be a function)\n  new Array(1, 2, 3);\n  function Array() { ... }\n\n// case 2.  declared in a function\n  (function(){\n    a = new Array(1, 2, 3);\n    b = Array(5, 6);\n    var Array;\n  })();\n\n  // or\n  (function(Array){\n    return Array(5, 6, 7);\n  })();\n\n  // or\n  (function(){\n    return new Array(1, 2, 3, 4);\n    function Array() { ... }\n  })();\n\n  // etc.\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.1.2 obj.toString() ==> obj+“”

    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n

    1.2 Install (NPM)

    \n
    \n\n\n

    \nUglifyJS is now available through NPM — npm install uglify-js should do\nthe job.\n

    \n
    \n\n
    \n\n
    \n

    1.3 Install latest code from GitHub

    \n
    \n\n\n\n\n\n
    ## clone the repository\nmkdir -p /where/you/wanna/put/it\ncd /where/you/wanna/put/it\ngit clone git://github.com/mishoo/UglifyJS.git\n\n## make the module available to Node\nmkdir -p ~/.node_libraries/\ncd ~/.node_libraries/\nln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js\n\n## and if you want the CLI script too:\nmkdir -p ~/bin\ncd ~/bin\nln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs\n  # (then add ~/bin to your $PATH if it's not there already)\n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4 Usage

    \n
    \n\n\n

    \nThere is a command-line tool that exposes the functionality of this library\nfor your shell-scripting needs:\n

    \n\n\n\n
    uglifyjs [ options... ] [ filename ]\n
    \n\n\n

    \nfilename should be the last argument and should name the file from which\nto read the JavaScript code. If you don't specify it, it will read code\nfrom STDIN.\n

    \n

    \nSupported options:\n

    \n
      \n
    • -b or --beautify — output indented code; when passed, additional\n options control the beautifier:\n\n
        \n
      • -i N or --indent N — indentation level (number of spaces)\n\n
      • \n
      • -q or --quote-keys — quote keys in literal objects (by default,\n only keys that cannot be identifier names will be quotes).\n\n
      • \n
      \n\n
    • \n
    • --ascii — pass this argument to encode non-ASCII characters as\n \\uXXXX sequences. By default UglifyJS won't bother to do it and will\n output Unicode characters instead. (the output is always encoded in UTF8,\n but if you pass this option you'll only get ASCII).\n\n
    • \n
    • -nm or --no-mangle — don't mangle names.\n\n
    • \n
    • -nmf or --no-mangle-functions – in case you want to mangle variable\n names, but not touch function names.\n\n
    • \n
    • -ns or --no-squeeze — don't call ast_squeeze() (which does various\n optimizations that result in smaller, less readable code).\n\n
    • \n
    • -mt or --mangle-toplevel — mangle names in the toplevel scope too\n (by default we don't do this).\n\n
    • \n
    • --no-seqs — when ast_squeeze() is called (thus, unless you pass\n --no-squeeze) it will reduce consecutive statements in blocks into a\n sequence. For example, \"a = 10; b = 20; foo();\" will be written as\n \"a=10,b=20,foo();\". In various occasions, this allows us to discard the\n block brackets (since the block becomes a single statement). This is ON\n by default because it seems safe and saves a few hundred bytes on some\n libs that I tested it on, but pass --no-seqs to disable it.\n\n
    • \n
    • --no-dead-code — by default, UglifyJS will remove code that is\n obviously unreachable (code that follows a return, throw, break or\n continue statement and is not a function/variable declaration). Pass\n this option to disable this optimization.\n\n
    • \n
    • -nc or --no-copyright — by default, uglifyjs will keep the initial\n comment tokens in the generated code (assumed to be copyright information\n etc.). If you pass this it will discard it.\n\n
    • \n
    • -o filename or --output filename — put the result in filename. If\n this isn't given, the result goes to standard output (or see next one).\n\n
    • \n
    • --overwrite — if the code is read from a file (not from STDIN) and you\n pass --overwrite then the output will be written in the same file.\n\n
    • \n
    • --ast — pass this if you want to get the Abstract Syntax Tree instead\n of JavaScript as output. Useful for debugging or learning more about the\n internals.\n\n
    • \n
    • -v or --verbose — output some notes on STDERR (for now just how long\n each operation takes).\n\n
    • \n
    • -d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace\n all instances of the specified symbol where used as an identifier\n (except where symbol has properly declared by a var declaration or\n use as function parameter or similar) with the specified value. This\n argument may be specified multiple times to define multiple\n symbols - if no value is specified the symbol will be replaced with\n the value true, or you can specify a numeric value (such as\n 1024), a quoted string value (such as =\"object\"= or\n ='https://github.com'), or the name of another symbol or keyword (such as =null or document).\n This allows you, for example, to assign meaningful names to key\n constant values but discard the symbolic names in the uglified\n version for brevity/efficiency, or when used wth care, allows\n UglifyJS to operate as a form of conditional compilation\n whereby defining appropriate values may, by dint of the constant\n folding and dead code removal features above, remove entire\n superfluous code blocks (e.g. completely remove instrumentation or\n trace code for production use).\n Where string values are being defined, the handling of quotes are\n likely to be subject to the specifics of your command shell\n environment, so you may need to experiment with quoting styles\n depending on your platform, or you may find the option\n --define-from-module more suitable for use.\n\n
    • \n
    • -define-from-module SOMEMODULE — will load the named module (as\n per the NodeJS require() function) and iterate all the exported\n properties of the module defining them as symbol names to be defined\n (as if by the --define option) per the name of each property\n (i.e. without the module name prefix) and given the value of the\n property. This is a much easier way to handle and document groups of\n symbols to be defined rather than a large number of --define\n options.\n\n
    • \n
    • --unsafe — enable other additional optimizations that are known to be\n unsafe in some contrived situations, but could still be generally useful.\n For now only these:\n\n
        \n
      • foo.toString() ==> foo+\"\"\n
      • \n
      • new Array(x,…) ==> [x,…]\n
      • \n
      • new Array(x) ==> Array(x)\n\n
      • \n
      \n\n
    • \n
    • --max-line-len (default 32K characters) — add a newline after around\n 32K characters. I've seen both FF and Chrome croak when all the code was\n on a single line of around 670K. Pass –max-line-len 0 to disable this\n safety feature.\n\n
    • \n
    • --reserved-names — some libraries rely on certain names to be used, as\n pointed out in issue #92 and #81, so this option allow you to exclude such\n names from the mangler. For example, to keep names require and $super\n intact you'd specify –reserved-names \"require,$super\".\n\n
    • \n
    • --inline-script – when you want to include the output literally in an\n HTML <script> tag you can use this option to prevent </script from\n showing up in the output.\n\n
    • \n
    • --lift-vars – when you pass this, UglifyJS will apply the following\n transformations (see the notes in API, ast_lift_variables):\n\n
        \n
      • put all var declarations at the start of the scope\n
      • \n
      • make sure a variable is declared only once\n
      • \n
      • discard unused function arguments\n
      • \n
      • discard unused inner (named) functions\n
      • \n
      • finally, try to merge assignments into that one var declaration, if\n possible.\n
      • \n
      \n\n
    • \n
    \n\n\n\n
    \n\n
    \n

    1.4.1 API

    \n
    \n\n\n

    \nTo use the library from JavaScript, you'd do the following (example for\nNodeJS):\n

    \n\n\n\n
    var jsp = require(\"uglify-js\").parser;\nvar pro = require(\"uglify-js\").uglify;\n\nvar orig_code = \"... JS code here\";\nvar ast = jsp.parse(orig_code); // parse code and get the initial AST\nast = pro.ast_mangle(ast); // get a new AST with mangled names\nast = pro.ast_squeeze(ast); // get an AST with compression optimizations\nvar final_code = pro.gen_code(ast); // compressed code here\n
    \n\n\n

    \nThe above performs the full compression that is possible right now. As you\ncan see, there are a sequence of steps which you can apply. For example if\nyou want compressed output but for some reason you don't want to mangle\nvariable names, you would simply skip the line that calls\npro.ast_mangle(ast).\n

    \n

    \nSome of these functions take optional arguments. Here's a description:\n

    \n
      \n
    • jsp.parse(code, strict_semicolons) – parses JS code and returns an AST.\n strict_semicolons is optional and defaults to false. If you pass\n true then the parser will throw an error when it expects a semicolon and\n it doesn't find it. For most JS code you don't want that, but it's useful\n if you want to strictly sanitize your code.\n\n
    • \n
    • pro.ast_lift_variables(ast) – merge and move var declarations to the\n scop of the scope; discard unused function arguments or variables; discard\n unused (named) inner functions. It also tries to merge assignments\n following the var declaration into it.\n\n

      \n If your code is very hand-optimized concerning var declarations, this\n lifting variable declarations might actually increase size. For me it\n helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also\n note that (since it's not enabled by default) this operation isn't yet\n heavily tested (please report if you find issues!).\n

      \n

      \n Note that although it might increase the image size (on jQuery it gains\n 865 bytes, 243 after gzip) it's technically more correct: in certain\n situations, dead code removal might drop variable declarations, which\n would not happen if the variables are lifted in advance.\n

      \n

      \n Here's an example of what it does:\n

    • \n
    \n\n\n\n\n\n
    function f(a, b, c, d, e) {\n    var q;\n    var w;\n    w = 10;\n    q = 20;\n    for (var i = 1; i < 10; ++i) {\n        var boo = foo(a);\n    }\n    for (var i = 0; i < 1; ++i) {\n        var boo = bar(c);\n    }\n    function foo(){ ... }\n    function bar(){ ... }\n    function baz(){ ... }\n}\n\n// transforms into ==>\n\nfunction f(a, b, c) {\n    var i, boo, w = 10, q = 20;\n    for (i = 1; i < 10; ++i) {\n        boo = foo(a);\n    }\n    for (i = 0; i < 1; ++i) {\n        boo = bar(c);\n    }\n    function foo() { ... }\n    function bar() { ... }\n}\n
    \n\n\n
      \n
    • pro.ast_mangle(ast, options) – generates a new AST containing mangled\n (compressed) variable and function names. It supports the following\n options:\n\n
        \n
      • toplevel – mangle toplevel names (by default we don't touch them).\n
      • \n
      • except – an array of names to exclude from compression.\n
      • \n
      • defines – an object with properties named after symbols to\n replace (see the --define option for the script) and the values\n representing the AST replacement value.\n\n
      • \n
      \n\n
    • \n
    • pro.ast_squeeze(ast, options) – employs further optimizations designed\n to reduce the size of the code that gen_code would generate from the\n AST. Returns a new AST. options can be a hash; the supported options\n are:\n\n
        \n
      • make_seqs (default true) which will cause consecutive statements in a\n block to be merged using the \"sequence\" (comma) operator\n\n
      • \n
      • dead_code (default true) which will remove unreachable code.\n\n
      • \n
      \n\n
    • \n
    • pro.gen_code(ast, options) – generates JS code from the AST. By\n default it's minified, but using the options argument you can get nicely\n formatted output. options is, well, optional :-) and if you pass it it\n must be an object and supports the following properties (below you can see\n the default values):\n\n
        \n
      • beautify: false – pass true if you want indented output\n
      • \n
      • indent_start: 0 (only applies when beautify is true) – initial\n indentation in spaces\n
      • \n
      • indent_level: 4 (only applies when beautify is true) --\n indentation level, in spaces (pass an even number)\n
      • \n
      • quote_keys: false – if you pass true it will quote all keys in\n literal objects\n
      • \n
      • space_colon: false (only applies when beautify is true) – wether\n to put a space before the colon in object literals\n
      • \n
      • ascii_only: false – pass true if you want to encode non-ASCII\n characters as \\uXXXX.\n
      • \n
      • inline_script: false – pass true to escape occurrences of\n </script in strings\n
      • \n
      \n\n
    • \n
    \n\n\n
    \n\n
    \n\n
    \n

    1.4.2 Beautifier shortcoming – no more comments

    \n
    \n\n\n

    \nThe beautifier can be used as a general purpose indentation tool. It's\nuseful when you want to make a minified file readable. One limitation,\nthough, is that it discards all comments, so you don't really want to use it\nto reformat your code, unless you don't have, or don't care about, comments.\n

    \n

    \nIn fact it's not the beautifier who discards comments — they are dumped at\nthe parsing stage, when we build the initial AST. Comments don't really\nmake sense in the AST, and while we could add nodes for them, it would be\ninconvenient because we'd have to add special rules to ignore them at all\nthe processing stages.\n

    \n
    \n\n
    \n\n
    \n

    1.4.3 Use as a code pre-processor

    \n
    \n\n\n

    \nThe --define option can be used, particularly when combined with the\nconstant folding logic, as a form of pre-processor to enable or remove\nparticular constructions, such as might be used for instrumenting\ndevelopment code, or to produce variations aimed at a specific\nplatform.\n

    \n

    \nThe code below illustrates the way this can be done, and how the\nsymbol replacement is performed.\n

    \n\n\n\n
    CLAUSE1: if (typeof DEVMODE === 'undefined') {\n    DEVMODE = true;\n}\n\nCLAUSE2: function init() {\n    if (DEVMODE) {\n        console.log(\"init() called\");\n    }\n    ....\n    DEVMODE &amp;&amp; console.log(\"init() complete\");\n}\n\nCLAUSE3: function reportDeviceStatus(device) {\n    var DEVMODE = device.mode, DEVNAME = device.name;\n    if (DEVMODE === 'open') {\n        ....\n    }\n}\n
    \n\n\n

    \nWhen the above code is normally executed, the undeclared global\nvariable DEVMODE will be assigned the value true (see CLAUSE1)\nand so the init() function (CLAUSE2) will write messages to the\nconsole log when executed, but in CLAUSE3 a locally declared\nvariable will mask access to the DEVMODE global symbol.\n

    \n

    \nIf the above code is processed by UglifyJS with an argument of\n--define DEVMODE=false then UglifyJS will replace DEVMODE with the\nboolean constant value false within CLAUSE1 and CLAUSE2, but it\nwill leave CLAUSE3 as it stands because there DEVMODE resolves to\na validly declared variable.\n

    \n

    \nAnd more so, the constant-folding features of UglifyJS will recognise\nthat the if condition of CLAUSE1 is thus always false, and so will\nremove the test and body of CLAUSE1 altogether (including the\notherwise slightly problematical statement false = true; which it\nwill have formed by replacing DEVMODE in the body). Similarly,\nwithin CLAUSE2 both calls to console.log() will be removed\naltogether.\n

    \n

    \nIn this way you can mimic, to a limited degree, the functionality of\nthe C/C++ pre-processor to enable or completely remove blocks\ndepending on how certain symbols are defined - perhaps using UglifyJS\nto generate different versions of source aimed at different\nenvironments\n

    \n

    \nIt is recommmended (but not made mandatory) that symbols designed for\nthis purpose are given names consisting of UPPER_CASE_LETTERS to\ndistinguish them from other (normal) symbols and avoid the sort of\nclash that CLAUSE3 above illustrates.\n

    \n
    \n
    \n\n
    \n\n
    \n

    1.5 Compression – how good is it?

    \n
    \n\n\n

    \nHere are updated statistics. (I also updated my Google Closure and YUI\ninstallations).\n

    \n

    \nWe're still a lot better than YUI in terms of compression, though slightly\nslower. We're still a lot faster than Closure, and compression after gzip\nis comparable.\n

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
    jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
    paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
    prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
    thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
    \n\n\n
    \n\n
    \n\n
    \n

    1.6 Bugs?

    \n
    \n\n\n

    \nUnfortunately, for the time being there is no automated test suite. But I\nran the compressor manually on non-trivial code, and then I tested that the\ngenerated code works as expected. A few hundred times.\n

    \n

    \nDynarchLIB was started in times when there was no good JS minifier.\nTherefore I was quite religious about trying to write short code manually,\nand as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a\n= 10 : b = 20”, though the more readable version would clearly be to use\n“if/else”.\n

    \n

    \nSince the parser/compressor runs fine on DL and jQuery, I'm quite confident\nthat it's solid enough for production use. If you can identify any bugs,\nI'd love to hear about them (use the Google Group or email me directly).\n

    \n
    \n\n
    \n\n
    \n

    1.7 Links

    \n
    \n\n\n\n\n\n
    \n\n
    \n\n
    \n

    1.8 License

    \n
    \n\n\n

    \nUglifyJS is released under the BSD license:\n

    \n\n\n\n
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\nBased on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n
    \n\n\n
    \n

    Footnotes:

    \n
    \n

    1 I even reported a few bugs and suggested some fixes in the original\n parse-js library, and Marijn pushed fixes literally in minutes.\n

    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n

    Date: 2011-12-09 14:59:08 EET

    \n

    Author: Mihai Bazon

    \n

    Org version 7.7 with Emacs version 23

    \nValidate XHTML 1.0\n\n
    \n\n\n", + "readmeFilename": "README.html", + "_id": "uglify-js@1.2.5", + "dist": { + "shasum": "6756affde8e6702e9ff5c60f956db984d1a293f7" + }, + "_from": "uglify-js@1.2.5", + "_resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.2.5.tgz" +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ new file mode 100644 index 0000000..e4cb23d --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/package.json~ @@ -0,0 +1,24 @@ +{ + "name" : "uglify-js", + + "description" : "JavaScript parser and compressor/beautifier toolkit", + + "author" : { + "name" : "Mihai Bazon", + "email" : "mihai.bazon@gmail.com", + "url" : "http://mihai.bazon.net/blog" + }, + + "version" : "1.2.3", + + "main" : "./uglify-js.js", + + "bin" : { + "uglifyjs" : "./bin/uglifyjs" + }, + + "repository": { + "type": "git", + "url": "git@github.com:mishoo/UglifyJS.git" + } +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js new file mode 100755 index 0000000..f19369e --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/beautify.js @@ -0,0 +1,28 @@ +#! /usr/bin/env node + +global.sys = require("sys"); +var fs = require("fs"); + +var jsp = require("../lib/parse-js"); +var pro = require("../lib/process"); + +var filename = process.argv[2]; +fs.readFile(filename, "utf8", function(err, text){ + try { + var ast = time_it("parse", function(){ return jsp.parse(text); }); + ast = time_it("mangle", function(){ return pro.ast_mangle(ast); }); + ast = time_it("squeeze", function(){ return pro.ast_squeeze(ast); }); + var gen = time_it("generate", function(){ return pro.gen_code(ast, false); }); + sys.puts(gen); + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + } +}); + +function time_it(name, cont) { + var t1 = new Date().getTime(); + try { return cont(); } + finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); } +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js new file mode 100755 index 0000000..02c19a9 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/testparser.js @@ -0,0 +1,403 @@ +#! /usr/bin/env node + +var parseJS = require("../lib/parse-js"); +var sys = require("sys"); + +// write debug in a very straightforward manner +var debug = function(){ + sys.log(Array.prototype.slice.call(arguments).join(', ')); +}; + +ParserTestSuite(function(i, input, desc){ + try { + parseJS.parse(input); + debug("ok " + i + ": " + desc); + } catch(e){ + debug("FAIL " + i + " " + desc + " (" + e + ")"); + } +}); + +function ParserTestSuite(callback){ + var inps = [ + ["var abc;", "Regular variable statement w/o assignment"], + ["var abc = 5;", "Regular variable statement with assignment"], + ["/* */;", "Multiline comment"], + ['/** **/;', 'Double star multiline comment'], + ["var f = function(){;};", "Function expression in var assignment"], + ['hi; // moo\n;', 'single line comment'], + ['var varwithfunction;', 'Dont match keywords as substrings'], // difference between `var withsomevar` and `"str"` (local search and lits) + ['a + b;', 'addition'], + ["'a';", 'single string literal'], + ["'a\\n';", 'single string literal with escaped return'], + ['"a";', 'double string literal'], + ['"a\\n";', 'double string literal with escaped return'], + ['"var";', 'string is a keyword'], + ['"variable";', 'string starts with a keyword'], + ['"somevariable";', 'string contains a keyword'], + ['"somevar";', 'string ends with a keyword'], + ['500;', 'int literal'], + ['500.;', 'float literal w/o decimals'], + ['500.432;', 'float literal with decimals'], + ['.432432;', 'float literal w/o int'], + ['(a,b,c);', 'parens and comma'], + ['[1,2,abc];', 'array literal'], + ['var o = {a:1};', 'object literal unquoted key'], + ['var o = {"b":2};', 'object literal quoted key'], // opening curly may not be at the start of a statement... + ['var o = {c:c};', 'object literal keyname is identifier'], + ['var o = {a:1,"b":2,c:c};', 'object literal combinations'], + ['var x;\nvar y;', 'two lines'], + ['var x;\nfunction n(){; }', 'function def'], + ['var x;\nfunction n(abc){; }', 'function def with arg'], + ['var x;\nfunction n(abc, def){ ;}', 'function def with args'], + ['function n(){ "hello"; }', 'function def with body'], + ['/a/;', 'regex literal'], + ['/a/b;', 'regex literal with flag'], + ['/a/ / /b/;', 'regex div regex'], + ['a/b/c;', 'triple division looks like regex'], + ['+function(){/regex/;};', 'regex at start of function body'], + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=86 + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=430 + + // first tests for the lexer, should also parse as program (when you append a semi) + + // comments + ['//foo!@#^&$1234\nbar;', 'single line comment'], + ['/* abcd!@#@$* { } && null*/;', 'single line multi line comment'], + ['/*foo\nbar*/;','multi line comment'], + ['/*x*x*/;','multi line comment with *'], + ['/**/;','empty comment'], + // identifiers + ["x;",'1 identifier'], + ["_x;",'2 identifier'], + ["xyz;",'3 identifier'], + ["$x;",'4 identifier'], + ["x$;",'5 identifier'], + ["_;",'6 identifier'], + ["x5;",'7 identifier'], + ["x_y;",'8 identifier'], + ["x+5;",'9 identifier'], + ["xyz123;",'10 identifier'], + ["x1y1z1;",'11 identifier'], + ["foo\\u00D8bar;",'12 identifier unicode escape'], + //["foo�bar;",'13 identifier unicode embedded (might fail)'], + // numbers + ["5;", '1 number'], + ["5.5;", '2 number'], + ["0;", '3 number'], + ["0.0;", '4 number'], + ["0.001;", '5 number'], + ["1.e2;", '6 number'], + ["1.e-2;", '7 number'], + ["1.E2;", '8 number'], + ["1.E-2;", '9 number'], + [".5;", '10 number'], + [".5e3;", '11 number'], + [".5e-3;", '12 number'], + ["0.5e3;", '13 number'], + ["55;", '14 number'], + ["123;", '15 number'], + ["55.55;", '16 number'], + ["55.55e10;", '17 number'], + ["123.456;", '18 number'], + ["1+e;", '20 number'], + ["0x01;", '22 number'], + ["0XCAFE;", '23 number'], + ["0x12345678;", '24 number'], + ["0x1234ABCD;", '25 number'], + ["0x0001;", '26 number'], + // strings + ["\"foo\";", '1 string'], + ["\'foo\';", '2 string'], + ["\"x\";", '3 string'], + ["\'\';", '4 string'], + ["\"foo\\tbar\";", '5 string'], + ["\"!@#$%^&*()_+{}[]\";", '6 string'], + ["\"/*test*/\";", '7 string'], + ["\"//test\";", '8 string'], + ["\"\\\\\";", '9 string'], + ["\"\\u0001\";", '10 string'], + ["\"\\uFEFF\";", '11 string'], + ["\"\\u10002\";", '12 string'], + ["\"\\x55\";", '13 string'], + ["\"\\x55a\";", '14 string'], + ["\"a\\\\nb\";", '15 string'], + ['";"', '16 string: semi in a string'], + ['"a\\\nb";', '17 string: line terminator escape'], + // literals + ["null;", "null"], + ["true;", "true"], + ["false;", "false"], + // regex + ["/a/;", "1 regex"], + ["/abc/;", "2 regex"], + ["/abc[a-z]*def/g;", "3 regex"], + ["/\\b/;", "4 regex"], + ["/[a-zA-Z]/;", "5 regex"], + + // program tests (for as far as they havent been covered above) + + // regexp + ["/foo(.*)/g;", "another regexp"], + // arrays + ["[];", "1 array"], + ["[ ];", "2 array"], + ["[1];", "3 array"], + ["[1,2];", "4 array"], + ["[1,2,,];", "5 array"], + ["[1,2,3];", "6 array"], + ["[1,2,3,,,];", "7 array"], + // objects + ["{};", "1 object"], + ["({x:5});", "2 object"], + ["({x:5,y:6});", "3 object"], + ["({x:5,});", "4 object"], + ["({if:5});", "5 object"], + ["({ get x() {42;} });", "6 object"], + ["({ set y(a) {1;} });", "7 object"], + // member expression + ["o.m;", "1 member expression"], + ["o['m'];", "2 member expression"], + ["o['n']['m'];", "3 member expression"], + ["o.n.m;", "4 member expression"], + ["o.if;", "5 member expression"], + // call and invoke expressions + ["f();", "1 call/invoke expression"], + ["f(x);", "2 call/invoke expression"], + ["f(x,y);", "3 call/invoke expression"], + ["o.m();", "4 call/invoke expression"], + ["o['m'];", "5 call/invoke expression"], + ["o.m(x);", "6 call/invoke expression"], + ["o['m'](x);", "7 call/invoke expression"], + ["o.m(x,y);", "8 call/invoke expression"], + ["o['m'](x,y);", "9 call/invoke expression"], + ["f(x)(y);", "10 call/invoke expression"], + ["f().x;", "11 call/invoke expression"], + + // eval + ["eval('x');", "1 eval"], + ["(eval)('x');", "2 eval"], + ["(1,eval)('x');", "3 eval"], + ["eval(x,y);", "4 eval"], + // new expression + ["new f();", "1 new expression"], + ["new o;", "2 new expression"], + ["new o.m;", "3 new expression"], + ["new o.m(x);", "4 new expression"], + ["new o.m(x,y);", "5 new expression"], + // prefix/postfix + ["++x;", "1 pre/postfix"], + ["x++;", "2 pre/postfix"], + ["--x;", "3 pre/postfix"], + ["x--;", "4 pre/postfix"], + ["x ++;", "5 pre/postfix"], + ["x /* comment */ ++;", "6 pre/postfix"], + ["++ /* comment */ x;", "7 pre/postfix"], + // unary operators + ["delete x;", "1 unary operator"], + ["void x;", "2 unary operator"], + ["+ x;", "3 unary operator"], + ["-x;", "4 unary operator"], + ["~x;", "5 unary operator"], + ["!x;", "6 unary operator"], + // meh + ["new Date++;", "new date ++"], + ["+x++;", " + x ++"], + // expression expressions + ["1 * 2;", "1 expression expressions"], + ["1 / 2;", "2 expression expressions"], + ["1 % 2;", "3 expression expressions"], + ["1 + 2;", "4 expression expressions"], + ["1 - 2;", "5 expression expressions"], + ["1 << 2;", "6 expression expressions"], + ["1 >>> 2;", "7 expression expressions"], + ["1 >> 2;", "8 expression expressions"], + ["1 * 2 + 3;", "9 expression expressions"], + ["(1+2)*3;", "10 expression expressions"], + ["1*(2+3);", "11 expression expressions"], + ["xy;", "13 expression expressions"], + ["x<=y;", "14 expression expressions"], + ["x>=y;", "15 expression expressions"], + ["x instanceof y;", "16 expression expressions"], + ["x in y;", "17 expression expressions"], + ["x&y;", "18 expression expressions"], + ["x^y;", "19 expression expressions"], + ["x|y;", "20 expression expressions"], + ["x+y>>= y;", "1 assignment"], + ["x <<= y;", "2 assignment"], + ["x = y;", "3 assignment"], + ["x += y;", "4 assignment"], + ["x /= y;", "5 assignment"], + // comma + ["x, y;", "comma"], + // block + ["{};", "1 block"], + ["{x;};", "2 block"], + ["{x;y;};", "3 block"], + // vars + ["var x;", "1 var"], + ["var x,y;", "2 var"], + ["var x=1,y=2;", "3 var"], + ["var x,y=2;", "4 var"], + // empty + [";", "1 empty"], + ["\n;", "2 empty"], + // expression statement + ["x;", "1 expression statement"], + ["5;", "2 expression statement"], + ["1+2;", "3 expression statement"], + // if + ["if (c) x; else y;", "1 if statement"], + ["if (c) x;", "2 if statement"], + ["if (c) {} else {};", "3 if statement"], + ["if (c1) if (c2) s1; else s2;", "4 if statement"], + // while + ["do s; while (e);", "1 while statement"], + ["do { s; } while (e);", "2 while statement"], + ["while (e) s;", "3 while statement"], + ["while (e) { s; };", "4 while statement"], + // for + ["for (;;) ;", "1 for statement"], + ["for (;c;x++) x;", "2 for statement"], + ["for (i;i> 1; +var c = 8 >>> 1; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js new file mode 100644 index 0000000..022f7a3 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue34.js @@ -0,0 +1,3 @@ +var a = {}; +a["this"] = 1; +a["that"] = 2; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js new file mode 100644 index 0000000..0b76103 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue4.js @@ -0,0 +1,3 @@ +var a = 2e3; +var b = 2e-3; +var c = 2e-5; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js new file mode 100644 index 0000000..031e85b --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue48.js @@ -0,0 +1 @@ +var s, i; s = ''; i = 0; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js new file mode 100644 index 0000000..060f9df --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue50.js @@ -0,0 +1,9 @@ +function bar(a) { + try { + foo(); + } catch(e) { + alert("Exception caught (foo not defined)"); + } + alert(a); // 10 in FF, "[object Error]" in IE +} +bar(10); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js new file mode 100644 index 0000000..4f8b32f --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue53.js @@ -0,0 +1 @@ +x = (y, z) diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js new file mode 100644 index 0000000..967052e --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue54.1.js @@ -0,0 +1,3 @@ +foo.toString(); +a.toString(16); +b.toString.call(c); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js new file mode 100644 index 0000000..14054d0 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue68.js @@ -0,0 +1,5 @@ +function f() { + if (a) return; + g(); + function g(){} +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js new file mode 100644 index 0000000..d25ecd6 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue69.js @@ -0,0 +1 @@ +[(a,b)] diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js new file mode 100644 index 0000000..6158861 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/issue9.js @@ -0,0 +1,4 @@ +var a = { + a: 1, + b: 2, // <-- trailing comma +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js new file mode 100644 index 0000000..c271a26 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/mangle.js @@ -0,0 +1,5 @@ +(function() { + var x = function fun(a, fun, b) { + return fun; + }; +}()); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js new file mode 100644 index 0000000..a675b1c --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/null_string.js @@ -0,0 +1 @@ +var nullString = "\0" \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js new file mode 100644 index 0000000..b631f4c --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/strict-equals.js @@ -0,0 +1,3 @@ +typeof a === 'string' +b + "" !== c + "" +d < e === f < g diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js new file mode 100644 index 0000000..609a35d --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/var.js @@ -0,0 +1,3 @@ +// var declarations after each other should be combined +var a = 1; +var b = 2; \ No newline at end of file diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js new file mode 100644 index 0000000..6a15c46 --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/whitespace.js @@ -0,0 +1,21 @@ +function id(a) { + // Form-Feed + // Vertical Tab + // No-Break Space + ᠎// Mongolian Vowel Separator +  // En quad +  // Em quad +  // En space +  // Em space +  // Three-Per-Em Space +  // Four-Per-Em Space +  // Six-Per-Em Space +  // Figure Space +  // Punctuation Space +  // Thin Space +  // Hair Space +  // Narrow No-Break Space +  // Medium Mathematical Space +  // Ideographic Space + return a; +} diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js new file mode 100644 index 0000000..de266ed --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test/with.js @@ -0,0 +1,2 @@ +with({}) { +}; diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js new file mode 100644 index 0000000..5d334ff --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/scripts.js @@ -0,0 +1,55 @@ +var fs = require('fs'), + uglify = require('../../uglify-js'), + jsp = uglify.parser, + nodeunit = require('nodeunit'), + path = require('path'), + pro = uglify.uglify; + +var Script = process.binding('evals').Script; + +var scriptsPath = __dirname; + +function compress(code) { + var ast = jsp.parse(code); + ast = pro.ast_mangle(ast); + ast = pro.ast_squeeze(ast, { no_warnings: true }); + ast = pro.ast_squeeze_more(ast); + return pro.gen_code(ast); +}; + +var testDir = path.join(scriptsPath, "compress", "test"); +var expectedDir = path.join(scriptsPath, "compress", "expected"); + +function getTester(script) { + return function(test) { + var testPath = path.join(testDir, script); + var expectedPath = path.join(expectedDir, script); + var content = fs.readFileSync(testPath, 'utf-8'); + var outputCompress = compress(content); + + // Check if the noncompressdata is larger or same size as the compressed data + test.ok(content.length >= outputCompress.length); + + // Check that a recompress gives the same result + var outputReCompress = compress(content); + test.equal(outputCompress, outputReCompress); + + // Check if the compressed output is what is expected + var expected = fs.readFileSync(expectedPath, 'utf-8'); + test.equal(outputCompress, expected.replace(/(\r?\n)+$/, "")); + + test.done(); + }; +}; + +var tests = {}; + +var scripts = fs.readdirSync(testDir); +for (var i in scripts) { + var script = scripts[i]; + if (/\.js$/.test(script)) { + tests[script] = getTester(script); + } +} + +module.exports = nodeunit.testCase(tests); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js new file mode 100644 index 0000000..256ad1c --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/269.js @@ -0,0 +1,13 @@ +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +var test_code = "var JSON;JSON||(JSON={});"; + +var ast = jsp.parse(test_code, false, false); +var nonembed_token_code = pro.gen_code(ast); +ast = jsp.parse(test_code, false, true); +var embed_token_code = pro.gen_code(ast); + +console.log("original: " + test_code); +console.log("no token: " + nonembed_token_code); +console.log(" token: " + embed_token_code); diff --git a/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js new file mode 100644 index 0000000..2c6257e --- /dev/null +++ b/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/tmp/app.js @@ -0,0 +1,22315 @@ +/* Modernizr 2.0.6 (Custom Build) | MIT & BSD + * Build: http://www.modernizr.com/download/#-iepp + */ +;window.Modernizr=function(a,b,c){function w(a,b){return!!~(""+a).indexOf(b)}function v(a,b){return typeof a===b}function u(a,b){return t(prefixes.join(a+";")+(b||""))}function t(a){j.cssText=a}var d="2.0.6",e={},f=b.documentElement,g=b.head||b.getElementsByTagName("head")[0],h="modernizr",i=b.createElement(h),j=i.style,k,l=Object.prototype.toString,m={},n={},o={},p=[],q,r={}.hasOwnProperty,s;!v(r,c)&&!v(r.call,c)?s=function(a,b){return r.call(a,b)}:s=function(a,b){return b in a&&v(a.constructor.prototype[b],c)};for(var x in m)s(m,x)&&(q=x.toLowerCase(),e[q]=m[x](),p.push((e[q]?"":"no-")+q));t(""),i=k=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.3", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( !array ) { + return -1; + } + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
    a"; + + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + + // Support interoperable removal of hyphenated or camelcased keys + if ( !thisCache[ name ] ) { + name = jQuery.camelCase( name ); + } + + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + nodeHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + hooks = boolHook; + + // Use nodeHook if available( IE6/7 ) + } else if ( nodeHook ) { + hooks = nodeHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + jQuery.attr( elem, name, "" ); + elem.removeAttribute( name ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabindex propHook to attrHooks for back-compat +jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode; + return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return (ret.nodeValue = value + ""); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = jQuery.nodeName( elem, "input" ) ? elem.type : "", + val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /
    ", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + */ + +(function() { + this.loggly = function(opts) { + this.user_agent = get_agent(); + this.browser_size = get_size(); + log_methods = {'error': 5, 'warn': 4, 'info': 3, 'debug': 2, 'log': 1}; + if (!opts.url) throw new Error("Please include a Loggly HTTP URL."); + if (!opts.level) { + this.level = log_methods['info']; + } else { + this.level = log_methods[opts.level]; + } + this.log = function(data) { + if (log_methods['log'] == this.level) { + opts.data = data; + janky(opts); + } + }; + this.debug = function(data) { + if (log_methods['debug'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.info = function(data) { + if (log_methods['info'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.warn = function(data) { + if (log_methods['warn'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + this.error = function(data) { + if (log_methods['error'] >= this.level) { + opts.data = data; + janky(opts); + } + }; + }; + this.janky = function(opts) { + janky._form(function(iframe, form) { + form.setAttribute("action", opts.url); + form.setAttribute("method", "post"); + janky._input(iframe, form, opts.data); + form.submit(); + setTimeout(function(){ + document.body.removeChild(iframe); + }, 2000); + }); + }; + this.janky._form = function(cb) { + var iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + iframe.style.display = "none"; + setTimeout(function() { + var form = iframe.contentWindow.document.createElement("form"); + iframe.contentWindow.document.body.appendChild(form); + cb(iframe, form); + }, 0); + }; + this.janky._input = function(iframe, form, data) { + var inp = iframe.contentWindow.document.createElement("input"); + inp.setAttribute("type", "hidden"); + inp.setAttribute("name", "source"); + inp.value = "castor " + data; + form.appendChild(inp); + }; + this.get_agent = function () { + return navigator.appCodeName + navigator.appName + navigator.appVersion; + }; + this.get_size = function () { + var width = 0; var height = 0; + if( typeof( window.innerWidth ) == 'number' ) { + width = window.innerWidth; height = window.innerHeight; + } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { + width = document.documentElement.clientWidth; height = document.documentElement.clientHeight; + } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { + width = document.body.clientWidth; height = document.body.clientHeight; + } + return {'height': height, 'width': width}; + }; +})(); + + +jsworld={};jsworld.formatIsoDateTime=function(a,b){if(typeof a==="undefined")a=new Date;if(typeof b==="undefined")b=false;var c=jsworld.formatIsoDate(a)+" "+jsworld.formatIsoTime(a);if(b){var d=a.getHours()-a.getUTCHours();var e=Math.abs(d);var f=a.getUTCMinutes();var g=a.getMinutes();if(g!=f&&f<30&&d<0)e--;if(g!=f&&f>30&&d>0)e--;var h;if(g!=f)h=":30";else h=":00";var i;if(e<10)i="0"+e+h;else i=""+e+h;if(d<0)i="-"+i;else i="+"+i;c=c+i}return c};jsworld.formatIsoDate=function(a){if(typeof a==="undefined")a=new Date;var b=a.getFullYear();var c=a.getMonth()+1;var d=a.getDate();return b+"-"+jsworld._zeroPad(c,2)+"-"+jsworld._zeroPad(d,2)};jsworld.formatIsoTime=function(a){if(typeof a==="undefined")a=new Date;var b=a.getHours();var c=a.getMinutes();var d=a.getSeconds();return jsworld._zeroPad(b,2)+":"+jsworld._zeroPad(c,2)+":"+jsworld._zeroPad(d,2)};jsworld.parseIsoDateTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d)(\d\d)(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);var f=parseInt(b[4],10);var g=parseInt(b[5],10);var h=parseInt(b[6],10);if(d<1||d>12||e<1||e>31||f<0||f>23||g<0||g>59||h<0||h>59)throw"Error: Invalid ISO-8601 date/time value";var i=new Date(c,d-1,e,f,g,h);if(i.getDate()!=e||i.getMonth()+1!=d)throw"Error: Invalid date";return i};jsworld.parseIsoDate=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/);if(b===null)b=a.match(/^(\d\d\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(d<1||d>12||e<1||e>31)throw"Error: Invalid ISO-8601 date value";var f=new Date(c,d-1,e);if(f.getDate()!=e||f.getMonth()+1!=d)throw"Error: Invalid date";return f};jsworld.parseIsoTime=function(a){if(typeof a!="string")throw"Error: The parameter must be a string";var b=a.match(/^(\d\d):(\d\d):(\d\d)/);if(b===null)b=a.match(/^(\d\d)(\d\d)(\d\d)/);if(b===null)throw"Error: Invalid ISO-8601 date/time string";var c=parseInt(b[1],10);var d=parseInt(b[2],10);var e=parseInt(b[3],10);if(c<0||c>23||d<0||d>59||e<0||e>59)throw"Error: Invalid ISO-8601 time value";return new Date(0,0,0,c,d,e)};jsworld._trim=function(a){var b=" \n\r\t\f \u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";for(var c=0;c=0;c--){if(b.indexOf(a.charAt(c))===-1){a=a.substring(0,c+1);break}}return b.indexOf(a.charAt(0))===-1?a:""};jsworld._isNumber=function(a){if(typeof a=="number")return true;if(typeof a!="string")return false;var b=a+"";return/^-?(\d+|\d*\.\d+)$/.test(b)};jsworld._isInteger=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\d+$/.test(b)};jsworld._isFloat=function(a){if(typeof a!="number"&&typeof a!="string")return false;var b=a+"";return/^-?\.\d+?$/.test(b)};jsworld._hasOption=function(a,b){if(typeof a!="string"||typeof b!="string")return false;if(b.indexOf(a)!=-1)return true;else return false};jsworld._stringReplaceAll=function(a,b,c){var d;if(b.length==1&&c.length==1){d="";for(var e=0;e0){if(d.length>0)g=parseInt(d.shift(),10);if(isNaN(g))throw"Error: Invalid grouping";if(g==-1){e=a.substring(0,f)+e;break}f-=g;if(f<1){e=a.substring(0,f+g)+e;break}e=c+a.substring(f,f+g)+e}return e};jsworld._formatFractionPart=function(a,b){for(var c=0;a.length0)return a;else throw"Empty or no string"};if(a==null||typeof a!="object")throw"Error: Invalid/missing locale properties";if(typeof a.decimal_point!="string")throw"Error: Invalid/missing decimal_point property";this.decimal_point=a.decimal_point;if(typeof a.thousands_sep!="string")throw"Error: Invalid/missing thousands_sep property";this.thousands_sep=a.thousands_sep;if(typeof a.grouping!="string")throw"Error: Invalid/missing grouping property";this.grouping=a.grouping;if(typeof a.int_curr_symbol!="string")throw"Error: Invalid/missing int_curr_symbol property";if(!/[A-Za-z]{3}.?/.test(a.int_curr_symbol))throw"Error: Invalid int_curr_symbol property";this.int_curr_symbol=a.int_curr_symbol;if(typeof a.currency_symbol!="string")throw"Error: Invalid/missing currency_symbol property";this.currency_symbol=a.currency_symbol;if(typeof a.frac_digits!="number"&&a.frac_digits<0)throw"Error: Invalid/missing frac_digits property";this.frac_digits=a.frac_digits;if(a.mon_decimal_point===null||a.mon_decimal_point==""){if(this.frac_digits>0)throw"Error: Undefined mon_decimal_point property";else a.mon_decimal_point=""}if(typeof a.mon_decimal_point!="string")throw"Error: Invalid/missing mon_decimal_point property";this.mon_decimal_point=a.mon_decimal_point;if(typeof a.mon_thousands_sep!="string")throw"Error: Invalid/missing mon_thousands_sep property";this.mon_thousands_sep=a.mon_thousands_sep;if(typeof a.mon_grouping!="string")throw"Error: Invalid/missing mon_grouping property";this.mon_grouping=a.mon_grouping;if(typeof a.positive_sign!="string")throw"Error: Invalid/missing positive_sign property";this.positive_sign=a.positive_sign;if(typeof a.negative_sign!="string")throw"Error: Invalid/missing negative_sign property";this.negative_sign=a.negative_sign;if(a.p_cs_precedes!==0&&a.p_cs_precedes!==1)throw"Error: Invalid/missing p_cs_precedes property, must be 0 or 1";this.p_cs_precedes=a.p_cs_precedes;if(a.n_cs_precedes!==0&&a.n_cs_precedes!==1)throw"Error: Invalid/missing n_cs_precedes, must be 0 or 1";this.n_cs_precedes=a.n_cs_precedes;if(a.p_sep_by_space!==0&&a.p_sep_by_space!==1&&a.p_sep_by_space!==2)throw"Error: Invalid/missing p_sep_by_space property, must be 0, 1 or 2";this.p_sep_by_space=a.p_sep_by_space;if(a.n_sep_by_space!==0&&a.n_sep_by_space!==1&&a.n_sep_by_space!==2)throw"Error: Invalid/missing n_sep_by_space property, must be 0, 1, or 2";this.n_sep_by_space=a.n_sep_by_space;if(a.p_sign_posn!==0&&a.p_sign_posn!==1&&a.p_sign_posn!==2&&a.p_sign_posn!==3&&a.p_sign_posn!==4)throw"Error: Invalid/missing p_sign_posn property, must be 0, 1, 2, 3 or 4";this.p_sign_posn=a.p_sign_posn;if(a.n_sign_posn!==0&&a.n_sign_posn!==1&&a.n_sign_posn!==2&&a.n_sign_posn!==3&&a.n_sign_posn!==4)throw"Error: Invalid/missing n_sign_posn property, must be 0, 1, 2, 3 or 4";this.n_sign_posn=a.n_sign_posn;if(typeof a.int_frac_digits!="number"&&a.int_frac_digits<0)throw"Error: Invalid/missing int_frac_digits property";this.int_frac_digits=a.int_frac_digits;if(a.int_p_cs_precedes!==0&&a.int_p_cs_precedes!==1)throw"Error: Invalid/missing int_p_cs_precedes property, must be 0 or 1";this.int_p_cs_precedes=a.int_p_cs_precedes;if(a.int_n_cs_precedes!==0&&a.int_n_cs_precedes!==1)throw"Error: Invalid/missing int_n_cs_precedes property, must be 0 or 1";this.int_n_cs_precedes=a.int_n_cs_precedes;if(a.int_p_sep_by_space!==0&&a.int_p_sep_by_space!==1&&a.int_p_sep_by_space!==2)throw"Error: Invalid/missing int_p_sep_by_spacev, must be 0, 1 or 2";this.int_p_sep_by_space=a.int_p_sep_by_space;if(a.int_n_sep_by_space!==0&&a.int_n_sep_by_space!==1&&a.int_n_sep_by_space!==2)throw"Error: Invalid/missing int_n_sep_by_space property, must be 0, 1, or 2";this.int_n_sep_by_space=a.int_n_sep_by_space;if(a.int_p_sign_posn!==0&&a.int_p_sign_posn!==1&&a.int_p_sign_posn!==2&&a.int_p_sign_posn!==3&&a.int_p_sign_posn!==4)throw"Error: Invalid/missing int_p_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_p_sign_posn=a.int_p_sign_posn;if(a.int_n_sign_posn!==0&&a.int_n_sign_posn!==1&&a.int_n_sign_posn!==2&&a.int_n_sign_posn!==3&&a.int_n_sign_posn!==4)throw"Error: Invalid/missing int_n_sign_posn property, must be 0, 1, 2, 3 or 4";this.int_n_sign_posn=a.int_n_sign_posn;if(a==null||typeof a!="object")throw"Error: Invalid/missing time locale properties";try{this.abday=this._parseList(a.abday,7)}catch(b){throw"Error: Invalid abday property: "+b}try{this.day=this._parseList(a.day,7)}catch(b){throw"Error: Invalid day property: "+b}try{this.abmon=this._parseList(a.abmon,12)}catch(b){throw"Error: Invalid abmon property: "+b}try{this.mon=this._parseList(a.mon,12)}catch(b){throw"Error: Invalid mon property: "+b}try{this.d_fmt=this._validateFormatString(a.d_fmt)}catch(b){throw"Error: Invalid d_fmt property: "+b}try{this.t_fmt=this._validateFormatString(a.t_fmt)}catch(b){throw"Error: Invalid t_fmt property: "+b}try{this.d_t_fmt=this._validateFormatString(a.d_t_fmt)}catch(b){throw"Error: Invalid d_t_fmt property: "+b}try{var c=this._parseList(a.am_pm,2);this.am=c[0];this.pm=c[1]}catch(b){this.am="";this.pm=""}this.getAbbreviatedWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.abday;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.abday[a]};this.getWeekdayName=function(a){if(typeof a=="undefined"||a===null)return this.day;if(!jsworld._isInteger(a)||a<0||a>6)throw"Error: Invalid weekday argument, must be an integer [0..6]";return this.day[a]};this.getAbbreviatedMonthName=function(a){if(typeof a=="undefined"||a===null)return this.abmon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.abmon[a]};this.getMonthName=function(a){if(typeof a=="undefined"||a===null)return this.mon;if(!jsworld._isInteger(a)||a<0||a>11)throw"Error: Invalid month argument, must be an integer [0..11]";return this.mon[a]};this.getDecimalPoint=function(){return this.decimal_point};this.getCurrencySymbol=function(){return this.currency_symbol};this.getIntCurrencySymbol=function(){return this.int_curr_symbol.substring(0,3)};this.currencySymbolPrecedes=function(){if(this.p_cs_precedes==1)return true;else return false};this.intCurrencySymbolPrecedes=function(){if(this.int_p_cs_precedes==1)return true;else return false};this.getMonetaryDecimalPoint=function(){return this.mon_decimal_point};this.getFractionalDigits=function(){return this.frac_digits};this.getIntFractionalDigits=function(){return this.int_frac_digits}};jsworld.NumericFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.format=function(a,b){if(typeof a=="string")a=jsworld._trim(a);if(!jsworld._isNumber(a))throw"Error: The input is not a number";var c=parseFloat(a,10);var d=jsworld._getPrecision(b);if(d!=-1)c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.grouping,this.lc.thousands_sep);var g=d!=-1?jsworld._formatFractionPart(e.fraction,d):e.fraction;var h=g.length?f+this.lc.decimal_point+g:f;if(jsworld._hasOption("~",b)||c===0){return h}else{if(jsworld._hasOption("+",b)||c<0){if(c>0)return"+"+h;else if(c<0)return"-"+h;else return h}else{return h}}}};jsworld.DateTimeFormatter=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.formatDate=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoDate(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_fmt)};this.formatTime=function(a){var b=null;if(typeof a=="string"){try{b=jsworld.parseIsoTime(a)}catch(c){b=jsworld.parseIsoDateTime(a)}}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.t_fmt)};this.formatDateTime=function(a){var b=null;if(typeof a=="string"){b=jsworld.parseIsoDateTime(a)}else if(a!==null&&typeof a=="object"){b=a}else{throw"Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string"}return this._applyFormatting(b,this.lc.d_t_fmt)};this._applyFormatting=function(a,b){b=b.replace(/%%/g,"%");b=b.replace(/%a/g,this.lc.abday[a.getDay()]);b=b.replace(/%A/g,this.lc.day[a.getDay()]);b=b.replace(/%b/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%B/g,this.lc.mon[a.getMonth()]);b=b.replace(/%d/g,jsworld._zeroPad(a.getDate(),2));b=b.replace(/%e/g,jsworld._spacePad(a.getDate(),2));b=b.replace(/%F/g,a.getFullYear()+"-"+jsworld._zeroPad(a.getMonth()+1,2)+"-"+jsworld._zeroPad(a.getDate(),2));b=b.replace(/%h/g,this.lc.abmon[a.getMonth()]);b=b.replace(/%H/g,jsworld._zeroPad(a.getHours(),2));b=b.replace(/%I/g,jsworld._zeroPad(this._hours12(a.getHours()),2));b=b.replace(/%k/g,a.getHours());b=b.replace(/%l/g,this._hours12(a.getHours()));b=b.replace(/%m/g,jsworld._zeroPad(a.getMonth()+1,2));b=b.replace(/%n/g,"\n");b=b.replace(/%M/g,jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%p/g,this._getAmPm(a.getHours()));b=b.replace(/%P/g,this._getAmPm(a.getHours()).toLocaleLowerCase());b=b.replace(/%R/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2));b=b.replace(/%S/g,jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%T/g,jsworld._zeroPad(a.getHours(),2)+":"+jsworld._zeroPad(a.getMinutes(),2)+":"+jsworld._zeroPad(a.getSeconds(),2));b=b.replace(/%w/g,this.lc.day[a.getDay()]);b=b.replace(/%y/g,(new String(a.getFullYear())).substring(2));b=b.replace(/%Y/g,a.getFullYear());b=b.replace(/%Z/g,"");b=b.replace(/%[a-zA-Z]/g,"");return b};this._hours12=function(a){if(a===0)return 12;else if(a>12)return a-12;else return a};this._getAmPm=function(a){if(a===0||a>12)return this.lc.pm;else return this.lc.am}};jsworld.MonetaryFormatter=function(a,b,c){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.currencyFractionDigits={AFN:0,ALL:0,AMD:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,COP:0,CRC:0,DJF:0,GNF:0,GYD:0,HUF:0,IDR:0,IQD:0,IRR:0,ISK:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LAK:0,LBP:0,LYD:3,MGA:0,MMK:0,MNT:0,MRO:0,MUR:0,OMR:3,PKR:0,PYG:0,RSD:0,RWF:0,SLL:0,SOS:0,STD:0,SYP:0,TND:3,TWD:0,TZS:0,UGX:0,UZS:0,VND:0,VUV:0,XAF:0,XOF:0,XPF:0,YER:0,ZMK:0};if(typeof b=="string"){this.currencyCode=b.toUpperCase();var d=this.currencyFractionDigits[this.currencyCode];if(typeof d!="number")d=2;this.lc.frac_digits=d;this.lc.int_frac_digits=d}else{this.currencyCode=this.lc.int_curr_symbol.substring(0,3).toUpperCase()}this.intSep=this.lc.int_curr_symbol.charAt(3);if(this.currencyCode==this.lc.int_curr_symbol.substring(0,3)){this.internationalFormatting=false;this.curSym=this.lc.currency_symbol}else{if(typeof c=="string"){this.curSym=c;this.internationalFormatting=false}else{this.internationalFormatting=true}}this.getCurrencySymbol=function(){return this.curSym};this.currencySymbolPrecedes=function(a){if(typeof a=="string"&&a=="i"){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.internationalFormatting){if(this.lc.int_p_cs_precedes==1)return true;else return false}else{if(this.lc.p_cs_precedes==1)return true;else return false}}};this.getDecimalPoint=function(){return this.lc.mon_decimal_point};this.getFractionalDigits=function(a){if(typeof a=="string"&&a=="i"){return this.lc.int_frac_digits}else{if(this.internationalFormatting)return this.lc.int_frac_digits;else return this.lc.frac_digits}};this.format=function(a,b){var c;if(typeof a=="string"){a=jsworld._trim(a);c=parseFloat(a);if(typeof c!="number"||isNaN(c))throw"Error: Amount string not a number"}else if(typeof a=="number"){c=a}else{throw"Error: Amount not a number"}var d=jsworld._getPrecision(b);if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))d=this.lc.int_frac_digits;else d=this.lc.frac_digits}c=Math.round(c*Math.pow(10,d))/Math.pow(10,d);var e=jsworld._splitNumber(String(c));var f;if(c===0)f="0";else f=jsworld._hasOption("^",b)?e.integer:jsworld._formatIntegerPart(e.integer,this.lc.mon_grouping,this.lc.mon_thousands_sep);var g;if(d==-1){if(this.internationalFormatting||jsworld._hasOption("i",b))g=jsworld._formatFractionPart(e.fraction,this.lc.int_frac_digits);else g=jsworld._formatFractionPart(e.fraction,this.lc.frac_digits)}else{g=jsworld._formatFractionPart(e.fraction,d)}var h;if(this.lc.frac_digits>0||g.length)h=f+this.lc.mon_decimal_point+g;else h=f;if(jsworld._hasOption("~",b)){return h}else{var i=jsworld._hasOption("!",b)?true:false;var j=c<0?"-":"+";if(this.internationalFormatting||jsworld._hasOption("i",b)){if(i)return this._formatAsInternationalCurrencyWithNoSym(j,h);else return this._formatAsInternationalCurrency(j,h)}else{if(i)return this._formatAsLocalCurrencyWithNoSym(j,h);else return this._formatAsLocalCurrency(j,h)}}};this._formatAsLocalCurrency=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.p_sign_posn===0&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b+" "+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b+this.curSym}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+" "+b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+this.curSym+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign+" "+this.curSym}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+this.curSym+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.curSym+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.curSym+this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.curSym+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.curSym+" "+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return"("+b+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return"("+this.curSym+b+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return"("+b+" "+this.curSym+")"}else if(this.lc.n_sign_posn===0&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return"("+this.curSym+" "+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b+" "+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b+this.curSym}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+" "+b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+this.curSym+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign+" "+this.curSym}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+this.curSym+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.curSym+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.curSym+this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.curSym+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.curSym+" "+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrency=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_p_sign_posn===0&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign+this.intSep+this.currencyCode}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return"("+b+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+b+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return"("+b+this.intSep+this.currencyCode+")"}else if(this.lc.int_n_sign_posn===0&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return"("+this.currencyCode+this.intSep+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b+this.currencyCode}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.currencyCode+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign+this.intSep+this.currencyCode}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+this.currencyCode+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.currencyCode+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.currencyCode+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.currencyCode+this.intSep+this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsLocalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.p_sign_posn===0){return"("+b+")"}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===1&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===2&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===3&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===0&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===1&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+" "+b}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===0){return b+" "+this.lc.positive_sign}else if(this.lc.p_sign_posn===4&&this.lc.p_sep_by_space===2&&this.lc.p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.n_sign_posn===0){return"("+b+")"}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===1&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===2&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===3&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===0&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===1&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+" "+b}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===0){return b+" "+this.lc.negative_sign}else if(this.lc.n_sign_posn===4&&this.lc.n_sep_by_space===2&&this.lc.n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC MONETARY definition"};this._formatAsInternationalCurrencyWithNoSym=function(a,b){if(a=="+"){if(this.lc.int_p_sign_posn===0){return"("+b+")"}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===1&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===2&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===3&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===0){return b+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===0&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===1&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+this.intSep+b}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===0){return b+this.intSep+this.lc.positive_sign}else if(this.lc.int_p_sign_posn===4&&this.lc.int_p_sep_by_space===2&&this.lc.int_p_cs_precedes===1){return this.lc.positive_sign+b}}else if(a=="-"){if(this.lc.int_n_sign_posn===0){return"("+b+")"}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===1&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===2&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===3&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===0){return b+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===0&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===1&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+this.intSep+b}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===0){return b+this.intSep+this.lc.negative_sign}else if(this.lc.int_n_sign_posn===4&&this.lc.int_n_sep_by_space===2&&this.lc.int_n_cs_precedes===1){return this.lc.negative_sign+b}}throw"Error: Invalid POSIX LC_MONETARY definition"}};jsworld.NumericParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=jsworld._trim(a);b=jsworld._stringReplaceAll(a,this.lc.thousands_sep,"");b=jsworld._stringReplaceAll(b,this.lc.decimal_point,".");if(jsworld._isNumber(b))return parseFloat(b,10);else throw"Parse error: Invalid number string"}};jsworld.DateTimeParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance.";this.lc=a;this.parseTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.t_fmt,a);var c=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(c)return jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous time string"};this.parseDate=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_fmt,a);var c=false;if(b.year!==null&&b.month!==null&&b.day!==null){c=true}if(c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2);else throw"Parse error: Invalid date string"};this.parseDateTime=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._extractTokens(this.lc.d_t_fmt,a);var c=false;var d=false;if(b.hour!==null&&b.minute!==null&&b.second!==null){c=true}else if(b.hourAmPm!==null&&b.am!==null&&b.minute!==null&&b.second!==null){if(b.am){b.hour=parseInt(b.hourAmPm,10)}else{if(b.hourAmPm==12)b.hour=0;else b.hour=parseInt(b.hourAmPm,10)+12}c=true}if(b.year!==null&&b.month!==null&&b.day!==null){d=true}if(d&&c)return jsworld._zeroPad(b.year,4)+"-"+jsworld._zeroPad(b.month,2)+"-"+jsworld._zeroPad(b.day,2)+" "+jsworld._zeroPad(b.hour,2)+":"+jsworld._zeroPad(b.minute,2)+":"+jsworld._zeroPad(b.second,2);else throw"Parse error: Invalid/ambiguous date/time string"};this._extractTokens=function(a,b){var c={year:null,month:null,day:null,hour:null,hourAmPm:null,am:null,minute:null,second:null,weekday:null};while(a.length>0){if(a.charAt(0)=="%"&&a.charAt(1)!=""){var d=a.substring(0,2);if(d=="%%"){b=b.substring(1)}else if(d=="%a"){for(var e=0;e31)throw"Parse error: Unrecognised day of the month (%e)";b=b.substring(f.length)}else if(d=="%F"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else{throw"Parse error: Unrecognised date (%F)"}if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)";if(jsworld._stringStartsWith(b,"-"))b=b.substring(1);else throw"Parse error: Unrecognised date (%F)";if(/^0[1-9]|[1-2][0-9]|3[0-1]/.test(b)){c.day=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised date (%F)"}else if(d=="%H"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%H)"}else if(d=="%I"){if(/^0[1-9]|1[0-2]/.test(b)){c.hourAmPm=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised hour (%I)"}else if(d=="%k"){var g=b.match(/^(\d{1,2})/);c.hour=parseInt(g,10);if(isNaN(c.hour)||c.hour<0||c.hour>23)throw"Parse error: Unrecognised hour (%k)";b=b.substring(g.length)}else if(d=="%l"){var g=b.match(/^(\d{1,2})/);c.hourAmPm=parseInt(g,10);if(isNaN(c.hourAmPm)||c.hourAmPm<1||c.hourAmPm>12)throw"Parse error: Unrecognised hour (%l)";b=b.substring(g.length)}else if(d=="%m"){if(/^0[1-9]|1[0-2]/.test(b)){c.month=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised month (%m)"}else if(d=="%M"){if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised minute (%M)"}else if(d=="%n"){if(b.charAt(0)=="\n")b=b.substring(1);else throw"Parse error: Unrecognised new line (%n)"}else if(d=="%p"){if(jsworld._stringStartsWith(b,this.lc.am)){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm)){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%p)"}else if(d=="%P"){if(jsworld._stringStartsWith(b,this.lc.am.toLowerCase())){c.am=true;b=b.substring(this.lc.am.length)}else if(jsworld._stringStartsWith(b,this.lc.pm.toLowerCase())){c.am=false;b=b.substring(this.lc.pm.length)}else throw"Parse error: Unrecognised AM/PM value (%P)"}else if(d=="%R"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%R)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%R)"}else if(d=="%S"){if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised second (%S)"}else if(d=="%T"){if(/^[0-1][0-9]|2[0-3]/.test(b)){c.hour=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.minute=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)";if(jsworld._stringStartsWith(b,":"))b=b.substring(1);else throw"Parse error: Unrecognised time (%T)";if(/^[0-5][0-9]/.test(b)){c.second=parseInt(b.substring(0,2),10);b=b.substring(2)}else throw"Parse error: Unrecognised time (%T)"}else if(d=="%w"){if(/^\d/.test(b)){c.weekday=parseInt(b.substring(0,1),10);b=b.substring(1)}else throw"Parse error: Unrecognised weekday number (%w)"}else if(d=="%y"){if(/^\d\d/.test(b)){var h=parseInt(b.substring(0,2),10);if(h>50)c.year=1900+h;else c.year=2e3+h;b=b.substring(2)}else throw"Parse error: Unrecognised year (%y)"}else if(d=="%Y"){if(/^\d\d\d\d/.test(b)){c.year=parseInt(b.substring(0,4),10);b=b.substring(4)}else throw"Parse error: Unrecognised year (%Y)"}else if(d=="%Z"){if(a.length===0)break}a=a.substring(2)}else{if(a.charAt(0)!=b.charAt(0))throw'Parse error: Unexpected symbol "'+b.charAt(0)+'" in date/time string';a=a.substring(1);b=b.substring(1)}}return c}};jsworld.MonetaryParser=function(a){if(typeof a!="object"||a._className!="jsworld.Locale")throw"Constructor error: You must provide a valid jsworld.Locale instance";this.lc=a;this.parse=function(a){if(typeof a!="string")throw"Parse error: Argument must be a string";var b=this._detectCurrencySymbolType(a);var c,d;if(b=="local"){c="local";d=a.replace(this.lc.getCurrencySymbol(),"")}else if(b=="int"){c="int";d=a.replace(this.lc.getIntCurrencySymbol(),"")}else if(b=="none"){c="local";d=a}else throw"Parse error: Internal assert failure";d=jsworld._stringReplaceAll(d,this.lc.mon_thousands_sep,"");d=d.replace(this.lc.mon_decimal_point,".");d=d.replace(/\s*/g,"");d=this._removeLocalNonNegativeSign(d,c);d=this._normaliseNegativeSign(d,c);if(jsworld._isNumber(d))return parseFloat(d,10);else throw"Parse error: Invalid currency amount string"};this._detectCurrencySymbolType=function(a){if(this.lc.getCurrencySymbol().length>this.lc.getIntCurrencySymbol().length){if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else return"none"}else{if(a.indexOf(this.lc.getIntCurrencySymbol())!=-1)return"int";else if(a.indexOf(this.lc.getCurrencySymbol())!=-1)return"local";else return"none"}};this._removeLocalNonNegativeSign=function(a,b){a=a.replace(this.lc.positive_sign,"");if((b=="local"&&this.lc.p_sign_posn===0||b=="int"&&this.lc.int_p_sign_posn===0)&&/\(\d+\.?\d*\)/.test(a)){a=a.replace("(","");a=a.replace(")","")}return a};this._normaliseNegativeSign=function(a,b){a=a.replace(this.lc.negative_sign,"-");if(b=="local"&&this.lc.n_sign_posn===0||b=="int"&&this.lc.int_n_sign_posn===0){if(/^\(\d+\.?\d*\)$/.test(a)){a=a.replace("(","");a=a.replace(")","");return"-"+a}}if(b=="local"&&this.lc.n_sign_posn==2||b=="int"&&this.lc.int_n_sign_posn==2){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}if(b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==3||b=="local"&&this.lc.n_cs_precedes===0&&this.lc.n_sign_posn==4||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==3||b=="int"&&this.lc.int_n_cs_precedes===0&&this.lc.int_n_sign_posn==4){if(/^\d+\.?\d*-$/.test(a)){a=a.replace("-","");return"-"+a}}return a}} + + +if(typeof POSIX_LC == "undefined") var POSIX_LC = {}; + +POSIX_LC.en_US = { + "decimal_point" : ".", + "thousands_sep" : ",", + "grouping" : "3", + "abday" : ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], + "day" : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], + "abmon" : ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], + "mon" : ["January","February","March","April","May","June","July","August","September","October","November","December"], + "d_fmt" : "%m/%e/%y", + "t_fmt" : "%I:%M:%S %p", + "d_t_fmt" : "%B %e, %Y %I:%M:%S %p %Z", + "am_pm" : ["AM","PM"], + "int_curr_symbol" : "USD ", + "currency_symbol" : "\u0024", + "mon_decimal_point" : ".", + "mon_thousands_sep" : ",", + "mon_grouping" : "3", + "positive_sign" : "", + "negative_sign" : "-", + "int_frac_digits" : 2, + "frac_digits" : 2, + "p_cs_precedes" : 1, + "n_cs_precedes" : 1, + "p_sep_by_space" : 0, + "n_sep_by_space" : 0, + "p_sign_posn" : 1, + "n_sign_posn" : 1, + "int_p_cs_precedes" : 1, + "int_n_cs_precedes" : 1, + "int_p_sep_by_space" : 0, + "int_n_sep_by_space" : 0, + "int_p_sign_posn" : 1, + "int_n_sign_posn" : 1 +} + +if(typeof POSIX_LC == "undefined") var POSIX_LC = {}; + +POSIX_LC.fr_FR = { + "decimal_point" : ",", + "thousands_sep" : "\u00a0", + "grouping" : "3", + "abday" : ["dim.","lun.","mar.", + "mer.","jeu.","ven.", + "sam."], + "day" : ["dimanche","lundi","mardi", + "mercredi","jeudi","vendredi", + "samedi"], + "abmon" : ["janv.","f\u00e9vr.","mars", + "avr.","mai","juin", + "juil.","ao\u00fbt","sept.", + "oct.","nov.","d\u00e9c."], + "mon" : ["janvier","f\u00e9vrier","mars", + "avril","mai","juin", + "juillet","ao\u00fbt","septembre", + "octobre","novembre","d\u00e9cembre"], + "d_fmt" : "%d/%m/%y", + "t_fmt" : "%H:%M:%S", + "d_t_fmt" : "%e %B %Y %H:%M:%S %Z", + "am_pm" : ["AM","PM"], + "int_curr_symbol" : "EUR ", + "currency_symbol" : "\u20ac", + "mon_decimal_point" : ",", + "mon_thousands_sep" : "\u00a0", + "mon_grouping" : "3", + "positive_sign" : "", + "negative_sign" : "-", + "int_frac_digits" : 2, + "frac_digits" : 2, + "p_cs_precedes" : 0, + "n_cs_precedes" : 0, + "p_sep_by_space" : 1, + "n_sep_by_space" : 1, + "p_sign_posn" : 1, + "n_sign_posn" : 1, + "int_p_cs_precedes" : 0, + "int_n_cs_precedes" : 0, + "int_p_sep_by_space" : 1, + "int_n_sep_by_space" : 1, + "int_p_sign_posn" : 1, + "int_n_sign_posn" : 1 +}; + +/** https://github.com/csnover/js-iso8601 */(function(n,f){var u=n.parse,c=[1,4,5,6,7,10,11];n.parse=function(t){var i,o,a=0;if(o=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(t)){for(var v=0,r;r=c[v];++v)o[r]=+o[r]||0;o[2]=(+o[2]||1)-1,o[3]=+o[3]||1,o[8]!=="Z"&&o[9]!==f&&(a=o[10]*60+o[11],o[9]==="+"&&(a=0-a)),i=n.UTC(o[1],o[2],o[3],o[4],o[5]+a,o[6],o[7])}else i=u?u(t):NaN;return i}})(Date) + +/*! + * geo-location-javascript v0.4.3 + * http://code.google.com/p/geo-location-javascript/ + * + * Copyright (c) 2009 Stan Wiechers + * Licensed under the MIT licenses. + * + * Revision: $Rev: 68 $: + * Author: $Author: whoisstan $: + * Date: $Date: 2010-02-15 13:42:19 +0100 (Mon, 15 Feb 2010) $: + */ +var geo_position_js=function() { + + var pub = {}; + var provider=null; + + pub.getCurrentPosition = function(successCallback,errorCallback,options) + { + provider.getCurrentPosition(successCallback, errorCallback,options); + } + + pub.init = function() + { + try + { + if (typeof(geo_position_js_simulator)!="undefined") + { + provider=geo_position_js_simulator; + } + else if (typeof(bondi)!="undefined" && typeof(bondi.geolocation)!="undefined") + { + provider=bondi.geolocation; + } + else if (typeof(navigator.geolocation)!="undefined") + { + provider=navigator.geolocation; + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + function _successCallback(p) + { + //for mozilla geode,it returns the coordinates slightly differently + if(typeof(p.latitude)!="undefined") + { + successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude,longitude:p.longitude}}); + } + else + { + successCallback(p); + } + } + provider.getCurrentPosition(_successCallback,errorCallback,options); + } + } + else if(typeof(window.google)!="undefined" && typeof(google.gears)!="undefined") + { + provider=google.gears.factory.create('beta.geolocation'); + } + else if ( typeof(Mojo) !="undefined" && typeof(Mojo.Service.Request)!="Mojo.Service.Request") + { + provider=true; + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + + parameters={}; + if(options) + { + //http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition + if (options.enableHighAccuracy && options.enableHighAccuracy==true) + { + parameters.accuracy=1; + } + if (options.maximumAge) + { + parameters.maximumAge=options.maximumAge; + } + if (options.responseTime) + { + if(options.responseTime<5) + { + parameters.responseTime=1; + } + else if (options.responseTime<20) + { + parameters.responseTime=2; + } + else + { + parameters.timeout=3; + } + } + } + + + r=new Mojo.Service.Request('palm://com.palm.location', { + method:"getCurrentPosition", + parameters:parameters, + onSuccess: function(p){successCallback({timestamp:p.timestamp, coords: {latitude:p.latitude, longitude:p.longitude,heading:p.heading}});}, + onFailure: function(e){ + if (e.errorCode==1) + { + errorCallback({code:3,message:"Timeout"}); + } + else if (e.errorCode==2) + { + errorCallback({code:2,message:"Position Unavailable"}); + } + else + { + errorCallback({code:0,message:"Unknown Error: webOS-code"+errorCode}); + } + } + }); + } + + } + else if (typeof(device)!="undefined" && typeof(device.getServiceObject)!="undefined") + { + provider=device.getServiceObject("Service.Location", "ILocation"); + + //override default method implementation + pub.getCurrentPosition = function(successCallback, errorCallback, options) + { + function callback(transId, eventCode, result) { + if (eventCode == 4) + { + errorCallback({message:"Position unavailable", code:2}); + } + else + { + //no timestamp of location given? + successCallback({timestamp:null, coords: {latitude:result.ReturnValue.Latitude, longitude:result.ReturnValue.Longitude, altitude:result.ReturnValue.Altitude,heading:result.ReturnValue.Heading}}); + } + } + //location criteria + var criteria = new Object(); + criteria.LocationInformationClass = "BasicLocationInformation"; + //make the call + provider.ILocation.GetLocation(criteria,callback); + } + } + } + catch (e){ + alert("error="+e); + if(typeof(console)!="undefined") + { + console.log(e); + } + return false; + } + return provider!=null; + } + + + return pub; +}(); +// Couldn't get unminified version to work , go here for docs => https://github.com/iamnoah/writeCapture +(function(E,a){var j=a.document;function A(Q){var Z=j.createElement("div");j.body.insertBefore(Z,null);E.replaceWith(Z,'\n
    \n
    \n
    \n \n\n
    \n
    \n \n
    \n

    '); + __out.push(__sanitize(t('Invite Link'))); + __out.push(' '); + __out.push(__sanitize(USER.referral_url)); + __out.push('

    \n\n \n\n
    \n\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/login": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('
    \n\t

    '); + __out.push(__sanitize(t('Sign In'))); + __out.push('

    \n\t
    \n\t\t
    \n\n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\n\t\t\t
    \n\n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\t\t\t
    \n\t\t\t\t\n\t\t\t
    \n\n\t\t\t
    \n\n
    \n\n

    '); + __out.push(__sanitize(t('Forgot Password?'))); + __out.push('

    \n\n\t\t
    \n\t
    \n
    \n\n
    \n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/modules/credit_card": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var printCard; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + if (this.cards === "new") { + __out.push('\n
    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n \n \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n \n
    \n
    \n
    \n'); + } else { + __out.push('\n '); + printCard = __bind(function(card, index) { + var exp, style; + __out.push('\n
    \n '); + style = "background-position:-173px"; + __out.push('\n '); + if (card.get("card_type") === "Visa") { + style = "background-position:0px"; + } + __out.push('\n '); + if (card.get("card_type") === "MasterCard") { + style = "background-position:-42px"; + } + __out.push('\n '); + if (card.get("card_type") === "American Express") { + style = "background-position:-130px"; + } + __out.push('\n '); + if (card.get("card_type") === "Discover Card") { + style = "background-position:-85px"; + } + __out.push('\n
    \n
    \n ****'); + __out.push(__sanitize(card.get("card_number"))); + __out.push('\n \n '); + if (card.get("card_expiration")) { + __out.push('\n '); + __out.push(__sanitize(t('Expiry'))); + __out.push('\n '); + exp = card.get('card_expiration').split('-'); + __out.push('\n '); + __out.push(__sanitize("" + exp[0] + "-" + exp[1])); + __out.push('\n '); + } + __out.push('\n \n \n \n '); + if (card.get("default")) { + __out.push('\n ('); + __out.push(__sanitize(t('default card'))); + __out.push(')\n '); + } + __out.push('\n '); + if (this.cards.length > 1 && !card.get("default")) { + __out.push('\n '); + __out.push(__sanitize(t('make default'))); + __out.push('\n '); + } + __out.push('\n \n '); + __out.push(__sanitize(t('Edit'))); + __out.push('\n \n '); + if (this.cards.length > 1) { + __out.push('\n '); + __out.push(__sanitize(t('Delete'))); + __out.push('\n '); + } + __out.push('\n
    \n '); + _.each(this.cards.models, printCard); + __out.push('\n
    \n
    \n\n'); + } + __out.push('\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/modules/sub_header": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('
    \n
    '); + __out.push(__sanitize(this.heading)); + __out.push('
    \n
    \n '); + if (window.USER.first_name) { + __out.push('\n '); + __out.push(__sanitize(t('Hello Greeting', { + name: USER.first_name + }))); + __out.push('\n '); + } + __out.push('\n
    \n
    \n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/promotions": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var promo, _i, _len, _ref; + __out.push(require('templates/clients/modules/sub_header').call(this, { + heading: t("Promotions") + })); + __out.push('\n\n
    \n
    \n
    \n \n \n
    \n
    \n \n \n\n \n
    \n '); + if (this.promos.length > 0) { + __out.push('\n
    \n

    '); + __out.push(__sanitize(t('Your Available Promotions'))); + __out.push('

    \n \n \n\n \n \n \n \n \n \n \n \n '); + _ref = this.promos; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + promo = _ref[_i]; + __out.push('\n \n \n \n \n \n \n '); + } + __out.push('\n \n
    '); + __out.push(__sanitize(t('Code'))); + __out.push(''); + __out.push(__sanitize(t('Details'))); + __out.push(''); + __out.push(__sanitize(t('Starts'))); + __out.push(''); + __out.push(__sanitize(t('Expires'))); + __out.push('
    '); + __out.push(__sanitize(promo.code)); + __out.push(''); + __out.push(__sanitize(promo.description)); + __out.push(''); + __out.push(__sanitize(app.helpers.formatDate(promo.starts_at, true, "America/Los_Angeles"))); + __out.push(''); + __out.push(__sanitize(app.helpers.formatDate(promo.ends_at, true, "America/Los_Angeles"))); + __out.push('
    \n
    \n '); + } else { + __out.push('\n\n

    '); + __out.push(__sanitize(t('No Active Promotions'))); + __out.push('

    \n '); + } + __out.push('\n\n
    \n
    \n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/clients/request": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + var showFavoriteLocation; + showFavoriteLocation = function(location, index) { + var alphabet; + __out.push('\n '); + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + __out.push('\n
    \n '); + __out.push(__sanitize(location.nickname)); + return __out.push('\n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n

    '); + __out.push(__sanitize(t('Driver Name:'))); + __out.push('

    \n

    \n
    \n

    '); + __out.push(__sanitize(t('Driver #:'))); + __out.push('

    \n

    \n
    \n

    '); + __out.push(__sanitize(t('Pickup Address:'))); + __out.push('

    \n

    \n
    \n ');
+      __out.push(__sanitize(t('Add to Favorite Locations')));
+      __out.push('\n
    \n
    \n

    \n '); + __out.push(__sanitize(t('Nickname:'))); + __out.push('\n \n \n \n \n
    \n
    \n
    \n
    \n

    '); + __out.push(__sanitize(t('Your last trip'))); + __out.push('

    \n
    \n \n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n ');
+      __out.push(__sanitize(t('Star')));
+      __out.push('\n \n \n
    \n \n
    \n \n
    \n \n
    \n \n\n
    \n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "templates/shared/menu": function(exports, require, module) {module.exports = function(__obj) { + if (!__obj) __obj = {}; + var __out = [], __capture = function(callback) { + var out = __out, result; + __out = []; + callback.call(this); + result = __out.join(''); + __out = out; + return __safe(result); + }, __sanitize = function(value) { + if (value && value.ecoSafe) { + return value; + } else if (typeof value !== 'undefined' && value != null) { + return __escape(value); + } else { + return ''; + } + }, __safe, __objSafe = __obj.safe, __escape = __obj.escape; + __safe = __obj.safe = function(value) { + if (value && value.ecoSafe) { + return value; + } else { + if (!(typeof value !== 'undefined' && value != null)) value = ''; + var result = new String(value); + result.ecoSafe = true; + return result; + } + }; + if (!__escape) { + __escape = __obj.escape = function(value) { + return ('' + value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + }; + } + (function() { + (function() { + __out.push('\n'); + }).call(this); + + }).call(__obj); + __obj.safe = __objSafe, __obj.escape = __escape; + return __out.join(''); +}}, "translations/en": function(exports, require, module) {(function() { + exports.translations = { + "Uber": "Uber", + "Sign Up": "Sign Up", + "Ride Request": "Ride Request", + "Invite Friends": "Invite Friends", + "Promotions": "Promotions", + "Billing": "Billing", + "Settings": "Settings", + "Forgot Password?": "Forgot Password?", + "Password Recovery": "Password Recovery", + "Login": "Login", + "Trip Detail": "Trip Detail", + "Password Reset": "Password Reset", + "Confirm Email": "Confirm Email", + "Request Ride": "Request Ride", + "Credit Card Number": "Credit Card Number", + "month": "month", + "01-Jan": "01-Jan", + "02-Feb": "02-Feb", + "03-Mar": "03-Mar", + "04-Apr": "04-Apr", + "05-May": "05-May", + "06-Jun": "06-Jun", + "07-Jul": "07-Jul", + "08-Aug": "08-Aug", + "09-Sep": "09-Sep", + "10-Oct": "10-Oct", + "11-Nov": "11-Nov", + "12-Dec": "12-Dec", + "year": "year", + "CVV": "CVV", + "Category": "Category", + "personal": "personal", + "business": "business", + "Default Credit Card": "Default Credit Card", + "Add Credit Card": "Add Credit Card", + "Expiry": "Expiry", + "default card": "default card", + "make default": "make default", + "Edit": "Edit", + "Delete": "Delete", + "Expiry Month": "Expiry Month", + "Expiry Year": "Expiry Year", + "Unable to Verify Card": "Unable to verify card at this time. Please try again later.", + "Credit Card Update Succeeded": "Your card has been successfully updated!", + "Credit Card Update Failed": "We couldn't save your changes. Please try again in a few minutes.", + "Credit Card Delete Succeeded": "Your card has been deleted!", + "Credit Card Delete Failed": "We were unable to delete your card. Please try again later.", + "Credit Card Update Category Succeeded": "Successfully changed card category!", + "Credit Card Update Category Failed": "We couldn't change your card category. Please try again in a few minutes.", + "Credit Card Update Default Succeeded": "Successfully changed default card!", + "Credit Card Update Default Failed": "We couldn't change your default card. Please try again in a few minutes.", + "Hello Greeting": "Hello, <%= name %>", + "Card Ending in": "Card Ending in", + "Trip Map": "Trip Map", + "Amount": "Amount: <%= amount %>", + "Last Attempt to Bill": "Last Attempt to Bill: <%= date %>", + "Charge": "Charge", + "Uber Credit Balance Note": "Your account has an UberCredit balance of <%= amount %>. When billing for trips, we'll deplete your UberCredit balance before applying charges to your credit card.", + "Please Add Credit Card": "Please add a credit card to bill your outstanding charges.", + "Credit Cards": "Credit Cards", + "add a new credit card": "add a new credit card", + "Account Balance": "Account Balance", + "Arrears": "Arrears", + "Billing Succeeded": "Your card was successfully billed.", + "Confirm Email Succeeded": "Successfully confirmed email token, redirecting to log in page...", + "Confirm Email Failed": "Unable to confirm email. Please contact support@uber.com if this problem persists.", + "Email Already Confirmed": "Your email address has already been confirmed, redirecting to log in page...", + "Credit Card Added": "Credit Card Added", + "No Credit Card": "No Credit Card", + "Mobile Number Confirmed": "Mobile Number Confirmed", + "No Confirmed Mobile": "No Confirmed Mobile", + "E-mail Address Confirmed": "E-mail Address Confirmed", + "No Confirmed E-mail": "No Confirmed E-mail", + 'Reply to sign up text': 'Reply "GO" to the text message you received at sign up.', + "Resend text message": "Resend text message", + "Click sign up link": "Click the link in the email you received at sign up.", + "Resend email": "Resend email", + "Add a credit card to ride": "Add a credit card and you'll be ready to ride Uber.", + "Your Most Recent Trip": "Your Most Recent Trip", + "details": "details", + "Your Trip History ": "Your Trip History ", + "Status": "Status", + "Here's how it works:": "Here's how it works:", + "Show all trips": "Show all trips", + "Set your location:": "Set your location:", + "App search for address": "iPhone/Android app: fix the pin or search for an address", + "SMS text address": "SMS: text your address to UBRCAB (827222)", + "Confirm pickup request": "Confirm your pickup request", + "Uber sends ETA": "Uber will send you an ETA (usually within 5-10 minutes)", + "Car arrives": "When your car is arriving, Uber will inform you again.", + "Ride to destination": "Hop in the car and tell the driver your destination.", + "Thank your driver": "That’s it! Please thank your driver but remember that your tip is included and no cash is necessary.", + "Trip started here": "Trip started here", + "Trip ended here": "Trip ended here", + "Sending Email": "Sending email...", + "Resend Email Succeeded": "We just sent the email. Please click on the confirmation link you recieve.", + "Resend Email Failed": "There was an error sending the email. Please contact support if the problem persists.", + "Resend Text Succeeded": 'We just sent the text message. Please reply "GO" to the message you recieve. It may take a few minutes for the message to reach you phone.', + "Resend Text Failed": "There was an error sending the text message. Please contact support if the problem persists.", + "Password Reset Error": "There was an error processing your password reset request.", + "New Password": "New Password", + "Forgot Password": "Forgot Password", + "Forgot Password Error": "Your email address could not be found. Please make sure to use the same email address you used when you signed up.", + "Forgot Password Success": "Please check your email for a link to reset your password.", + "Forgot Password Enter Email": 'Enter your email address and Uber will send you a link to reset your password. If you remember your password, you can sign in here.', + "Invite friends": "Invite friends", + "Give $ Get $": "Give $10, Get $10", + "Give $ Get $ Description": "Every friend you invite to Uber gets $10 of Uber credit. After someone you’ve invited takes his/her first ride, you get $10 of Uber credits too!", + "What are you waiting for?": "So, what are you waiting for? Invite away!", + "Tweet": "Tweet", + "Invite Link": "Email or IM this link to your friends:", + "Email Address": "Email Address", + "Reset Password": "Reset Password", + "Enter Promotion Code": "If you have a promotion code, enter it here:", + "Your Active Promotions": "Your Active Promotions", + "Code": "Code", + "Details": "Details", + "Trips Remaining": "Trips Remaining", + "Expires": "Expires", + "No Active Promotions": "There are no active promotions on your account.", + "Your Available Promotions": "Your Available Promotions", + "Where do you want us to pick you up?": "Where do you want us to pick you up?", + "Address to search": "Address to search", + "Search": "Search", + "Driver Name:": "Driver Name:", + "Driver #:": "Driver #:", + "Pickup Address:": "Pickup Address:", + "Add to Favorite Locations": "Add to Favorite Locations", + "Star": "Star", + "Nickname:": "Nickname:", + "Add": "Add", + "Your last trip": "Your last trip", + "Please rate your driver:": "Please rate your driver:", + "Comments: (optional)": "Comments: (optional)", + "Rate Trip": "Rate Trip", + "Pickup time:": "Pickup time:", + "Miles:": "Miles:", + "Trip time:": "Trip time:", + "Fare:": "Fare:", + "Favorite Locations": "Favorite Locations", + "Search Results": "Search Results", + "You have no favorite locations saved.": "You have no favorite locations saved.", + "Loading...": "Loading...", + "Request Pickup": "Request Pickup", + "Cancel Pickup": "Cancel Pickup", + "Requesting Closest Driver": "Requesting the closest driver to pick you up...", + "En Route": "You are currently en route...", + "Rate Last Trip": "Please rate your trip to make another request", + "Rate Before Submitting": "Please rate your trip before submitting the form", + "Address too short": "Address too short", + "or did you mean": "or did you mean", + "Search Address Failed": "Unable to find the given address. Please enter another address close to your location.", + "Sending pickup request...": "Sending pickup request...", + "Cancel Request Prompt": "Are you sure you want to cancel your request?", + "Cancel Request Arrived Prompt": 'Are you sure you want to cancel your request? Your driver has arrived so there is a $10 cancellation fee. It may help to call your driver now', + "Favorite Location Nickname Length Error": "Nickname has to be atleast 3 characters", + "Favorite Location Save Succeeded": "Location Saved!", + "Favorite Location Save Failed": "Unable to save your location. Please try again later.", + "Favorite Location Title": "Favorite Location <%= id %>", + "Search Location Title": "Search Location <%= id %>", + "ETA Message": "ETA: Around <%= minutes %> Minutes", + "Nearest Cab Message": "The closest driver is approximately <%= minutes %> minute(s) away", + "Arrival ETA Message": "Your Uber will arrive in about <%= minutes %> minute(s)", + "Arriving Now Message": "Your Uber is arriving now...", + "Rating Driver Failed": "Unable to contact server. Please try again later or email support if this issue persists.", + "Account Information": "Account Information", + "Mobile Phone Information": "Mobile Phone Information", + "settings": "settings", + "Information": "Information", + "Picture": "Picture", + "Change password": "Change password", + "Your current Picture": "Your current Picture", + "Your Favorite Locations": "Your Favorite Locations", + "You have no favorite locations saved.": "You have no favorite locations saved.", + "Purpose of Mobile": "We send text messages to your mobile phone to tell you when your driver is arriving. You can also request trips using text messages.", + "Country": "Country", + "Mobile Number": "Mobile Number", + "Submit": "Submit", + "Favorite Location": "Favorite Location", + "No Approximate Address": "Could not find an approximate address", + "Address:": "Address:", + "Information Update Succeeded": "Your information has been updated!", + "Information Update Failed": "We couldn't update your information. Please try again in few minutes or contact support if the problem persists.", + "Location Delete Succeeded": "Location deleted!", + "Location Delete Failed": "We were unable to delete your favorite location. Please try again later or contact support of the issue persists.", + "Location Edit Succeeded": "Changes Saved!", + "Location Edit Failed": "We couldn't save your changes. Please try again in a few minutes.", + "Picture Update Succeeded": "Your picture has been updated!", + "Picture Update Failed": "We couldn't change your picture. Please try again in a few minutes.", + "Personal Information": "Personal Information", + "Mobile Phone Number": "Mobile Phone Number", + "Payment Information": "Payment Information", + "Purpose of Credit Card": "We keep your credit card on file so that your trip go as fast as possible. You will not be charged until you take a trip.", + "Your card will not be charged until you take a trip.": "Your card will not be charged until you take a trip.", + "Credit Card Number": "Credit Card Number", + "Expiration Date": "Expiration Date", + "Promotion Code": "Promotion Code", + "Enter Promo Here": "If you have a code for a promotion, invitation or group deal, you can enter it here.", + "Promotion Code Input Label": "Promotion, Invite or Groupon Code (optional)", + "Terms and Conditions": "Terms and Conditions", + "HELP": "HELP", + "STOP": "STOP", + "Legal Information": "Legal Information", + "Sign Up Agreement": "By signing up, I agree to the Uber <%= terms_link %> and <%= privacy_link %> and understand that Uber is a request tool, not a transportation carrier.", + "Sign Up Agreement Error": "You must agree to the Uber Terms and Conditions and Privacy Policy to continue.", + "Message and Data Rates Disclosure": "Message and Data Rates May Apply. Reply <%= help_string %> to 827-222 for help. Reply <%= stop_string %> to 827-222 to stop texts. For additional assistance, visit support.uber.com or call (866) 576-1039. Supported Carriers: AT&T, Sprint, Verizon, and T-Mobile.", + "I Agree": "I agree to the Terms & Conditions and Privacy Policy", + "Security Code": "Security Code", + "Type of Card": "Type of Card", + "Personal": "Personal", + "Business": "Business", + "Code": "Code", + "Zip or Postal Code": "Zip or Postal Code", + "Your Trip": "Your Trip", + "Trip Info": "Trip Info", + "Request a fare review": "Request a fare review", + "Fare Review Submitted": "Your fare review has been submitted. We'll get back to you soon about your request. Sorry for any inconvenience this may have caused!", + "Fair Price Consideration": "We're committed to delivering Uber service at a fair price. Before requesting a fare review, please consider:", + "Your Fare Calculation": "Your Fare Calculation", + "Charges": "Charges", + "Discounts": "Discounts", + "Total Charge": "Total Charge", + "Uber pricing information": "Uber pricing information", + "Uber Pricing Information Message": "<%= learn_link %> is published on our website.", + "GPS Point Capture Disclosure": "Due to a finite number of GPS point captures, corners on your trip map may appear cut off or rounded. These minor inaccuracies result in a shorter measured distance, which always results in a cheaper trip.", + "Fare Review Note": "Please elaborate on why this trip requires a fare review. Your comments below will help us better establish the correct price for your trip:", + "Fare Review Error": "There was an error submitting the review. Please ensure that you have a message.", + "Sign In": "Sign In" + }; +}).call(this); +}, "translations/fr": function(exports, require, module) {(function() { + exports.translations = { + "Uber": "Uber", + "Sign Up": "Inscription", + "Ride Request": "Passer une Commande", + "Invite Friends": "Inviter vos Amis", + "Promotions": "Promotions", + "Billing": "Paiement", + "Settings": "Paramètres", + "Forgot Password?": "Mot de passe oublié ?", + "Password Recovery": "Récupération du mot de passe", + "Login": "Connexion", + "Trip Detail": "Détail de la Course", + "Password Reset": "Réinitialisation du mot de passe", + "Confirm Email": "Confirmation de l’e-mail", + "Request Ride": "Passer une Commande", + "Credit Card Number": "Numéro de Carte de Crédit", + "month": "mois", + "01-Jan": "01-Jan", + "02-Feb": "02-Fév", + "03-Mar": "03-Mar", + "04-Apr": "04-Avr", + "05-May": "05-Mai", + "06-Jun": "06-Juin", + "07-Jul": "07-Jui", + "08-Aug": "08-Aoû", + "09-Sep": "09-Sep", + "10-Oct": "10-Oct", + "11-Nov": "11-Nov", + "12-Dec": "12-Déc", + "year": "année", + "CVV": "Code de Sécurité", + "Category": "Type", + "personal": "personnel", + "business": "entreprise", + "Default Credit Card": "Carte par Défaut", + "Add Credit Card": "Ajouter une Carte", + "Expiry": "Expire", + "default card": "carte par défaut", + "make default": "choisir par défaut", + "Edit": "Modifier", + "Delete": "Supprimer", + "Expiry Month": "Mois d’Expiration", + "Expiry Year": "Année d’Expiration", + "Unable to Verify Card": "Impossible de vérifier la carte pour le moment. Merci de réessayer un peu plus tard.", + "Credit Card Update Succeeded": "Votre carte a été mise à jour avec succès !", + "Credit Card Update Failed": "Nous ne pouvons enregistrer vos changements. Merci de réessayer dans quelques minutes.", + "Credit Card Delete Succeeded": "Votre carte a été supprimée !", + "Credit Card Delete Failed": "Nous n’avons pas été en mesure de supprimer votre carte. Merci de réessayer plus tard.", + "Credit Card Update Category Succeeded": "Changement de catégorie de carte réussi !", + "Credit Card Update Category Failed": "Nous ne pouvons pas changer la catégorie de votre carte. Merci de réessayer dans quelques minutes.", + "Credit Card Update Default Succeeded": "Carte par défaut changée avec succès !", + "Credit Card Update Default Failed": "Nous ne pouvons pas changer votre carte par défaut. Merci de réessayer dans quelques minutes.", + "Hello Greeting": "Bonjour, <%= name %>", + "Card Ending in": "La carte expire dans", + "Trip Map": "Carte des Courses", + "Amount": "Montant: <%= amount %>", + "Last Attempt to Bill": "Dernière tentative de prélèvement : <%= date %>", + "Charge": "Débit", + "Uber Credit Balance Note": "Votre compte a un solde de <%= amount %> UberCredits. Lorsque nous facturons des courses, nous réduirons votre solde d’UberCredits avant de prélever votre carte de crédit.", + "Please Add Credit Card": "Merci d’ajouter une carte de crédit pour que nous puissions vous facturer.", + "Credit Cards": "Cartes de crédit", + "add a new credit card": "Ajouter une nouvelle carte de crédit", + "Account Balance": "Solde du compte", + "Arrears": "Arriérés", + "Billing Succeeded": "Votre carte a été correctement débitée.", + "Confirm Email Succeeded": "L’adresse e-mail a bien été validée, vous êtes redirigé vers le tableau de bord...", + "Confirm Email Failed": "Impossible de confirmer l’adresse e-mail. Merci de contacter support@uber.com si le problème persiste.", + "Credit Card Added": "Carte de crédit ajoutée", + "No Credit Card": "Pas de carte de crédit", + "Mobile Number Confirmed": "Numéro de téléphone confirmé", + "No Confirmed Mobile": "Pas de numéro de téléphone confirmé", + "E-mail Address Confirmed": "Adresse e-mail confirmée", + "No Confirmed E-mail": "Pas d’adresse e-mail confirmée", + 'Reply to sign up text': 'Répondre "GO" au SMS que vous avez reçu à l’inscription.', + "Resend text message": "Renvoyer le SMS", + "Click sign up link": "Cliquez sur le lien contenu dans l’e-mail reçu à l’inscription.", + "Resend email": "Renvoyer l’e-mail", + "Add a credit card to ride": "Ajouter une carte de crédit et vous serez prêt à voyager avec Uber.", + "Your Most Recent Trip": "Votre course la plus récente", + "details": "détails", + "Your Trip History": "Historique de votre trajet", + "Status": "Statut", + "Here's how it works:": "Voici comment ça marche :", + "Show all trips": "Montrer toutes les courses", + "Set your location:": "Définir votre position :", + "App search for address": "Application iPhone/Android : positionner la punaise ou rechercher une adresse", + "SMS text address": "SMS : envoyez votre adresse à UBRCAB (827222)", + "Confirm pickup request": "Validez la commande", + "Uber sends ETA": "Uber envoie un temps d’attente estimé (habituellement entre 5 et 10 minutes)", + "Car arrives": "Lorsque votre voiture arrive, Uber vous en informera encore..", + "Ride to destination": "Montez dans la voiture et donnez votre destination au chauffeur.", + "Thank your driver": "C’est tout ! Remerciez le chauffeur mais souvenez-vous que les pourboires sont compris et qu’il n’est pas nécessaire d’avoir du liquide sur soi.", + "Trip started here": "La course a commencé ici.", + "Trip ended here": "La course s’est terminée ici.", + "Sending Email": "Envoi de l’e-mail...", + "Resend Email Succeeded": "Nous venons d’envoyer l’e-mail. Merci de cliquer sur le lien de confirmation que vous avez reçu.", + "Resend Email Failed": "Il y a eu un problème lors de l’envoi de l’email. Merci de contacter le support si le problème persiste.", + "Resend Text Succeeded": 'Nous venons d’envoyer le SMS. Merci de répondre "GO" au message que vous avez reçu. Il se peut que cela prenne quelques minutes pour que le message arrive sur votre téléphone.', + "Resend Text Failed": "Il y a eu un problème lors de l’envoi du SMS. Merci de contacter le support si le problème persiste.", + "Password Reset Error": "Il y a eu une error lors de la réinitialisation de votre mot de passe.", + "New Password:": "Nouveau mot de passe:", + "Forgot Password Error": "Votre nom d’utilisateur / adresse email ne peut être trouvé. Merci d’utiliser la même qu’à l’inscription.", + "Forgot Password Success": "Merci de consulter votre boîte mail pour suivre la demande de ‘réinitialisation de mot de passe.", + "Forgot Password Enter Email": "Merci de saisir votre adresse email et nous vous enverrons un lien vous permettant de réinitialiser votre mot de passe :", + "Invite friends": "Inviter vos amis", + "Give $ Get $": "Donnez $10, Recevez $10", + "Give $ Get $ Description": "Chaque ami que vous invitez à Uber recevra $10 de crédits Uber. Dès lors qu’une personne que vous aurez invité aura utilisé Uber pour la première, vous recevrez $10 de crédits Uber également !", + "What are you waiting for?": "N’attendez plus ! Lancez les invitations !", + "Tweet": "Tweeter", + "Invite Link": "Envoyez ce lien par email ou messagerie instantanée à vos amis :", + "Enter Promotion Code": "Si vous avez un code promo, saisissez-le ici:", + "Your Active Promotions": "Vos Codes Promos Actifs", + "Code": "Code", + "Details": "Détails", + "Trips Remaining": "Courses restantes", + "Expires": "Expire", + "No Active Promotions": "Vous n’avez pas de code promo actif.", + "Your Available Promotions": "Votres Promos Disponibles", + "Where do you want us to pick you up?": "Où souhaitez-vous que nous vous prenions en charge ?", + "Address to search": "Adresse à rechercher", + "Search": "Chercher", + "Driver Name:": "Nom du chauffeur:", + "Driver #:": "# Chauffeur:", + "Pickup Address:": "Lieu de prise en charge:", + "Add to Favorite Locations": "Ajoutez aux Lieux Favoris", + "Star": "Étoiles", + "Nickname:": "Pseudo", + "Add": "Ajouter", + "Your last trip": "Votre dernière course", + "Please rate your driver:": "Merci de noter votre chauffeur :", + "Comments: (optional)": "Commentaires: (optionnel)", + "Rate Trip": "Notez votre course", + "Pickup time:": "Heure de Prise en Charge :", + "Miles:": "Kilomètres :", + "Trip time:": "Temps de course :", + "Fare:": "Tarif :", + "Favorite Locations": "Lieux Favoris", + "Search Results": "Résultats", + "You have no favorite locations saved.": "Vous n’avez pas de lieux de prise en charge favoris.", + "Loading...": "Chargement...", + "Request Pickup": "Commander ici", + "Cancel Pickup": "Annuler", + "Requesting Closest Driver": "Nous demandons au chauffeur le plus proche de vous prendre en charge...", + "En Route": "Vous êtes actuellement en route...", + "Rate Last Trip": "Merci de noter votre précédent trajet pour faire une autre course.", + "Rate Before Submitting": "Merci de noter votre trajet avant de le valider.", + "Address too short": "L’adresse est trop courte", + "or did you mean": "ou vouliez-vous dire", + "Search Address Failed": "Impossible de trouver l’adresse spécifiée. Merci de saisir une autre adresse proche de l’endroit où vous vous trouvez.", + "Sending pickup request...": "Envoi de la demande de prise en charge...", + "Cancel Request Prompt": "Voulez-vous vraiment annuler votre demande ?", + "Cancel Request Arrived Prompt": 'Voulez-vous vraiment annuler votre demande ? Votre chauffeur est arrivé, vous serez donc facturé de $10 de frais d’annulation. Il pourrait être utile que vous appeliez votre chauffeur maintenant.', + "Favorite Location Nickname Length Error": "Le pseudo doit faire au moins 3 caractères de long", + "Favorite Location Save Succeeded": "Adresse enregistrée !", + "Favorite Location Save Failed": "Impossible d’enregistrer votre adresse. Merci de réessayer ultérieurement.", + "Favorite Location Title": "Adresse favorie <%= id %>", + "Search Location Title": "Recherche d’adresse <%= id %>", + "ETA Message": "Temps d’attente estimé: environ <%= minutes %> minutes", + "Nearest Cab Message": "Le chauffeur le plus proche sera là dans <%= minutes %> minute(s)", + "Arrival ETA Message": "Votre chauffeur arrivera dans <%= minutes %> minute(s)", + "Arriving Now Message": "Votre chauffeur est en approche...", + "Rating Driver Failed": "Impossible de contacter le serveur. Merci de réessayer ultérieurement ou de contacter le support si le problème persiste.", + "settings": "Paramètres", + "Information": "Information", + "Picture": "Photo", + "Change password": "Modifier votre mot de passe", + "Your current Picture": "Votre photo", + "Your Favorite Locations": "Vos lieux favoris", + "You have no favorite locations saved.": "Vous n’avez pas de lieu favori", + "Account Information": "Informations Personnelles", + "Mobile Phone Information": "Informations de Mobile", + "Change Your Password": "Changez votre mot de passe.", + "Country": "Pays", + "Language": "Langue", + "Favorite Location": "Lieu favori", + "No Approximate Address": "Impossible de trouver une adresse même approximative", + "Address:": "Adresse :", + "Information Update Succeeded": "Vos informations ont été mises à jour !", + "Information Update Failed": "Nous n’avons pas pu mettre à jour vos informations. Merci de réessayer dans quelques instants ou de contacter le support si le problème persiste.", + "Location Delete Succeeded": "Adresse supprimée !", + "Location Delete Failed": "Nous n’avons pas pu supprimée votre adresse favorie. Merci de réessayer plus tard ou de contacter le support si le problème persiste.", + "Location Edit Succeeded": "Modifications sauvegardées !", + "Location Edit Failed": "Nous n’avons pas pu sauvegarder vos modifications. Merci de réessayer dans quelques minutes.", + "Picture Update Succeeded": "Votre photo a été mise à jour !", + "Picture Update Failed": "Nous n’avons pas pu mettre à jour votre photo. Merci de réessayer dans quelques instants.", + "Personal Information": "Informations Personnelles", + "Mobile Phone Number": "Numéro de Téléphone Portable", + "Payment Information": "Informations de Facturation", + "Your card will not be charged until you take a trip.": "Votre carte ne sera pas débitée avant votre premier trajet.", + "Card Number": "Numéro de Carte", + "Promotion Code Input Label": "Code promo, code d’invitation ou “deal” acheté en ligne (optionnel)", + "Terms and Conditions": "Conditions Générales", + "HELP": "HELP", + "STOP": "STOP", + "Sign Up Agreement": "En souscrivant, j’accepte les <%= terms_link %> et <%= privacy_link %> et comprends qu’Uber est un outil de commande de chauffeur, et non un transporteur.", + "Sign Up Agreement Error": "Vous devez accepter les Conditions Générales d’utilisation d’Uber Terms and Conditions et la Politique de Confidentialité pour continuer.", + "Message and Data Rates Disclosure": "Les frais d’envoi de SMS et de consommation de données peuvent s’appliquer. Répondez <%= help_string %> au 827-222 pour obtenir de l’aide. Répondez <%= stop_string %> au 827-222 pour ne plus recevoir de SMS. Pour plus d’aide, visitez support.uber.com ou appelez le (866) 576-1039. Opérateurs supportés: AT&T, Sprint, Verizon, T-Mobile, Orange, SFR et Bouygues Telecom.", + "Zip/Postal Code": "Code Postal", + "Expiration Date": "Date D'expiration", + "Security Code": "Code de Sécurité", + "Type of Card": "Type", + "Personal": "Personnel", + "Business": "Entreprise", + "Promotion Code": "Code Promo", + "Legal Information": "Mentions Légales", + "I Agree": "J'accepte.", + "Your Trip": "Votre Course", + "Trip Info": "Informations de la Course", + "Request a fare review": "Demander un contrôle du tarif", + "Fare Review Submitted": "Votre demande de contrôle du tarif a été soumis. Nous reviendrons vers vous rapidement concernant cette demande. Nous nous excusons pour les dérangements éventuellement occasionnés !", + "Fair Price Consideration": "Nous nous engageons à proposer Uber à un tarif juste. Avant de demander un contrôle du tarif, merci de prendre en compte :", + "Your Fare Calculation": "Calcul du Prix", + "Charges": "Coûts", + "Discounts": "Réductions", + "Total Charge": "Coût total", + "Uber pricing information": "Information sur les prix d’Uber", + "Uber Pricing Information Message": "<%= learn_link %> est disponible sur notre site web.", + "GPS Point Capture Disclosure": "A cause d’un nombre limité de coordonnées GPS sauvegardées, les angles de votre trajet sur la carte peuvent apparaître coupés ou arrondis. Ces légères incohérences débouchent sur des distances mesurées plus courtes, ce qui implique toujours un prix du trajet moins élevé.", + "Fare Review Note": "Merci de nous expliquer pourquoi le tarif de cette course nécessite d’être contrôlé. Vos commentaires ci-dessous nous aideront à établir un prix plus juste si nécessaire :", + "Fare Review Error": "Il y a eu une erreur lors de l’envoi de la demande. Assurez-vous d’avoir bien ajouté une description à votre demande." + }; +}).call(this); +}, "views/clients/billing": function(exports, require, module) {(function() { + var clientsBillingTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsBillingTemplate = require('templates/clients/billing'); + exports.ClientsBillingView = (function() { + __extends(ClientsBillingView, UberView); + function ClientsBillingView() { + ClientsBillingView.__super__.constructor.apply(this, arguments); + } + ClientsBillingView.prototype.id = 'billing_view'; + ClientsBillingView.prototype.className = 'view_container'; + ClientsBillingView.prototype.events = { + 'click a#add_card': 'addCard', + 'click .charge_arrear': 'chargeArrear' + }; + ClientsBillingView.prototype.render = function() { + this.RefreshUserInfo(__bind(function() { + var cards, newForm; + this.HideSpinner(); + $(this.el).html(clientsBillingTemplate()); + if (USER.payment_gateway.payment_profiles.length === 0) { + newForm = new app.views.clients.modules.creditcard; + $(this.el).find("#add_card_wrapper").html(newForm.render(0).el); + } else { + cards = new app.views.clients.modules.creditcard; + $("#cards").html(cards.render("all").el); + } + return this.delegateEvents(); + }, this)); + return this; + }; + ClientsBillingView.prototype.addCard = function(e) { + var newCard; + e.preventDefault(); + newCard = new app.views.clients.modules.creditcard; + $('#cards').append(newCard.render("new").el); + return $("a#add_card").hide(); + }; + ClientsBillingView.prototype.chargeArrear = function(e) { + var $el, arrearId, attrs, cardId, options, tryCharge; + e.preventDefault(); + $(".error_message").text(""); + $el = $(e.currentTarget); + arrearId = $el.attr('id'); + cardId = $el.parent().find('#card_to_charge').val(); + this.ShowSpinner('submit'); + tryCharge = new app.models.clientbills({ + id: arrearId + }); + attrs = { + payment_profile_id: cardId, + dataType: 'json' + }; + options = { + success: __bind(function(data, textStatus, jqXHR) { + $el.parent().find(".success_message").text(t("Billing Succeeded")); + $el.hide(); + return $el.parent().find('#card_to_charge').hide(); + }, this), + error: __bind(function(jqXHR, status, errorThrown) { + return $el.parent().find(".error_message").text(JSON.parse(status.responseText).error); + }, this), + complete: __bind(function() { + return this.HideSpinner(); + }, this) + }; + return tryCharge.save(attrs, options); + }; + return ClientsBillingView; + })(); +}).call(this); +}, "views/clients/confirm_email": function(exports, require, module) {(function() { + var clientsConfirmEmailTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsConfirmEmailTemplate = require('templates/clients/confirm_email'); + exports.ClientsConfirmEmailView = (function() { + __extends(ClientsConfirmEmailView, UberView); + function ClientsConfirmEmailView() { + ClientsConfirmEmailView.__super__.constructor.apply(this, arguments); + } + ClientsConfirmEmailView.prototype.id = 'confirm_email_view'; + ClientsConfirmEmailView.prototype.className = 'view_container'; + ClientsConfirmEmailView.prototype.render = function(token) { + var attrs; + $(this.el).html(clientsConfirmEmailTemplate()); + attrs = { + data: { + email_token: token + }, + success: __bind(function(data, textStatus, jqXHR) { + var show_dashboard; + this.HideSpinner(); + show_dashboard = function() { + return app.routers.clients.navigate('!/dashboard', true); + }; + if (data.status === 'OK') { + $('.success_message').show(); + return _.delay(show_dashboard, 3000); + } else if (data.status === 'ALREADY_COMFIRMED') { + $('.already_confirmed_message').show(); + return _.delay(show_dashboard, 3000); + } else { + return $('.error_message').show(); + } + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('.error_message').show(); + }, this), + complete: function(status) { + return $('#attempt_text').hide(); + }, + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/self" + }; + $.ajax(attrs); + this.ShowSpinner('submit'); + return this; + }; + return ClientsConfirmEmailView; + })(); +}).call(this); +}, "views/clients/dashboard": function(exports, require, module) {(function() { + var clientsDashboardTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsDashboardTemplate = require('templates/clients/dashboard'); + exports.ClientsDashboardView = (function() { + var displayFirstTrip; + __extends(ClientsDashboardView, UberView); + function ClientsDashboardView() { + this.showAllTrips = __bind(this.showAllTrips, this); + this.render = __bind(this.render, this); + ClientsDashboardView.__super__.constructor.apply(this, arguments); + } + ClientsDashboardView.prototype.id = 'dashboard_view'; + ClientsDashboardView.prototype.className = 'view_container'; + ClientsDashboardView.prototype.events = { + 'click a.confirmation': 'confirmationClick', + 'click #resend_email': 'resendEmail', + 'click #resend_mobile': 'resendMobile', + 'click #show_all_trips': 'showAllTrips' + }; + ClientsDashboardView.prototype.render = function() { + var displayPage, downloadTrips; + this.HideSpinner(); + displayPage = __bind(function() { + $(this.el).html(clientsDashboardTemplate()); + this.confirmationsSetup(); + return this.RequireMaps(__bind(function() { + if (USER.trips.models[0]) { + if (!USER.trips.models[0].get("points")) { + return USER.trips.models[0].fetch({ + data: { + relationships: 'points' + }, + success: __bind(function() { + this.CacheData("USERtrips", USER.trips); + return displayFirstTrip(); + }, this) + }); + } else { + return displayFirstTrip(); + } + } + }, this)); + }, this); + downloadTrips = __bind(function() { + return this.DownloadUserTrips(displayPage, false, 10); + }, this); + this.RefreshUserInfo(downloadTrips); + return this; + }; + displayFirstTrip = __bind(function() { + var bounds, endPos, map, myOptions, path, polyline, startPos; + myOptions = { + zoom: 12, + mapTypeId: google.maps.MapTypeId.ROADMAP, + zoomControl: false, + rotateControl: false, + panControl: false, + mapTypeControl: false, + scrollwheel: false + }; + if (USER.trips.length === 10) { + $("#show_all_trips").show(); + } + if (USER.trips.length > 0) { + map = new google.maps.Map(document.getElementById("trip_details_map"), myOptions); + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(USER.trips.models[0].get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + map.fitBounds(bounds); + startPos = new google.maps.Marker({ + position: _.first(path), + map: map, + title: t('Trip started here'), + icon: 'https://uber-static.s3.amazonaws.com/marker_start.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: map, + title: t('Trip ended here'), + icon: 'https://uber-static.s3.amazonaws.com/marker_end.png' + }); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + return polyline.setMap(map); + } + }, ClientsDashboardView); + ClientsDashboardView.prototype.confirmationsSetup = function() { + var blink, cardForm, element, _ref, _ref2, _ref3, _ref4, _ref5; + blink = function(element) { + var opacity; + opacity = 0.5; + if (element.css('opacity') === "0.5") { + opacity = 1.0; + } + return element.fadeTo(2000, opacity, function() { + return blink(element); + }); + }; + if (((_ref = window.USER) != null ? (_ref2 = _ref.payment_gateway) != null ? (_ref3 = _ref2.payment_profiles) != null ? _ref3.length : void 0 : void 0 : void 0) === 0) { + element = $('#confirmed_credit_card'); + cardForm = new app.views.clients.modules.creditcard; + $('#card.info').append(cardForm.render().el); + blink(element); + } + if (((_ref4 = window.USER) != null ? _ref4.confirm_email : void 0) === false) { + element = $('#confirmed_email'); + blink(element); + } + if ((((_ref5 = window.USER) != null ? _ref5.confirm_mobile : void 0) != null) === false) { + element = $('#confirmed_mobile'); + return blink(element); + } + }; + ClientsDashboardView.prototype.confirmationClick = function(e) { + e.preventDefault(); + $('.info').hide(); + $('#more_info').show(); + switch (e.currentTarget.id) { + case "card": + return $('#card.info').slideToggle(); + case "mobile": + return $('#mobile.info').slideToggle(); + case "email": + return $('#email.info').slideToggle(); + } + }; + ClientsDashboardView.prototype.resendEmail = function(e) { + var $el; + e.preventDefault(); + $el = $(e.currentTarget); + $el.removeAttr('href').prop({ + disabled: true + }); + $el.html(t("Sending Email")); + return $.ajax({ + type: 'GET', + url: API + '/users/request_confirm_email', + data: { + token: USER.token + }, + dataType: 'json', + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Resend Email Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.html(t("Resend Email Failed")); + }, this) + }); + }; + ClientsDashboardView.prototype.resendMobile = function(e) { + var $el; + e.preventDefault(); + $el = $(e.currentTarget); + $el.removeAttr('href').prop({ + disabled: true + }); + $el.html("Sending message..."); + return $.ajax({ + type: 'GET', + url: API + '/users/request_confirm_mobile', + data: { + token: USER.token + }, + dataType: 'json', + success: __bind(function(data, textStatus, jqXHR) { + return $el.html(t("Resend Text Succeeded")); + }, this), + error: __bind(function(jqXHR, textStatus, errorThrown) { + return $el.html(t("Resend Text Failed")); + }, this) + }); + }; + ClientsDashboardView.prototype.showAllTrips = function(e) { + e.preventDefault(); + $(e.currentTarget).hide(); + return this.DownloadUserTrips(this.render, true, 1000); + }; + return ClientsDashboardView; + }).call(this); +}).call(this); +}, "views/clients/forgot_password": function(exports, require, module) {(function() { + var clientsForgotPasswordTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + clientsForgotPasswordTemplate = require('templates/clients/forgot_password'); + exports.ClientsForgotPasswordView = (function() { + __extends(ClientsForgotPasswordView, UberView); + function ClientsForgotPasswordView() { + ClientsForgotPasswordView.__super__.constructor.apply(this, arguments); + } + ClientsForgotPasswordView.prototype.id = 'forgotpassword_view'; + ClientsForgotPasswordView.prototype.className = 'view_container modal_view_container'; + ClientsForgotPasswordView.prototype.events = { + "submit #password_reset": "passwordReset", + "click #password_reset_submit": "passwordReset", + "submit #forgot_password": "forgotPassword", + "click #forgot_password_submit": "forgotPassword" + }; + ClientsForgotPasswordView.prototype.render = function(token) { + this.HideSpinner(); + $(this.el).html(clientsForgotPasswordTemplate({ + token: token + })); + this.delegateEvents(); + return this; + }; + ClientsForgotPasswordView.prototype.forgotPassword = function(e) { + var attrs; + e.preventDefault(); + $('.success_message').hide(); + $(".error_message").hide(); + attrs = { + data: { + login: $("#login").val() + }, + success: __bind(function(data, textStatus, jqXHR) { + this.HideSpinner(); + $('.success_message').show(); + return $("#forgot_password").hide(); + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('.error_message').show(); + }, this), + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/forgot_password" + }; + $.ajax(attrs); + return this.ShowSpinner('submit'); + }; + ClientsForgotPasswordView.prototype.passwordReset = function(e) { + var attrs; + e.preventDefault(); + attrs = { + data: { + email_token: $("#token").val(), + password: $("#password").val() + }, + success: __bind(function(data, textStatus, jqXHR) { + this.HideSpinner(); + $.cookie('token', data.token); + amplify.store('USERjson', data); + app.refreshMenu(); + return location.hash = '!/dashboard'; + }, this), + error: __bind(function(e) { + this.HideSpinner(); + return $('#error_reset').show(); + }, this), + dataType: 'json', + type: 'PUT', + url: "" + API + "/users/self" + }; + $.ajax(attrs); + return this.ShowSpinner('submit'); + }; + return ClientsForgotPasswordView; + })(); +}).call(this); +}, "views/clients/invite": function(exports, require, module) {(function() { + var clientsInviteTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsInviteTemplate = require('templates/clients/invite'); + exports.ClientsInviteView = (function() { + __extends(ClientsInviteView, UberView); + function ClientsInviteView() { + ClientsInviteView.__super__.constructor.apply(this, arguments); + } + ClientsInviteView.prototype.id = 'invite_view'; + ClientsInviteView.prototype.className = 'view_container'; + ClientsInviteView.prototype.render = function() { + this.ReadUserInfo(); + this.HideSpinner(); + $(this.el).html(clientsInviteTemplate()); + console.log(screen); + return this; + }; + return ClientsInviteView; + })(); +}).call(this); +}, "views/clients/login": function(exports, require, module) {(function() { + var clientsLoginTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsLoginTemplate = require('templates/clients/login'); + exports.ClientsLoginView = (function() { + __extends(ClientsLoginView, UberView); + function ClientsLoginView() { + ClientsLoginView.__super__.constructor.apply(this, arguments); + } + ClientsLoginView.prototype.id = 'login_view'; + ClientsLoginView.prototype.className = 'view_container modal_view_container'; + ClientsLoginView.prototype.events = { + 'submit form': 'authenticate', + 'click button': 'authenticate' + }; + ClientsLoginView.prototype.initialize = function() { + _.bindAll(this, 'render'); + return this.render(); + }; + ClientsLoginView.prototype.render = function() { + this.HideSpinner(); + $(this.el).html(clientsLoginTemplate()); + this.delegateEvents(); + return this.place(); + }; + ClientsLoginView.prototype.authenticate = function(e) { + e.preventDefault(); + return $.ajax({ + type: 'POST', + url: API + '/auth/web_login/client', + data: { + login: $("#login").val(), + password: $("#password").val() + }, + dataType: 'json', + success: function(data, textStatus, jqXHR) { + $.cookie('user', JSON.stringify(data)); + $.cookie('token', data.token); + amplify.store('USERjson', data); + $('header').html(app.views.shared.menu.render().el); + return app.routers.clients.navigate('!/dashboard', true); + }, + error: function(jqXHR, textStatus, errorThrown) { + $.cookie('user', null); + $.cookie('token', null); + if (jqXHR.status === 403) { + $.cookie('redirected_user', JSON.stringify(JSON.parse(jqXHR.responseText).error_obj), { + domain: '.uber.com' + }); + window.location = 'http://partners.uber.com/'; + } + return $('.error_message').html(JSON.parse(jqXHR.responseText).error).hide().fadeIn(); + } + }); + }; + return ClientsLoginView; + })(); +}).call(this); +}, "views/clients/modules/credit_card": function(exports, require, module) {(function() { + var creditCardTemplate; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + creditCardTemplate = require('templates/clients/modules/credit_card'); + exports.CreditCardView = (function() { + __extends(CreditCardView, UberView); + function CreditCardView() { + CreditCardView.__super__.constructor.apply(this, arguments); + } + CreditCardView.prototype.id = 'creditcard_view'; + CreditCardView.prototype.className = 'module_container'; + CreditCardView.prototype.events = { + 'submit #credit_card_form': 'processNewCard', + 'click #new_card': 'processNewCard', + 'change #card_number': 'showCardType', + 'click .edit_card_show': 'showEditCard', + 'click .edit_card': 'editCard', + 'click .delete_card': 'deleteCard', + 'click .make_default': 'makeDefault', + 'change .use_case': 'saveUseCase' + }; + CreditCardView.prototype.initialize = function() { + return app.collections.paymentprofiles.bind("refresh", __bind(function() { + return this.RefreshUserInfo(__bind(function() { + this.render("all"); + return this.HideSpinner(); + }, this)); + }, this)); + }; + CreditCardView.prototype.render = function(cards) { + if (cards == null) { + cards = "new"; + } + if (cards === "all") { + app.collections.paymentprofiles.reset(USER.payment_gateway.payment_profiles); + cards = app.collections.paymentprofiles; + } + $(this.el).html(creditCardTemplate({ + cards: cards + })); + return this; + }; + CreditCardView.prototype.processNewCard = function(e) { + var $el, attrs, model, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $("#credit_card_form"); + $el.find('.error_message').html(""); + attrs = { + card_number: $el.find('#card_number').val(), + card_code: $el.find('#card_code').val(), + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + use_case: $el.find('#use_case').val(), + "default": $el.find('#default_check').prop("checked") + }; + options = { + statusCode: { + 200: __bind(function(e) { + this.HideSpinner(); + $('#cc_form_wrapper').hide(); + app.collections.paymentprofiles.trigger("refresh"); + $(this.el).remove(); + $("a#add_card").show(); + return $('section').html(app.views.clients.billing.render().el); + }, this), + 406: __bind(function(e) { + var error, errors, _i, _len, _ref, _results; + this.HideSpinner(); + errors = JSON.parse(e.responseText); + _ref = _.keys(errors); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + error = _ref[_i]; + _results.push(error === "top_of_form" ? $("#top_of_form").html(errors[error]) : $("#credit_card_form").find("#" + error).parent().find(".error_message").html(errors[error])); + } + return _results; + }, this), + 420: __bind(function(e) { + this.HideSpinner(); + return $("#top_of_form").html(t("Unable to Verify Card")); + }, this) + } + }; + this.ShowSpinner("submit"); + model = new app.models.paymentprofile; + model.save(attrs, options); + return app.collections.paymentprofiles.add(model); + }; + CreditCardView.prototype.showCardType = function(e) { + var $el, reAmerica, reDiscover, reMaster, reVisa, validCard; + reVisa = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/; + reMaster = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/; + reAmerica = /^6011-?\d{4}-?\d{4}-?\d{4}$/; + reDiscover = /^3[4,7]\d{13}$/; + $el = $("#card_logos"); + validCard = false; + if (e.currentTarget.value.match(reVisa)) { + validCard = true; + } else if (e.currentTarget.value.match(reMaster)) { + $el.css('background-position', "-60px"); + validCard = true; + } else if (e.currentTarget.value.match(reAmerica)) { + $el.css('background-position', "-120px"); + validCard = true; + } else if (e.currentTarget.value.match(reDiscover)) { + $el.css('background-position', "-180px"); + validCard = true; + } + if (validCard) { + $el.css('width', "60px"); + return $el.css('margin-left', "180px"); + } else { + $el.css('width', "250px"); + return $el.css('margin-left', "80px"); + } + }; + CreditCardView.prototype.showEditCard = function(e) { + var $el, id; + e.preventDefault(); + $el = $(e.currentTarget); + if ($el.html() === t("Edit")) { + id = $el.html(t("Cancel")).parents("tr").attr("id").substring(1); + return $("#e" + id).show(); + } else { + id = $el.html(t("Edit")).parents("tr").attr("id").substring(1); + return $("#e" + id).hide(); + } + }; + CreditCardView.prototype.editCard = function(e) { + var $el, attrs, id, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + $el.attr('disabled', 'disabled'); + this.ShowSpinner('submit'); + attrs = { + card_expiration_month: $el.find('#card_expiration_month').val(), + card_expiration_year: $el.find('#card_expiration_year').val(), + card_code: $el.find('#card_code').val() + }; + options = { + success: __bind(function(response) { + this.HideSpinner(); + this.ShowSuccess(t("Credit Card Update Succeeded")); + $("#e" + id).hide(); + $("#d" + id).find(".edit_card_show").html(t("Edit")); + return app.collections.paymentprofiles.trigger("refresh"); + }, this), + error: __bind(function(e) { + this.HideSpinner(); + this.ShowError(t("Credit Card Update Failed")); + return $el.removeAttr('disabled'); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + CreditCardView.prototype.deleteCard = function(e) { + var $el, id, options; + e.preventDefault(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + this.ClearGlobalStatus(); + this.ShowSpinner('submit'); + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Credit Card Delete Succeeded")); + $("form").hide(); + app.collections.paymentprofiles.trigger("refresh"); + return $('section').html(app.views.clients.billing.render().el); + }, this), + error: __bind(function(xhr, e) { + this.HideSpinner(); + return this.ShowError(t("Credit Card Delete Failed")); + }, this) + }; + return app.collections.paymentprofiles.models[id].destroy(options); + }; + CreditCardView.prototype.saveUseCase = function(e) { + var $el, attrs, id, options, use_case; + this.ClearGlobalStatus(); + $el = $(e.currentTarget); + use_case = $el.val(); + id = $el.parents("tr").attr("id").substring(1); + attrs = { + use_case: use_case + }; + options = { + success: __bind(function(response) { + return this.ShowSuccess(t("Credit Card Update Category Succeeded")); + }, this), + error: __bind(function(e) { + return this.ShowError(t("Credit Card Update Category Failed")); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + CreditCardView.prototype.makeDefault = function(e) { + var $el, attrs, id, options; + e.preventDefault(); + this.ClearGlobalStatus(); + $el = $(e.currentTarget).parents("td"); + id = $el.parents("tr").attr("id").substring(1); + attrs = { + "default": true + }; + options = { + success: __bind(function(response) { + this.ShowSuccess(t("Credit Card Update Default Succeeded")); + return app.collections.paymentprofiles.trigger("refresh"); + }, this), + error: __bind(function(e) { + return this.ShowError(t("Credit Card Update Default Failed")); + }, this) + }; + app.collections.paymentprofiles.models[id].set(attrs); + return app.collections.paymentprofiles.models[id].save({}, options); + }; + return CreditCardView; + })(); +}).call(this); +}, "views/clients/promotions": function(exports, require, module) {(function() { + var clientsPromotionsTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsPromotionsTemplate = require('templates/clients/promotions'); + exports.ClientsPromotionsView = (function() { + __extends(ClientsPromotionsView, UberView); + function ClientsPromotionsView() { + this.render = __bind(this.render, this); + ClientsPromotionsView.__super__.constructor.apply(this, arguments); + } + ClientsPromotionsView.prototype.id = 'promotions_view'; + ClientsPromotionsView.prototype.className = 'view_container'; + ClientsPromotionsView.prototype.events = { + 'submit form': 'submitPromo', + 'click button': 'submitPromo' + }; + ClientsPromotionsView.prototype.initialize = function() { + if (this.model) { + return this.RefreshUserInfo(this.render); + } + }; + ClientsPromotionsView.prototype.render = function() { + var renderTemplate; + this.ReadUserInfo(); + renderTemplate = __bind(function() { + $(this.el).html(clientsPromotionsTemplate({ + promos: window.USER.unexpired_client_promotions || [] + })); + return this.HideSpinner(); + }, this); + this.DownloadUserPromotions(renderTemplate); + return this; + }; + ClientsPromotionsView.prototype.submitPromo = function(e) { + var attrs, model, options, refreshTable; + e.preventDefault(); + this.ClearGlobalStatus(); + refreshTable = __bind(function() { + $('section').html(this.render().el); + return this.HideSpinner(); + }, this); + attrs = { + code: $('#code').val() + }; + options = { + success: __bind(function(response) { + this.HideSpinner(); + if (response.get('first_name')) { + return this.ShowSuccess("Your promotion has been applied in the form of an account credit. Click here to check your balance."); + } else { + this.ShowSuccess("Your promotion has successfully been applied"); + return this.RefreshUserInfo(this.render, true); + } + }, this), + statusCode: { + 400: __bind(function(e) { + this.ShowError(JSON.parse(e.responseText).error); + return this.HideSpinner(); + }, this) + } + }; + this.ShowSpinner("submit"); + model = new app.models.promotions; + return model.save(attrs, options); + }; + return ClientsPromotionsView; + })(); +}).call(this); +}, "views/clients/request": function(exports, require, module) {(function() { + var clientsRequestTemplate; + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }; + clientsRequestTemplate = require('templates/clients/request'); + exports.ClientsRequestView = (function() { + __extends(ClientsRequestView, UberView); + function ClientsRequestView() { + this.AjaxCall = __bind(this.AjaxCall, this); + this.AskDispatch = __bind(this.AskDispatch, this); + this.removeMarkers = __bind(this.removeMarkers, this); + this.displaySearchLoc = __bind(this.displaySearchLoc, this); + this.displayFavLoc = __bind(this.displayFavLoc, this); + this.showFavLoc = __bind(this.showFavLoc, this); + this.addToFavLoc = __bind(this.addToFavLoc, this); + this.removeCabs = __bind(this.removeCabs, this); + this.requestRide = __bind(this.requestRide, this); + this.rateTrip = __bind(this.rateTrip, this); + this.locationChange = __bind(this.locationChange, this); + this.panToLocation = __bind(this.panToLocation, this); + this.clickLocation = __bind(this.clickLocation, this); + this.searchLocation = __bind(this.searchLocation, this); + this.mouseoutLocation = __bind(this.mouseoutLocation, this); + this.mouseoverLocation = __bind(this.mouseoverLocation, this); + this.fetchTripDetails = __bind(this.fetchTripDetails, this); + this.submitRating = __bind(this.submitRating, this); + this.setStatus = __bind(this.setStatus, this); + this.initialize = __bind(this.initialize, this); + ClientsRequestView.__super__.constructor.apply(this, arguments); + } + ClientsRequestView.prototype.id = 'request_view'; + ClientsRequestView.prototype.className = 'view_container'; + ClientsRequestView.prototype.pollInterval = 2 * 1000; + ClientsRequestView.prototype.events = { + "submit #search_form": "searchAddress", + "click .locations_link": "locationLinkHandle", + "mouseover .location_row": "mouseoverLocation", + "mouseout .location_row": "mouseoutLocation", + "click .location_row": "clickLocation", + "click #search_location": "searchLocation", + "click #pickupHandle": "pickupHandle", + "click .stars": "rateTrip", + "submit #rating_form": "submitRating", + "click #addToFavButton": "showFavLoc", + "click #favLocNickname": "selectInputText", + "submit #favLoc_form": "addToFavLoc" + }; + ClientsRequestView.prototype.status = ""; + ClientsRequestView.prototype.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png"; + ClientsRequestView.prototype.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png"; + ClientsRequestView.prototype.initialize = function() { + var displayCabs; + displayCabs = __bind(function() { + return this.AskDispatch("NearestCab"); + }, this); + this.showCabs = _.throttle(displayCabs, this.pollInterval); + return this.numSearchToDisplay = 1; + }; + ClientsRequestView.prototype.setStatus = function(status) { + var autocomplete; + if (this.status === status) { + return; + } + try { + google.maps.event.trigger(this.map, 'resize'); + } catch (_e) {} + switch (status) { + case "init": + this.AskDispatch("StatusClient"); + this.status = "init"; + return this.ShowSpinner("load"); + case "ready": + this.HideSpinner(); + $(".panel").hide(); + $("#top_bar").fadeIn(); + $("#location_panel").fadeIn(); + $("#location_panel_control").fadeIn(); + $("#pickupHandle").attr("class", "button_green").fadeIn().find("span").html(t("Request Pickup")); + this.pickup_icon.setDraggable(true); + this.map.panTo(this.pickup_icon.getPosition()); + this.showCabs(); + try { + this.pickup_icon.setMap(this.map); + this.displayFavLoc(); + autocomplete = new google.maps.places.Autocomplete(document.getElementById('address'), { + types: ['geocode'] + }); + autocomplete.bindTo('bounds', this.map); + } catch (_e) {} + return this.status = "ready"; + case "searching": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#status_message").html(t("Requesting Closest Driver")); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "searching"; + case "waiting": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "waiting"; + case "arriving": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").attr("class", "button_red").fadeIn().find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.pickup_icon.setMap(this.map); + return this.status = "arriving"; + case "riding": + this.HideSpinner(); + this.removeMarkers(); + $(".panel").hide(); + $("#top_bar").fadeOut(); + $("#pickupHandle").fadeIn().attr("class", "button_red").find("span").html(t("Cancel Pickup")); + $("#waiting_riding").fadeIn(); + this.pickup_icon.setDraggable(false); + this.status = "riding"; + return $("#status_message").html(t("En Route")); + case "rate": + this.HideSpinner(); + $(".panel").hide(); + $("#pickupHandle").fadeOut(); + $("#trip_completed_panel").fadeIn(); + $('#status_message').html(t("Rate Last Trip")); + return this.status = "rate"; + } + }; + ClientsRequestView.prototype.render = function() { + this.ReadUserInfo(); + this.HideSpinner(); + this.ShowSpinner("load"); + $(this.el).html(clientsRequestTemplate()); + this.cabs = []; + this.RequireMaps(__bind(function() { + var center, myOptions, streetViewPano; + center = new google.maps.LatLng(37.7749295, -122.4194155); + this.markers = []; + this.pickup_icon = new google.maps.Marker({ + position: center, + draggable: true, + clickable: true, + icon: this.pickupMarker + }); + this.geocoder = new google.maps.Geocoder(); + myOptions = { + zoom: 12, + center: center, + mapTypeId: google.maps.MapTypeId.ROADMAP, + rotateControl: false, + rotateControl: false, + panControl: false + }; + this.map = new google.maps.Map($(this.el).find("#map_wrapper_right")[0], myOptions); + if (this.status === "ready") { + this.pickup_icon.setMap(this.map); + } + if (geo_position_js.init()) { + geo_position_js.getCurrentPosition(__bind(function(data) { + var location; + location = new google.maps.LatLng(data.coords.latitude, data.coords.longitude); + this.pickup_icon.setPosition(location); + this.map.panTo(location); + return this.map.setZoom(16); + }, this)); + } + this.setStatus("init"); + streetViewPano = this.map.getStreetView(); + google.maps.event.addListener(streetViewPano, 'visible_changed', __bind(function() { + if (streetViewPano.getVisible()) { + this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker_large.png"; + this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker_large.png"; + } else { + this.pickupMarker = "https://uber-static.s3.amazonaws.com/pickup_marker.png"; + this.cabMarker = "https://uber-static.s3.amazonaws.com/cab_marker.png"; + } + this.pickup_icon.setIcon(this.pickupMarker); + return _.each(this.cabs, __bind(function(cab) { + return cab.setIcon(this.cabMarker); + }, this)); + }, this)); + if (this.status === "ready") { + return this.displayFavLoc(); + } + }, this)); + return this; + }; + ClientsRequestView.prototype.submitRating = function(e) { + var $el, message, rating; + e.preventDefault(); + $el = $(e.currentTarget); + rating = 0; + _(5).times(function(num) { + if ($el.find(".stars#" + (num + 1)).attr("src") === "/web/img/star_active.png") { + return rating = num + 1; + } + }); + if (rating === 0) { + $("#status_message").html("").html(t("Rate Before Submitting")); + } else { + this.ShowSpinner("submit"); + this.AskDispatch("RatingDriver", { + rating: rating + }); + } + message = $el.find("#comments").val().toString(); + if (message.length > 5) { + return this.AskDispatch("Feedback", { + message: message + }); + } + }; + ClientsRequestView.prototype.fetchTripDetails = function(id) { + var trip; + trip = new app.models.trip({ + id: id + }); + return trip.fetch({ + data: { + relationships: 'points,driver,city' + }, + dataType: 'json', + success: __bind(function() { + var bounds, endPos, path, polyline, startPos; + bounds = new google.maps.LatLngBounds(); + path = []; + _.each(trip.get('points'), __bind(function(point) { + path.push(new google.maps.LatLng(point.lat, point.lng)); + return bounds.extend(_.last(path)); + }, this)); + startPos = new google.maps.Marker({ + position: _.first(path), + map: this.map, + title: t("Trip started here"), + icon: 'https://uber-static.s3.amazonaws.com/carstart.png' + }); + endPos = new google.maps.Marker({ + position: _.last(path), + map: this.map, + title: t("Trip ended here"), + icon: 'https://uber-static.s3.amazonaws.com/carstop.png' + }); + polyline = new google.maps.Polyline({ + path: path, + strokeColor: '#003F87', + strokeOpacity: 1, + strokeWeight: 5 + }); + polyline.setMap(this.map); + this.map.fitBounds(bounds); + $("#tripTime").html(app.helpers.parseDateTime(trip.get('pickup_local_time'), trip.get('city.timezone'))); + $("#tripDist").html(app.helpers.RoundNumber(trip.get('distance'), 2)); + $("#tripDur").html(app.helpers.FormatSeconds(trip.get('duration'))); + return $("#tripFare").html(app.helpers.FormatCurrency(trip.get('fare'))); + }, this) + }); + }; + ClientsRequestView.prototype.searchAddress = function(e) { + var $locationsDiv, address, alphabet, bounds, showResults; + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + try { + e.preventDefault(); + } catch (_e) {} + $('.error_message').html(""); + $locationsDiv = $("
    "); + address = $('#address').val(); + bounds = new google.maps.LatLngBounds(); + if (address.length < 5) { + $('#status_message').html(t("Address too short")).fadeIn(); + return false; + } + showResults = __bind(function(address, index) { + var first_cell, row, second_cell; + if (index < this.numSearchToDisplay) { + first_cell = "
    " + address.formatted_address + "
    " + (t('or did you mean')) + "
    " + address.formatted_address + "